diff --git a/tree/ntuple/v7/src/RNTupleProcessor.cxx b/tree/ntuple/v7/src/RNTupleProcessor.cxx index 6b861b898e5f1..616fb7afe714f 100644 --- a/tree/ntuple/v7/src/RNTupleProcessor.cxx +++ b/tree/ntuple/v7/src/RNTupleProcessor.cxx @@ -71,14 +71,19 @@ ROOT::Experimental::Internal::RNTupleProcessor::RNTupleProcessor(const std::vect model->Freeze(); fEntry = model->CreateEntry(); - // Use the value pointers from the model's in the entry managed by the processor. This way, the pointers returned by - // RNTupleModel::MakeField can be used in the processor loop to access the corresponding field values. - for (const auto &value : model->GetDefaultEntry()) { + for (const auto &value : *fEntry) { auto &field = value.GetField(); auto token = fEntry->GetToken(field.GetFieldName()); - auto valuePtr = value.GetPtr(); - fEntry->BindValue(token, valuePtr); - fFieldContexts.emplace_back(field.Clone(field.GetFieldName()), fEntry->GetToken(field.GetFieldName())); + + // If the model has a default entry, use the value pointers from the entry in the entry managed by the + // processor. This way, the pointers returned by RNTupleModel::MakeField can be used in the processor loop to + // access the corresponding field values. + if (!model->IsBare()) { + auto valuePtr = model->GetDefaultEntry().GetPtr(token); + fEntry->BindValue(token, valuePtr); + } + + fFieldContexts.emplace_back(field.Clone(field.GetFieldName()), token); } ConnectFields(); diff --git a/tree/ntuple/v7/test/ntuple_processor.cxx b/tree/ntuple/v7/test/ntuple_processor.cxx index 7eb6605368af1..165e7d1dc60b9 100644 --- a/tree/ntuple/v7/test/ntuple_processor.cxx +++ b/tree/ntuple/v7/test/ntuple_processor.cxx @@ -40,7 +40,7 @@ TEST(RNTupleProcessor, Basic) EXPECT_EQ(nEntries, 10); } -TEST(RNTupleProcessor, BasicWithModel) +TEST(RNTupleProcessor, WithModel) { FileRaii fileGuard("test_ntuple_processor_basic_with_model.root"); { @@ -68,6 +68,33 @@ TEST(RNTupleProcessor, BasicWithModel) } } +TEST(RNTupleProcessor, WithBareModel) +{ + FileRaii fileGuard("test_ntuple_processor_basic_with_model.root"); + { + auto model = RNTupleModel::Create(); + auto fldX = model->MakeField("x"); + auto fldY = model->MakeField("y"); + auto fldZ = model->MakeField("z"); + auto ntuple = RNTupleWriter::Recreate(std::move(model), "ntuple", fileGuard.GetPath()); + + for (unsigned i = 0; i < 10; ++i) { + *fldX = static_cast(i); + *fldY = static_cast(i) * 2.f; + *fldZ = static_cast(i) * 3.f; + ntuple->Fill(); + } + } + + auto model = RNTupleModel::CreateBare(); + model->MakeField("y"); + std::vector ntuples = {{"ntuple", fileGuard.GetPath()}}; + + for (const auto &entry : RNTupleProcessor(ntuples, std::move(model))) { + EXPECT_EQ(static_cast(entry.GetGlobalEntryIndex()) * 2.f, *entry->GetPtr("y")); + } +} + TEST(RNTupleProcessor, SimpleChain) { FileRaii fileGuard1("test_ntuple_processor_simple_chain1.root");