Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions roottest/root/io/hadd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,14 @@ ROOTTEST_ADD_TEST(test_hadd_regr_20872_2
PASSREGEX "root://eospublic.cern.ch//eos/root-eos/h1/dstarmb.root cannot be both the target and an input!"
)
endif()

# Verify that the hadd (or rather, the RNTupleMerger) is able to cope with RNTuples written before schema version
# 1.0.0.1 (meaning they have the wrong type name normalization)
configure_file(test_hadd_merge_rntuple_634_1.root . COPYONLY)
configure_file(test_hadd_merge_rntuple_634_2.root . COPYONLY)
configure_file(check_merge_rntuple_634.C . COPYONLY)
ROOTTEST_ADD_TEST(test_hadd_merge_rntuple_634,
PRECMD ${CMAKE_COMMAND} -E rm -f test_hadd_merge_rntuple_634_merged.root
COMMAND ${ROOT_hadd_CMD} -f test_hadd_merge_rntuple_634_merged.root test_hadd_merge_rntuple_634_1.root test_hadd_merge_rntuple_634_2.root
POSTCMD ${ROOT_root_CMD} -q check_merge_rntuple_634.C
PASSRC 0)
16 changes: 16 additions & 0 deletions roottest/root/io/hadd/check_merge_rntuple_634.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
int check_merge_rntuple_634()
{
// Verify that the given RNTuple is readable
auto reader = ROOT::RNTupleReader::Open("Events", "test_hadd_merge_rntuple_634_merged.root");
const auto &model = reader->GetModel();
const auto &desc = reader->GetDescriptor();
for (const auto &fdesc : desc.GetFieldIterable(desc.GetFieldZeroId())) {
if (fdesc.GetTypeName() != ROOT::Internal::GetRenormalizedTypeName(fdesc.GetTypeName())) {
std::cerr << "Type name is not renormalized! " << fdesc.GetTypeName() << " vs " <<
ROOT::Internal::GetRenormalizedTypeName(fdesc.GetTypeName()) << "\n";
return 1;
}
}

return 0;
}
Binary file not shown.
Binary file not shown.
8 changes: 8 additions & 0 deletions tree/ntuple/inc/ROOT/RPageStorage.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ namespace ROOT {

class RNTupleModel;

namespace Experimental {
namespace Internal {
class RNTupleMerger;
}
} // namespace Experimental

namespace Internal {

class RPageAllocator;
Expand Down Expand Up @@ -445,6 +451,8 @@ public:
*/
// clang-format on
class RPagePersistentSink : public RPageSink {
friend class ROOT::Experimental::Internal::RNTupleMerger;

private:
/// Used to map the IDs of the descriptor to the physical IDs issued during header/footer serialization
ROOT::Internal::RNTupleSerializer::RContext fSerializationContext;
Expand Down
17 changes: 17 additions & 0 deletions tree/ntuple/src/RNTupleDescriptor.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,23 @@ ROOT::RResult<void> ROOT::Internal::RNTupleDescriptorBuilder::AddClusterGroup(RC
void ROOT::Internal::RNTupleDescriptorBuilder::SetSchemaFromExisting(const RNTupleDescriptor &descriptor)
{
fDescriptor = descriptor.CloneSchema();

if (descriptor.fVersionMajor == 0 && descriptor.fVersionMinor == 0 && descriptor.fVersionPatch < 1) {
// In case we are copying the schema from a pre-1.0.0.1 RNTuple we need to patch all field type names
// to use the proper normalization.
std::vector<ROOT::DescriptorId_t> toVisit;
toVisit.push_back(fDescriptor.GetFieldZeroId());
while (!toVisit.empty()) {
auto fieldId = toVisit.back();
toVisit.pop_back();
for (auto &field : fDescriptor.GetFieldIterable(fieldId)) {
auto prev = field.fTypeName;
const_cast<ROOT::RFieldDescriptor &>(field).fTypeName =
ROOT::Internal::GetRenormalizedTypeName(field.fTypeName);
toVisit.push_back(field.GetId());
}
}
}
}

void ROOT::Internal::RNTupleDescriptorBuilder::BeginHeaderExtension()
Expand Down
7 changes: 4 additions & 3 deletions tree/ntuple/src/RNTupleMerger.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,8 @@ CompareDescriptorStructure(const ROOT::RNTupleDescriptor &dst, const ROOT::RNTup

// Require that fields types match
// TODO(gparolini): allow non-identical but compatible types
const auto &srcTyName = field.fSrc->GetTypeName();
const auto &srcTyName = ROOT::Internal::GetRenormalizedTypeName(field.fSrc->GetTypeName());
// This is already renormalized by construction (see RNTupleDescriptorBuilder::SetSchemaFromExisting)
const auto &dstTyName = field.fDst->GetTypeName();
if (srcTyName != dstTyName) {
std::stringstream ss;
Expand Down Expand Up @@ -1147,8 +1148,8 @@ static void AddColumnsFromField(std::vector<RColumnMergeInfo> &columns, const RO
}

// Since we disallow merging fields of different types, src and dstFieldDesc must have the same type name.
assert(srcFieldDesc.GetTypeName() == dstFieldDesc.GetTypeName());
info.fInMemoryType = ColumnInMemoryType(srcFieldDesc.GetTypeName(), info.fColumnType);
assert(srcDesc.GetTypeNameForComparison(srcFieldDesc) == dstFieldDesc.GetTypeName());
info.fInMemoryType = ColumnInMemoryType(dstFieldDesc.GetTypeName(), info.fColumnType);
columns.emplace_back(info);
}

Expand Down
2 changes: 2 additions & 0 deletions tree/ntuple/src/RPageStorage.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,8 @@ ROOT::Internal::RPagePersistentSink::InitFromDescriptor(const ROOT::RNTupleDescr
{
// Create new descriptor
fDescriptorBuilder.SetSchemaFromExisting(srcDescriptor);
// This is needed to be able to use GetTypeNameForComparison()
fDescriptorBuilder.SetVersionForWriting();
const auto &descriptor = fDescriptorBuilder.GetDescriptor();

// Create column/page ranges
Expand Down
Loading