29std::uint64_t GetNewModelId()
31 static std::atomic<std::uint64_t> gLastModelId = 0;
32 return ++gLastModelId;
40 auto source = fieldMap.at(
target);
41 const bool hasCompatibleStructure =
42 (source->GetStructure() ==
target->GetStructure()) ||
44 if (!hasCompatibleStructure)
45 return R__FAIL(
"field mapping structural mismatch: " + source->GetFieldName() +
" --> " +
target->GetFieldName());
47 if (
target->GetTypeName() != source->GetTypeName())
48 return R__FAIL(
"field mapping type mismatch: " + source->GetFieldName() +
" --> " +
target->GetFieldName());
56 auto parent =
f->GetParent();
60 parent = parent->GetParent();
67 auto *sourceBreakPoint = fnBreakPoint(source);
69 return R__FAIL(
"unsupported field mapping (source structure)");
70 auto *targetBreakPoint = fnBreakPoint(
target);
72 return R__FAIL(
"unsupported field mapping (target structure)");
74 if (!sourceBreakPoint && !targetBreakPoint) {
78 if (sourceBreakPoint && targetBreakPoint) {
79 if (sourceBreakPoint == targetBreakPoint) {
83 if (
auto it = fieldMap.find(targetBreakPoint); it != fieldMap.end() && it->second == sourceBreakPoint) {
88 return R__FAIL(
"field mapping structure mismatch: " + source->GetFieldName() +
" --> " +
target->GetFieldName());
92 return R__FAIL(
"field mapping structure mismatch: " + source->GetFieldName() +
" --> " +
target->GetFieldName());
101 for (
const auto &
f : *field) {
107 fFieldMap.insert(fieldMap.begin(), fieldMap.end());
120std::unique_ptr<ROOT::Experimental::RNTupleModel::RProjectedFields>
123 auto cloneFieldZero = std::unique_ptr<RFieldZero>(
static_cast<RFieldZero *
>(
fFieldZero->Clone(
"").release()));
125 clone->fModel = newModel;
129 for (
const auto &
f : *
clone->GetFieldZero()) {
130 if (
f.GetQualifiedFieldName() == k->GetQualifiedFieldName()) {
131 clone->fFieldMap[&
f] =
clone->fModel->FindField(
v->GetQualifiedFieldName());
160 std::swap(
fOpenChangeset.fAddedProjectedFields, toCommit.fAddedProjectedFields);
166 auto fieldp = field.get();
173 std::function<std::string(
const std::string &)> mapping)
175 auto fieldp = field.get();
188 auto fieldNameStr = std::string(fieldName);
190 throw RException(
R__FAIL(
"field name '" + fieldNameStr +
"' already exists in NTuple model"));
211 return CreateBare(std::make_unique<RFieldZero>());
214std::unique_ptr<ROOT::Experimental::RNTupleModel>
217 auto model = std::unique_ptr<RNTupleModel>(
new RNTupleModel(std::move(fieldZero)));
218 model->fProjectedFields = std::make_unique<RProjectedFields>(model.get());
224 return Create(std::make_unique<RFieldZero>());
227std::unique_ptr<ROOT::Experimental::RNTupleModel>
230 auto model =
CreateBare(std::move(fieldZero));
231 model->fDefaultEntry = std::unique_ptr<REntry>(
new REntry(model->fModelId));
237 auto cloneModel = std::unique_ptr<RNTupleModel>(
239 cloneModel->fModelId = GetNewModelId();
245 cloneModel->fDefaultEntry = std::unique_ptr<REntry>(
new REntry(cloneModel->fModelId));
246 for (
const auto &
f : cloneModel->fFieldZero->GetSubFields()) {
247 cloneModel->fDefaultEntry->AddValue(
f->CreateValue());
255 if (fieldName.empty())
259 for (
auto subfieldName :
ROOT::Split(fieldName,
".")) {
260 const auto subfields = field->GetSubFields();
261 auto it = std::find_if(subfields.begin(), subfields.end(),
262 [&](
const auto *
f) { return f->GetFieldName() == subfieldName; });
263 if (it != subfields.end()) {
289 std::function<std::string(
const std::string &)> mapping)
294 auto fieldName = field->GetFieldName();
297 auto sourceField =
FindField(mapping(fieldName));
299 return R__FAIL(
"no such field: " + mapping(fieldName));
300 fieldMap[field.get()] = sourceField;
301 for (
const auto &subField : *field) {
302 sourceField =
FindField(mapping(subField.GetQualifiedFieldName()));
304 return R__FAIL(
"no such field: " + mapping(fieldName));
305 fieldMap[&subField] = sourceField;
317std::shared_ptr<ROOT::Experimental::RNTupleCollectionWriter>
319 std::unique_ptr<RNTupleModel> collectionModel)
323 if (!collectionModel) {
327 auto collectionWriter = std::make_shared<RNTupleCollectionWriter>(std::move(collectionModel->fDefaultEntry));
329 auto field = std::make_unique<RCollectionField>(fieldName, collectionWriter, std::move(collectionModel->fFieldZero));
330 field->SetDescription(collectionModel->GetDescription());
333 fDefaultEntry->AddValue(field->BindValue(std::shared_ptr<void>(collectionWriter->GetOffsetPtr(), [](
void *) {})));
337 return collectionWriter;
343 throw RException(
R__FAIL(
"invalid attempt to get mutable zero field of unfrozen model"));
365 throw RException(
R__FAIL(
"invalid attempt to get default entry of unfrozen model"));
377 entry->AddValue(
f->CreateValue());
389 entry->AddValue(
f->BindValue(
nullptr));
397 throw RException(
R__FAIL(
"invalid attempt to get field token of unfrozen model"));
399 const auto &topLevelFields =
fFieldZero->GetSubFields();
400 auto it = std::find_if(topLevelFields.begin(), topLevelFields.end(),
401 [&fieldName](
const RFieldBase *
f) { return f->GetFieldName() == fieldName; });
403 if (it == topLevelFields.end()) {
417 return f->CreateBulk();
#define R__FORWARD_ERROR(res)
Short-hand to return an RResult<T> in an error state (i.e. after checking)
#define R__FORWARD_RESULT(res)
Short-hand to return an RResult<T> value from a subroutine to the calling stack frame.
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
TObject * clone(const char *newname) const override
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
An artificial field that transforms an RNTuple column that contains the offset of collections into co...
The field token identifies a top-level field in this entry.
The REntry is a collection of values in an ntuple corresponding to a complete row in the data set.
Base class for all ROOT issued exceptions.
Similar to RValue but manages an array of consecutive values.
A field translates read and write calls from/to underlying columns to/from tree values.
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
The container field for an ntuple model, which itself has no physical representation.
FieldMap_t fFieldMap
Maps the source fields from fModel to the target projected fields attached to fFieldZero.
RProjectedFields(std::unique_ptr< RFieldZero > fieldZero)
RResult< void > EnsureValidMapping(const RFieldBase *target, const FieldMap_t &fieldMap)
Asserts that the passed field is a valid target of the source field provided in the field map.
std::unordered_map< const RFieldBase *, const RFieldBase * > FieldMap_t
The map keys are the projected target fields, the map values are the backing source fields Note that ...
std::unique_ptr< RFieldZero > fFieldZero
The projected fields are attached to this zero field.
const RFieldBase * GetSourceField(const RFieldBase *target) const
RResult< void > Add(std::unique_ptr< RFieldBase > field, const FieldMap_t &fieldMap)
Adds a new projected field.
std::unique_ptr< RProjectedFields > Clone(const RNTupleModel *newModel) const
The new model needs to be a clone of fModel.
Internal::RNTupleModelChangeset fOpenChangeset
RUpdater(RNTupleWriter &writer)
void CommitUpdate()
Commit changes since the last call to BeginUpdate().
void BeginUpdate()
Begin a new set of alterations to the underlying model.
std::uint64_t fNewModelId
The model ID after committing.
RResult< void > AddProjectedField(std::unique_ptr< RFieldBase > field, std::function< std::string(const std::string &)> mapping)
void AddField(std::unique_ptr< RFieldBase > field)
std::unordered_set< std::string > fFieldNames
Keeps track of which field names are taken, including projected field names.
std::string fDescription
Free text set by the user.
void EnsureValidFieldName(std::string_view fieldName)
Checks that user-provided field names are valid in the context of this NTuple model.
std::uint64_t fModelId
Every model has a unique ID to distinguish it from other models.
REntry::RFieldToken GetToken(std::string_view fieldName) const
Creates a token to be used in REntry methods to address a top-level field.
RResult< void > AddProjectedField(std::unique_ptr< RFieldBase > field, std::function< std::string(const std::string &)> mapping)
Adds a top-level field based on existing fields.
void EnsureNotBare() const
Throws an RException if fDefaultEntry is nullptr.
std::unique_ptr< RNTupleModel > Clone() const
void EnsureNotFrozen() const
Throws an RException if fFrozen is true.
REntry & GetDefaultEntry()
std::shared_ptr< RNTupleCollectionWriter > MakeCollection(std::string_view fieldName, std::unique_ptr< RNTupleModel > collectionModel)
Ingests a model for a sub collection and attaches it to the current model.
const RFieldBase & GetField(std::string_view fieldName) const
std::unique_ptr< REntry > CreateBareEntry() const
In a bare entry, all values point to nullptr.
std::unique_ptr< REntry > CreateEntry() const
RFieldBase::RBulk CreateBulk(std::string_view fieldName) const
Calls the given field's CreateBulk() method. Throws an exception if no field with the given name exis...
static std::unique_ptr< RNTupleModel > Create()
std::unique_ptr< RProjectedFields > fProjectedFields
The set of projected top-level fields.
void SetDescription(std::string_view description)
std::unique_ptr< REntry > fDefaultEntry
Contains field values corresponding to the created top-level fields.
RFieldBase * FindField(std::string_view fieldName) const
The field name can be a top-level field or a nested field. Returns nullptr if the field is not in the...
RNTupleModel(std::unique_ptr< RFieldZero > fieldZero)
static std::unique_ptr< RNTupleModel > CreateBare()
A bare model has no default entry.
void AddField(std::unique_ptr< RFieldBase > field)
Adds a field whose type is not known at compile time.
RFieldZero & GetFieldZero()
Non-const access to the root field is used to commit clusters during writing and to set the on-disk f...
bool fIsFrozen
Changed by Freeze() / Unfreeze() and by the RUpdater.
std::unique_ptr< RFieldZero > fFieldZero
Hierarchy of fields consisting of simple types and collections (sub trees)
An RNTuple that gets filled with entries (data) and writes them to storage.
void Throw()
Throws an RException with fError.
The class is used as a return type for operations that can fail; wraps a value of type T or an RError...
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
The incremental changes to a RNTupleModel