28std::uint64_t GetNewModelId()
30 static std::atomic<std::uint64_t> gLastModelId = 0;
31 return ++gLastModelId;
52 auto source = fieldMap.at(
target);
53 const bool hasCompatibleStructure =
54 (source->GetStructure() ==
target->GetStructure()) ||
56 if (!hasCompatibleStructure)
57 return R__FAIL(
"field mapping structural mismatch: " + source->GetFieldName() +
" --> " +
target->GetFieldName());
59 if (
target->GetTypeName() != source->GetTypeName())
60 return R__FAIL(
"field mapping type mismatch: " + source->GetFieldName() +
" --> " +
target->GetFieldName());
63 auto fnHasArrayParent = [](
const RFieldBase &
f) ->
bool {
64 auto parent =
f.GetParent();
66 if (parent->GetNRepetitions() > 0)
68 parent = parent->GetParent();
72 if (fnHasArrayParent(*source) || fnHasArrayParent(*
target)) {
73 return R__FAIL(
"unsupported field mapping across fixed-size arrays");
94 auto *sourceBreakPoint = fnBreakPoint(source);
96 return R__FAIL(
"unsupported field mapping (source structure)");
97 auto *targetBreakPoint = fnBreakPoint(
target);
99 return R__FAIL(
"unsupported field mapping (target structure)");
101 if (!sourceBreakPoint && !targetBreakPoint) {
105 if (sourceBreakPoint && targetBreakPoint) {
106 if (sourceBreakPoint == targetBreakPoint) {
110 if (
auto it = fieldMap.find(targetBreakPoint); it != fieldMap.end() && it->second == sourceBreakPoint) {
115 return R__FAIL(
"field mapping structure mismatch: " + source->GetFieldName() +
" --> " +
target->GetFieldName());
119 return R__FAIL(
"field mapping structure mismatch: " + source->GetFieldName() +
" --> " +
target->GetFieldName());
125 auto result = EnsureValidMapping(field.get(), fieldMap);
128 for (
const auto &
f : *field) {
129 result = EnsureValidMapping(&
f, fieldMap);
134 fFieldMap.insert(fieldMap.begin(), fieldMap.end());
135 fFieldZero->Attach(std::move(field));
142 if (
auto it = fFieldMap.find(
target); it != fFieldMap.end())
147std::unique_ptr<ROOT::Experimental::Internal::RProjectedFields>
150 auto cloneFieldZero = std::unique_ptr<RFieldZero>(
static_cast<RFieldZero *
>(fFieldZero->Clone(
"").release()));
151 auto clone = std::unique_ptr<RProjectedFields>(
new RProjectedFields(std::move(cloneFieldZero)));
152 clone->fModel = &newModel;
155 for (
const auto &[k,
v] : fFieldMap) {
156 for (
const auto &
f : clone->GetFieldZero()) {
157 if (
f.GetQualifiedFieldName() == k->GetQualifiedFieldName()) {
158 clone->fFieldMap[&
f] = &newModel.
GetConstField(
v->GetQualifiedFieldName());
167 : fWriter(
writer), fOpenChangeset(fWriter.GetUpdatableModel())
173 fOpenChangeset.fModel.Unfreeze();
176 std::swap(fOpenChangeset.fModel.fModelId, fNewModelId);
181 fOpenChangeset.fModel.Freeze();
182 std::swap(fOpenChangeset.fModel.fModelId, fNewModelId);
183 if (fOpenChangeset.IsEmpty())
186 std::swap(fOpenChangeset.fAddedFields, toCommit.fAddedFields);
187 std::swap(fOpenChangeset.fAddedProjectedFields, toCommit.fAddedProjectedFields);
188 fWriter.GetSink().UpdateSchema(toCommit, fWriter.GetNEntries());
193 auto fieldp = field.get();
194 fOpenChangeset.fModel.AddField(std::move(field));
195 fOpenChangeset.fAddedFields.emplace_back(fieldp);
202 auto fieldp = field.get();
203 auto result = fOpenChangeset.fModel.AddProjectedField(std::move(field), mapping);
205 fOpenChangeset.fAddedProjectedFields.emplace_back(fieldp);
215 if (fieldName.empty()) {
218 auto fieldNameStr = std::string(fieldName);
220 throw RException(
R__FAIL(
"field name '" + fieldNameStr +
"' already exists in NTuple model"));
241 return CreateBare(std::make_unique<RFieldZero>());
244std::unique_ptr<ROOT::Experimental::RNTupleModel>
247 auto model = std::unique_ptr<RNTupleModel>(
new RNTupleModel(std::move(fieldZero)));
248 model->fProjectedFields = std::make_unique<Internal::RProjectedFields>(*model);
254 return Create(std::make_unique<RFieldZero>());
257std::unique_ptr<ROOT::Experimental::RNTupleModel>
260 auto model = CreateBare(std::move(fieldZero));
261 model->fDefaultEntry = std::unique_ptr<REntry>(
new REntry(model->fModelId, model->fSchemaId));
267 auto cloneModel = std::unique_ptr<RNTupleModel>(
268 new RNTupleModel(std::unique_ptr<RFieldZero>(
static_cast<RFieldZero *
>(fFieldZero->Clone(
"").release()))));
269 cloneModel->fModelId = GetNewModelId();
273 cloneModel->fSchemaId = fSchemaId;
275 cloneModel->fSchemaId = cloneModel->fModelId;
277 cloneModel->fIsFrozen = fIsFrozen;
278 cloneModel->fFieldNames = fFieldNames;
279 cloneModel->fDescription = fDescription;
280 cloneModel->fProjectedFields = fProjectedFields->Clone(*cloneModel);
281 cloneModel->fRegisteredSubfields = fRegisteredSubfields;
283 cloneModel->fDefaultEntry = std::unique_ptr<REntry>(
new REntry(cloneModel->fModelId, cloneModel->fSchemaId));
284 for (
const auto &
f : cloneModel->fFieldZero->GetSubFields()) {
285 cloneModel->fDefaultEntry->AddValue(
f->CreateValue());
287 for (
const auto &
f : cloneModel->fRegisteredSubfields) {
288 cloneModel->AddSubfield(
f, *cloneModel->fDefaultEntry);
296 if (fieldName.empty())
300 for (
auto subfieldName :
ROOT::Split(fieldName,
".")) {
302 auto it = std::find_if(subfields.begin(), subfields.end(),
303 [&](
const auto *
f) { return f->GetFieldName() == subfieldName; });
304 if (it != subfields.end()) {
320 EnsureValidFieldName(field->GetFieldName());
323 fDefaultEntry->AddValue(field->CreateValue());
324 fFieldNames.insert(field->GetFieldName());
325 fFieldZero->Attach(std::move(field));
329 bool initializeValue)
const
331 auto field = FindField(qualifiedFieldName);
333 entry.
AddValue(field->CreateValue());
335 entry.
AddValue(field->BindValue(
nullptr));
340 if (qualifiedFieldName.empty())
343 if (fFieldNames.find(std::string(qualifiedFieldName)) != fFieldNames.end()) {
345 R__FAIL(
"cannot register top-level field \"" + std::string(qualifiedFieldName) +
"\" as a subfield"));
348 if (fRegisteredSubfields.find(std::string(qualifiedFieldName)) != fRegisteredSubfields.end())
349 throw RException(
R__FAIL(
"subfield \"" + std::string(qualifiedFieldName) +
"\" already registered"));
353 auto *field = FindField(qualifiedFieldName);
355 throw RException(
R__FAIL(
"could not find subfield \"" + std::string(qualifiedFieldName) +
"\" in model"));
358 auto parent = field->GetParent();
359 while (parent && !parent->GetFieldName().empty()) {
363 "registering a subfield as part of a collection, fixed-sized array or std::variant is not supported"));
365 parent = parent->GetParent();
369 AddSubfield(qualifiedFieldName, *fDefaultEntry);
370 fRegisteredSubfields.emplace(qualifiedFieldName);
379 auto fieldName = field->GetFieldName();
382 auto sourceField = FindField(mapping(fieldName));
384 return R__FAIL(
"no such field: " + mapping(fieldName));
385 fieldMap[field.get()] = sourceField;
386 for (
const auto &subField : *field) {
387 sourceField = FindField(mapping(subField.GetQualifiedFieldName()));
389 return R__FAIL(
"no such field: " + mapping(fieldName));
390 fieldMap[&subField] = sourceField;
393 EnsureValidFieldName(fieldName);
394 auto result = fProjectedFields->Add(std::move(field), fieldMap);
398 fFieldNames.insert(fieldName);
405 throw RException(
R__FAIL(
"invalid attempt to get mutable zero field of frozen model"));
412 throw RException(
R__FAIL(
"invalid attempt to get mutable field of frozen model"));
413 auto f = FindField(fieldName);
422 auto f = FindField(fieldName);
432 return *fDefaultEntry;
438 throw RException(
R__FAIL(
"invalid attempt to get default entry of unfrozen model"));
440 return *fDefaultEntry;
448 auto entry = std::unique_ptr<REntry>(
new REntry(fModelId, fSchemaId));
449 for (
const auto &
f : fFieldZero->GetSubFields()) {
450 entry->AddValue(
f->CreateValue());
452 for (
const auto &
f : fRegisteredSubfields) {
453 AddSubfield(
f, *entry);
463 auto entry = std::unique_ptr<REntry>(
new REntry(fModelId, fSchemaId));
464 for (
const auto &
f : fFieldZero->GetSubFields()) {
465 entry->AddValue(
f->BindValue(
nullptr));
467 for (
const auto &
f : fRegisteredSubfields) {
468 AddSubfield(
f, *entry,
false );
475 const auto &topLevelFields = fFieldZero->GetSubFields();
476 auto it = std::find_if(topLevelFields.begin(), topLevelFields.end(),
477 [&fieldName](
const RFieldBase *
f) { return f->GetFieldName() == fieldName; });
479 if (it == topLevelFields.end()) {
490 auto f = FindField(fieldName);
493 return f->CreateBulk();
501 fModelId = GetNewModelId();
502 fSchemaId = fModelId;
504 fDefaultEntry->fModelId = fModelId;
505 fDefaultEntry->fSchemaId = fSchemaId;
518 fDescription = std::string(description);
523 std::size_t
bytes = 0;
524 std::size_t minPageBufferSize = 0;
527 std::size_t nColumns = 0;
528 for (
auto &&field : *fFieldZero) {
529 for (
const auto &
r : field.GetColumnRepresentatives()) {
530 nColumns +=
r.size();
531 for (
auto columnType :
r) {
542 bytes += minPageBufferSize;
#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...
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 r
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
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 bytes
static std::unique_ptr< RColumnElementBase > Generate(EColumnType type)
If CppT == void, use the default C++ type for the given column type.
The projected fields of a RNTupleModel
std::unique_ptr< RProjectedFields > Clone(const RNTupleModel &newModel) const
The new model needs to be a clone of fModel.
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 ...
const RFieldBase * GetSourceField(const RFieldBase *target) const
RResult< void > Add(std::unique_ptr< RFieldBase > field, const FieldMap_t &fieldMap)
Adds a new projected field.
An artificial field that transforms an RNTuple column that contains the offset of collections into co...
The field token identifies a (sub)field in this entry.
The REntry is a collection of values in an ntuple corresponding to a complete row in the data set.
void AddValue(RFieldBase::RValue &&value)
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.
const RFieldBase * GetParent() const
std::vector< RFieldBase * > GetSubFields()
The container field for an ntuple model, which itself has no physical representation.
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.
RResult< void > AddProjectedField(std::unique_ptr< RFieldBase > field, FieldMappingFunc_t mapping)
void AddField(std::unique_ptr< RFieldBase > field)
The RNTupleModel encapulates the schema of an ntuple.
std::unordered_set< std::string > fFieldNames
Keeps track of which field names are taken, including projected field names.
void EnsureValidFieldName(std::string_view fieldName)
Checks that user-provided field names are valid in the context of this RNTuple model.
std::uint64_t fModelId
Every model has a unique ID to distinguish it from other models.
std::function< std::string(const std::string &)> FieldMappingFunc_t
User provided function that describes the mapping of existing source fields to projected fields in te...
std::unique_ptr< Internal::RProjectedFields > fProjectedFields
The set of projected top-level fields.
const RFieldBase & GetConstField(std::string_view fieldName) const
std::uint64_t fSchemaId
Models have a separate schema ID to remember that the clone of a frozen model still has the same sche...
REntry::RFieldToken GetToken(std::string_view fieldName) const
Creates a token to be used in REntry methods to address a field present in the entry.
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.
RFieldZero & GetMutableFieldZero()
Mutable access to the root field is used to make adjustments to the fields.
REntry & GetDefaultEntry()
std::size_t EstimateWriteMemoryUsage(const RNTupleWriteOptions &options=RNTupleWriteOptions()) const
Estimate the memory usage for this model during writing.
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()
void AddSubfield(std::string_view fieldName, REntry &entry, bool initializeValue=true) const
Add a subfield to the provided entry.
RResult< void > AddProjectedField(std::unique_ptr< RFieldBase > field, FieldMappingFunc_t mapping)
Adds a top-level field based on existing fields.
void SetDescription(std::string_view description)
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)
RFieldBase & GetMutableField(std::string_view fieldName)
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.
void RegisterSubfield(std::string_view qualifiedFieldName)
Register a subfield so it can be accessed directly from entries belonging to the model.
std::unique_ptr< RFieldZero > fFieldZero
Hierarchy of fields consisting of simple types and collections (sub trees)
Common user-tunable settings for storing ntuples.
int GetCompression() const
std::size_t GetPageBufferBudget() const
std::size_t GetApproxZippedClusterSize() const
std::size_t GetInitialNElementsPerPage() const
bool GetUseBufferedWrite() const
std::size_t GetMaxUnzippedPageSize() const
EImplicitMT GetUseImplicitMT() const
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...
RProjectedFields & GetProjectedFieldsOfModel(RNTupleModel &model)
RResult< void > EnsureValidNameForRNTuple(std::string_view name, std::string_view where)
Check whether a given string is a valid name according to the RNTuple specification.
RFieldZero & GetFieldZeroOfModel(RNTupleModel &model)
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