diff --git a/tree/ntuple/inc/ROOT/RFieldBase.hxx b/tree/ntuple/inc/ROOT/RFieldBase.hxx index a492c5f102cb8..bc444b6033ae4 100644 --- a/tree/ntuple/inc/ROOT/RFieldBase.hxx +++ b/tree/ntuple/inc/ROOT/RFieldBase.hxx @@ -532,10 +532,11 @@ protected: std::uint32_t CompareOnDiskField(const RFieldDescriptor &fieldDesc, std::uint32_t ignoreBits) const; /// Compares the field to the provieded on-disk field descriptor. Throws an exception if the fields don't match. /// Optionally, a set of bits can be provided that should be ignored in the comparison. - void EnsureMatchingOnDiskField(const RFieldDescriptor &fieldDesc, std::uint32_t ignoreBits = 0) const; + RResult EnsureMatchingOnDiskField(const RFieldDescriptor &fieldDesc, std::uint32_t ignoreBits = 0) const; /// Many fields accept a range of type prefixes for schema evolution, /// e.g. std::unique_ptr< and std::optional< for nullable fields - void EnsureMatchingTypePrefix(const RFieldDescriptor &fieldDesc, const std::vector &prefixes) const; + RResult + EnsureMatchingTypePrefix(const RFieldDescriptor &fieldDesc, const std::vector &prefixes) const; /// Factory method to resurrect a field from the stored on-disk type information. This overload takes an already /// normalized type name and type alias. diff --git a/tree/ntuple/src/RField.cxx b/tree/ntuple/src/RField.cxx index e7e32ca2856bb..49ced471b153a 100644 --- a/tree/ntuple/src/RField.cxx +++ b/tree/ntuple/src/RField.cxx @@ -78,7 +78,7 @@ void ROOT::RCardinalityField::GenerateColumns(const ROOT::RNTupleDescriptor &des void ROOT::RCardinalityField::ReconcileOnDiskField(const RNTupleDescriptor &desc) { const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId()); - EnsureMatchingOnDiskField(fieldDesc, kDiffTypeVersion | kDiffStructure | kDiffTypeName); + EnsureMatchingOnDiskField(fieldDesc, kDiffTypeVersion | kDiffStructure | kDiffTypeName).ThrowOnError(); if (fieldDesc.GetStructure() == ENTupleStructure::kPlain) { if (fieldDesc.GetTypeName().rfind("ROOT::RNTupleCardinality<", 0) != 0) { throw RException(R__FAIL("RCardinalityField " + GetQualifiedFieldName() + @@ -664,7 +664,7 @@ void ROOT::RRecordField::ReconcileOnDiskField(const RNTupleDescriptor &desc) R__ASSERT(GetTypeName().empty()); const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId()); - EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName | kDiffTypeVersion); + EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName | kDiffTypeVersion).ThrowOnError(); // The on-disk ID of subfields is matched by field name. So we inherently support reordering of fields // and we will ignore extra on-disk fields. @@ -879,8 +879,8 @@ void ROOT::RNullableField::ReconcileOnDiskField(const RNTupleDescriptor &desc) static const std::vector prefixes = {"std::optional<", "std::unique_ptr<"}; const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId()); - EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName); - EnsureMatchingTypePrefix(fieldDesc, prefixes); + EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName).ThrowOnError(); + EnsureMatchingTypePrefix(fieldDesc, prefixes).ThrowOnError(); } ROOT::RNTupleLocalIndex ROOT::RNullableField::GetItemIndex(ROOT::NTupleSize_t globalIndex) @@ -1099,8 +1099,8 @@ void ROOT::RAtomicField::ReconcileOnDiskField(const RNTupleDescriptor &desc) static const std::vector prefixes = {"std::atomic<"}; const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId()); - EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName); - EnsureMatchingTypePrefix(fieldDesc, prefixes); + EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName).ThrowOnError(); + EnsureMatchingTypePrefix(fieldDesc, prefixes).ThrowOnError(); } std::vector ROOT::RAtomicField::SplitValue(const RValue &value) const diff --git a/tree/ntuple/src/RFieldBase.cxx b/tree/ntuple/src/RFieldBase.cxx index 50d69fe9e9c93..c4dbdbccb3474 100644 --- a/tree/ntuple/src/RFieldBase.cxx +++ b/tree/ntuple/src/RFieldBase.cxx @@ -1018,14 +1018,15 @@ void ROOT::RFieldBase::ReconcileOnDiskField(const RNTupleDescriptor &desc) // The default implementation throws an exception if the on-disk ID is set and there are any meaningful differences // to the on-disk field. Derived classes may overwrite this and relax the checks to support automatic schema // evolution. - EnsureMatchingOnDiskField(desc.GetFieldDescriptor(fOnDiskId)); + EnsureMatchingOnDiskField(desc.GetFieldDescriptor(fOnDiskId)).ThrowOnError(); } -void ROOT::RFieldBase::EnsureMatchingOnDiskField(const RFieldDescriptor &fieldDesc, std::uint32_t ignoreBits) const +ROOT::RResult +ROOT::RFieldBase::EnsureMatchingOnDiskField(const RFieldDescriptor &fieldDesc, std::uint32_t ignoreBits) const { const std::uint32_t diffBits = CompareOnDiskField(fieldDesc, ignoreBits); if (diffBits == 0) - return; + return RResult::Success(); std::ostringstream errMsg; errMsg << "in-memory field " << GetQualifiedFieldName() << " of type " << GetTypeName() << " is incompatible " @@ -1045,17 +1046,17 @@ void ROOT::RFieldBase::EnsureMatchingOnDiskField(const RFieldDescriptor &fieldDe if (diffBits & kDiffNRepetitions) { errMsg << " repetition count " << GetNRepetitions() << " vs. " << fieldDesc.GetNRepetitions() << ";"; } - throw RException(R__FAIL(errMsg.str())); + return R__FAIL(errMsg.str()); } -void ROOT::RFieldBase::EnsureMatchingTypePrefix(const RFieldDescriptor &fieldDesc, - const std::vector &prefixes) const +ROOT::RResult ROOT::RFieldBase::EnsureMatchingTypePrefix(const RFieldDescriptor &fieldDesc, + const std::vector &prefixes) const { for (const auto &p : prefixes) { if (fieldDesc.GetTypeName().rfind(p, 0) == 0) - return; + return RResult::Success(); } - throw RException(R__FAIL("incompatible type " + fieldDesc.GetTypeName() + " for field " + GetQualifiedFieldName())); + return R__FAIL("incompatible type " + fieldDesc.GetTypeName() + " for field " + GetQualifiedFieldName()); } std::uint32_t ROOT::RFieldBase::CompareOnDiskField(const RFieldDescriptor &fieldDesc, std::uint32_t ignoreBits) const diff --git a/tree/ntuple/src/RFieldMeta.cxx b/tree/ntuple/src/RFieldMeta.cxx index 6b03feff5e8bc..72b5c5f3a636c 100644 --- a/tree/ntuple/src/RFieldMeta.cxx +++ b/tree/ntuple/src/RFieldMeta.cxx @@ -513,7 +513,7 @@ std::unique_ptr ROOT::RClassField::BeforeConnectPageSource(ROO void ROOT::RClassField::ReconcileOnDiskField(const RNTupleDescriptor &desc) { - EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeVersion | kDiffTypeName); + EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeVersion | kDiffTypeName).ThrowOnError(); } void ROOT::RClassField::ConstructValue(void *where) const @@ -611,7 +611,7 @@ std::unique_ptr ROOT::REnumField::CloneImpl(std::string_view n void ROOT::REnumField::ReconcileOnDiskField(const RNTupleDescriptor &desc) { // TODO(jblomer): allow enum to enum conversion only by rename rule - EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName | kDiffTypeVersion); + EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName | kDiffTypeVersion).ThrowOnError(); } std::vector ROOT::REnumField::SplitValue(const RValue &value) const @@ -677,8 +677,8 @@ void ROOT::RPairField::ReconcileOnDiskField(const RNTupleDescriptor &desc) static const std::vector prefixes = {"std::pair<", "std::tuple<"}; const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId()); - EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName); - EnsureMatchingTypePrefix(fieldDesc, prefixes); + EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName).ThrowOnError(); + EnsureMatchingTypePrefix(fieldDesc, prefixes).ThrowOnError(); const auto nOnDiskSubfields = fieldDesc.GetLinkIds().size(); if (nOnDiskSubfields != 2) { @@ -822,7 +822,7 @@ void ROOT::RProxiedCollectionField::GenerateColumns(const ROOT::RNTupleDescripto void ROOT::RProxiedCollectionField::ReconcileOnDiskField(const RNTupleDescriptor &desc) { - EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName); + EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName).ThrowOnError(); } void ROOT::RProxiedCollectionField::ConstructValue(void *where) const @@ -989,7 +989,7 @@ std::unique_ptr ROOT::RStreamerField::BeforeConnectPageSource( void ROOT::RStreamerField::ReconcileOnDiskField(const RNTupleDescriptor &desc) { - EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName | kDiffTypeVersion); + EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName | kDiffTypeVersion).ThrowOnError(); } void ROOT::RStreamerField::ConstructValue(void *where) const @@ -1224,8 +1224,8 @@ void ROOT::RTupleField::ReconcileOnDiskField(const RNTupleDescriptor &desc) static const std::vector prefixes = {"std::pair<", "std::tuple<"}; const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId()); - EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName); - EnsureMatchingTypePrefix(fieldDesc, prefixes); + EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName).ThrowOnError(); + EnsureMatchingTypePrefix(fieldDesc, prefixes).ThrowOnError(); const auto nOnDiskSubfields = fieldDesc.GetLinkIds().size(); const auto nSubfields = fSubfields.size(); @@ -1386,8 +1386,8 @@ void ROOT::RVariantField::ReconcileOnDiskField(const RNTupleDescriptor &desc) static const std::vector prefixes = {"std::variant<"}; const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId()); - EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName); - EnsureMatchingTypePrefix(fieldDesc, prefixes); + EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName).ThrowOnError(); + EnsureMatchingTypePrefix(fieldDesc, prefixes).ThrowOnError(); if (fSubfields.size() != fieldDesc.GetLinkIds().size()) { throw RException(R__FAIL("number of variants on-disk do not match for " + GetQualifiedFieldName())); diff --git a/tree/ntuple/src/RFieldSequenceContainer.cxx b/tree/ntuple/src/RFieldSequenceContainer.cxx index b6db8dd1dcd34..49150d46b3094 100644 --- a/tree/ntuple/src/RFieldSequenceContainer.cxx +++ b/tree/ntuple/src/RFieldSequenceContainer.cxx @@ -80,8 +80,8 @@ void ROOT::RArrayField::ReconcileOnDiskField(const RNTupleDescriptor &desc) static const std::vector prefixes = {"std::array<"}; const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId()); - EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName); - EnsureMatchingTypePrefix(fieldDesc, prefixes); + EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName).ThrowOnError(); + EnsureMatchingTypePrefix(fieldDesc, prefixes).ThrowOnError(); } void ROOT::RArrayField::ConstructValue(void *where) const @@ -442,7 +442,7 @@ std::unique_ptr ROOT::RRVecField::BeforeConnectPageSource(Inte void ROOT::RRVecField::ReconcileOnDiskField(const RNTupleDescriptor &desc) { - EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName); + EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName).ThrowOnError(); } void ROOT::RRVecField::ConstructValue(void *where) const @@ -624,7 +624,7 @@ void ROOT::RVectorField::GenerateColumns(const ROOT::RNTupleDescriptor &desc) void ROOT::RVectorField::ReconcileOnDiskField(const RNTupleDescriptor &desc) { - EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName); + EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName).ThrowOnError(); } void ROOT::RVectorField::RVectorDeleter::operator()(void *objPtr, bool dtorOnly) @@ -728,7 +728,7 @@ void ROOT::RField>::GenerateColumns(const ROOT::RNTupleDescrip void ROOT::RField>::ReconcileOnDiskField(const RNTupleDescriptor &desc) { - EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName); + EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName).ThrowOnError(); } std::vector ROOT::RField>::SplitValue(const RValue &value) const @@ -828,7 +828,8 @@ void ROOT::RArrayAsRVecField::ReadInClusterImpl(RNTupleLocalIndex localIndex, vo void ROOT::RArrayAsRVecField::ReconcileOnDiskField(const RNTupleDescriptor &desc) { const auto &fieldDesc = desc.GetFieldDescriptor(GetOnDiskId()); - EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName | kDiffTypeVersion | kDiffStructure | kDiffNRepetitions); + EnsureMatchingOnDiskField(fieldDesc, kDiffTypeName | kDiffTypeVersion | kDiffStructure | kDiffNRepetitions) + .ThrowOnError(); if (fieldDesc.GetTypeName().rfind("std::array<", 0) != 0) { throw RException(R__FAIL("RArrayAsRVecField " + GetQualifiedFieldName() + " expects an on-disk array field")); }