summaryrefslogtreecommitdiffstats
path: root/document
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@yahooinc.com>2023-02-22 12:41:47 +0100
committerGitHub <noreply@github.com>2023-02-22 12:41:47 +0100
commit10383524e05d70e4fb975c19d1dd57b855f914a5 (patch)
treea60b817cbc7e3df20605fc934641bc5a4b2a1285 /document
parentda4c1f2994d98e68a8196e271cbaad3c3c09cbb7 (diff)
parentda0b9d14547e6c98b0472f1834f086a0e1efd717 (diff)
Merge pull request #26128 from vespa-engine/vekterli/fix-supertype-match-for-doc-sel-field-lookups
Fix C++ document selection regression where supertype in field expression would not match as expected
Diffstat (limited to 'document')
-rw-r--r--document/src/tests/documentselectparsertest.cpp5
-rw-r--r--document/src/vespa/document/select/valuenodes.cpp20
2 files changed, 18 insertions, 7 deletions
diff --git a/document/src/tests/documentselectparsertest.cpp b/document/src/tests/documentselectparsertest.cpp
index ce4b69419a3..5e14a080f27 100644
--- a/document/src/tests/documentselectparsertest.cpp
+++ b/document/src/tests/documentselectparsertest.cpp
@@ -673,8 +673,9 @@ TEST_F(DocumentSelectParserTest, operators_1)
// Inherited doctypes
PARSE("testdoctype2", *_doc[4], True);
PARSE("testdoctype2", *_doc[3], False);
- PARSE("testdoctype1", *_doc[4], False); // testdoctype2 inherits testdoctype1, but we use exact matching for types
- PARSE("testdoctype1.headerval = 10", *_doc[4], Invalid);
+ PARSE("testdoctype1", *_doc[4], False); // testdoctype2 inherits testdoctype1, but we use exact matching for "standalone" doctype matches.
+ PARSE("testdoctype1.headerval = 10", *_doc[4], True); // But _field lookups_ use is-a type matching semantics.
+ PARSE("testdoctype2.headerval = 10", *_doc[4], True); // Exact type match with parent field also works transparently
}
TEST_F(DocumentSelectParserTest, operators_2)
diff --git a/document/src/vespa/document/select/valuenodes.cpp b/document/src/vespa/document/select/valuenodes.cpp
index 8102a944ff0..b3052cc07e2 100644
--- a/document/src/vespa/document/select/valuenodes.cpp
+++ b/document/src/vespa/document/select/valuenodes.cpp
@@ -20,10 +20,20 @@ LOG_SETUP(".document.select.valuenode");
namespace document::select {
namespace {
- bool documentTypeEqualsName(const DocumentType& type, vespalib::stringref name)
- {
- return (type.getName() == name);
+
+[[nodiscard]] bool document_type_is_a(const DocumentType& type, vespalib::stringref name) {
+ if (type.getName() == name) {
+ return true;
+ }
+ // No exact match; try to recursively match name against any types inherited from.
+ for (const auto* parent : type.getInheritedTypes()) {
+ if (document_type_is_a(*parent, name)) {
+ return true;
+ }
}
+ return false;
+}
+
}
InvalidValueNode::InvalidValueNode(vespalib::stringref name)
@@ -409,7 +419,7 @@ FieldValueNode::getValue(const Context& context) const
const Document& doc = *context._doc;
- if (!documentTypeEqualsName(doc.getType(), _doctype)) {
+ if (!document_type_is_a(doc.getType(), _doctype)) {
return std::make_unique<InvalidValue>();
}
// Imported fields can only be meaningfully evaluated inside Proton, so we
@@ -473,7 +483,7 @@ FieldValueNode::traceValue(const Context &context, std::ostream& out) const
return defaultTrace(getValue(context), out);
}
const Document &doc(*context._doc);
- if (!documentTypeEqualsName(doc.getType(), _doctype)) {
+ if (!document_type_is_a(doc.getType(), _doctype)) {
out << "Document is of type " << doc.getType() << " which isn't a "
<< _doctype << " document, thus resolving invalid.\n";
return std::make_unique<InvalidValue>();