diff options
39 files changed, 261 insertions, 283 deletions
diff --git a/integration/intellij/build.gradle b/integration/intellij/build.gradle index 535911c5b8e..8f8c71ad5c7 100644 --- a/integration/intellij/build.gradle +++ b/integration/intellij/build.gradle @@ -36,7 +36,7 @@ compileJava { } group 'ai.vespa' -version '1.2.0' // Also update pom.xml version if this is changed +version '1.3.0' // Also update pom.xml version if this is changed sourceCompatibility = 11 @@ -61,10 +61,10 @@ buildSearchableOptions { patchPluginXml { version = project.version sinceBuild = '203' - untilBuild = '213.*' + untilBuild = '222.*' // in changeNotes you can add a description of the changes in this version (would appear in the plugin page in preferences\plugins) changeNotes = """ - Complete grammar (no more red squiggles) + Support for IntelliJ 2022 """ } diff --git a/integration/intellij/pom.xml b/integration/intellij/pom.xml index d7146a60f7a..841c2ad7ee1 100644 --- a/integration/intellij/pom.xml +++ b/integration/intellij/pom.xml @@ -9,7 +9,7 @@ <relativePath>../parent/pom.xml</relativePath> </parent> <artifactId>vespa-intellij</artifactId> <!-- Not used - plugin is build by gradle --> - <version>1.2.0</version> <!-- See copy-zip below, which depends on this being the same as the v. in build.gradle --> + <version>1.3.0</version> <!-- See copy-zip below, which depends on this being the same as the v. in build.gradle --> <description> Maven wrapper for the gradle build of this IntelliJ plugin. </description> diff --git a/searchcore/src/tests/proton/attribute/attribute_test.cpp b/searchcore/src/tests/proton/attribute/attribute_test.cpp index 800cb8aa0ce..e5314d1bf5d 100644 --- a/searchcore/src/tests/proton/attribute/attribute_test.cpp +++ b/searchcore/src/tests/proton/attribute/attribute_test.cpp @@ -149,7 +149,7 @@ public: { setup(1); } - ~AttributeWriterTest(); + ~AttributeWriterTest() override; void setup(uint32_t threads) { _aw.reset(); _attributeFieldWriterReal = std::make_unique<ForegroundTaskExecutor>(threads); diff --git a/searchcore/src/tests/proton/docsummary/docsummary.cpp b/searchcore/src/tests/proton/docsummary/docsummary.cpp index 93e8f3d248b..b034b77086c 100644 --- a/searchcore/src/tests/proton/docsummary/docsummary.cpp +++ b/searchcore/src/tests/proton/docsummary/docsummary.cpp @@ -35,6 +35,7 @@ #include <vespa/searchlib/tensor/tensor_attribute.h> #include <vespa/searchlib/transactionlog/nosyncproxy.h> #include <vespa/searchlib/transactionlog/translogserver.h> +#include <vespa/searchsummary/docsummary/i_docsum_field_writer_factory.h> #include <vespa/searchsummary/docsummary/i_docsum_store_document.h> #include <vespa/searchsummary/docsummary/summaryfieldconverter.h> #include <vespa/vespalib/data/simple_buffer.h> @@ -77,6 +78,19 @@ using namespace vespalib::slime; namespace proton { +class MockDocsumFieldWriterFactory : public search::docsummary::IDocsumFieldWriterFactory +{ +public: + std::unique_ptr<DocsumFieldWriter> create_docsum_field_writer(const vespalib::string& fieldName, const vespalib::string& overrideName, const vespalib::string& argument, bool& rc) override { + (void) fieldName; + (void) overrideName; + (void) argument; + (void) rc; + return {}; + } + +}; + class DirMaker { public: @@ -1121,7 +1135,8 @@ Fixture::Fixture() std::string cfgId("summary"); _summaryCfg = ConfigGetter<vespa::config::search::SummaryConfig>::getConfig( cfgId, ::config::FileSpec(TEST_PATH("summary.cfg"))); - _resultCfg.ReadConfig(*_summaryCfg, cfgId.c_str()); + auto docsum_field_writer_factory = std::make_unique<MockDocsumFieldWriterFactory>(); + _resultCfg.ReadConfig(*_summaryCfg, cfgId.c_str(), *docsum_field_writer_factory); } Fixture::~Fixture() = default; diff --git a/searchcore/src/tests/proton/docsummary/summary.cfg b/searchcore/src/tests/proton/docsummary/summary.cfg index cceb15c8fd2..33641351c02 100644 --- a/searchcore/src/tests/proton/docsummary/summary.cfg +++ b/searchcore/src/tests/proton/docsummary/summary.cfg @@ -61,31 +61,54 @@ classes[2].id 2 classes[2].fields[2] classes[2].fields[0].name "aa" classes[2].fields[0].type "integer" +classes[2].fields[0].command "copy" +classes[2].fields[0].source "ab" classes[2].fields[1].name "ab" classes[2].fields[1].type "integer" +classes[2].fields[1].command "empty" classes[3].name "class3" classes[3].id 3 classes[3].fields[10] classes[3].fields[0].name "ba" classes[3].fields[0].type "integer" +classes[3].fields[0].command "attribute" +classes[3].fields[0].source "ba" classes[3].fields[1].name "bb" classes[3].fields[1].type "float" +classes[3].fields[1].command "attribute" +classes[3].fields[1].source "bb" classes[3].fields[2].name "bc" classes[3].fields[2].type "longstring" +classes[3].fields[2].command "attribute" +classes[3].fields[2].source "bc" classes[3].fields[3].name "bd" classes[3].fields[3].type "jsonstring" +classes[3].fields[3].command "attribute" +classes[3].fields[3].source "bd" classes[3].fields[4].name "be" classes[3].fields[4].type "jsonstring" +classes[3].fields[4].command "attribute" +classes[3].fields[4].source "be" classes[3].fields[5].name "bf" classes[3].fields[5].type "jsonstring" +classes[3].fields[5].command "attribute" +classes[3].fields[5].source "bf" classes[3].fields[6].name "bg" classes[3].fields[6].type "jsonstring" +classes[3].fields[6].command "attribute" +classes[3].fields[6].source "bg" classes[3].fields[7].name "bh" classes[3].fields[7].type "jsonstring" +classes[3].fields[7].command "attribute" +classes[3].fields[7].source "bh" classes[3].fields[8].name "bi" classes[3].fields[8].type "jsonstring" +classes[3].fields[8].command "attribute" +classes[3].fields[8].source "bi" classes[3].fields[9].name "bj" classes[3].fields[9].type "tensor" +classes[3].fields[9].command "attribute" +classes[3].fields[9].source "bj" classes[4].name "class4" classes[4].id 4 classes[4].fields[1] @@ -98,18 +121,28 @@ classes[5].fields[0].name "sp2" classes[5].fields[0].type "int64" classes[5].fields[1].name "sp2x" classes[5].fields[1].type "xmlstring" +classes[5].fields[1].command "positions" +classes[5].fields[1].source "sp2" classes[5].fields[2].name "ap2" classes[5].fields[2].type "jsonstring" classes[5].fields[3].name "ap2x" classes[5].fields[3].type "xmlstring" +classes[5].fields[3].command "positions" +classes[5].fields[3].source "ap2" classes[5].fields[4].name "wp2" classes[5].fields[4].type "jsonstring" classes[5].fields[5].name "wp2x" classes[5].fields[5].type "xmlstring" +classes[5].fields[5].command "positions" +classes[5].fields[5].source "wp2" classes[6].name "class6" classes[6].id 6 classes[6].fields[6] classes[6].fields[0].name "ba" classes[6].fields[0].type "integer" +classes[6].fields[0].command "attribute" +classes[6].fields[0].source "ba" classes[6].fields[1].name "bb" classes[6].fields[1].type "float" +classes[6].fields[1].command "attribute" +classes[6].fields[1].source "bb" diff --git a/searchcore/src/tests/proton/matching/match_phase_limiter/match_phase_limiter_test.cpp b/searchcore/src/tests/proton/matching/match_phase_limiter/match_phase_limiter_test.cpp index 73771d700b4..5b3b9f962f7 100644 --- a/searchcore/src/tests/proton/matching/match_phase_limiter/match_phase_limiter_test.cpp +++ b/searchcore/src/tests/proton/matching/match_phase_limiter/match_phase_limiter_test.cpp @@ -41,7 +41,7 @@ struct MockSearch : SearchIterator { bool postings_fetched; uint32_t last_seek = beginId(); uint32_t last_unpack = beginId(); - MockSearch(const vespalib::string &term_in) + explicit MockSearch(const vespalib::string &term_in) : spec("", 0, 0), term(term_in), _strict(vespalib::Trinary::True), tfmda(), postings_fetched(false) {} MockSearch(const FieldSpec &spec_in, const vespalib::string &term_in, bool strict_in, const TermFieldMatchDataArray &tfmda_in, bool postings_fetched_in) @@ -65,16 +65,14 @@ struct MockBlueprint : SimpleLeafBlueprint { { setEstimate(HitEstimate(756, false)); } - virtual SearchIterator::UP createLeafSearch(const TermFieldMatchDataArray &tfmda, - bool strict) const override + SearchIterator::UP createLeafSearch(const TermFieldMatchDataArray &tfmda, bool strict) const override { if (postings_fetched) { EXPECT_EQUAL(postings_strict.isStrict(), strict); } - return SearchIterator::UP(new MockSearch(spec, term, strict, tfmda, - postings_fetched)); + return std::make_unique<MockSearch>(spec, term, strict, tfmda, postings_fetched); } - virtual void fetchPostings(const search::queryeval::ExecuteInfo &execInfo) override { + void fetchPostings(const search::queryeval::ExecuteInfo &execInfo) override { postings_strict = execInfo; postings_fetched = true; } @@ -88,7 +86,7 @@ struct MockSearchable : Searchable { { (void) requestContext; ++create_cnt; - return Blueprint::UP(new MockBlueprint(field, termAsString(term))); + return std::make_unique<MockBlueprint>(field, termAsString(term)); } }; @@ -175,7 +173,7 @@ TEST("require that the attribute limiter works correctly") { EXPECT_EQUAL(1u, searchable.create_cnt); SearchIterator::UP s2 = limiter.create_search(42, diverse ? 3 : 42, strict); EXPECT_EQUAL(1u, searchable.create_cnt); - MockSearch *ms = dynamic_cast<MockSearch*>(s1.get()); + auto *ms = dynamic_cast<MockSearch*>(s1.get()); ASSERT_TRUE(ms != nullptr); EXPECT_EQUAL("limiter_attribute", ms->spec.getName()); EXPECT_EQUAL(0u, ms->spec.getFieldId()); @@ -208,7 +206,7 @@ TEST("require that no limiter has no behavior") { SearchIterator::UP search = limiter.maybe_limit(prepare(new MockSearch("search")), 1.0, 100000000, nullptr); limiter.updateDocIdSpaceEstimate(1000, 9000); EXPECT_EQUAL(std::numeric_limits<size_t>::max(), limiter.getDocIdSpaceEstimate()); - MockSearch *ms = dynamic_cast<MockSearch*>(search.get()); + auto *ms = dynamic_cast<MockSearch*>(search.get()); ASSERT_TRUE(ms != nullptr); EXPECT_EQUAL("search", ms->term); EXPECT_FALSE(limiter.was_limited()); @@ -226,7 +224,7 @@ TEST("require that the match phase limiter may chose not to limit the query") { SearchIterator::UP search = limiter.maybe_limit(prepare(new MockSearch("search")), 0.005, 100000, nullptr); limiter.updateDocIdSpaceEstimate(1000, 9000); EXPECT_EQUAL(10000u, limiter.getDocIdSpaceEstimate()); - MockSearch *ms = dynamic_cast<MockSearch*>(search.get()); + auto *ms = dynamic_cast<MockSearch*>(search.get()); ASSERT_TRUE(ms != nullptr); EXPECT_EQUAL("search", ms->term); EXPECT_FALSE(limiter.was_limited()); @@ -254,7 +252,7 @@ TEST_F("require that the match phase limiter may chose not to limit the query wh SearchIterator::UP search = limiter.maybe_limit(prepare(new MockSearch("search")), 0.10, 1900000, nullptr); limiter.updateDocIdSpaceEstimate(1000, 1899000); EXPECT_EQUAL(1900000u, limiter.getDocIdSpaceEstimate()); - MockSearch *ms = dynamic_cast<MockSearch *>(search.get()); + auto *ms = dynamic_cast<MockSearch *>(search.get()); ASSERT_TRUE(ms != nullptr); EXPECT_EQUAL("search", ms->term); EXPECT_FALSE(limiter.was_limited()); @@ -266,11 +264,11 @@ TEST_F("require that the match phase limiter may chose to limit the query even w SearchIterator::UP search = limiter.maybe_limit(prepare(new MockSearch("search")), 0.10, 2100000, nullptr); limiter.updateDocIdSpaceEstimate(1000, 2099000); EXPECT_EQUAL(159684u, limiter.getDocIdSpaceEstimate()); - LimitedSearch *strict_and = dynamic_cast<LimitedSearch*>(search.get()); + auto *strict_and = dynamic_cast<LimitedSearch*>(search.get()); ASSERT_TRUE(strict_and != nullptr); - const MockSearch *ms1 = dynamic_cast<const MockSearch*>(&strict_and->getFirst()); + const auto *ms1 = dynamic_cast<const MockSearch*>(&strict_and->getFirst()); ASSERT_TRUE(ms1 != nullptr); - const MockSearch *ms2 = dynamic_cast<const MockSearch*>(&strict_and->getSecond()); + const auto *ms2 = dynamic_cast<const MockSearch*>(&strict_and->getSecond()); ASSERT_TRUE(ms2 != nullptr); EXPECT_EQUAL("[;;-100000]", ms1->term); EXPECT_EQUAL("search", ms2->term); @@ -300,11 +298,11 @@ TEST("require that the match phase limiter is able to pre-limit the query") { SearchIterator::UP search = limiter.maybe_limit(prepare(new MockSearch("search")), 0.1, 100000, trace.maybeCreateCursor(7, "limit")); limiter.updateDocIdSpaceEstimate(1000, 9000); EXPECT_EQUAL(1680u, limiter.getDocIdSpaceEstimate()); - LimitedSearch *strict_and = dynamic_cast<LimitedSearch*>(search.get()); + auto *strict_and = dynamic_cast<LimitedSearch*>(search.get()); ASSERT_TRUE(strict_and != nullptr); - const MockSearch *ms1 = dynamic_cast<const MockSearch*>(&strict_and->getFirst()); + const auto *ms1 = dynamic_cast<const MockSearch*>(&strict_and->getFirst()); ASSERT_TRUE(ms1 != nullptr); - const MockSearch *ms2 = dynamic_cast<const MockSearch*>(&strict_and->getSecond()); + const auto *ms2 = dynamic_cast<const MockSearch*>(&strict_and->getSecond()); ASSERT_TRUE(ms2 != nullptr); EXPECT_EQUAL("[;;-5000]", ms1->term); EXPECT_EQUAL("search", ms2->term); @@ -352,11 +350,11 @@ TEST("require that the match phase limiter is able to post-limit the query") { SearchIterator::UP search = limiter.maybe_limit(prepare(new MockSearch("search")), 0.1, 100000, nullptr); limiter.updateDocIdSpaceEstimate(1000, 9000); EXPECT_EQUAL(1680u, limiter.getDocIdSpaceEstimate()); - LimitedSearch *strict_and = dynamic_cast<LimitedSearch*>(search.get()); + auto *strict_and = dynamic_cast<LimitedSearch*>(search.get()); ASSERT_TRUE(strict_and != nullptr); - const MockSearch *ms1 = dynamic_cast<const MockSearch*>(&strict_and->getFirst()); + const auto *ms1 = dynamic_cast<const MockSearch*>(&strict_and->getFirst()); ASSERT_TRUE(ms1 != nullptr); - const MockSearch *ms2 = dynamic_cast<const MockSearch*>(&strict_and->getSecond()); + const auto *ms2 = dynamic_cast<const MockSearch*>(&strict_and->getSecond()); ASSERT_TRUE(ms2 != nullptr); EXPECT_EQUAL("search", ms1->term); EXPECT_EQUAL("[;;-15000]", ms2->term); @@ -382,9 +380,9 @@ void verifyDiversity(AttributeLimiter::DiversityCutoffStrategy strategy) SearchIterator::UP search = limiter.maybe_limit(prepare(new MockSearch("search")), 0.1, 100000, nullptr); limiter.updateDocIdSpaceEstimate(1000, 9000); EXPECT_EQUAL(1680u, limiter.getDocIdSpaceEstimate()); - LimitedSearch *strict_and = dynamic_cast<LimitedSearch*>(search.get()); + auto *strict_and = dynamic_cast<LimitedSearch*>(search.get()); ASSERT_TRUE(strict_and != nullptr); - const MockSearch *ms1 = dynamic_cast<const MockSearch*>(&strict_and->getFirst()); + const auto *ms1 = dynamic_cast<const MockSearch*>(&strict_and->getFirst()); ASSERT_TRUE(ms1 != nullptr); if (strategy == AttributeLimiter::LOOSE) { EXPECT_EQUAL("[;;-5000;category;500;131;loose]", ms1->term); diff --git a/searchcore/src/vespa/searchcore/proton/docsummary/docsumcontext.cpp b/searchcore/src/vespa/searchcore/proton/docsummary/docsumcontext.cpp index 942dac63955..9a4ec121d3b 100644 --- a/searchcore/src/vespa/searchcore/proton/docsummary/docsumcontext.cpp +++ b/searchcore/src/vespa/searchcore/proton/docsummary/docsumcontext.cpp @@ -71,13 +71,13 @@ makeSlimeParams(size_t chunkSize) { vespalib::Slime::UP DocsumContext::createSlimeReply() { - _docsumWriter.InitState(_attrMgr, &_docsumState); + IDocsumWriter::ResolveClassInfo rci = _docsumWriter.resolveClassInfo(_docsumState._args.getResultClassName()); + _docsumWriter.InitState(_attrMgr, _docsumState, rci); const size_t estimatedChunkSize(std::min(0x200000ul, _docsumState._docsumbuf.size()*0x400ul)); vespalib::Slime::UP response(std::make_unique<vespalib::Slime>(makeSlimeParams(estimatedChunkSize))); Cursor & root = response->setObject(); Cursor & array = root.setArray(DOCSUMS); const Symbol docsumSym = response->insert(DOCSUM); - IDocsumWriter::ResolveClassInfo rci = _docsumWriter.resolveClassInfo(_docsumState._args.getResultClassName()); _docsumState._omit_summary_features = (rci.outputClass != nullptr) ? rci.outputClass->omit_summary_features() : true; uint32_t num_ok(0); for (uint32_t docId : _docsumState._docsumbuf) { diff --git a/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.cpp b/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.cpp index 3e3a3529e46..6a0133e913d 100644 --- a/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.cpp +++ b/searchcore/src/vespa/searchcore/proton/docsummary/summarymanager.cpp @@ -9,7 +9,7 @@ #include <vespa/juniper/rpinterface.h> #include <vespa/searchcore/proton/flushengine/shrink_lid_space_flush_target.h> #include <vespa/vespalib/util/lambdatask.h> -#include <vespa/searchsummary/docsummary/docsumconfig.h> +#include <vespa/searchsummary/docsummary/docsum_field_writer_factory.h> #include <vespa/searchsummary/docsummary/keywordextractor.h> #include <vespa/vespalib/util/exceptions.h> #include <vespa/fastlib/text/normwordfolder.h> @@ -92,8 +92,10 @@ SummarySetup(const vespalib::string & baseDir, const SummaryConfig & summaryCfg, _docStore(std::move(docStore)), _repo(std::move(repo)) { + _juniperConfig = std::make_unique<juniper::Juniper>(&_juniperProps, _wordFolder.get()); auto resultConfig = std::make_unique<ResultConfig>(); - if (!resultConfig->ReadConfig(summaryCfg, make_string("SummaryManager(%s)", baseDir.c_str()).c_str())) { + auto docsum_field_writer_factory = std::make_unique<DocsumFieldWriterFactory>(summaryCfg.usev8geopositions, *this); + if (!resultConfig->ReadConfig(summaryCfg, make_string("SummaryManager(%s)", baseDir.c_str()).c_str(), *docsum_field_writer_factory)) { std::ostringstream oss; ::config::OstreamConfigWriter writer(oss); writer.write(summaryCfg); @@ -101,11 +103,10 @@ SummarySetup(const vespalib::string & baseDir, const SummaryConfig & summaryCfg, (make_string("Could not initialize summary result config for directory '%s' based on summary config '%s'", baseDir.c_str(), oss.str().c_str())); } + docsum_field_writer_factory.reset(); - _juniperConfig = std::make_unique<juniper::Juniper>(&_juniperProps, _wordFolder.get()); _docsumWriter = std::make_unique<DynamicDocsumWriter>(std::move(resultConfig), std::unique_ptr<KeywordExtractor>()); - DynamicDocsumConfig dynCfg(*this, _docsumWriter.get()); - dynCfg.configure(summarymapCfg); + (void) summarymapCfg; } IDocsumStore::UP diff --git a/searchcore/src/vespa/searchcore/proton/matching/query.cpp b/searchcore/src/vespa/searchcore/proton/matching/query.cpp index aaacb971ee0..ec289c06122 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/query.cpp +++ b/searchcore/src/vespa/searchcore/proton/matching/query.cpp @@ -52,7 +52,7 @@ inject(Node::UP query, Node::UP to_inject) { if (auto * my_and = dynamic_cast<search::query::And *>(query.get())) { my_and->append(std::move(to_inject)); } else if (dynamic_cast<search::query::Rank *>(query.get()) || dynamic_cast<search::query::AndNot *>(query.get())) { - search::query::Intermediate & root = static_cast<search::query::Intermediate &>(*query); + auto & root = static_cast<search::query::Intermediate &>(*query); root.prepend(inject(root.stealFirst(), std::move(to_inject))); } else { auto new_root = std::make_unique<ProtonAnd>(); @@ -82,7 +82,7 @@ find_location_terms(Node *tree) { return locations; } -GeoLocationSpec parse_location_string(string str) { +GeoLocationSpec parse_location_string(const string & str) { GeoLocationSpec empty; if (str.empty()) { return empty; diff --git a/searchcore/src/vespa/searchcore/proton/matching/querylimiter.h b/searchcore/src/vespa/searchcore/proton/matching/querylimiter.h index 67faf74a65d..c3e6e9af475 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/querylimiter.h +++ b/searchcore/src/vespa/searchcore/proton/matching/querylimiter.h @@ -17,7 +17,7 @@ public: class Token { public: typedef std::unique_ptr<Token> UP; - virtual ~Token() { } + virtual ~Token() = default; }; public: QueryLimiter(); @@ -31,7 +31,9 @@ private: QueryLimiter & _limiter; public: LimitedToken(const Doom & doom, QueryLimiter & limiter); - virtual ~LimitedToken(); + LimitedToken(const NoLimitToken &) = delete; + LimitedToken & operator =(const NoLimitToken &) = delete; + ~LimitedToken() override; }; void grabToken(const Doom & doom); void releaseToken(); diff --git a/searchcore/src/vespa/searchcore/proton/matching/querynodes.h b/searchcore/src/vespa/searchcore/proton/matching/querynodes.h index bbe58338b12..20d602b7814 100644 --- a/searchcore/src/vespa/searchcore/proton/matching/querynodes.h +++ b/searchcore/src/vespa/searchcore/proton/matching/querynodes.h @@ -61,7 +61,7 @@ public: ProtonTermData & operator = (const ProtonTermData &); ProtonTermData(ProtonTermData &&) = default; ProtonTermData & operator = (ProtonTermData &&) = default; - ~ProtonTermData(); + ~ProtonTermData() override; void resolveFromChildren(const std::vector<search::query::Node *> &children); void allocateTerms(search::fef::MatchDataLayout &mdl); void setDocumentFrequency(uint32_t estHits, uint32_t numDocs); @@ -93,9 +93,9 @@ struct ProtonTermBase : public Base, } // ITermData interface - uint32_t getPhraseLength() const override final { return numTerms<Base>(*this); } - search::query::Weight getWeight() const override final { return Base::getWeight(); } - uint32_t getUniqueId() const override final { return Base::getId(); } + uint32_t getPhraseLength() const final { return numTerms<Base>(*this); } + search::query::Weight getWeight() const final { return Base::getWeight(); } + uint32_t getUniqueId() const final { return Base::getId(); } }; template <typename Base> diff --git a/searchcore/src/vespa/searchcore/proton/server/fileconfigmanager.cpp b/searchcore/src/vespa/searchcore/proton/server/fileconfigmanager.cpp index 820e61bc7a7..5ee70575916 100644 --- a/searchcore/src/vespa/searchcore/proton/server/fileconfigmanager.cpp +++ b/searchcore/src/vespa/searchcore/proton/server/fileconfigmanager.cpp @@ -328,6 +328,7 @@ FileConfigManager::loadConfig(const DocumentDBConfig ¤tSnapshot, search::S addEmptyFile(snapDir, "ranking-expressions.cfg"); addEmptyFile(snapDir, "onnx-models.cfg"); addEmptyFile(snapDir, "imported-fields.cfg"); + addEmptyFile(snapDir, "summarymap.cfg"); DocumentDBConfigHelper dbc(spec, _docTypeName); diff --git a/searchlib/src/tests/attribute/searchable/attributeblueprint_test.cpp b/searchlib/src/tests/attribute/searchable/attributeblueprint_test.cpp index 67bd0286884..29dbf33d29c 100644 --- a/searchlib/src/tests/attribute/searchable/attributeblueprint_test.cpp +++ b/searchlib/src/tests/attribute/searchable/attributeblueprint_test.cpp @@ -72,7 +72,7 @@ public: } AttributeGuard::UP getAttribute(const string &) const override { - return AttributeGuard::UP(new AttributeGuard(_attribute_vector)); + return std::make_unique<AttributeGuard>(_attribute_vector); } std::unique_ptr<attribute::AttributeReadGuard> diff --git a/searchlib/src/vespa/searchcommon/attribute/i_search_context.h b/searchlib/src/vespa/searchcommon/attribute/i_search_context.h index ff62c535e7f..aa5e216ecd9 100644 --- a/searchlib/src/vespa/searchcommon/attribute/i_search_context.h +++ b/searchlib/src/vespa/searchcommon/attribute/i_search_context.h @@ -25,7 +25,7 @@ private: virtual int32_t onFind(DocId docId, int32_t elementId) const = 0; public: - virtual ~ISearchContext() {} + virtual ~ISearchContext() = default; virtual unsigned int approximateHits() const = 0; diff --git a/searchlib/src/vespa/searchcommon/attribute/iattributecontext.h b/searchlib/src/vespa/searchcommon/attribute/iattributecontext.h index bb349057ca9..9c89b6a0f8b 100644 --- a/searchlib/src/vespa/searchcommon/attribute/iattributecontext.h +++ b/searchlib/src/vespa/searchcommon/attribute/iattributecontext.h @@ -12,9 +12,9 @@ namespace search::attribute { **/ class IAttributeContext : public IAttributeExecutor { public: - typedef vespalib::string string; + using string = vespalib::string; /** Convenience typedefs **/ - typedef std::unique_ptr<IAttributeContext> UP; + using UP = std::unique_ptr<IAttributeContext>; /** * Returns the attribute vector with the given name. @@ -48,7 +48,7 @@ public: /** * Virtual destructor to allow safe subclassing. **/ - virtual ~IAttributeContext() {} + virtual ~IAttributeContext() = default; }; } diff --git a/searchlib/src/vespa/searchlib/attribute/attribute_blueprint_factory.cpp b/searchlib/src/vespa/searchlib/attribute/attribute_blueprint_factory.cpp index 5905995d586..57423f42a10 100644 --- a/searchlib/src/vespa/searchlib/attribute/attribute_blueprint_factory.cpp +++ b/searchlib/src/vespa/searchlib/attribute/attribute_blueprint_factory.cpp @@ -153,7 +153,7 @@ public: .diversityCutoffStrict(diversityCutoffStrict)) {} - SearchIterator::UP createLeafSearch(const TermFieldMatchDataArray &tfmda, bool strict) const override { + SearchIteratorUP createLeafSearch(const TermFieldMatchDataArray &tfmda, bool strict) const override { assert(tfmda.size() == 1); return _search_context->createIterator(tfmda[0], strict); } @@ -406,22 +406,7 @@ public: } } - SearchIterator::UP createLeafSearch(const TermFieldMatchDataArray &tfmda, bool) const override - { - assert(tfmda.size() == 1); - assert(getState().numFields() == 1); - if (_terms.empty()) { - return std::make_unique<queryeval::EmptySearch>(); - } - std::vector<DocumentWeightIterator> iterators; - const size_t numChildren = _terms.size(); - iterators.reserve(numChildren); - for (const IDocumentWeightAttribute::LookupResult &r : _terms) { - _attr.create(r.posting_idx, iterators); - } - bool field_is_filter = getState().fields()[0].isFilter(); - return SearchType::create(*tfmda[0], field_is_filter, _weights, std::move(iterators)); - } + SearchIterator::UP createLeafSearch(const TermFieldMatchDataArray &tfmda, bool) const override; std::unique_ptr<SearchIterator> createFilterSearch(bool strict, FilterConstraint constraint) const override; std::unique_ptr<queryeval::MatchingElementsSearch> create_matching_elements_search(const MatchingElementsFields &fields) const override { @@ -434,6 +419,26 @@ public: }; template <typename SearchType> +SearchIterator::UP +DirectWeightedSetBlueprint<SearchType>::createLeafSearch(const TermFieldMatchDataArray &tfmda, bool) const +{ + assert(tfmda.size() == 1); + assert(getState().numFields() == 1); + if (_terms.empty()) { + return std::make_unique<queryeval::EmptySearch>(); + } + std::vector<DocumentWeightIterator> iterators; + const size_t numChildren = _terms.size(); + iterators.reserve(numChildren); + for (const IDocumentWeightAttribute::LookupResult &r : _terms) { + _attr.create(r.posting_idx, iterators); + } + bool field_is_filter = getState().fields()[0].isFilter(); + return SearchType::create(*tfmda[0], field_is_filter, _weights, std::move(iterators)); +} + + +template <typename SearchType> DirectWeightedSetBlueprint<SearchType>::~DirectWeightedSetBlueprint() = default; template <typename SearchType> diff --git a/searchlib/src/vespa/searchlib/common/geo_location_parser.cpp b/searchlib/src/vespa/searchlib/common/geo_location_parser.cpp index d829e1b93e4..cb69d2346ce 100644 --- a/searchlib/src/vespa/searchlib/common/geo_location_parser.cpp +++ b/searchlib/src/vespa/searchlib/common/geo_location_parser.cpp @@ -2,7 +2,6 @@ #include "geo_location_parser.h" #include <limits> -#include <vespa/vespalib/stllike/asciistream.h> #include <vespa/vespalib/data/slime/slime.h> #include <vespa/vespalib/data/slime/json_format.h> diff --git a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp index 17e50216a23..afd5e349da9 100644 --- a/searchlib/src/vespa/searchlib/query/query_term_simple.cpp +++ b/searchlib/src/vespa/searchlib/query/query_term_simple.cpp @@ -3,7 +3,6 @@ #include "base.h" #include "query_term_simple.h" #include <vespa/vespalib/objects/visit.h> -#include <vespa/vespalib/text/utf8.h> #include <vespa/vespalib/util/classname.h> #include <vespa/vespalib/locale/c.h> #include <cmath> @@ -314,7 +313,7 @@ QueryTermSimple::getClassName() const void visit(vespalib::ObjectVisitor &self, const vespalib::string &name, const search::QueryTermSimple *obj) { - if (obj != 0) { + if (obj != nullptr) { self.openStruct(name, obj->getClassName()); obj->visitMembers(self); self.closeStruct(); diff --git a/searchlib/src/vespa/searchlib/queryeval/blueprint.h b/searchlib/src/vespa/searchlib/queryeval/blueprint.h index b7fe627d854..83836f874f0 100644 --- a/searchlib/src/vespa/searchlib/queryeval/blueprint.h +++ b/searchlib/src/vespa/searchlib/queryeval/blueprint.h @@ -169,7 +169,7 @@ protected: public: class IPredicate { public: - virtual ~IPredicate() {} + virtual ~IPredicate() = default; virtual bool check(const Blueprint & bp) const = 0; }; diff --git a/searchlib/src/vespa/searchlib/queryeval/fake_requestcontext.cpp b/searchlib/src/vespa/searchlib/queryeval/fake_requestcontext.cpp index a123d3f6cd1..8b633302ff7 100644 --- a/searchlib/src/vespa/searchlib/queryeval/fake_requestcontext.cpp +++ b/searchlib/src/vespa/searchlib/queryeval/fake_requestcontext.cpp @@ -6,6 +6,11 @@ namespace search::queryeval { +FakeRequestContext::FakeRequestContext() + : FakeRequestContext(nullptr) +{ +} + FakeRequestContext::FakeRequestContext(attribute::IAttributeContext * context, vespalib::steady_time softDoom, vespalib::steady_time hardDoom) : _clock(std::make_unique<vespalib::TestClock>()), _doom(_clock->clock(), softDoom, hardDoom, false), diff --git a/searchlib/src/vespa/searchlib/queryeval/fake_requestcontext.h b/searchlib/src/vespa/searchlib/queryeval/fake_requestcontext.h index 4d7e092a812..9f829c9473c 100644 --- a/searchlib/src/vespa/searchlib/queryeval/fake_requestcontext.h +++ b/searchlib/src/vespa/searchlib/queryeval/fake_requestcontext.h @@ -19,10 +19,11 @@ namespace search::queryeval { class FakeRequestContext : public IRequestContext { public: - FakeRequestContext(attribute::IAttributeContext * context = nullptr, + FakeRequestContext(); + FakeRequestContext(attribute::IAttributeContext * context, vespalib::steady_time soft=vespalib::steady_time::max(), vespalib::steady_time hard=vespalib::steady_time::max()); - ~FakeRequestContext(); + ~FakeRequestContext() override; const vespalib::Doom & getDoom() const override { return _doom; } const attribute::IAttributeVector *getAttribute(const vespalib::string &name) const override { return _attributeContext diff --git a/searchsummary/src/tests/docsummary/matched_elements_filter/matched_elements_filter_test.cpp b/searchsummary/src/tests/docsummary/matched_elements_filter/matched_elements_filter_test.cpp index 22b3ae69165..4fcf8c10401 100644 --- a/searchsummary/src/tests/docsummary/matched_elements_filter/matched_elements_filter_test.cpp +++ b/searchsummary/src/tests/docsummary/matched_elements_filter/matched_elements_filter_test.cpp @@ -70,6 +70,8 @@ private: ArrayDataType _array_type; MapDataType _map_type; WeightedSetDataType _wset_type; + bool _empty_values; + bool _skip_set_values; StructFieldValue::UP make_elem_value(const std::string& name, int weight) const { auto result = std::make_unique<StructFieldValue>(*_elem_type); @@ -85,7 +87,9 @@ public: _elem_type(make_struct_elem_type()), _array_type(*_elem_type), _map_type(*DataType::STRING, *_elem_type), - _wset_type(*DataType::STRING, false, false) + _wset_type(*DataType::STRING, false, false), + _empty_values(false), + _skip_set_values(false) { _doc_type.addField(Field("array", _array_type)); _doc_type.addField(Field("map", _map_type)); @@ -105,32 +109,50 @@ public: auto doc = std::make_unique<Document>(_doc_type, DocumentId("id:test:test::0")); { ArrayFieldValue array_value(_array_type); - array_value.append(make_elem_value("a", 3)); - array_value.append(make_elem_value("b", 5)); - array_value.append(make_elem_value("c", 7)); - doc->setValue("array", array_value); + if (!_empty_values) { + array_value.append(make_elem_value("a", 3)); + array_value.append(make_elem_value("b", 5)); + array_value.append(make_elem_value("c", 7)); + } + if (!_skip_set_values) { + doc->setValue("array", array_value); + } } { MapFieldValue map_value(_map_type); - map_value.put(StringFieldValue("a"), *make_elem_value("a", 3)); - map_value.put(StringFieldValue("b"), *make_elem_value("b", 5)); - map_value.put(StringFieldValue("c"), *make_elem_value("c", 7)); - doc->setValue("map", map_value); + if (!_empty_values) { + map_value.put(StringFieldValue("a"), *make_elem_value("a", 3)); + map_value.put(StringFieldValue("b"), *make_elem_value("b", 5)); + map_value.put(StringFieldValue("c"), *make_elem_value("c", 7)); + } + if (!_skip_set_values) { + doc->setValue("map", map_value); + } } { MapFieldValue map2_value(_map_type); - map2_value.put(StringFieldValue("dummy"), *make_elem_value("dummy", 2)); - doc->setValue("map2", map2_value); + if (!_empty_values) { + map2_value.put(StringFieldValue("dummy"), *make_elem_value("dummy", 2)); + } + if (!_skip_set_values) { + doc->setValue("map2", map2_value); + } } { WeightedSetFieldValue wset_value(_wset_type); - wset_value.add(StringFieldValue("a"), 13); - wset_value.add(StringFieldValue("b"), 15); - wset_value.add(StringFieldValue("c"), 17); - doc->setValue("wset", wset_value); + if (!_empty_values) { + wset_value.add(StringFieldValue("a"), 13); + wset_value.add(StringFieldValue("b"), 15); + wset_value.add(StringFieldValue("c"), 17); + } + if (!_skip_set_values) { + doc->setValue("wset", wset_value); + } } return std::make_unique<DocsumStoreDocument>(std::move(doc)); } + void set_empty_values() { _empty_values = true; } + void set_skip_set_values() { _skip_set_values = true; } }; DocsumStore::~DocsumStore() = default; @@ -218,7 +240,9 @@ public: EXPECT_EQ(exp.slime, act); } const MatchingElementsFields& fields() const { return *_fields; } -}; + void set_empty_values() { _doc_store.set_empty_values(); } + void set_skip_set_values() { _doc_store.set_skip_set_values(); } + }; MatchedElementsFilterTest::~MatchedElementsFilterTest() = default; @@ -232,6 +256,10 @@ TEST_F(MatchedElementsFilterTest, filters_elements_in_array_field_value) "{'name':'b','weight':5}," "{'name':'c','weight':7}]"); expect_filtered("array", {0, 1, 100}, "[]"); + set_empty_values(); + expect_filtered("array", {}, "null"); + set_skip_set_values(); + expect_filtered("array", {}, "null"); } TEST_F(MatchedElementsFilterTest, matching_elements_fields_is_setup_for_array_field_value) @@ -252,6 +280,10 @@ TEST_F(MatchedElementsFilterTest, filters_elements_in_map_field_value) "{'key':'b','value':{'name':'b','weight':5}}," "{'key':'c','value':{'name':'c','weight':7}}]"); expect_filtered("map", {0, 1, 100}, "[]"); + set_empty_values(); + expect_filtered("map", {}, "null"); + set_skip_set_values(); + expect_filtered("map", {}, "null"); } TEST_F(MatchedElementsFilterTest, filter_elements_in_weighed_set_field_value) @@ -262,6 +294,10 @@ TEST_F(MatchedElementsFilterTest, filter_elements_in_weighed_set_field_value) expect_filtered("wset", {2}, "[{'item':'c','weight':17}]"); expect_filtered("wset", {0, 1, 2}, "[{'item':'a','weight':13},{'item':'b','weight':15},{'item':'c','weight':17}]"); expect_filtered("wset", {0, 1, 100}, "[]"); + set_empty_values(); + expect_filtered("wset", {}, "null"); + set_skip_set_values(); + expect_filtered("wset", {}, "null"); } TEST_F(MatchedElementsFilterTest, matching_elements_fields_is_setup_for_map_field_value) diff --git a/searchsummary/src/vespa/searchsummary/docsummary/CMakeLists.txt b/searchsummary/src/vespa/searchsummary/docsummary/CMakeLists.txt index 963c94f7796..8070bed8b03 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/CMakeLists.txt +++ b/searchsummary/src/vespa/searchsummary/docsummary/CMakeLists.txt @@ -7,7 +7,6 @@ vespa_add_library(searchsummary_docsummary OBJECT attributedfw.cpp check_undefined_value_visitor.cpp copy_dfw.cpp - docsumconfig.cpp docsum_field_writer.cpp docsum_field_writer_factory.cpp docsum_store_document.cpp diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.cpp b/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.cpp deleted file mode 100644 index 0c2adcbfaa5..00000000000 --- a/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "docsumconfig.h" -#include "docsum_field_writer_factory.h" -#include "docsumwriter.h" -#include <vespa/vespalib/util/exceptions.h> - -namespace search::docsummary { - -using vespalib::IllegalArgumentException; -using vespalib::make_string; - -const ResultConfig & -DynamicDocsumConfig::getResultConfig() const { - return *_writer->GetResultConfig(); -} - -std::unique_ptr<IDocsumFieldWriterFactory> -DynamicDocsumConfig::make_docsum_field_writer_factory() -{ - return std::make_unique<DocsumFieldWriterFactory>(getResultConfig().useV8geoPositions(), getEnvironment()); -} - -void -DynamicDocsumConfig::configure(const vespa::config::search::SummarymapConfig &cfg) -{ - std::vector<string> strCfg; - auto docsum_field_writer_factory = make_docsum_field_writer_factory(); - for (const auto & o : cfg.override) { - bool rc(false); - auto fieldWriter = docsum_field_writer_factory->create_docsum_field_writer(o.field, o.command, o.arguments, rc); - if (rc && fieldWriter) { - rc = _writer->Override(o.field.c_str(), std::move(fieldWriter)); // OBJECT HAND-OVER - } - if (!rc) { - throw IllegalArgumentException(o.command + " override operation failed during initialization"); - } - } -} - -} diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.h b/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.h deleted file mode 100644 index 2b0f90a8e8b..00000000000 --- a/searchsummary/src/vespa/searchsummary/docsummary/docsumconfig.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include <vespa/config-summarymap.h> - -namespace search { class MatchingElementsFields; } -namespace search::docsummary { - -class IDocsumEnvironment; -class IDocsumFieldWriterFactory; -class DocsumFieldWriter; -class DynamicDocsumWriter; -class ResultConfig; - -class DynamicDocsumConfig -{ -public: - DynamicDocsumConfig(const IDocsumEnvironment& env, DynamicDocsumWriter * writer) : - _env(env), - _writer(writer) - { } - virtual ~DynamicDocsumConfig() = default; - void configure(const vespa::config::search::SummarymapConfig &cfg); -protected: - using string = vespalib::string; - const IDocsumEnvironment& getEnvironment() { return _env; } - const ResultConfig & getResultConfig() const; - - virtual std::unique_ptr<IDocsumFieldWriterFactory> make_docsum_field_writer_factory(); -private: - const IDocsumEnvironment& _env; - DynamicDocsumWriter * _writer; -}; - -} - diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp b/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp index 89de20b6a81..181af0ca9a3 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.cpp @@ -60,7 +60,7 @@ DynamicDocsumWriter::insertDocsum(const ResolveClassInfo & rci, uint32_t docid, vespalib::slime::Cursor & docsum = topInserter.insertObject(); for (uint32_t i = 0; i < rci.outputClass->GetNumEntries(); ++i) { const ResConfigEntry *resCfg = rci.outputClass->GetEntry(i); - const DocsumFieldWriter *writer = _overrideTable[resCfg->_enumValue].get(); + const DocsumFieldWriter *writer = resCfg->_docsum_field_writer.get(); if (state->_args.needField(resCfg->_bindname) && ! writer->isDefaultValue(docid, state)) { const Memory field_name(resCfg->_bindname.data(), resCfg->_bindname.size()); ObjectInserter inserter(docsum, field_name); @@ -78,7 +78,7 @@ DynamicDocsumWriter::insertDocsum(const ResolveClassInfo & rci, uint32_t docid, for (uint32_t i = 0; i < rci.outputClass->GetNumEntries(); ++i) { const ResConfigEntry *outCfg = rci.outputClass->GetEntry(i); if ( ! state->_args.needField(outCfg->_bindname)) continue; - const DocsumFieldWriter *writer = _overrideTable[outCfg->_enumValue].get(); + const DocsumFieldWriter *writer = outCfg->_docsum_field_writer.get(); const Memory field_name(outCfg->_bindname.data(), outCfg->_bindname.size()); ObjectInserter inserter(docsum, field_name); if (writer != nullptr) { @@ -96,60 +96,31 @@ DynamicDocsumWriter::insertDocsum(const ResolveClassInfo & rci, uint32_t docid, DynamicDocsumWriter::DynamicDocsumWriter(std::unique_ptr<ResultConfig> config, std::unique_ptr<KeywordExtractor> extractor) : _resultConfig(std::move(config)), - _keywordExtractor(std::move(extractor)), - _numFieldWriterStates(0), - _overrideTable(_resultConfig->GetFieldNameEnum().GetNumEntries()) + _keywordExtractor(std::move(extractor)) { } DynamicDocsumWriter::~DynamicDocsumWriter() = default; -bool -DynamicDocsumWriter::Override(const char *fieldName, std::unique_ptr<DocsumFieldWriter> writer) -{ - uint32_t fieldEnumValue = _resultConfig->GetFieldNameEnum().Lookup(fieldName); - - if (fieldEnumValue >= _overrideTable.size() || _overrideTable[fieldEnumValue]) { - if (fieldEnumValue >= _overrideTable.size()) { - LOG(warning, "cannot override docsum field '%s'; undefined field name", fieldName); - } else if (_overrideTable[fieldEnumValue] != nullptr) { - LOG(warning, "cannot override docsum field '%s'; already overridden", fieldName); - } - return false; - } - - writer->setIndex(fieldEnumValue); - auto writer_ptr = writer.get(); - _overrideTable[fieldEnumValue] = std::move(writer); - if (writer_ptr->setFieldWriterStateIndex(_numFieldWriterStates)) { - ++_numFieldWriterStates; - } - - bool generated = writer_ptr->IsGenerated(); - for (auto & result_class : *_resultConfig) { - if (result_class.GetIndexFromEnumValue(fieldEnumValue) >= 0) { - result_class.getDynamicInfo().update_override_counts(generated); - } - } - - return true; -} - - void -DynamicDocsumWriter::InitState(const IAttributeManager & attrMan, GetDocsumsState *state) +DynamicDocsumWriter::InitState(const IAttributeManager & attrMan, GetDocsumsState& state, const ResolveClassInfo& rci) { - state->_kwExtractor = _keywordExtractor.get(); - state->_attrCtx = attrMan.createContext(); - state->_attributes.resize(_overrideTable.size()); - state->_fieldWriterStates.resize(_numFieldWriterStates); - for (size_t i(0); i < state->_attributes.size(); i++) { - const DocsumFieldWriter *fw = _overrideTable[i].get(); + state._kwExtractor = _keywordExtractor.get(); + state._attrCtx = attrMan.createContext(); + auto result_class = rci.outputClass; + if (result_class == nullptr) { + return; + } + size_t num_entries = result_class->GetNumEntries(); + state._attributes.resize(num_entries); + state._fieldWriterStates.resize(result_class->get_num_field_writer_states()); + for (size_t i(0); i < num_entries; i++) { + const DocsumFieldWriter *fw = result_class->GetEntry(i)->_docsum_field_writer.get(); if (fw) { const vespalib::string & attributeName = fw->getAttributeName(); if (!attributeName.empty()) { - state->_attributes[i] = state->_attrCtx->getAttribute(attributeName); + state._attributes[i] = state._attrCtx->getAttribute(attributeName); } } } diff --git a/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.h b/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.h index 9ae44623475..c0579638593 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.h +++ b/searchsummary/src/vespa/searchsummary/docsummary/docsumwriter.h @@ -36,7 +36,7 @@ public: }; virtual ~IDocsumWriter() = default; - virtual void InitState(const search::IAttributeManager & attrMan, GetDocsumsState *state) = 0; + virtual void InitState(const search::IAttributeManager & attrMan, GetDocsumsState& state, const ResolveClassInfo& rci) = 0; virtual void insertDocsum(const ResolveClassInfo & rci, uint32_t docid, GetDocsumsState *state, IDocsumStore *docinfos, Inserter & target) = 0; virtual ResolveClassInfo resolveClassInfo(vespalib::stringref outputClassName) const = 0; @@ -49,8 +49,6 @@ class DynamicDocsumWriter : public IDocsumWriter private: std::unique_ptr<ResultConfig> _resultConfig; std::unique_ptr<KeywordExtractor> _keywordExtractor; - uint32_t _numFieldWriterStates; - std::vector<std::unique_ptr<const DocsumFieldWriter>> _overrideTable; ResolveClassInfo resolveOutputClass(vespalib::stringref outputClassName) const; @@ -62,8 +60,7 @@ public: const ResultConfig *GetResultConfig() { return _resultConfig.get(); } - bool Override(const char *fieldName, std::unique_ptr<DocsumFieldWriter> writer); - void InitState(const search::IAttributeManager & attrMan, GetDocsumsState *state) override; + void InitState(const search::IAttributeManager & attrMan, GetDocsumsState& state, const ResolveClassInfo& rci) override; void insertDocsum(const ResolveClassInfo & outputClassInfo, uint32_t docid, GetDocsumsState *state, IDocsumStore *docinfos, Inserter & inserter) override; diff --git a/searchsummary/src/vespa/searchsummary/docsummary/matched_elements_filter_dfw.cpp b/searchsummary/src/vespa/searchsummary/docsummary/matched_elements_filter_dfw.cpp index e83860ed8bf..6f53c0b1c84 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/matched_elements_filter_dfw.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/matched_elements_filter_dfw.cpp @@ -76,6 +76,9 @@ filter_matching_elements_in_input_field_while_converting_to_slime(const FieldVal assert(converted->isLiteral()); auto& literal = static_cast<const LiteralFieldValueB&>(*converted); vespalib::stringref buf = literal.getValueRef(); + if (buf.empty()) { + return; + } Slime input_field_as_slime; BinaryFormat::decode(vespalib::Memory(buf.data(), buf.size()), input_field_as_slime); inject(input_field_as_slime.get(), target); diff --git a/searchsummary/src/vespa/searchsummary/docsummary/res_config_entry.cpp b/searchsummary/src/vespa/searchsummary/docsummary/res_config_entry.cpp index 668fb9b519b..b00b5d975a2 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/res_config_entry.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/res_config_entry.cpp @@ -1,16 +1,20 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "res_config_entry.h" +#include "docsum_field_writer.h" namespace search::docsummary { ResConfigEntry::ResConfigEntry() noexcept : _type(RES_BAD), _bindname(), - _enumValue(0) + _enumValue(0), + _docsum_field_writer() { } ResConfigEntry::~ResConfigEntry() = default; +ResConfigEntry::ResConfigEntry(ResConfigEntry&&) noexcept = default; + } diff --git a/searchsummary/src/vespa/searchsummary/docsummary/res_config_entry.h b/searchsummary/src/vespa/searchsummary/docsummary/res_config_entry.h index 771125b1f45..6277e955c3d 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/res_config_entry.h +++ b/searchsummary/src/vespa/searchsummary/docsummary/res_config_entry.h @@ -4,9 +4,12 @@ #include "res_type.h" #include <vespa/vespalib/stllike/string.h> +#include <memory> namespace search::docsummary { +class DocsumFieldWriter; + /** * This struct describes a single docsum field (name and type). **/ @@ -14,8 +17,10 @@ struct ResConfigEntry { ResType _type; vespalib::string _bindname; int _enumValue; + std::unique_ptr<DocsumFieldWriter> _docsum_field_writer; ResConfigEntry() noexcept; ~ResConfigEntry(); + ResConfigEntry(ResConfigEntry&&) noexcept; }; } diff --git a/searchsummary/src/vespa/searchsummary/docsummary/resultclass.cpp b/searchsummary/src/vespa/searchsummary/docsummary/resultclass.cpp index 9930c39cb7b..78a9804ccd4 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/resultclass.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/resultclass.cpp @@ -1,6 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "resultclass.h" +#include "docsum_field_writer.h" #include "resultconfig.h" #include <vespa/vespalib/stllike/hashtable.hpp> #include <cassert> @@ -14,7 +15,8 @@ ResultClass::ResultClass(const char *name, util::StringEnum & fieldEnum) _fieldEnum(fieldEnum), _enumMap(), _dynInfo(), - _omit_summary_features(false) + _omit_summary_features(false), + _num_field_writer_states(0) { } @@ -28,7 +30,7 @@ ResultClass::GetIndexFromName(const char* name) const } bool -ResultClass::AddConfigEntry(const char *name, ResType type) +ResultClass::AddConfigEntry(const char *name, ResType type, std::unique_ptr<DocsumFieldWriter> docsum_field_writer) { if (_nameMap.find(name) != _nameMap.end()) return false; @@ -39,10 +41,25 @@ ResultClass::AddConfigEntry(const char *name, ResType type) e._bindname = name; e._enumValue = _fieldEnum.Add(name); assert(e._enumValue >= 0); - _entries.push_back(e); + if (docsum_field_writer) { + docsum_field_writer->setIndex(_entries.size()); + bool generated = docsum_field_writer->IsGenerated(); + getDynamicInfo().update_override_counts(generated); + if (docsum_field_writer->setFieldWriterStateIndex(_num_field_writer_states)) { + ++_num_field_writer_states; + } + } + e._docsum_field_writer = std::move(docsum_field_writer); + _entries.push_back(std::move(e)); return true; } +bool +ResultClass::AddConfigEntry(const char *name, ResType type) +{ + return AddConfigEntry(name, type, {}); +} + void ResultClass::CreateEnumMap() { diff --git a/searchsummary/src/vespa/searchsummary/docsummary/resultclass.h b/searchsummary/src/vespa/searchsummary/docsummary/resultclass.h index 39e94e5050e..e11032d1aac 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/resultclass.h +++ b/searchsummary/src/vespa/searchsummary/docsummary/resultclass.h @@ -50,6 +50,7 @@ private: // Whether or not summary features should be omitted when filling this summary class. // As default, summary features are always included. bool _omit_summary_features; + size_t _num_field_writer_states; public: typedef std::unique_ptr<ResultClass> UP; @@ -95,10 +96,13 @@ public: * @return true(success)/false(fail) * @param name the name of the field to add. * @param type the type of the field to add. + * @param docsum_field_writer field writer for writing field **/ + bool AddConfigEntry(const char *name, ResType type, std::unique_ptr<DocsumFieldWriter> docsum_field_writer); bool AddConfigEntry(const char *name, ResType type); + /** * This method may be called to create an internal mapping from * field name enumerated value to field index. When building up a @@ -169,6 +173,8 @@ public: bool omit_summary_features() const { return _omit_summary_features; } + + size_t get_num_field_writer_states() const noexcept { return _num_field_writer_states; } }; } diff --git a/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.cpp b/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.cpp index f5e4c5d34cf..63ccf80d4e7 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.cpp +++ b/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.cpp @@ -1,6 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "resultconfig.h" +#include "docsum_field_writer.h" +#include "docsum_field_writer_factory.h" #include "resultclass.h" #include <vespa/vespalib/util/exceptions.h> #include <vespa/vespalib/stllike/hash_map.hpp> @@ -99,7 +101,7 @@ bool ResultConfig::wantedV8geoPositions() { } bool -ResultConfig::ReadConfig(const vespa::config::search::SummaryConfig &cfg, const char *configId) +ResultConfig::ReadConfig(const vespa::config::search::SummaryConfig &cfg, const char *configId, IDocsumFieldWriterFactory& docsum_field_writer_factory) { bool rc = true; Reset(); @@ -129,10 +131,20 @@ ResultConfig::ReadConfig(const vespa::config::search::SummaryConfig &cfg, const for (unsigned int j = 0; rc && (j < cfg_class.fields.size()); j++) { const char *fieldtype = cfg_class.fields[j].type.c_str(); const char *fieldname = cfg_class.fields[j].name.c_str(); + vespalib::string override_name = cfg_class.fields[j].command; + vespalib::string source_name = cfg_class.fields[j].source; auto res_type = ResTypeUtils::get_res_type(fieldtype); LOG(debug, "Reconfiguring class '%s' field '%s' of type '%s'", cfg_class.name.c_str(), fieldname, fieldtype); if (res_type != RES_BAD) { - rc = resClass->AddConfigEntry(fieldname, res_type); + std::unique_ptr<DocsumFieldWriter> docsum_field_writer; + if (!override_name.empty()) { + docsum_field_writer = docsum_field_writer_factory.create_docsum_field_writer(fieldname, override_name, source_name, rc); + if (!rc) { + LOG(error, "%s override operation failed during initialization", override_name.c_str()); + break; + } + } + rc = resClass->AddConfigEntry(fieldname, res_type, std::move(docsum_field_writer)); } else { LOG(error, "%s %s.fields[%d]: unknown type '%s'", configId, cfg_class.name.c_str(), j, fieldtype); rc = false; diff --git a/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.h b/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.h index 220c988b634..9aaf6fa65b3 100644 --- a/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.h +++ b/searchsummary/src/vespa/searchsummary/docsummary/resultconfig.h @@ -8,6 +8,7 @@ namespace search::docsummary { +class IDocsumFieldWriterFactory; class ResultClass; /** @@ -176,7 +177,7 @@ public: * @return true(success)/false(fail) * @param configId reference on server **/ - bool ReadConfig(const vespa::config::search::SummaryConfig &cfg, const char *configId); + bool ReadConfig(const vespa::config::search::SummaryConfig &cfg, const char *configId, IDocsumFieldWriterFactory& docsum_field_writer_factory); }; } diff --git a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp index 9c39d929e4c..0bf41f9a379 100644 --- a/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp +++ b/streamingvisitors/src/vespa/searchvisitor/searchvisitor.cpp @@ -161,7 +161,7 @@ SearchVisitor::SummaryGenerator::get_streaming_docsums_state(const vespalib::str if (_stack_dump.has_value()) { ds._args.SetStackDump(_stack_dump.value().size(), _stack_dump.value().data()); } - _docsumWriter->InitState(_attr_manager, &ds); + _docsumWriter->InitState(_attr_manager, ds, state->get_resolve_class_info()); auto insres = _docsum_states.insert(std::make_pair(summary_class, std::move(state))); return *insres.first->second; } diff --git a/streamingvisitors/src/vespa/vsm/vsm/CMakeLists.txt b/streamingvisitors/src/vespa/vsm/vsm/CMakeLists.txt index 6afb61078c7..1e766baf0ed 100644 --- a/streamingvisitors/src/vespa/vsm/vsm/CMakeLists.txt +++ b/streamingvisitors/src/vespa/vsm/vsm/CMakeLists.txt @@ -9,7 +9,6 @@ vespa_add_library(vsm_vsmbase OBJECT slimefieldwriter.cpp snippetmodifier.cpp vsm-adapter.cpp - docsumconfig.cpp DEPENDS vsm_vconfig ) diff --git a/streamingvisitors/src/vespa/vsm/vsm/docsumconfig.cpp b/streamingvisitors/src/vespa/vsm/vsm/docsumconfig.cpp deleted file mode 100644 index 59e56e657be..00000000000 --- a/streamingvisitors/src/vespa/vsm/vsm/docsumconfig.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "docsumconfig.h" -#include <vespa/searchsummary/docsummary/resultconfig.h> -#include <vespa/vsm/config/config-vsmfields.h> -#include "docsum_field_writer_factory.h" - -using vespa::config::search::vsm::VsmfieldsConfig; - -namespace vsm { - -DynamicDocsumConfig::DynamicDocsumConfig(const search::docsummary::IDocsumEnvironment& env, search::docsummary::DynamicDocsumWriter* writer, std::shared_ptr<VsmfieldsConfig> vsm_fields_config) - : Parent(env, writer), - _vsm_fields_config(std::move(vsm_fields_config)) -{ -} - -std::unique_ptr<search::docsummary::IDocsumFieldWriterFactory> -DynamicDocsumConfig::make_docsum_field_writer_factory() -{ - return std::make_unique<DocsumFieldWriterFactory>(getResultConfig().useV8geoPositions(), getEnvironment(), *_vsm_fields_config); -} - -} diff --git a/streamingvisitors/src/vespa/vsm/vsm/docsumconfig.h b/streamingvisitors/src/vespa/vsm/vsm/docsumconfig.h deleted file mode 100644 index 760d493dbc1..00000000000 --- a/streamingvisitors/src/vespa/vsm/vsm/docsumconfig.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include <vespa/searchsummary/docsummary/docsumconfig.h> - -namespace vespa::config::search::vsm { -namespace internal { class InternalVsmfieldsType; } -typedef const internal::InternalVsmfieldsType VsmfieldsConfig; -} -namespace vsm { - -class DynamicDocsumConfig : public search::docsummary::DynamicDocsumConfig -{ -public: - using Parent = search::docsummary::DynamicDocsumConfig; - using VsmfieldsConfig = vespa::config::search::vsm::VsmfieldsConfig; -private: - std::shared_ptr<VsmfieldsConfig> _vsm_fields_config; -public: - DynamicDocsumConfig(const search::docsummary::IDocsumEnvironment& env, search::docsummary::DynamicDocsumWriter* writer, std::shared_ptr<VsmfieldsConfig> vsm_fields_config); -private: - std::unique_ptr<search::docsummary::IDocsumFieldWriterFactory> make_docsum_field_writer_factory() override; -}; - -} - diff --git a/streamingvisitors/src/vespa/vsm/vsm/vsm-adapter.cpp b/streamingvisitors/src/vespa/vsm/vsm/vsm-adapter.cpp index 2bf6b2f3972..e220cf685e2 100644 --- a/streamingvisitors/src/vespa/vsm/vsm/vsm-adapter.cpp +++ b/streamingvisitors/src/vespa/vsm/vsm/vsm-adapter.cpp @@ -1,7 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "vsm-adapter.hpp" -#include "docsumconfig.h" +#include "docsum_field_writer_factory.h" #include "i_matching_elements_filler.h" #include <vespa/searchlib/common/matching_elements.h> #include <vespa/searchsummary/docsummary/keywordextractor.h> @@ -144,16 +144,18 @@ VSMAdapter::configure(const VSMConfigSnapshot & snapshot) // create new docsum tools auto docsumTools = std::make_unique<DocsumTools>(); - // configure juniper (used when configuring DynamicDocsumConfig) + // configure juniper (used by search::docsummary::DocsumFieldWriterFactory) _juniperProps = std::make_unique<JuniperProperties>(*juniperrc); auto juniper = std::make_unique<juniper::Juniper>(_juniperProps.get(), &_wordFolder); docsumTools->setJuniper(std::move(juniper)); // init result config auto resCfg = std::make_unique<ResultConfig>(); - if ( ! resCfg->ReadConfig(*summary.get(), _configId.c_str())) { + auto docsum_field_writer_factory = std::make_unique<DocsumFieldWriterFactory>(summary.get()->usev8geopositions, *docsumTools, *_fieldsCfg.get()); + if ( ! resCfg->ReadConfig(*summary.get(), _configId.c_str(), *docsum_field_writer_factory)) { throw std::runtime_error("(re-)configuration of VSM (docsum tools) failed due to bad summary config"); } + docsum_field_writer_factory.reset(); // init keyword extractor auto kwExtractor = std::make_unique<KeywordExtractor>(nullptr); @@ -165,10 +167,6 @@ VSMAdapter::configure(const VSMConfigSnapshot & snapshot) auto writer = std::make_unique<DynamicDocsumWriter>(std::move(resCfg), std::move(kwExtractor)); docsumTools->set_writer(std::move(writer)); - // configure dynamic docsum writer - DynamicDocsumConfig dynDocsumConfig(*docsumTools, docsumTools->getDocsumWriter(), _fieldsCfg.get()); - dynDocsumConfig.configure(*summaryMap.get()); - // configure new docsum tools if (docsumTools->obtainFieldNames(vsmSummary)) { // latch new docsum tools into production |