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
5 changes: 5 additions & 0 deletions tree/ntuple/src/RFieldBase.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,11 @@ std::size_t ROOT::RFieldBase::ReadBulk(const RBulkSpec &bulkSpec)
return RBulkSpec::kAllSet;
}

if (fIsArtificial || !fReadCallbacks.empty()) {
// Fields with schema evolution treatment must not go through an optimized read
return RFieldBase::ReadBulkImpl(bulkSpec);
}

return ReadBulkImpl(bulkSpec);
}

Expand Down
46 changes: 46 additions & 0 deletions tree/ntuple/test/ntuple_evolution_shape.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,52 @@ struct AddedMember {
EXPECT_EVALUATE_EQ("ptrAddedMember->fInt3", 93);
}

TEST(RNTupleEvolution, AddedMemberBulkRead)
{
FileRaii fileGuard("test_ntuple_evolution_added_member_bulk_read.root");

ExecInFork([&] {
// The child process writes the file and exits, but the file must be preserved to be read by the parent.
fileGuard.PreserveFile();

ASSERT_TRUE(gInterpreter->Declare(R"(
struct AddedMemberBulkRead {
int fX = 137;
};
)"));

auto model = RNTupleModel::Create();
model->AddField(RFieldBase::Create("f", "AddedMemberBulkRead").Unwrap());

auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
writer->Fill();

// Reset / close the writer and flush the file.
writer.reset();
});

ASSERT_TRUE(gInterpreter->Declare(R"(
struct AddedMemberBulkRead {
ROOT::RVec<int> fNew;
int fX = 137;
};
)"));

auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
ASSERT_EQ(1, reader->GetNEntries());

void *ptr = reader->GetModel().GetDefaultEntry().GetPtr<void>("f").get();
DeclarePointer("AddedMemberBulkRead", "ptrAddedMemberBulkRead", ptr);

reader->LoadEntry(0);
EXPECT_EVALUATE_EQ("ptrAddedMemberBulkRead->fX", 137);
EXPECT_EVALUATE_EQ("ptrAddedMemberBulkRead->fNew.empty()", true);

auto bulk = reader->GetModel().CreateBulk("f.fNew");
auto values = static_cast<ROOT::RVec<int> *>(bulk.ReadBulk(ROOT::RNTupleLocalRange(0, 0, 1)));
EXPECT_TRUE(values[0].empty());
}

TEST(RNTupleEvolution, AddedMemberObject)
{
FileRaii fileGuard("test_ntuple_evolution_added_member_object.root");
Expand Down
Loading