// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "attribute_field_writer.h" #include #include #include #include #include #include using search::attribute::BasicType; using search::attribute::IAttributeVector; using search::attribute::getUndefined; using search::attribute::IArrayReadView; using vespalib::slime::Cursor; namespace search::docsummary { AttributeFieldWriter::AttributeFieldWriter(vespalib::Memory fieldName) : _fieldName(fieldName) { } AttributeFieldWriter::~AttributeFieldWriter() = default; namespace { template class WriteField : public AttributeFieldWriter { protected: const IArrayReadView* _array_read_view; vespalib::ConstArrayRef _content; WriteField(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash &stash); ~WriteField() override; private: uint32_t fetch(uint32_t docId) override; }; class WriteStringField : public WriteField { public: WriteStringField(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash& stash); ~WriteStringField() override; void print(uint32_t idx, Cursor &cursor) override; }; class WriteStringFieldNeverSkip : public WriteField { public: WriteStringFieldNeverSkip(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash& stash) : WriteField(fieldName, attr, stash) {} ~WriteStringFieldNeverSkip() override = default; void print(uint32_t idx, Cursor &cursor) override; }; template class WriteFloatField : public WriteField { public: WriteFloatField(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash& stash); ~WriteFloatField() override; void print(uint32_t idx, Cursor &cursor) override; }; template class WriteIntField : public WriteField { public: WriteIntField(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash& stash); ~WriteIntField() override; void print(uint32_t idx, Cursor &cursor) override; }; template const search::attribute::IArrayReadView* make_array_read_view(const IAttributeVector& attribute, vespalib::Stash& stash) { auto multi_value_attribute = attribute.as_multi_value_attribute(); if (multi_value_attribute != nullptr) { return multi_value_attribute->make_read_view(search::attribute::IMultiValueAttribute::ArrayTag(), stash); } return nullptr; } template WriteField::WriteField(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash& stash) : AttributeFieldWriter(fieldName), _array_read_view(make_array_read_view(attr, stash)), _content() { } template WriteField::~WriteField() = default; template uint32_t WriteField::fetch(uint32_t docId) { if (_array_read_view) { _content = _array_read_view->get_values(docId); } return _content.size(); } WriteStringField::WriteStringField(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash& stash) : WriteField(fieldName, attr, stash) { } WriteStringField::~WriteStringField() = default; void WriteStringField::print(uint32_t idx, Cursor &cursor) { if (idx < _content.size()) { const char *s = _content[idx]; if (s[0] != '\0') { cursor.setString(_fieldName, vespalib::Memory(s)); } } } void WriteStringFieldNeverSkip::print(uint32_t idx, Cursor &cursor) { if (idx < _content.size()) { const char *s = _content[idx]; cursor.setString(_fieldName, vespalib::Memory(s)); } else { cursor.setString(_fieldName, vespalib::Memory("")); } } template WriteFloatField::WriteFloatField(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash& stash) : WriteField(fieldName, attr, stash) { } template WriteFloatField::~WriteFloatField() = default; template void WriteFloatField::print(uint32_t idx, Cursor &cursor) { if (idx < this->_content.size()) { double val = this->_content[idx]; if (!search::attribute::isUndefined(val)) { cursor.setDouble(this->_fieldName, val); } } } template WriteIntField::WriteIntField(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash& stash) : WriteField(fieldName, attr, stash) { } template WriteIntField::~WriteIntField() = default; template void WriteIntField::print(uint32_t idx, Cursor &cursor) { if (idx < this->_content.size()) { auto val = this->_content[idx]; if (val != getUndefined()) { cursor.setLong(this->_fieldName, val); } } } } AttributeFieldWriter& AttributeFieldWriter::create(vespalib::Memory fieldName, const IAttributeVector& attr, vespalib::Stash& stash, bool keep_empty_strings) { switch (attr.getBasicType()) { case BasicType::INT8: return stash.create>(fieldName, attr, stash); case BasicType::INT16: return stash.create>(fieldName, attr, stash); case BasicType::INT32: return stash.create>(fieldName, attr, stash); case BasicType::INT64: return stash.create>(fieldName, attr, stash); case BasicType::FLOAT: return stash.create>(fieldName, attr, stash); case BasicType::DOUBLE: return stash.create>(fieldName, attr, stash); case BasicType::STRING: if (keep_empty_strings) { return stash.create(fieldName, attr, stash); } else { return stash.create(fieldName, attr, stash); } default: assert(false); } } }