File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -402,11 +402,18 @@ You will not normally use this directly; see `RNTupleModel::RUpdater` instead.
402402*/
403403// clang-format on
404404struct RNTupleModelChangeset {
405+ struct RAddedColumnRepr {
406+ ROOT::RFieldBase *fField = nullptr ;
407+ std::uint16_t fNumNewColumns = 0 ;
408+ };
409+
405410 RNTupleModel &fModel ;
406411 // / Points to the fields in fModel that were added as part of an updater transaction
407412 std::vector<ROOT::RFieldBase *> fAddedFields ;
408413 // / Points to the projected fields in fModel that were added as part of an updater transaction
409414 std::vector<ROOT::RFieldBase *> fAddedProjectedFields ;
415+ // / Points to fields in fModel that had new column representations appended to them.
416+ std::vector<RAddedColumnRepr> fAddedColumnReprs ;
410417
411418 RNTupleModelChangeset (RNTupleModel &model) : fModel (model) {}
412419 bool IsEmpty () const { return fAddedFields .empty () && fAddedProjectedFields .empty (); }
@@ -420,6 +427,9 @@ struct RNTupleModelChangeset {
420427 // / \see RNTupleModel::AddProjectedField()
421428 ROOT::RResult<void >
422429 AddProjectedField (std::unique_ptr<ROOT::RFieldBase> field, RNTupleModel::FieldMappingFunc_t mapping);
430+
431+ ROOT::RResult<void >
432+ AddColumnRepr (ROOT::RFieldBase *field, const ROOT::RFieldBase::RColumnRepresentations::Selection_t &reprs);
423433};
424434
425435} // namespace Internal
Original file line number Diff line number Diff line change @@ -830,7 +830,15 @@ ROOT::RFieldBase::RColumnRepresentations::Selection_t ROOT::RFieldBase::GetColum
830830
831831void ROOT::RFieldBase::SetColumnRepresentatives (const RColumnRepresentations::Selection_t &representatives)
832832{
833- if (fState != EState::kUnconnected )
833+ const auto isNewSelectionASuperset = [&]() {
834+ if (representatives.size () < fColumnRepresentatives .size ())
835+ return false ;
836+ for (auto i = 0u ; i < fColumnRepresentatives .size (); ++i)
837+ if (representatives[i] != fColumnRepresentatives [i].get ())
838+ return false ;
839+ return true ;
840+ };
841+ if (fState != EState::kUnconnected && !(fState == EState::kConnectedToSink && isNewSelectionASuperset ()))
834842 throw RException (R__FAIL (" cannot set column representative once field is connected" ));
835843 const auto &validTypes = GetColumnRepresentations ().GetSerializationTypes ();
836844 fColumnRepresentatives .clear ();
Original file line number Diff line number Diff line change @@ -287,6 +287,27 @@ ROOT::RNTupleModel::RUpdater::AddProjectedField(std::unique_ptr<ROOT::RFieldBase
287287 return R__FORWARD_RESULT (fOpenChangeset .AddProjectedField (std::move (field), std::move (mapping)));
288288}
289289
290+ ROOT::RResult<void > ROOT::Internal::RNTupleModelChangeset::AddColumnRepr (
291+ ROOT::RFieldBase *field, const ROOT::RFieldBase::RColumnRepresentations::Selection_t &newReprs)
292+ {
293+ auto reprs = field->GetColumnRepresentatives ();
294+ const auto nPrev = reprs.size ();
295+ for (auto newRepr : newReprs)
296+ // NOTE: we don't need to check for duplicates because SetColumnRepresentatives will do that for us.
297+ reprs.push_back (newRepr);
298+
299+ field->SetColumnRepresentatives (reprs);
300+ const auto nNew = field->GetColumnRepresentatives ().size ();
301+ assert (reprs.size () > 0 && reprs[0 ].size () <= 2 );
302+ const auto cardinality = static_cast <std::uint16_t >(reprs[0 ].size ());
303+ assert (nNew >= nPrev);
304+ std::uint16_t nAdded = (nNew - nPrev) * cardinality;
305+ if (nAdded > 0 )
306+ fAddedColumnReprs .push_back (RAddedColumnRepr{field, nAdded});
307+
308+ return RResult<void >::Success ();
309+ }
310+
290311void ROOT::RNTupleModel::EnsureValidFieldName (std::string_view fieldName)
291312{
292313 RResult<void > nameValid = ROOT::Internal::EnsureValidNameForRNTuple (fieldName, " Field" );
Original file line number Diff line number Diff line change @@ -125,12 +125,20 @@ void ROOT::Internal::RPageSinkBuf::UpdateSchema(const ROOT::Internal::RNTupleMod
125125 GetProjectedFieldsOfModel (*fInnerModel ).Add (std::move (cloned), fieldMap);
126126 return p;
127127 };
128+ auto cloneAddColumnRepr = [&](const RNTupleModelChangeset::RAddedColumnRepr &repr) {
129+ auto &innerField = fInnerModel ->GetMutableField (repr.fField ->GetFieldName ());
130+ innerField.SetColumnRepresentatives (repr.fField ->GetColumnRepresentatives ());
131+ ROOT::Internal::CallConnectExtendedColumnsToPageSinkOnField (innerField, *this , firstEntry);
132+ return repr;
133+ };
128134 RNTupleModelChangeset innerChangeset{*fInnerModel };
129135 fInnerModel ->Unfreeze ();
130136 std::transform (changeset.fAddedFields .cbegin (), changeset.fAddedFields .cend (),
131137 std::back_inserter (innerChangeset.fAddedFields ), cloneAddField);
132138 std::transform (changeset.fAddedProjectedFields .cbegin (), changeset.fAddedProjectedFields .cend (),
133139 std::back_inserter (innerChangeset.fAddedProjectedFields ), cloneAddProjectedField);
140+ std::transform (changeset.fAddedColumnReprs .cbegin (), changeset.fAddedColumnReprs .cend (),
141+ std::back_inserter (innerChangeset.fAddedColumnReprs ), cloneAddColumnRepr);
134142 fInnerModel ->Freeze ();
135143 fInnerSink ->UpdateSchema (innerChangeset, firstEntry);
136144}
Original file line number Diff line number Diff line change @@ -868,6 +868,9 @@ void ROOT::Internal::RPagePersistentSink::UpdateSchema(const ROOT::Internal::RNT
868868 for (const auto &descendant : *f)
869869 nNewPhysicalColumns += getNColumns (descendant);
870870 }
871+ for (auto added : changeset.fAddedColumnReprs ) {
872+ nNewPhysicalColumns += added.fNumNewColumns ;
873+ }
871874 fDescriptorBuilder .ShiftAliasColumns (nNewPhysicalColumns);
872875 }
873876
@@ -913,6 +916,9 @@ void ROOT::Internal::RPagePersistentSink::UpdateSchema(const ROOT::Internal::RNT
913916 for (auto &descendant : *f)
914917 addProjectedField (descendant);
915918 }
919+ for (const auto & [f, _] : changeset.fAddedColumnReprs ) {
920+ ROOT::Internal::CallConnectExtendedColumnsToPageSinkOnField (*f, *this , firstEntry);
921+ }
916922
917923 const auto nColumns = descriptor.GetNPhysicalColumns ();
918924 fOpenColumnRanges .reserve (fOpenColumnRanges .size () + (nColumns - nColumnsBeforeUpdate));
You can’t perform that action at this time.
0 commit comments