31 auto source = fieldMap.at(
target);
32 const bool hasCompatibleStructure =
33 (source->GetStructure() ==
target->GetStructure()) ||
35 if (!hasCompatibleStructure)
36 return R__FAIL(
"field mapping structural mismatch: " + source->GetName() +
" --> " +
target->GetName());
38 if (
target->GetType() != source->GetType())
39 return R__FAIL(
"field mapping type mismatch: " + source->GetName() +
" --> " +
target->GetName());
58 auto *sourceBreakPoint = fnBreakPoint(source);
60 return R__FAIL(
"unsupported field mapping (source structure)");
61 auto *targetBreakPoint = fnBreakPoint(
target);
63 return R__FAIL(
"unsupported field mapping (target structure)");
65 if (!sourceBreakPoint && !targetBreakPoint) {
69 if (sourceBreakPoint && targetBreakPoint) {
70 if (sourceBreakPoint == targetBreakPoint) {
74 if (
auto it = fieldMap.find(targetBreakPoint); it != fieldMap.end() && it->second == sourceBreakPoint) {
79 return R__FAIL(
"field mapping structure mismatch: " + source->GetName() +
" --> " +
target->GetName());
83 return R__FAIL(
"field mapping structure mismatch: " + source->GetName() +
" --> " +
target->GetName());
90 auto result = EnsureValidMapping(field.get(), fieldMap);
93 for (
const auto &
f : *field) {
94 result = EnsureValidMapping(&
f, fieldMap);
99 fFieldMap.insert(fieldMap.begin(), fieldMap.end());
107 if (
auto it = fFieldMap.find(
target); it != fFieldMap.end())
112std::unique_ptr<ROOT::Experimental::RNTupleModel::RProjectedFields>
115 auto cloneFieldZero = std::unique_ptr<RFieldZero>(
static_cast<RFieldZero *
>(
fFieldZero->Clone(
"").release()));
117 clone->fModel = newModel;
120 for (
const auto &[k,
v] : fFieldMap) {
121 for (
const auto &
f : *
clone->GetFieldZero()) {
122 if (
f.GetQualifiedFieldName() == k->GetQualifiedFieldName()) {
123 clone->fFieldMap[&
f] =
clone->fModel->GetField(
v->GetQualifiedFieldName());
132 : fWriter(
writer), fOpenChangeset(*fWriter.fModel)
138 fOpenChangeset.fModel.Unfreeze();
143 fOpenChangeset.fModel.Freeze();
144 if (fOpenChangeset.IsEmpty())
147 std::swap(fOpenChangeset.fAddedFields, toCommit.fAddedFields);
148 std::swap(fOpenChangeset.fAddedProjectedFields, toCommit.fAddedProjectedFields);
149 fWriter.fSink->UpdateSchema(toCommit, fWriter.fNEntries);
154 auto fieldp = field.get();
155 fOpenChangeset.fModel.AddField(std::move(field));
156 fOpenChangeset.fAddedFields.emplace_back(fieldp);
161 std::function<std::string(
const std::string &)> mapping)
163 auto fieldp = field.get();
164 auto result = fOpenChangeset.fModel.AddProjectedField(std::move(field), mapping);
166 fOpenChangeset.fAddedProjectedFields.emplace_back(fieldp);
176 auto fieldNameStr = std::string(fieldName);
177 if (
fFieldNames.insert(fieldNameStr).second ==
false) {
178 throw RException(
R__FAIL(
"field name '" + fieldNameStr +
"' already exists in NTuple model"));
200 auto model = std::unique_ptr<RNTupleModel>(
new RNTupleModel());
201 model->fProjectedFields = std::make_unique<RProjectedFields>(model.get());
207 auto model = CreateBare();
208 model->fDefaultEntry = std::unique_ptr<REntry>(
new REntry());
214 auto cloneModel = std::unique_ptr<RNTupleModel>(
new RNTupleModel());
215 auto cloneFieldZero = fFieldZero->Clone(
"");
216 cloneModel->fModelId = fModelId;
217 cloneModel->fFieldZero = std::unique_ptr<RFieldZero>(
static_cast<RFieldZero *
>(cloneFieldZero.release()));
218 cloneModel->fFieldNames = fFieldNames;
219 cloneModel->fDescription = fDescription;
220 cloneModel->fProjectedFields = fProjectedFields->Clone(cloneModel.get());
222 cloneModel->fDefaultEntry = std::unique_ptr<REntry>(
new REntry(fModelId));
223 for (
const auto &
f : cloneModel->fFieldZero->GetSubFields()) {
224 cloneModel->fDefaultEntry->AddValue(
f->GenerateValue());
236 EnsureValidFieldName(field->GetName());
239 fDefaultEntry->AddValue(field->GenerateValue());
240 fFieldZero->Attach(std::move(field));
245 std::function<std::string(
const std::string &)> mapping)
250 auto fieldName = field->GetName();
253 auto sourceField = GetField(mapping(fieldName));
255 return R__FAIL(
"no such field: " + mapping(fieldName));
256 fieldMap[field.get()] = sourceField;
257 for (
const auto &subField : *field) {
258 sourceField = GetField(mapping(subField.GetQualifiedFieldName()));
260 return R__FAIL(
"no such field: " + mapping(fieldName));
261 fieldMap[&subField] = sourceField;
264 EnsureValidFieldName(fieldName);
265 auto result = fProjectedFields->Add(std::move(field), fieldMap);
267 fFieldNames.erase(fieldName);
274 std::string_view fieldName, std::unique_ptr<RNTupleModel> collectionModel)
277 EnsureValidFieldName(fieldName);
278 if (!collectionModel) {
281 auto collectionNTuple = std::make_shared<RCollectionNTupleWriter>(std::move(collectionModel->fDefaultEntry));
282 auto field = std::make_unique<RCollectionField>(fieldName, collectionNTuple, std::move(collectionModel));
284 fDefaultEntry->AddValue(field->BindValue(collectionNTuple->GetOffsetPtr()));
285 fFieldZero->Attach(std::move(field));
286 return collectionNTuple;
292 if (fieldName.empty())
296 for (
auto subfieldName :
ROOT::Split(fieldName,
".")) {
299 std::find_if(subfields.begin(), subfields.end(), [&](
const auto *
f) { return f->GetName() == subfieldName; });
300 if (it != subfields.end()) {
314 throw RException(
R__FAIL(
"invalid attempt to get default entry of unfrozen model"));
316 return fDefaultEntry.get();
324 auto entry = std::unique_ptr<REntry>(
new REntry(fModelId));
325 for (
const auto &
f : fFieldZero->GetSubFields()) {
326 entry->AddValue(
f->GenerateValue());
336 auto entry = std::unique_ptr<REntry>(
new REntry(fModelId));
337 for (
const auto &
f : fFieldZero->GetSubFields()) {
338 entry->AddValue(
f->BindValue(
nullptr));
355 static std::atomic<std::uint64_t> gLastModelId = 0;
356 fModelId = ++gLastModelId;
358 fDefaultEntry->fModelId = fModelId;
364 fDescription = std::string(description);
#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
A field translates read and write calls from/to underlying columns to/from tree values.
RFieldBase * GetParent() const
static RResult< void > EnsureValidFieldName(std::string_view fieldName)
Check whether a given string is a valid field name.
std::vector< RFieldBase * > GetSubFields() const
void Throw()
Throws an RException with fError.
An artificial field that transforms an RNTuple column that contains the offset of collections into co...
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.
The container field for an ntuple model, which itself has no physical representation.
Projected fields are fields whose columns are reused from existing fields.
std::unordered_map< const Detail::RFieldBase *, const Detail::RFieldBase * > FieldMap_t
The map keys are the projected target fields, the map values are the backing source fields Note that ...
RResult< void > Add(std::unique_ptr< Detail::RFieldBase > field, const FieldMap_t &fieldMap)
Adds a new projected field.
RResult< void > EnsureValidMapping(const Detail::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::unique_ptr< RProjectedFields > Clone(const RNTupleModel *newModel) const
The new model needs to be a clone of fModel.
const Detail::RFieldBase * GetSourceField(const Detail::RFieldBase *target) const
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.
void AddField(std::unique_ptr< Detail::RFieldBase > field)
RResult< void > AddProjectedField(std::unique_ptr< Detail::RFieldBase > field, std::function< std::string(const std::string &)> mapping)
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 NTuple model.
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() const
std::unique_ptr< REntry > CreateBareEntry() const
In a bare entry, all values point to nullptr.
std::unique_ptr< REntry > CreateEntry() const
static std::unique_ptr< RNTupleModel > Create()
void SetDescription(std::string_view description)
std::unique_ptr< REntry > fDefaultEntry
Contains field values corresponding to the created top-level fields.
std::shared_ptr< RCollectionNTupleWriter > MakeCollection(std::string_view fieldName, std::unique_ptr< RNTupleModel > collectionModel)
Ingests a model for a sub collection and attaches it to the current model.
RResult< void > AddProjectedField(std::unique_ptr< Detail::RFieldBase > field, std::function< std::string(const std::string &)> mapping)
Adds a top-level field based on existing fields.
const Detail::RFieldBase * GetField(std::string_view fieldName) const
static std::unique_ptr< RNTupleModel > CreateBare()
A bare model has no default entry.
void AddField(std::unique_ptr< Detail::RFieldBase > field)
Adds a field whose type is not known at compile time.
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.
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