diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2022-10-14 12:28:19 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2022-10-14 12:28:19 +0000 |
commit | 1d1b1f3754fd876c4ea4684fcb4887d4fbd77724 (patch) | |
tree | 85441528c2d84068c97fe1218a341ee997025da7 /searchlib | |
parent | 760768ad9a5f376275b06ed38a516e80cba1aa65 (diff) |
Handle that [docid] can use an optional attribute.
Diffstat (limited to 'searchlib')
-rw-r--r-- | searchlib/src/tests/sortspec/multilevelsort.cpp | 176 | ||||
-rw-r--r-- | searchlib/src/vespa/searchlib/common/sortresults.cpp | 44 | ||||
-rw-r--r-- | searchlib/src/vespa/searchlib/common/sortresults.h | 15 | ||||
-rw-r--r-- | searchlib/src/vespa/searchlib/common/sortspec.cpp | 10 | ||||
-rw-r--r-- | searchlib/src/vespa/searchlib/common/sortspec.h | 2 |
5 files changed, 142 insertions, 105 deletions
diff --git a/searchlib/src/tests/sortspec/multilevelsort.cpp b/searchlib/src/tests/sortspec/multilevelsort.cpp index 82bdf99ab2c..87dc6608c3f 100644 --- a/searchlib/src/tests/sortspec/multilevelsort.cpp +++ b/searchlib/src/tests/sortspec/multilevelsort.cpp @@ -16,11 +16,6 @@ LOG_SETUP("multilevelsort_test"); using namespace search; -typedef FastS_SortSpec::VectorRef VectorRef; -typedef IntegerAttributeTemplate<int8_t> Int8; -typedef IntegerAttributeTemplate<int16_t> Int16; -typedef IntegerAttributeTemplate<int32_t> Int32; -typedef IntegerAttributeTemplate<int64_t> Int64; typedef FloatingPointAttributeTemplate<float> Float; typedef FloatingPointAttributeTemplate<double> Double; typedef std::map<std::string, AttributeVector::SP > VectorMap; @@ -53,16 +48,16 @@ public: }; private: template<typename T> - T getRandomValue() { + static T getRandomValue() { T min = std::numeric_limits<T>::min(); T max = std::numeric_limits<T>::max(); return static_cast<T>(double(min) + (double(max) - double(min)) * (double(rand()) / double(RAND_MAX))); } template<typename T> - void fill(IntegerAttribute *attr, uint32_t size, uint32_t unique = 0); + static void fill(IntegerAttribute *attr, uint32_t size, uint32_t unique = 0); template<typename T> - void fill(FloatingPointAttribute *attr, uint32_t size, uint32_t unique = 0); - void fill(StringAttribute *attr, uint32_t size, const std::vector<std::string> &values); + static void fill(FloatingPointAttribute *attr, uint32_t size, uint32_t unique = 0); + static void fill(StringAttribute *attr, uint32_t size, const std::vector<std::string> &values); template <typename V> int compareTemplate(AttributeVector *vector, uint32_t a, uint32_t b); int compare(AttributeVector *vector, AttrType type, uint32_t a, uint32_t b); @@ -181,7 +176,7 @@ MultilevelSortTest::compare(AttributeVector *vector, AttrType type, uint32_t a, } else if (type == DOUBLE) { return compareTemplate<double>(vector, a, b); } else if (type == STRING) { - StringAttribute *vString = static_cast<StringAttribute*>(vector); + StringAttribute *vString = dynamic_cast<StringAttribute*>(vector); const char *va = vString->get(a); const char *vb = vString->get(b); std::string sa(va); @@ -199,106 +194,99 @@ MultilevelSortTest::compare(AttributeVector *vector, AttrType type, uint32_t a, } void -MultilevelSortTest::sortAndCheck(const std::vector<Spec> &spec, uint32_t num, +MultilevelSortTest::sortAndCheck(const std::vector<Spec> &specs, uint32_t num, uint32_t unique, const std::vector<std::string> &strValues) { VectorMap vec; // generate attribute vectors - for (uint32_t i = 0; i < spec.size(); ++i) { - std::string name = spec[i]._name; - AttrType type = spec[i]._type; + for (const auto & spec : specs) { + std::string name = spec._name; + AttrType type = spec._type; if (type == INT8) { Config cfg(BasicType::INT8, CollectionType::SINGLE); vec[name] = AttributeFactory::createAttribute(name, cfg); - fill<int8_t>(static_cast<IntegerAttribute *>(vec[name].get()), num, unique); + fill<int8_t>(dynamic_cast<IntegerAttribute *>(vec[name].get()), num, unique); } else if (type == INT16) { Config cfg(BasicType::INT16, CollectionType::SINGLE); vec[name] = AttributeFactory::createAttribute(name, cfg); - fill<int16_t>(static_cast<IntegerAttribute *>(vec[name].get()), num, unique); + fill<int16_t>(dynamic_cast<IntegerAttribute *>(vec[name].get()), num, unique); } else if (type == INT32) { Config cfg(BasicType::INT32, CollectionType::SINGLE); vec[name] = AttributeFactory::createAttribute(name, cfg); - fill<int32_t>(static_cast<IntegerAttribute *>(vec[name].get()), num, unique); + fill<int32_t>(dynamic_cast<IntegerAttribute *>(vec[name].get()), num, unique); } else if (type == INT64) { Config cfg(BasicType::INT64, CollectionType::SINGLE); vec[name] = AttributeFactory::createAttribute(name, cfg); - fill<int64_t>(static_cast<IntegerAttribute *>(vec[name].get()), num, unique); + fill<int64_t>(dynamic_cast<IntegerAttribute *>(vec[name].get()), num, unique); } else if (type == FLOAT) { Config cfg(BasicType::FLOAT, CollectionType::SINGLE); vec[name] = AttributeFactory::createAttribute(name, cfg); - fill<float>(static_cast<FloatingPointAttribute *>(vec[name].get()), num, unique); + fill<float>(dynamic_cast<FloatingPointAttribute *>(vec[name].get()), num, unique); } else if (type == DOUBLE) { Config cfg(BasicType::DOUBLE, CollectionType::SINGLE); vec[name] = AttributeFactory::createAttribute(name, cfg); - fill<double>(static_cast<FloatingPointAttribute *>(vec[name].get()), num, unique); + fill<double>(dynamic_cast<FloatingPointAttribute *>(vec[name].get()), num, unique); } else if (type == STRING) { Config cfg(BasicType::STRING, CollectionType::SINGLE); vec[name] = AttributeFactory::createAttribute(name, cfg); - fill(static_cast<StringAttribute *>(vec[name].get()), num, strValues); + fill(dynamic_cast<StringAttribute *>(vec[name].get()), num, strValues); } if (vec[name]) vec[name]->commit(); } - RankedHit *hits = new RankedHit[num]; + std::vector<RankedHit> hits; + hits.reserve(num); for (uint32_t i = 0; i < num; ++i) { - hits[i]._docId = i; - hits[i]._rankValue = getRandomValue<uint32_t>(); + hits.emplace_back(i, getRandomValue<uint32_t>()); } vespalib::TestClock clock; vespalib::Doom doom(clock.clock(), vespalib::steady_time::max()); search::uca::UcaConverterFactory ucaFactory; - FastS_SortSpec sorter(7, doom, ucaFactory); + FastS_SortSpec sorter("no-metastore", 7, doom, ucaFactory); // init sorter with sort data - for(uint32_t i = 0; i < spec.size(); ++i) { + for (const auto & spec : specs) { AttributeGuard ag; - if (spec[i]._type == RANK) { - sorter._vectors.push_back - (VectorRef(spec[i]._asc ? FastS_SortSpec::ASC_RANK : - FastS_SortSpec::DESC_RANK, nullptr, nullptr)); - } else if (spec[i]._type == DOCID) { - sorter._vectors.push_back - (VectorRef(spec[i]._asc ? FastS_SortSpec::ASC_DOCID : - FastS_SortSpec::DESC_DOCID, nullptr, nullptr)); + if (spec._type == RANK) { + sorter._vectors.emplace_back(spec._asc ? FastS_SortSpec::ASC_RANK : FastS_SortSpec::DESC_RANK, nullptr, nullptr); + } else if (spec._type == DOCID) { + sorter._vectors.emplace_back(spec._asc ? FastS_SortSpec::ASC_DOCID : FastS_SortSpec::DESC_DOCID, nullptr, nullptr); } else { - const search::attribute::IAttributeVector * v = vec[spec[i]._name].get(); - sorter._vectors.push_back - (VectorRef(spec[i]._asc ? FastS_SortSpec::ASC_VECTOR : - FastS_SortSpec::DESC_VECTOR, v, nullptr)); + const search::attribute::IAttributeVector * v = vec[spec._name].get(); + sorter._vectors.emplace_back(spec._asc ? FastS_SortSpec::ASC_VECTOR : FastS_SortSpec::DESC_VECTOR, v, nullptr); } } vespalib::Timer timer; - sorter.sortResults(hits, num, num); + sorter.sortResults(&hits[0], num, num); LOG(info, "sort time = %" PRId64 " ms", vespalib::count_ms(timer.elapsed())); - uint32_t *offsets = new uint32_t[num + 1]; - char *buf = new char[sorter.getSortDataSize(0, num)]; - sorter.copySortData(0, num, offsets, buf); + std::vector<uint32_t> offsets(num + 1, 0); + auto buf = std::make_unique<char []>(sorter.getSortDataSize(0, num)); + sorter.copySortData(0, num, &offsets[0], buf.get()); // check results for (uint32_t i = 0; i < num - 1; ++i) { - for (uint32_t j = 0; j < spec.size(); ++j) { + for (const Spec & spec : specs) { int cmp = 0; - if (spec[j]._type == RANK) { + if (spec._type == RANK) { if (hits[i].getRank() < hits[i+1].getRank()) { cmp = -1; } else if (hits[i].getRank() > hits[i+1].getRank()) { cmp = 1; } - } else if (spec[j]._type == DOCID) { + } else if (spec._type == DOCID) { if (hits[i].getDocId() < hits[i+1].getDocId()) { cmp = -1; } else if (hits[i].getDocId() > hits[i+1].getDocId()) { cmp = 1; } } else { - AttributeVector *av = vec[spec[j]._name].get(); - cmp = compare(av, spec[j]._type, - hits[i].getDocId(), hits[i+1].getDocId()); + AttributeVector *av = vec[spec._name].get(); + cmp = compare(av, spec._type, hits[i].getDocId(), hits[i+1].getDocId()); } - if (spec[j]._asc) { + if (spec._asc) { EXPECT_TRUE(cmp <= 0); if (cmp < 0) { break; @@ -311,56 +299,51 @@ MultilevelSortTest::sortAndCheck(const std::vector<Spec> &spec, uint32_t num, } } // check binary sort data - uint32_t minLen = std::min(sorter._sortDataArray[i]._len, - sorter._sortDataArray[i+1]._len); + uint32_t minLen = std::min(sorter._sortDataArray[i]._len, sorter._sortDataArray[i+1]._len); int cmp = memcmp(&sorter._binarySortData[0] + sorter._sortDataArray[i]._idx, &sorter._binarySortData[0] + sorter._sortDataArray[i+1]._idx, minLen); EXPECT_TRUE(cmp <= 0); EXPECT_TRUE(sorter._sortDataArray[i]._len == (offsets[i+1] - offsets[i])); cmp = memcmp(&sorter._binarySortData[0] + sorter._sortDataArray[i]._idx, - buf + offsets[i], sorter._sortDataArray[i]._len); + buf.get() + offsets[i], sorter._sortDataArray[i]._len); EXPECT_TRUE(cmp == 0); } EXPECT_TRUE(sorter._sortDataArray[num-1]._len == (offsets[num] - offsets[num-1])); int cmp = memcmp(&sorter._binarySortData[0] + sorter._sortDataArray[num-1]._idx, - buf + offsets[num-1], sorter._sortDataArray[num-1]._len); + buf.get() + offsets[num-1], sorter._sortDataArray[num-1]._len); EXPECT_TRUE(cmp == 0); - - delete [] hits; - delete [] offsets; - delete [] buf; } void MultilevelSortTest::testSort() { { std::vector<Spec> spec; - spec.push_back(Spec("int8", INT8)); - spec.push_back(Spec("int16", INT16)); - spec.push_back(Spec("int32", INT32)); - spec.push_back(Spec("int64", INT64)); - spec.push_back(Spec("float", FLOAT)); - spec.push_back(Spec("double", DOUBLE)); - spec.push_back(Spec("string", STRING)); - spec.push_back(Spec("rank", RANK)); - spec.push_back(Spec("docid", DOCID)); + spec.emplace_back("int8", INT8); + spec.emplace_back("int16", INT16); + spec.emplace_back("int32", INT32); + spec.emplace_back("int64", INT64); + spec.emplace_back("float", FLOAT); + spec.emplace_back("double", DOUBLE); + spec.emplace_back("string", STRING); + spec.emplace_back("rank", RANK); + spec.emplace_back("docid", DOCID); std::vector<std::string> strValues; - strValues.push_back("applications"); - strValues.push_back("places"); - strValues.push_back("system"); - strValues.push_back("vespa search core"); + strValues.emplace_back("applications"); + strValues.emplace_back("places"); + strValues.emplace_back("system"); + strValues.emplace_back("vespa search core"); srand(12345); sortAndCheck(spec, 5000, 4, strValues); srand(time(nullptr)); sortAndCheck(spec, 5000, 4, strValues); - strValues.push_back("multilevelsort"); - strValues.push_back("trondheim"); - strValues.push_back("ubuntu"); - strValues.push_back("fastserver4"); + strValues.emplace_back("multilevelsort"); + strValues.emplace_back("trondheim"); + strValues.emplace_back("ubuntu"); + strValues.emplace_back("fastserver4"); srand(56789); sortAndCheck(spec, 5000, 8, strValues); @@ -403,7 +386,7 @@ TEST("test that [docid] translates to [lid][paritionid]") { vespalib::TestClock clock; vespalib::Doom doom(clock.clock(), vespalib::steady_time::max()); search::uca::UcaConverterFactory ucaFactory; - FastS_SortSpec asc(7, doom, ucaFactory); + FastS_SortSpec asc("no-metastore", 7, doom, ucaFactory); RankedHit hits[2] = {RankedHit(91, 0.0), RankedHit(3, 2.0)}; search::AttributeManager mgr; search::AttributeContext ac(mgr); @@ -420,7 +403,7 @@ TEST("test that [docid] translates to [lid][paritionid]") { EXPECT_EQUAL(6u, sr2.second); EXPECT_EQUAL(0, memcmp(SECOND_ASC, sr2.first, 6)); - FastS_SortSpec desc(7, doom, ucaFactory); + FastS_SortSpec desc("no-metastore", 7, doom, ucaFactory); desc.Init("-[docid]", ac); desc.initWithoutSorting(hits, 2); sr1 = desc.getSortRef(0); @@ -431,4 +414,45 @@ TEST("test that [docid] translates to [lid][paritionid]") { EXPECT_EQUAL(0, memcmp(SECOND_DESC, sr2.first, 6)); } +TEST("test that [docid] uses attribute when one exists") { + vespalib::TestClock clock; + vespalib::Doom doom(clock.clock(), vespalib::steady_time::max()); + search::uca::UcaConverterFactory ucaFactory; + FastS_SortSpec asc("metastore", 7, doom, ucaFactory); + RankedHit hits[2] = {RankedHit(91, 0.0), RankedHit(3, 2.0)}; + Config cfg(BasicType::INT64, CollectionType::SINGLE); + auto metastore = AttributeFactory::createAttribute("metastore", cfg); + ASSERT_TRUE(metastore->addDocs(100)); + auto * iattr = dynamic_cast<IntegerAttribute *>(metastore.get()); + for (uint32_t lid(0); lid < 100; lid++) { + iattr->update(lid, lid); + } + metastore->commit(); + search::AttributeManager mgr; + mgr.add(metastore); + search::AttributeContext ac(mgr); + EXPECT_TRUE(asc.Init("+[docid]", ac)); + asc.initWithoutSorting(hits, 2); + constexpr uint8_t FIRST_ASC[8] = {0x80,0,0,0,0,0,0,91}; + constexpr uint8_t SECOND_ASC[8] = {0x80,0,0,0,0,0,0,3}; + constexpr uint8_t FIRST_DESC[8] = {0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff - 91}; + constexpr uint8_t SECOND_DESC[8] = {0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff - 3}; + auto sr1 = asc.getSortRef(0); + EXPECT_EQUAL(8u, sr1.second); + EXPECT_EQUAL(0, memcmp(FIRST_ASC, sr1.first, 8)); + auto sr2 = asc.getSortRef(1); + EXPECT_EQUAL(8u, sr2.second); + EXPECT_EQUAL(0, memcmp(SECOND_ASC, sr2.first, 8)); + + FastS_SortSpec desc("metastore", 7, doom, ucaFactory); + desc.Init("-[docid]", ac); + desc.initWithoutSorting(hits, 2); + sr1 = desc.getSortRef(0); + EXPECT_EQUAL(8u, sr1.second); + EXPECT_EQUAL(0, memcmp(FIRST_DESC, sr1.first, 8)); + sr2 = desc.getSortRef(1); + EXPECT_EQUAL(8u, sr2.second); + EXPECT_EQUAL(0, memcmp(SECOND_DESC, sr2.first, 8)); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchlib/src/vespa/searchlib/common/sortresults.cpp b/searchlib/src/vespa/searchlib/common/sortresults.cpp index 911e447715b..4eed49defc5 100644 --- a/searchlib/src/vespa/searchlib/common/sortresults.cpp +++ b/searchlib/src/vespa/searchlib/common/sortresults.cpp @@ -3,9 +3,9 @@ #include "sortresults.h" #include "sort.h" #include <vespa/searchcommon/attribute/iattributecontext.h> -#include <vespa/vespalib/util/array.hpp> - +#include <vespa/vespalib/util/array.h> #include <vespa/vespalib/util/issue.h> + using vespalib::Issue; #include <vespa/log/log.h> @@ -174,6 +174,7 @@ FastS_SortSpec::Add(IAttributeContext & vecMan, const SortInfo & sInfo) type = (sInfo._ascending) ? ASC_RANK : DESC_RANK; } else if ((sInfo._field.size() == 7) && (sInfo._field == "[docid]")) { type = (sInfo._ascending) ? ASC_DOCID : DESC_DOCID; + vector = vecMan.getAttribute(_documentmetastore); } else { type = (sInfo._ascending) ? ASC_VECTOR : DESC_VECTOR; vector = vecMan.getAttribute(sInfo._field); @@ -217,7 +218,9 @@ FastS_SortSpec::initSortData(const RankedHit *hits, uint32_t n) size_t variableWidth = 0; for (const auto & vec : _vectors) { if (vec._type >= ASC_DOCID) { // doc id - fixedWidth += sizeof(uint32_t) + sizeof(uint16_t); + fixedWidth = (vec._vector != nullptr) + ? vec._vector->getFixedWidth() + : sizeof(uint32_t) + sizeof(uint16_t); } else if (vec._type >= ASC_RANK) { // rank value fixedWidth += sizeof(search::HitRank); } else { @@ -239,21 +242,29 @@ FastS_SortSpec::initSortData(const RankedHit *hits, uint32_t n) for (uint32_t i(0), idx(0); (i < n) && !_doom.hard_doom(); ++i) { uint32_t len = 0; for (const auto & vec : _vectors) { - int written(0); + long written(0); if (available < std::max(sizeof(hits->_docId) + sizeof(_partitionId), sizeof(hits->_rankValue))) { mySortData = realloc(n, variableWidth, available, dataSize, mySortData); } do { switch (vec._type) { case ASC_DOCID: - serializeForSort<convertForSort<uint32_t, true> >(hits[i].getDocId(), mySortData); - serializeForSort<convertForSort<uint16_t, true> >(_partitionId, mySortData + sizeof(hits->_docId)); - written = sizeof(hits->_docId) + sizeof(_partitionId); + if (vec._vector != nullptr) { + written = vec._vector->serializeForAscendingSort(hits[i].getDocId(), mySortData, available, vec._converter); + } else { + serializeForSort<convertForSort<uint32_t, true> >(hits[i].getDocId(), mySortData); + serializeForSort<convertForSort<uint16_t, true> >(_partitionId, mySortData + sizeof(hits->_docId)); + written = sizeof(hits->_docId) + sizeof(_partitionId); + } break; case DESC_DOCID: - serializeForSort<convertForSort<uint32_t, false> >(hits[i].getDocId(), mySortData); - serializeForSort<convertForSort<uint16_t, false> >(_partitionId, mySortData + sizeof(hits->_docId)); - written = sizeof(hits->_docId) + sizeof(_partitionId); + if (vec._vector != nullptr) { + written = vec._vector->serializeForDescendingSort(hits[i].getDocId(), mySortData, available, vec._converter); + } else { + serializeForSort<convertForSort<uint32_t, false> >(hits[i].getDocId(), mySortData); + serializeForSort<convertForSort<uint16_t, false> >(_partitionId, mySortData + sizeof(hits->_docId)); + written = sizeof(hits->_docId) + sizeof(_partitionId); + } break; case ASC_RANK: serializeForSort<convertForSort<search::HitRank, true> >(hits[i].getRank(), mySortData); @@ -288,12 +299,13 @@ FastS_SortSpec::initSortData(const RankedHit *hits, uint32_t n) } } -FastS_SortSpec::FastS_SortSpec(uint32_t partitionId, const Doom & doom, const ConverterFactory & ucaFactory) : - _partitionId(partitionId), - _doom(doom), - _ucaFactory(ucaFactory), - _sortSpec(), - _vectors() +FastS_SortSpec::FastS_SortSpec(vespalib::stringref documentmetastore, uint32_t partitionId, const Doom & doom, const ConverterFactory & ucaFactory) + : _documentmetastore(documentmetastore), + _partitionId(partitionId), + _doom(doom), + _ucaFactory(ucaFactory), + _sortSpec(), + _vectors() { } diff --git a/searchlib/src/vespa/searchlib/common/sortresults.h b/searchlib/src/vespa/searchlib/common/sortresults.h index 9ea7d4f14ba..337863601d5 100644 --- a/searchlib/src/vespa/searchlib/common/sortresults.h +++ b/searchlib/src/vespa/searchlib/common/sortresults.h @@ -4,7 +4,7 @@ #include "rankedhit.h" #include "sortspec.h" -#include <vespa/vespalib/util/array.h> +#include <vespa/vespalib/stllike/allocator.h> #include <vespa/vespalib/util/doom.h> #define INSERT_SORT_LEVEL 80 @@ -72,7 +72,7 @@ public: struct VectorRef { - VectorRef(uint32_t type, const search::attribute::IAttributeVector * vector, const search::common::BlobConverter *converter) + VectorRef(uint32_t type, const search::attribute::IAttributeVector * vector, const search::common::BlobConverter *converter) noexcept : _type(type), _vector(vector), _converter(converter) @@ -84,17 +84,18 @@ public: struct SortData : public search::RankedHit { - SortData() : RankedHit(), _idx(0u), _len(0u), _pos(0u) {} + SortData() noexcept : RankedHit(), _idx(0u), _len(0u), _pos(0u) {} uint32_t _idx; uint32_t _len; uint32_t _pos; }; private: - typedef std::vector<VectorRef> VectorRefList; - typedef vespalib::Array<uint8_t> BinarySortData; - typedef vespalib::Array<SortData> SortDataArray; + using VectorRefList = std::vector<VectorRef>; + using BinarySortData = std::vector<uint8_t, vespalib::allocator_large<uint8_t>>; + using SortDataArray = std::vector<SortData, vespalib::allocator_large<SortData>>; using ConverterFactory = search::common::ConverterFactory; + vespalib::string _documentmetastore; uint16_t _partitionId; vespalib::Doom _doom; const ConverterFactory & _ucaFactory; @@ -110,7 +111,7 @@ private: public: FastS_SortSpec(const FastS_SortSpec &) = delete; FastS_SortSpec & operator = (const FastS_SortSpec &) = delete; - FastS_SortSpec(uint32_t partitionId, const vespalib::Doom & doom, const ConverterFactory & ucaFactory); + FastS_SortSpec(vespalib::stringref documentmetastore, uint32_t partitionId, const vespalib::Doom & doom, const ConverterFactory & ucaFactory); ~FastS_SortSpec() override; std::pair<const char *, size_t> getSortRef(size_t i) const { diff --git a/searchlib/src/vespa/searchlib/common/sortspec.cpp b/searchlib/src/vespa/searchlib/common/sortspec.cpp index e12f758e2d2..16f0c884535 100644 --- a/searchlib/src/vespa/searchlib/common/sortspec.cpp +++ b/searchlib/src/vespa/searchlib/common/sortspec.cpp @@ -36,7 +36,7 @@ LowercaseConverter::onConvert(const ConstBufferRef & src) const return {_buffer.begin(), _buffer.size()}; } -SortInfo::SortInfo(const vespalib::string & field, bool ascending, BlobConverter::SP converter) +SortInfo::SortInfo(vespalib::stringref field, bool ascending, BlobConverter::SP converter) noexcept : _field(field), _ascending(ascending), _converter(std::move(converter)) { } SortInfo::~SortInfo() = default; @@ -72,13 +72,13 @@ SortSpec::SortSpec(const vespalib::string & spec, const ConverterFactory & ucaFa for(; (p < e) && (*p != ')'); p++); if (*p == ')') { vespalib::string strength(strengthName, p - strengthName); - push_back(SortInfo(attr, ascending, ucaFactory.create(locale, strength))); + emplace_back(attr, ascending, ucaFactory.create(locale, strength)); } else { throw std::runtime_error(make_string("Missing ')' at %s attr=%s locale=%s strength=%s", p, attr.c_str(), localeName, strengthName)); } } else if (*p == ')') { vespalib::string locale(localeName, p-localeName); - push_back(SortInfo(attr, ascending, ucaFactory.create(locale, ""))); + emplace_back(attr, ascending, ucaFactory.create(locale, "")); } else { throw std::runtime_error(make_string("Missing ')' or ',' at %s attr=%s locale=%s", p, attr.c_str(), localeName)); } @@ -91,7 +91,7 @@ SortSpec::SortSpec(const vespalib::string & spec, const ConverterFactory & ucaFa for(; (p < e) && (*p != ')'); p++); if (*p == ')') { vespalib::string attr(attrName, p-attrName); - push_back(SortInfo(attr, ascending, std::make_shared<LowercaseConverter>())); + emplace_back(attr, ascending, std::make_shared<LowercaseConverter>()); } else { throw std::runtime_error("Missing ')'"); } @@ -99,7 +99,7 @@ SortSpec::SortSpec(const vespalib::string & spec, const ConverterFactory & ucaFa throw std::runtime_error("Unknown func " + vespalib::string(func, p-func)); } } else { - push_back(SortInfo(funcSpec, ascending, {})); + emplace_back(funcSpec, ascending, std::shared_ptr<search::common::BlobConverter>()); } } } diff --git a/searchlib/src/vespa/searchlib/common/sortspec.h b/searchlib/src/vespa/searchlib/common/sortspec.h index 7a5b6fb7f90..682612afd43 100644 --- a/searchlib/src/vespa/searchlib/common/sortspec.h +++ b/searchlib/src/vespa/searchlib/common/sortspec.h @@ -11,7 +11,7 @@ namespace search::common { struct SortInfo { - SortInfo(const vespalib::string & field, bool ascending, BlobConverter::SP converter); + SortInfo(vespalib::stringref field, bool ascending, BlobConverter::SP converter) noexcept; ~SortInfo(); vespalib::string _field; bool _ascending; |