Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleJoinTable.cxx
Go to the documentation of this file.
1/// \file RNTupleJoinTable.cxx
2/// \author Florine de Geus <florine.de.geus@cern.ch>
3/// \date 2024-04-02
4/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
5/// is welcome!
6
7/*************************************************************************
8 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. *
9 * All rights reserved. *
10 * *
11 * For the licensing terms see $ROOTSYS/LICENSE. *
12 * For the list of contributors see $ROOTSYS/README/CREDITS. *
13 *************************************************************************/
14
16
18 ROOT::Internal::RPageSource &pageSource, const std::vector<std::string> &joinFieldNames,
19 ROOT::NTupleSize_t entryOffset)
20 : fJoinFieldNames(joinFieldNames)
21{
22 static const std::unordered_set<std::string> allowedTypes = {"std::int8_t", "std::int16_t", "std::int32_t",
23 "std::int64_t", "std::uint8_t", "std::uint16_t",
24 "std::uint32_t", "std::uint64_t"};
25
26 pageSource.Attach();
27 std::vector<std::unique_ptr<ROOT::RFieldBase>> fields;
28 std::vector<ROOT::RFieldBase::RValue> fieldValues;
29 fieldValues.reserve(fJoinFieldNames.size());
30 {
31 auto descGuard = pageSource.GetSharedDescriptorGuard();
32
33 for (const auto &fieldName : fJoinFieldNames) {
34 auto fieldId = descGuard->FindFieldId(fieldName);
35 if (fieldId == ROOT::kInvalidDescriptorId) {
36 throw RException(R__FAIL("could not find join field \"" + std::string(fieldName) + "\" in RNTuple \"" +
37 descGuard->GetName() + "\""));
38 }
39
40 const auto &fieldDesc = descGuard->GetFieldDescriptor(fieldId);
41
42 if (allowedTypes.find(fieldDesc.GetTypeName()) == allowedTypes.end()) {
43 throw RException(R__FAIL("cannot use field \"" + fieldName + "\" with type \"" + fieldDesc.GetTypeName() +
44 "\" in join table: only integral types are allowed"));
45 }
46
47 auto field = std::make_unique<ROOT::RField<JoinValue_t>>(fieldDesc.GetFieldName());
48 field->SetOnDiskId(fieldDesc.GetId());
49
50 fieldValues.emplace_back(field->CreateValue());
51 fJoinFieldValueSizes.emplace_back(field->GetValueSize());
52 fields.emplace_back(std::move(field));
53 }
54 } // descGuard
55 for (auto &f : fields) {
57 }
58
59 std::vector<JoinValue_t> castJoinValues;
60 castJoinValues.reserve(fJoinFieldNames.size());
61
62 for (unsigned i = 0; i < pageSource.GetNEntries(); ++i) {
63 castJoinValues.clear();
64
65 for (auto &fieldValue : fieldValues) {
66 // TODO(fdegeus): use bulk reading
67 fieldValue.Read(i);
68 castJoinValues.push_back(fieldValue.GetRef<JoinValue_t>());
69 }
70
71 fMapping[RCombinedJoinFieldValue(castJoinValues)].push_back(i + entryOffset);
72 }
73}
74
75const std::vector<ROOT::NTupleSize_t> *ROOT ::Experimental::Internal::RNTupleJoinTable::REntryMapping::GetEntryIndexes(
76 const std::vector<JoinValue_t> &joinValues) const
77{
78 if (joinValues.size() != fJoinFieldNames.size())
79 throw RException(R__FAIL("number of value pointers must match number of join fields"));
80
81 if (const auto &entries = fMapping.find(RCombinedJoinFieldValue(joinValues)); entries != fMapping.end()) {
82 return &entries->second;
83 }
84
85 return nullptr;
86}
87
88//------------------------------------------------------------------------------
89
90std::unique_ptr<ROOT::Experimental::Internal::RNTupleJoinTable>
91ROOT::Experimental::Internal::RNTupleJoinTable::Create(const std::vector<std::string> &fieldNames)
92{
93 return std::unique_ptr<RNTupleJoinTable>(new RNTupleJoinTable(fieldNames));
94}
95
98 PartitionKey_t partitionKey, ROOT::NTupleSize_t entryOffset)
99{
100 auto joinMapping = std::unique_ptr<REntryMapping>(new REntryMapping(pageSource, fJoinFieldNames, entryOffset));
101 fPartitions[partitionKey].emplace_back(std::move(joinMapping));
102
103 return *this;
104}
105
107ROOT::Experimental::Internal::RNTupleJoinTable::GetEntryIndex(const std::vector<JoinValue_t> &joinValues) const
108{
109 for (const auto &partition : fPartitions) {
110 for (const auto &joinMapping : partition.second) {
111 auto entriesForMapping = joinMapping->GetEntryIndexes(joinValues);
112 if (entriesForMapping) {
113 return (*entriesForMapping)[0];
114 }
115 }
116 }
117
118 return kInvalidNTupleIndex;
119}
#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:322
#define f(i)
Definition RSha256.hxx:104
Provides a mapping from one or several join field values to an entry index.
REntryMapping(ROOT::Internal::RPageSource &pageSource, const std::vector< std::string > &joinFieldNames, ROOT::NTupleSize_t entryOffset=0)
Create a new entry mapping.
std::vector< std::size_t > fJoinFieldValueSizes
The size (in bytes) for each join field, corresponding to fJoinFieldNames.
std::vector< std::string > fJoinFieldNames
Names of the join fields used for the mapping to their respective entry indexes.
std::unordered_map< RCombinedJoinFieldValue, std::vector< ROOT::NTupleSize_t >, RCombinedJoinFieldValueHash > fMapping
The mapping itself.
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.
std::vector< std::string > fJoinFieldNames
Names of the join fields used for the mapping to their respective entry indexes.
ROOT::NTupleSize_t GetEntryIndex(const std::vector< JoinValue_t > &joinValues) const
Get an entry index (if it exists) for the given join field value(s), from any partition.
RNTupleJoinTable & Add(ROOT::Internal::RPageSource &pageSource, PartitionKey_t partitionKey=kDefaultPartitionKey, ROOT::NTupleSize_t entryOffset=0)
Add an entry mapping to the join table.
RNTupleJoinTable(const std::vector< std::string > &joinFieldNames)
Create an a new RNTupleJoinTable for the RNTuple represented by the provided page source.
std::unordered_map< PartitionKey_t, std::vector< std::unique_ptr< REntryMapping > > > fPartitions
Partitions of one or multiple entry mappings.
Abstract interface to read data from an ntuple.
void Attach(ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode mode=ROOT::Internal::RNTupleSerializer::EDescriptorDeserializeMode::kForReading)
Open the physical storage container and deserialize header and footer.
ROOT::NTupleSize_t GetNEntries()
RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
ROOT::DescriptorId_t FindFieldId(std::string_view fieldName, ROOT::DescriptorId_t parentId) const
void CallConnectPageSourceOnField(RFieldBase &, ROOT::Internal::RPageSource &)
constexpr NTupleSize_t kInvalidNTupleIndex
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
constexpr DescriptorId_t kInvalidDescriptorId