Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleProcessor.cxx
Go to the documentation of this file.
1/// \file RNTupleProcessor.cxx
2/// \ingroup NTuple
3/// \author Florine de Geus <florine.de.geus@cern.ch>
4/// \date 2024-03-26
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
17
18#include <ROOT/RFieldBase.hxx>
19#include <ROOT/RNTuple.hxx>
21#include <ROOT/StringUtils.hxx>
22
23#include <TDirectory.h>
24
25#include <iomanip>
26
27std::unique_ptr<ROOT::Internal::RPageSource> ROOT::Experimental::RNTupleOpenSpec::CreatePageSource() const
28{
29 if (const std::string *storagePath = std::get_if<std::string>(&fStorage))
31
32 auto dir = std::get<TDirectory *>(fStorage);
33 auto ntuple = std::unique_ptr<ROOT::RNTuple>(dir->Get<ROOT::RNTuple>(fNTupleName.c_str()));
35}
36
37std::unique_ptr<ROOT::Experimental::RNTupleProcessor>
39{
40 return std::unique_ptr<RNTupleSingleProcessor>(new RNTupleSingleProcessor(std::move(ntuple), processorName));
41}
42
43std::unique_ptr<ROOT::Experimental::RNTupleProcessor>
44ROOT::Experimental::RNTupleProcessor::CreateChain(std::vector<RNTupleOpenSpec> ntuples, std::string_view processorName)
45{
46 if (ntuples.empty())
47 throw RException(R__FAIL("at least one RNTuple must be provided"));
48
49 std::vector<std::unique_ptr<RNTupleProcessor>> innerProcessors;
50 innerProcessors.reserve(ntuples.size());
51
52 for (auto &ntuple : ntuples) {
53 innerProcessors.emplace_back(Create(std::move(ntuple)));
54 }
55
56 return CreateChain(std::move(innerProcessors), processorName);
57}
58
59std::unique_ptr<ROOT::Experimental::RNTupleProcessor>
60ROOT::Experimental::RNTupleProcessor::CreateChain(std::vector<std::unique_ptr<RNTupleProcessor>> innerProcessors,
61 std::string_view processorName)
62{
63 if (innerProcessors.empty())
64 throw RException(R__FAIL("at least one inner processor must be provided"));
65
66 return std::unique_ptr<RNTupleChainProcessor>(new RNTupleChainProcessor(std::move(innerProcessors), processorName));
67}
68
69std::unique_ptr<ROOT::Experimental::RNTupleProcessor>
71 const std::vector<std::string> &joinFields,
72 std::string_view processorName)
73{
74 if (joinFields.size() > 4) {
75 throw RException(R__FAIL("a maximum of four join fields is allowed"));
76 }
77
78 if (std::unordered_set(joinFields.begin(), joinFields.end()).size() < joinFields.size()) {
79 throw RException(R__FAIL("join fields must be unique"));
80 }
81
82 std::unique_ptr<RNTupleProcessor> primaryProcessor = Create(primaryNTuple, processorName);
83
84 std::unique_ptr<RNTupleProcessor> auxProcessor = Create(auxNTuple);
85
86 return CreateJoin(std::move(primaryProcessor), std::move(auxProcessor), joinFields, processorName);
87}
88
89std::unique_ptr<ROOT::Experimental::RNTupleProcessor>
90ROOT::Experimental::RNTupleProcessor::CreateJoin(std::unique_ptr<RNTupleProcessor> primaryProcessor,
91 std::unique_ptr<RNTupleProcessor> auxProcessor,
92 const std::vector<std::string> &joinFields,
93 std::string_view processorName)
94{
95 if (joinFields.size() > 4) {
96 throw RException(R__FAIL("a maximum of four join fields is allowed"));
97 }
98
99 if (std::unordered_set(joinFields.begin(), joinFields.end()).size() < joinFields.size()) {
100 throw RException(R__FAIL("join fields must be unique"));
101 }
102
103 return std::unique_ptr<RNTupleJoinProcessor>(
104 new RNTupleJoinProcessor(std::move(primaryProcessor), std::move(auxProcessor), joinFields, processorName));
105}
106
107//------------------------------------------------------------------------------
108
110 std::string_view processorName)
111 : RNTupleProcessor(processorName), fNTupleSpec(std::move(ntuple))
112{
113 if (fProcessorName.empty()) {
114 fProcessorName = fNTupleSpec.fNTupleName;
115 }
116}
117
119 std::shared_ptr<ROOT::Experimental::Internal::RNTupleProcessorEntry> entry)
120{
121 // The processor has already been initialized.
122 if (IsInitialized())
123 return;
124
125 if (!entry)
126 fEntry = std::make_shared<Internal::RNTupleProcessorEntry>();
127 else
128 fEntry = entry;
129
130 fPageSource = fNTupleSpec.CreatePageSource();
131 fPageSource->Attach();
132
133 fNEntries = fPageSource->GetNEntries();
134}
135
137{
138 Initialize();
139 auto desc = fPageSource->GetSharedDescriptorGuard();
140 auto fieldZeroId = desc->GetFieldZeroId();
141
142 // TODO handle subfields
143 return desc->FindFieldId(fieldName, fieldZeroId) != ROOT::kInvalidDescriptorId;
144}
145
146std::unique_ptr<ROOT::RFieldBase>
148 const std::string &typeName)
149{
150 assert(fPageSource);
151
152 std::string onDiskFieldName = qualifiedFieldName;
153
154 // Strip the "_join" prefix (for join fields) from the field name, if present.
155 if (onDiskFieldName.find("_join.") == 0) {
156 onDiskFieldName = onDiskFieldName.substr(6);
157 }
158
159 const auto &desc = fPageSource->GetSharedDescriptorGuard().GetRef();
160 ROOT::RFieldZero fieldZero;
162
163 const auto onDiskFieldId = desc.FindFieldId(onDiskFieldName);
164
165 if (onDiskFieldId == kInvalidDescriptorId) {
166 return nullptr;
167 }
168
169 std::unique_ptr<ROOT::RFieldBase> field;
170 if (typeName.empty()) {
171 const auto &fieldDesc = desc.GetFieldDescriptor(onDiskFieldId);
172 field = fieldDesc.CreateField(desc);
173 } else {
174 // Strip the parent field name prefix(es), if present.
175 std::string subfieldName = onDiskFieldName;
176 auto posDot = onDiskFieldName.find_last_of('.');
177 if (posDot != std::string::npos)
178 subfieldName = onDiskFieldName.substr(posDot + 1);
179
180 field = ROOT::RFieldBase::Create(subfieldName, typeName).Unwrap();
181 }
182
183 field->SetOnDiskId(onDiskFieldId);
184 fieldZero.Attach(std::move(field));
186 return std::move(fieldZero.ReleaseSubfields()[0]);
187}
188
190ROOT::Experimental::RNTupleSingleProcessor::AddFieldToEntry(const std::string &fieldName, const std::string &typeName,
191 void *valuePtr,
192 const Internal::RNTupleProcessorProvenance &provenance)
193{
194 auto fieldIdx = fEntry->FindFieldIndex(fieldName, typeName);
195 if (!fieldIdx) {
196 // Strip the processor name prefix(es), if present.
197 std::string qualifiedFieldName = fieldName;
198 if (provenance.IsPresentInFieldName(qualifiedFieldName)) {
199 qualifiedFieldName = qualifiedFieldName.substr(provenance.Get().size() + 1);
200 }
201
202 auto field = CreateAndConnectField(qualifiedFieldName, typeName);
203
204 if (!field) {
205 throw RException(R__FAIL("cannot register field with name \"" + qualifiedFieldName +
206 "\" because it is not present in the on-disk information of the RNTuple(s) this "
207 "processor is created from"));
208 }
209
210 fieldIdx = fEntry->AddField(qualifiedFieldName, std::move(field), valuePtr, provenance);
211 }
212
213 return *fieldIdx;
214}
215
217{
218 if (entryNumber >= fNEntries || !fEntry)
219 return kInvalidNTupleIndex;
220
221 for (auto fieldIdx : fFieldIdxs) {
222 fEntry->ReadValue(fieldIdx, entryNumber);
223 }
224
226 fCurrentEntryNumber = entryNumber;
227 return entryNumber;
228}
229
231 const std::unordered_set<ROOT::Experimental::Internal::RNTupleProcessorEntry::FieldIndex_t> &fieldIdxs,
232 const Internal::RNTupleProcessorProvenance & /* provenance */, bool updateFields)
233{
234 Initialize();
235
236 fFieldIdxs = fieldIdxs;
237
238 if (updateFields) {
239 for (const auto &fieldIdx : fFieldIdxs) {
240 const auto &currField = fEntry->GetValue(fieldIdx).GetField();
241 auto newField = CreateAndConnectField(fEntry->GetQualifiedFieldName(fieldIdx), currField.GetTypeName());
242
243 fEntry->UpdateField(fieldIdx, std::move(newField));
244 }
245 }
246}
247
254
256{
257 static constexpr int width = 32;
258
259 std::string ntupleNameTrunc = fNTupleSpec.fNTupleName.substr(0, width - 4);
260 if (ntupleNameTrunc.size() < fNTupleSpec.fNTupleName.size())
261 ntupleNameTrunc = fNTupleSpec.fNTupleName.substr(0, width - 6) + "..";
262
263 output << "+" << std::setfill('-') << std::setw(width - 1) << "+\n";
264 output << std::setfill(' ') << "| " << ntupleNameTrunc << std::setw(width - 2 - ntupleNameTrunc.size()) << " |\n";
265
266 if (const std::string *storage = std::get_if<std::string>(&fNTupleSpec.fStorage)) {
267 std::string storageTrunc = storage->substr(0, width - 5);
268 if (storageTrunc.size() < storage->size())
269 storageTrunc = storage->substr(0, width - 8) + "...";
270
271 output << std::setfill(' ') << "| " << storageTrunc << std::setw(width - 2 - storageTrunc.size()) << " |\n";
272 } else {
273 output << "| " << std::setw(width - 2) << " |\n";
274 }
275
276 output << "+" << std::setfill('-') << std::setw(width - 1) << "+\n";
277}
278
279//------------------------------------------------------------------------------
280
282 std::vector<std::unique_ptr<RNTupleProcessor>> processors, std::string_view processorName)
283 : RNTupleProcessor(processorName), fInnerProcessors(std::move(processors))
284{
285 if (fProcessorName.empty()) {
286 // `CreateChain` ensures there is at least one inner processor.
287 fProcessorName = fInnerProcessors[0]->GetProcessorName();
288 }
289
291}
292
294 std::shared_ptr<ROOT::Experimental::Internal::RNTupleProcessorEntry> entry)
295{
296 if (IsInitialized())
297 return;
298
299 if (!entry)
300 fEntry = std::make_shared<Internal::RNTupleProcessorEntry>();
301 else
302 fEntry = entry;
303
304 fInnerProcessors[0]->Initialize(fEntry);
305}
306
308{
310 fNEntries = 0;
311
312 for (unsigned i = 0; i < fInnerProcessors.size(); ++i) {
314 fInnerNEntries[i] = fInnerProcessors[i]->GetNEntries();
315 }
316
318 }
319 }
320
321 return fNEntries;
322}
323
325 const std::unordered_set<ROOT::Experimental::Internal::RNTupleProcessorEntry::FieldIndex_t> &fieldIdxs,
326 const Internal::RNTupleProcessorProvenance &provenance, bool /* updateFields */)
327{
328 Initialize();
329 fFieldIdxs = fieldIdxs;
330 fProvenance = provenance;
332}
333
335{
336 auto &innerProc = fInnerProcessors[processorNumber];
337 innerProc->Initialize(fEntry);
338 innerProc->Connect(fFieldIdxs, fProvenance, /*updateFields=*/true);
339}
340
342ROOT::Experimental::RNTupleChainProcessor::AddFieldToEntry(const std::string &fieldName, const std::string &typeName,
343 void *valuePtr,
344 const Internal::RNTupleProcessorProvenance &provenance)
345{
346 return fInnerProcessors[fCurrentProcessorNumber]->AddFieldToEntry(fieldName, typeName, valuePtr, provenance);
347}
348
350{
351 ROOT::NTupleSize_t localEntryNumber = entryNumber;
352 std::size_t currProcessorNumber = 0;
353 if (entryNumber < fCurrentEntryNumber) {
356 }
357
358 // As long as the entry fails to load from the current processor, we decrement the local entry number with the number
359 // of entries in this processor and try with the next processor until we find the correct local entry number.
360 while (fInnerProcessors[currProcessorNumber]->LoadEntry(localEntryNumber) == kInvalidNTupleIndex) {
361 if (fInnerNEntries[currProcessorNumber] == kInvalidNTupleIndex) {
362 fInnerNEntries[currProcessorNumber] = fInnerProcessors[currProcessorNumber]->GetNEntries();
363 }
364
365 localEntryNumber -= fInnerNEntries[currProcessorNumber];
366
367 // The provided global entry number is larger than the number of available entries.
368 if (++currProcessorNumber >= fInnerProcessors.size())
369 return kInvalidNTupleIndex;
370
371 ConnectInnerProcessor(currProcessorNumber);
372 }
373
374 fCurrentProcessorNumber = currProcessorNumber;
376 fCurrentEntryNumber = entryNumber;
377 return entryNumber;
378}
379
381 ROOT::NTupleSize_t entryOffset)
382{
383 for (unsigned i = 0; i < fInnerProcessors.size(); ++i) {
384 const auto &innerProc = fInnerProcessors[i];
385 // TODO can this be done (more) lazily? I.e. only when a match cannot be found in the current inner proc?
386 // At this stage, we don't want to fully initialize (i.e. set the entry of) the inner processor yet
387 innerProc->Initialize(nullptr);
388 innerProc->AddEntriesToJoinTable(joinTable, entryOffset);
389 entryOffset += innerProc->GetNEntries();
390 }
391}
392
394{
395 for (const auto &innerProc : fInnerProcessors) {
396 innerProc->PrintStructure(output);
397 }
398}
399
400//------------------------------------------------------------------------------
401
404private:
406 void GenerateColumns() final
407 {
408 throw RException(R__FAIL("RAuxiliaryProcessorField fields must only be used for reading"));
409 }
410
411public:
412 RAuxiliaryProcessorField(std::string_view fieldName, std::vector<std::unique_ptr<RFieldBase>> itemFields)
413 : ROOT::RRecordField(fieldName, "RAuxiliaryProcessorField")
414 {
415 AttachItemFields(std::move(itemFields));
416 }
417};
418} // namespace ROOT::Experimental::Internal
419
420ROOT::Experimental::RNTupleJoinProcessor::RNTupleJoinProcessor(std::unique_ptr<RNTupleProcessor> primaryProcessor,
421 std::unique_ptr<RNTupleProcessor> auxProcessor,
422 const std::vector<std::string> &joinFields,
423 std::string_view processorName)
424 : RNTupleProcessor(processorName),
425 fPrimaryProcessor(std::move(primaryProcessor)),
426 fAuxiliaryProcessor(std::move(auxProcessor)),
427 fJoinFieldNames(joinFields)
428{
429 if (fProcessorName.empty()) {
430 fProcessorName = fPrimaryProcessor->GetProcessorName();
431 }
432}
433
435 std::shared_ptr<ROOT::Experimental::Internal::RNTupleProcessorEntry> entry)
436{
437 if (IsInitialized())
438 return;
439
440 if (!entry)
441 fEntry = std::make_shared<Internal::RNTupleProcessorEntry>();
442 else
443 fEntry = entry;
444
445 fPrimaryProcessor->Initialize(fEntry);
446 fAuxiliaryProcessor->Initialize(fEntry);
447
448 if (!fJoinFieldNames.empty()) {
449 for (const auto &joinField : fJoinFieldNames) {
450 if (!fPrimaryProcessor->CanReadFieldFromDisk(joinField)) {
451 throw RException(R__FAIL("could not find join field \"" + joinField + "\" in primary processor \"" +
452 fPrimaryProcessor->GetProcessorName() + "\""));
453 }
454 if (!fAuxiliaryProcessor->CanReadFieldFromDisk(joinField)) {
455 throw RException(R__FAIL("could not find join field \"" + joinField + "\" in auxiliary processor \"" +
456 fAuxiliaryProcessor->GetProcessorName() + "\""));
457 }
458
459 // We prepend the name of the primary processor in this case to prevent reading from the wrong join field in
460 // composed join operations.
461 auto fieldIdx = AddFieldToEntry(fProcessorName + "._join." + joinField, "std::uint64_t", nullptr,
463 fJoinFieldIdxs.insert(fieldIdx);
464 }
465
467 }
468}
469
471 const std::unordered_set<ROOT::Experimental::Internal::RNTupleProcessorEntry::FieldIndex_t> &fieldIdxs,
472 const Internal::RNTupleProcessorProvenance &provenance, bool updateFields)
473{
474 Initialize();
475
476 auto auxProvenance = provenance.Evolve(fAuxiliaryProcessor->GetProcessorName());
477 for (const auto &fieldIdx : fieldIdxs) {
478 const auto &fieldProvenance = fEntry->GetFieldProvenance(fieldIdx);
479 if (fieldProvenance.Contains(auxProvenance))
480 fAuxiliaryFieldIdxs.insert(fieldIdx);
481 else
482 fFieldIdxs.insert(fieldIdx);
483 }
484
485 fPrimaryProcessor->Connect(fFieldIdxs, provenance, updateFields);
486 fAuxiliaryProcessor->Connect(fAuxiliaryFieldIdxs, auxProvenance, updateFields);
487}
488
490ROOT::Experimental::RNTupleJoinProcessor::AddFieldToEntry(const std::string &fieldName, const std::string &typeName,
491 void *valuePtr,
492 const Internal::RNTupleProcessorProvenance &provenance)
493{
494 auto auxProvenance = provenance.Evolve(fAuxiliaryProcessor->GetProcessorName());
495 if (auxProvenance.IsPresentInFieldName(fieldName)) {
496 // If the primaryProcessor has a field with the name of the auxProcessor (either as a "proper" field or because
497 // the primary processor itself is a join where its auxProcessor bears the same name as the current auxProcessor),
498 // there will be name conflicts, so error out.
499 if (fPrimaryProcessor->CanReadFieldFromDisk(fieldName)) {
500 throw RException(R__FAIL("ambiguous field name: \"" + fieldName +
501 "\" is present in the primary RNTupleProcessor \"" +
502 fPrimaryProcessor->GetProcessorName() +
503 "\", but may also refer to a field in the auxiliary RNTupleProcessor named \"" +
504 fAuxiliaryProcessor->GetProcessorName() +
505 "\". To avoid this ambiguity, rename the auxiliary RNTupleProcessor."));
506 }
507
508 auto fieldIdx = fAuxiliaryProcessor->AddFieldToEntry(fieldName, typeName, valuePtr, auxProvenance);
509 if (fieldIdx)
510 fAuxiliaryFieldIdxs.insert(fieldIdx);
511 return fieldIdx;
512 } else {
513 auto fieldIdx = fPrimaryProcessor->AddFieldToEntry(fieldName, typeName, valuePtr, provenance);
514 if (fieldIdx)
515 fFieldIdxs.insert(fieldIdx);
516 return fieldIdx;
517 }
518}
519
521{
522 for (const auto &fieldIdx : fAuxiliaryFieldIdxs) {
523 fEntry->SetFieldValidity(fieldIdx, isValid);
524 }
525}
526
528{
529 if (fPrimaryProcessor->LoadEntry(entryNumber) == kInvalidNTupleIndex) {
530 for (auto fieldIdx : fFieldIdxs) {
531 fEntry->SetFieldValidity(fieldIdx, false);
532 }
534 return kInvalidNTupleIndex;
535 }
536
537 fCurrentEntryNumber = entryNumber;
539
540 if (!fJoinTable) {
541 // The auxiliary processor's fields are valid if the entry could be loaded.
542 fAuxiliaryProcessor->LoadEntry(entryNumber);
543 return entryNumber;
544 }
545
546 if (!fJoinTableIsBuilt) {
547 fAuxiliaryProcessor->AddEntriesToJoinTable(*fJoinTable);
548 fJoinTableIsBuilt = true;
549 }
550
551 // Collect the values of the join fields for this entry.
552 std::vector<void *> valPtrs;
553 valPtrs.reserve(fJoinFieldIdxs.size());
554 for (const auto &fieldIdx : fJoinFieldIdxs) {
555 auto ptr = fEntry->GetValue(fieldIdx).GetPtr<void>();
556 valPtrs.push_back(ptr.get());
557 }
558
559 // Find the entry index corresponding to the join field values for each auxiliary processor and load the
560 // corresponding entry.
561 const auto entryIdx = fJoinTable->GetEntryIndex(valPtrs);
562
563 if (entryIdx == kInvalidNTupleIndex) {
565 } else {
567 for (const auto &fieldIdx : fAuxiliaryFieldIdxs) {
568 fEntry->ReadValue(fieldIdx, entryIdx);
569 }
570 }
571
572 return entryNumber;
573}
574
581
583 ROOT::NTupleSize_t entryOffset)
584{
585 fPrimaryProcessor->AddEntriesToJoinTable(joinTable, entryOffset);
586}
587
589{
590 std::ostringstream primaryStructureStr;
591 fPrimaryProcessor->PrintStructure(primaryStructureStr);
592 const auto primaryStructure = ROOT::Split(primaryStructureStr.str(), "\n", /*skipEmpty=*/true);
593 const auto primaryStructureWidth = primaryStructure.front().size();
594
595 std::ostringstream auxStructureStr;
596 fAuxiliaryProcessor->PrintStructure(auxStructureStr);
597 const auto auxStructure = ROOT::Split(auxStructureStr.str(), "\n", /*skipEmpty=*/true);
598
599 const auto maxLength = std::max(primaryStructure.size(), auxStructure.size());
600 for (unsigned i = 0; i < maxLength; i++) {
601 if (i < primaryStructure.size())
602 output << primaryStructure[i];
603 else
604 output << std::setw(primaryStructureWidth) << "";
605
606 if (i < auxStructure.size())
607 output << " " << auxStructure[i];
608
609 output << "\n";
610 }
611}
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition RError.hxx:300
Option_t Option_t width
RAuxiliaryProcessorField(std::string_view fieldName, std::vector< std::unique_ptr< RFieldBase > > itemFields)
void GenerateColumns() final
Implementations in derived classes should create the backing columns corresponding to the field type ...
Builds a join table on one or several fields of an RNTuple so it can be joined onto other RNTuples.
static std::unique_ptr< RNTupleJoinTable > Create(const std::vector< std::string > &joinFieldNames)
Create an RNTupleJoinTable from an existing RNTuple.
RNTupleJoinTable & Add(ROOT::Internal::RPageSource &pageSource, PartitionKey_t partitionKey=kDefaultPartitionKey, ROOT::NTupleSize_t entryOffset=0)
Add an entry mapping to the join table.
static constexpr PartitionKey_t kDefaultPartitionKey
std::string Get() const
Get the full processor provenance, in the form of "x.y.z".
bool IsPresentInFieldName(std::string_view fieldName) const
Check whether the provided field name contains this provenance.
RNTupleProcessorProvenance Evolve(const std::string &processorName) const
Add a new processor to the provenance.
void PrintStructureImpl(std::ostream &output) const final
Processor-specific implementation for printing its structure, called by PrintStructure().
void AddEntriesToJoinTable(Internal::RNTupleJoinTable &joinTable, ROOT::NTupleSize_t entryOffset=0) final
Add the entry mappings for this processor to the provided join table.
void ConnectInnerProcessor(std::size_t processorNumber)
Update the entry to reflect any missing fields in the current inner processor.
Internal::RNTupleProcessorEntry::FieldIndex_t AddFieldToEntry(const std::string &fieldName, const std::string &typeName, void *valuePtr=nullptr, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance()) final
Add a field to the entry.
Internal::RNTupleProcessorProvenance fProvenance
ROOT::NTupleSize_t GetNEntries() final
Get the total number of entries in this processor.
void Initialize(std::shared_ptr< Internal::RNTupleProcessorEntry > entry=nullptr) final
Initialize the processor by creating an (initially empty) fEntry, or setting an existing one.
std::vector< ROOT::NTupleSize_t > fInnerNEntries
void Connect(const std::unordered_set< Internal::RNTupleProcessorEntry::FieldIndex_t > &fieldIdxs, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance(), bool updateFields=false) final
Connect the provided fields indices in the entry to their on-disk fields.
ROOT::NTupleSize_t LoadEntry(ROOT::NTupleSize_t entryNumber) final
Load the entry identified by the provided (global) entry number (i.e., considering all RNTuples in th...
std::vector< std::unique_ptr< RNTupleProcessor > > fInnerProcessors
std::set< Internal::RNTupleProcessorEntry::FieldIndex_t > fJoinFieldIdxs
std::unordered_set< Internal::RNTupleProcessorEntry::FieldIndex_t > fAuxiliaryFieldIdxs
void PrintStructureImpl(std::ostream &output) const final
Processor-specific implementation for printing its structure, called by PrintStructure().
ROOT::NTupleSize_t LoadEntry(ROOT::NTupleSize_t entryNumber) final
Load the entry identified by the provided entry number of the primary processor.
void AddEntriesToJoinTable(Internal::RNTupleJoinTable &joinTable, ROOT::NTupleSize_t entryOffset=0) final
Add the entry mappings for this processor to the provided join table.
ROOT::NTupleSize_t GetNEntries() final
Get the total number of entries in this processor.
void SetAuxiliaryFieldValidity(bool validity)
Set the validity for all fields in the auxiliary processor at once.
void Connect(const std::unordered_set< Internal::RNTupleProcessorEntry::FieldIndex_t > &fieldIdxs, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance(), bool updateFields=false) final
Connect the provided fields indices in the entry to their on-disk fields.
std::unique_ptr< RNTupleProcessor > fPrimaryProcessor
void Initialize(std::shared_ptr< Internal::RNTupleProcessorEntry > entry=nullptr) final
Initialize the processor by creating an (initially empty) fEntry, or setting an existing one.
std::unique_ptr< Internal::RNTupleJoinTable > fJoinTable
std::unique_ptr< RNTupleProcessor > fAuxiliaryProcessor
Internal::RNTupleProcessorEntry::FieldIndex_t AddFieldToEntry(const std::string &fieldName, const std::string &typeName, void *valuePtr=nullptr, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance()) final
Add a field to the entry.
Specification of the name and location of an RNTuple, used for creating a new RNTupleProcessor.
std::variant< std::string, TDirectory * > fStorage
std::unique_ptr< ROOT::Internal::RPageSource > CreatePageSource() const
static std::unique_ptr< RNTupleProcessor > CreateJoin(RNTupleOpenSpec primaryNTuple, RNTupleOpenSpec auxNTuple, const std::vector< std::string > &joinFields, std::string_view processorName="")
Create an RNTupleProcessor for a join (i.e., a horizontal combination) of RNTuples.
ROOT::NTupleSize_t fNEntries
Total number of entries.
static std::unique_ptr< RNTupleProcessor > CreateChain(std::vector< RNTupleOpenSpec > ntuples, std::string_view processorName="")
Create an RNTupleProcessor for a chain (i.e., a vertical combination) of RNTuples.
std::shared_ptr< Internal::RNTupleProcessorEntry > fEntry
std::unordered_set< Internal::RNTupleProcessorEntry::FieldIndex_t > fFieldIdxs
bool IsInitialized() const
Check if the processor already has been initialized.
static std::unique_ptr< RNTupleProcessor > Create(RNTupleOpenSpec ntuple, std::string_view processorName="")
Create an RNTupleProcessor for a single RNTuple.
void AddEntriesToJoinTable(Internal::RNTupleJoinTable &joinTable, ROOT::NTupleSize_t entryOffset=0) final
Add the entry mappings for this processor to the provided join table.
void Connect(const std::unordered_set< Internal::RNTupleProcessorEntry::FieldIndex_t > &fieldIdxs, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance(), bool updateFields=false) final
Connect the provided fields indices in the entry to their on-disk fields.
void Initialize(std::shared_ptr< Internal::RNTupleProcessorEntry > entry=nullptr) final
Initialize the processor by creating an (initially empty) fEntry, or setting an existing one.
void PrintStructureImpl(std::ostream &output) const final
Processor-specific implementation for printing its structure, called by PrintStructure().
std::unique_ptr< ROOT::Internal::RPageSource > fPageSource
bool CanReadFieldFromDisk(std::string_view fieldName) final
Check if a field exists on-disk and can be read by the processor.
ROOT::NTupleSize_t LoadEntry(ROOT::NTupleSize_t entryNumber) final
Load the entry identified by the provided (global) entry number (i.e., considering all RNTuples in th...
Internal::RNTupleProcessorEntry::FieldIndex_t AddFieldToEntry(const std::string &fieldName, const std::string &typeName, void *valuePtr=nullptr, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance()) final
Add a field to the entry.
std::unique_ptr< ROOT::RFieldBase > CreateAndConnectField(const std::string &qualifiedFieldName, const std::string &typeName)
Create a new field and connect it to the processor's page source.
static std::unique_ptr< RPageSourceFile > CreateFromAnchor(const RNTuple &anchor, const ROOT::RNTupleReadOptions &options=ROOT::RNTupleReadOptions())
Used from the RNTuple class to build a datasource if the anchor is already available.
static std::unique_ptr< RPageSource > Create(std::string_view ntupleName, std::string_view location, const ROOT::RNTupleReadOptions &options=ROOT::RNTupleReadOptions())
Guess the concrete derived page source from the file name (location)
Base class for all ROOT issued exceptions.
Definition RError.hxx:79
virtual void GenerateColumns()
Implementations in derived classes should create the backing columns corresponding to the field type ...
static RResult< std::unique_ptr< RFieldBase > > Create(const std::string &fieldName, const std::string &typeName, const ROOT::RCreateFieldOptions &options, const ROOT::RNTupleDescriptor *desc, ROOT::DescriptorId_t fieldId)
Factory method to resurrect a field from the stored on-disk type information.
The container field for an ntuple model, which itself has no physical representation.
Definition RField.hxx:59
std::vector< std::unique_ptr< RFieldBase > > ReleaseSubfields()
Moves all subfields into the returned vector.
Definition RField.cxx:65
void Attach(std::unique_ptr< RFieldBase > child)
A public version of the Attach method that allows piece-wise construction of the zero field.
Definition RField.cxx:41
Representation of an RNTuple data set in a ROOT file.
Definition RNTuple.hxx:68
The field for an untyped record.
RRecordField(std::string_view name, const RRecordField &source)
Definition RField.cxx:573
void AttachItemFields(ContainerT &&itemFields)
void SetAllowFieldSubstitutions(RFieldZero &fieldZero, bool val)
Definition RField.cxx:36
void CallConnectPageSourceOnField(RFieldBase &, ROOT::Internal::RPageSource &)
constexpr NTupleSize_t kInvalidNTupleIndex
std::vector< std::string > Split(std::string_view str, std::string_view delims, bool skipEmpty=false)
Splits a string at each character in delims.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
constexpr DescriptorId_t kInvalidDescriptorId