Project
Loading...
Searching...
No Matches
ASoA.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#ifndef O2_FRAMEWORK_ASOA_H_
13#define O2_FRAMEWORK_ASOA_H_
14
15#if defined(__CLING__)
16#error "Please do not include this file in ROOT dictionary generation"
17#endif
18#include "Framework/Concepts.h"
20#include "Framework/Pack.h" // IWYU pragma: export
21#include "Framework/FunctionalHelpers.h" // IWYU pragma: export
22#include "Headers/DataHeader.h" // IWYU pragma: export
23#include "Headers/DataHeaderHelpers.h" // IWYU pragma: export
24#include "Framework/CompilerBuiltins.h" // IWYU pragma: export
25#include "Framework/Traits.h" // IWYU pragma: export
26#include "Framework/Expressions.h" // IWYU pragma: export
27#include "Framework/ArrowTypes.h" // IWYU pragma: export
28#include "Framework/ArrowTableSlicingCache.h" // IWYU pragma: export
29#include "Framework/SliceCache.h" // IWYU pragma: export
30#include "Framework/VariantHelpers.h" // IWYU pragma: export
31#include <fairmq/Version.h>
32#include <arrow/array/array_binary.h>
33#include <arrow/table.h> // IWYU pragma: export
34#include <arrow/array.h> // IWYU pragma: export
35#include <arrow/util/config.h> // IWYU pragma: export
36#include <gandiva/selection_vector.h> // IWYU pragma: export
37#include <array> // IWYU pragma: export
38#include <cassert>
39#include <fmt/format.h>
40#include <concepts>
41#include <cstring>
42#include <gsl/span> // IWYU pragma: export
43
45{
46struct MetaHeader;
47}
48
49namespace o2::framework
50{
51using ListVector = std::vector<std::vector<int64_t>>;
52using PointerReconstructor = std::function<std::byte*(fair::mq::shmem::MetaHeader&&)>;
53
54std::string cutString(std::string&& str);
55std::string strToUpper(std::string&& str);
56} // namespace o2::framework
57
58struct TClass;
59
60namespace o2::soa
61{
62void accessingInvalidIndexFor(const char* getter);
63void dereferenceWithWrongType(const char* getter, const char* target);
64void missingFilterDeclaration(int hash, int ai);
65void notBoundTable(const char* tableName);
66void* extractCCDBPayload(char* payload, size_t size, TClass const* cl, const char* what);
67
68// ASCII-only lowercase. Column labels are plain identifiers, so we deliberately
69// avoid the locale-aware std::tolower: it goes through the C locale facet on
70// every character and dominated getIndexFromLabel in profiles.
71constexpr inline char asciiToLower(char c)
72{
73 return (c >= 'A' && c <= 'Z') ? static_cast<char>(c + 32) : c;
74}
75
76template <typename... C>
78{
79 return std::vector<std::shared_ptr<arrow::Field>>{C::asArrowField()...};
80}
81} // namespace o2::soa
82
83namespace o2::soa
84{
86struct TableRef {
87 consteval TableRef()
88 : label_hash{0},
89 desc_hash{0},
90 origin_hash{0},
91 version{0}
92 {
93 }
94 consteval TableRef(uint32_t _label, uint32_t _desc, uint32_t _origin, uint32_t _version)
95 : label_hash{_label},
96 desc_hash{_desc},
97 origin_hash{_origin},
98 version{_version}
99 {
100 }
101 uint32_t label_hash;
102 uint32_t desc_hash;
103 uint32_t origin_hash;
104 uint32_t version;
105
106 constexpr bool operator==(TableRef const& other) const noexcept
107 {
108 return (this->label_hash == other.label_hash) &&
109 (this->desc_hash == other.desc_hash) &&
110 (this->origin_hash == other.origin_hash) &&
111 (this->version == other.version);
112 }
113
114 constexpr bool descriptionCompatible(TableRef const& other) const noexcept
115 {
116 return this->desc_hash == other.desc_hash;
117 }
118
119 constexpr bool descriptionCompatible(uint32_t _desc_hash) const noexcept
120 {
121 return this->desc_hash == _desc_hash;
122 }
123
124 constexpr TableRef(TableRef const&) = default;
125 constexpr TableRef& operator=(TableRef const&) = default;
126 constexpr TableRef(TableRef&&) = default;
127 constexpr TableRef& operator=(TableRef&&) = default;
128};
129
131template <size_t N1, size_t N2, std::array<TableRef, N1> ar1, std::array<TableRef, N2> ar2>
132consteval auto merge()
133{
134 constexpr const int duplicates = std::ranges::count_if(ar2.begin(), ar2.end(), [&](TableRef const& a) { return std::any_of(ar1.begin(), ar1.end(), [&](TableRef const& e) { return e == a; }); });
135 std::array<TableRef, N1 + N2 - duplicates> out;
136
137 auto pos = std::copy(ar1.begin(), ar1.end(), out.begin());
138 std::copy_if(ar2.begin(), ar2.end(), pos, [&](TableRef const& a) { return std::none_of(ar1.begin(), ar1.end(), [&](TableRef const& e) { return e == a; }); });
139 return out;
140}
141
142template <size_t N1, size_t N2, std::array<TableRef, N1> ar1, std::array<TableRef, N2> ar2, typename L>
143consteval auto merge_if(L l)
144{
145 constexpr const int to_remove = std::ranges::count_if(ar1.begin(), ar1.end(), [&](TableRef const& a) { return !l(a); });
146 constexpr const int duplicates = std::ranges::count_if(ar2.begin(), ar2.end(), [&](TableRef const& a) { return std::any_of(ar1.begin(), ar1.end(), [&](TableRef const& e) { return e == a; }) || !l(a); });
147 std::array<TableRef, N1 + N2 - duplicates - to_remove> out;
148
149 auto pos = std::copy_if(ar1.begin(), ar1.end(), out.begin(), [&](TableRef const& a) { return l(a); });
150 std::copy_if(ar2.begin(), ar2.end(), pos, [&](TableRef const& a) { return std::none_of(ar1.begin(), ar1.end(), [&](TableRef const& e) { return e == a; }) && l(a); });
151 return out;
152}
153
154template <size_t N, std::array<TableRef, N> ar, typename L>
155consteval auto remove_if(L l)
156{
157 constexpr const int to_remove = std::ranges::count_if(ar.begin(), ar.end(), [&l](TableRef const& e) { return l(e); });
158 std::array<TableRef, N - to_remove> out;
159 std::copy_if(ar.begin(), ar.end(), out.begin(), [&l](TableRef const& e) { return !l(e); });
160 return out;
161}
162
163template <size_t N1, size_t N2, std::array<TableRef, N1> ar1, std::array<TableRef, N2> ar2>
164consteval auto intersect()
165{
166 constexpr const int duplicates = std::ranges::count_if(ar2.begin(), ar2.end(), [&](TableRef const& a) { return std::any_of(ar1.begin(), ar1.end(), [&](TableRef const& e) { return e == a; }); });
167 std::array<TableRef, duplicates> out;
168 std::copy_if(ar1.begin(), ar1.end(), out.begin(), [](TableRef const& a) { return std::find(ar2.begin(), ar2.end(), a) != ar2.end(); });
169 return out;
170}
171
172template <typename T, typename... Ts>
173consteval auto mergeOriginals()
174 requires(sizeof...(Ts) == 1)
175{
177 return merge<T::originals.size(), T1::originals.size(), T::originals, T1::originals>();
178}
179
180template <typename T, typename... Ts>
181consteval auto mergeOriginals()
182 requires(sizeof...(Ts) > 1)
183{
184 constexpr auto tail = mergeOriginals<Ts...>();
185 return merge<T::originals.size(), tail.size(), T::originals, tail>();
186}
187
188template <typename T, typename... Ts>
189 requires(sizeof...(Ts) == 1)
190consteval auto intersectOriginals()
191{
193 return intersect<T::originals.size(), T1::originals.size(), T::originals, T1::originals>();
194}
195
196template <typename T, typename... Ts>
197 requires(sizeof...(Ts) > 1)
198consteval auto intersectOriginals()
199{
200 constexpr auto tail = intersectOriginals<Ts...>();
201 return intersect<T::originals.size(), tail.size(), T::originals, tail>();
202}
203} // namespace o2::soa
204
205namespace o2::soa
206{
208template <typename C>
210
211template <typename C>
212using is_persistent_column_t = std::conditional_t<is_persistent_column<C>, std::true_type, std::false_type>;
213
214template <typename C>
215using is_external_index_t = typename std::conditional_t<is_index_column<C>, std::true_type, std::false_type>;
216
217template <typename C>
218using is_self_index_t = typename std::conditional_t<is_self_index_column<C>, std::true_type, std::false_type>;
219} // namespace o2::soa
220
221namespace o2::aod
222{
223namespace
224{
225template <typename Key, size_t N, std::array<bool, N> map>
226static consteval int getIndexPosToKey_impl()
227{
228 constexpr const auto pos = std::find(map.begin(), map.end(), true);
229 if constexpr (pos != map.end()) {
230 return std::distance(map.begin(), pos);
231 } else {
232 return -1;
233 }
234}
235} // namespace
236
238template <typename D, typename... Cs>
240 static constexpr void isTableMetadata() {};
241 using columns = framework::pack<Cs...>;
245
246 template <typename Key, typename... PCs>
247 static consteval std::array<bool, sizeof...(PCs)> getMap(framework::pack<PCs...>)
248 {
249 return std::array<bool, sizeof...(PCs)>{[]() {
250 if constexpr (requires { PCs::index_targets.size(); }) {
251 return Key::template isIndexTargetOf<PCs::index_targets.size(), PCs::index_targets>();
252 } else {
253 return false;
254 }
255 }()...};
256 }
257
258 template <typename Key>
259 static consteval int getIndexPosToKey()
260 {
261 return getIndexPosToKey_impl<Key, framework::pack_size(persistent_columns_t{}), getMap<Key>(persistent_columns_t{})>();
262 }
263
264 static std::shared_ptr<arrow::Schema> getSchema()
265 {
266 return std::make_shared<arrow::Schema>([]<typename... C>(framework::pack<C...>&& p) { return o2::soa::createFieldsFromColumns(p); }(persistent_columns_t{}));
267 }
268};
269
270template <typename D>
272 static constexpr void isMetadataTrait() {};
273 using metadata = void;
274};
275
278template <uint32_t H>
279struct Hash {
280 static constexpr void isHash() {};
281 static constexpr uint32_t hash = H;
282 static constexpr char const* const str{""};
283};
284
286template <size_t N, std::array<soa::TableRef, N> ar, typename Key>
287consteval auto filterForKey()
288{
289 constexpr std::array<bool, N> test = []<size_t... Is>(std::index_sequence<Is...>) {
290 return std::array<bool, N>{(Key::template hasOriginal<ar[Is]>() || (o2::aod::MetadataTrait<o2::aod::Hash<ar[Is].desc_hash>>::metadata::template getIndexPosToKey<Key>() >= 0))...};
291 }(std::make_index_sequence<N>());
292 constexpr int correct = std::ranges::count(test.begin(), test.end(), true);
293 std::array<soa::TableRef, correct> out;
294 std::ranges::copy_if(ar.begin(), ar.end(), out.begin(), [&test](soa::TableRef const& r) { return test[std::distance(ar.begin(), std::find(ar.begin(), ar.end(), r))]; });
295 return out;
296}
297
299#define O2HASH(_Str_) \
300 template <> \
301 struct Hash<_Str_ ""_h> { \
302 static constexpr void isHash() {}; \
303 static constexpr uint32_t hash = _Str_ ""_h; \
304 static constexpr char const* const str{_Str_}; \
305 };
306
308#define O2ORIGIN(_Str_) \
309 template <> \
310 struct Hash<_Str_ ""_h> { \
311 static constexpr void isHash() {}; \
312 static constexpr void isOriginHash() {}; \
313 static constexpr header::DataOrigin origin{_Str_}; \
314 static constexpr uint32_t hash = _Str_ ""_h; \
315 static constexpr char const* const str{_Str_}; \
316 };
317
319static inline constexpr uint32_t version(const char* const str)
320{
321 if (str[0] == '\0') {
322 return 0;
323 }
324 size_t len = 0;
325 uint32_t res = 0;
326 while (str[len] != '/' && str[len] != '\0') {
327 ++len;
328 }
329 if (str[len - 1] == '\0') {
330 return -1;
331 }
332 for (auto i = len + 1; str[i] != '\0'; ++i) {
333 res = res * 10 + (int)(str[i] - '0');
334 }
335 return res;
336}
337
339static inline constexpr std::string_view description_str(const char* const str)
340{
341 size_t len = 0;
342 while (len < 15 && str[len] != '/') {
343 ++len;
344 }
345 return std::string_view{str, len};
346}
347
348static inline constexpr header::DataDescription description(const char* const str)
349{
350 size_t len = 0;
351 while (len < 15 && str[len] != '/') {
352 ++len;
353 }
354 char out[16];
355 for (auto i = 0; i < 16; ++i) {
356 out[i] = 0;
357 }
358 std::memcpy(out, str, len);
359 return {out};
360}
361
362// Helpers to get strings from TableRef
363template <soa::TableRef R>
364consteval const char* label()
365{
366 return o2::aod::Hash<R.label_hash>::str;
367}
368
369template <soa::TableRef R>
370consteval const char* origin_str()
371{
372 return o2::aod::Hash<R.origin_hash>::str;
373}
374
375template <soa::TableRef R>
377{
378 return o2::aod::Hash<R.origin_hash>::origin;
379}
380
381template <soa::TableRef R>
382consteval const char* signature()
383{
384 return o2::aod::Hash<R.desc_hash>::str;
385}
386
387template <soa::TableRef R>
389{
390 return {origin<R>(), description(signature<R>()), R.version};
391}
392
394template <soa::TableRef R>
395static constexpr auto sourceSpec()
396{
397 return fmt::format("{}/{}/{}/{}", label<R>(), origin_str<R>(), description_str(signature<R>()), R.version);
398}
399
401template <size_t N, std::array<soa::TableRef, N> ar, o2::aod::is_origin_hash O>
402consteval auto replaceOrigin()
403{
404 std::array<soa::TableRef, N> res;
405 for (auto i = 0U; i < N; ++i) {
406 res[i].label_hash = ar[i].label_hash;
407 res[i].desc_hash = ar[i].desc_hash;
408 res[i].origin_hash = O::hash;
409 res[i].version = ar[i].version;
410 }
411 return res;
412}
413} // namespace o2::aod
414
415namespace o2::soa
416{
417template <aod::is_aod_hash L, aod::is_aod_hash D, aod::is_origin_hash O, typename... Ts>
418class Table;
419
421struct Binding {
422 void const* ptr = nullptr;
423 uint32_t hash = 0;
424 // std::span<TableRef const> refs;
425
426 template <typename T>
427 void bind(T const* table)
428 {
429 ptr = table;
430 hash = o2::framework::TypeIdHelpers::uniqueId<T>();
431 // refs = std::span{T::originals};
432 }
433
434 template <typename T>
435 T const* get() const
436 {
437 if (hash == o2::framework::TypeIdHelpers::uniqueId<T>()) {
438 return static_cast<T const*>(ptr);
439 }
440 return nullptr;
441 }
442};
443
444using SelectionVector = std::vector<int64_t>;
445
446template <typename B, typename E>
448 constexpr static bool value = false;
449};
450
451template <aod::is_aod_hash A, aod::is_aod_hash B>
453 constexpr static bool value = false;
454};
455
456template <typename B, typename E>
458
459template <aod::is_aod_hash A, aod::is_aod_hash B>
461
465struct Chunked {
466 constexpr static bool chunked = true;
467};
468
471struct Flat {
472 constexpr static bool chunked = false;
473};
474
476template <typename T>
477struct unwrap {
478 using type = T;
479};
480
481template <typename T>
482struct unwrap<std::vector<T>> {
483 using type = T;
484};
485
486template <>
487struct unwrap<bool> {
488 using type = char;
489};
490
491template <typename T>
492using unwrap_t = typename unwrap<T>::type;
493
498template <typename T, typename ChunkingPolicy = Chunked>
499class ColumnIterator : ChunkingPolicy
500{
501 static constexpr char SCALE_FACTOR = std::same_as<std::decay_t<T>, bool> ? 3 : 0;
502
503 public:
508 ColumnIterator(arrow::ChunkedArray const* column)
509 : mColumn{column},
510 mCurrent{nullptr},
511 mCurrentPos{nullptr},
512 mGlobalOffset{nullptr},
513 mLast{nullptr},
514 mFirstIndex{0},
516 {
517 auto array = getCurrentArray();
518 mCurrent = reinterpret_cast<unwrap_t<T> const*>(array->values()->data());
519 mLast = mCurrent + array->length();
520 }
521
522 ColumnIterator() = default;
525
528
530 void nextChunk() const
531 {
532 auto previousArray = getCurrentArray();
533 mFirstIndex += previousArray->length();
535 auto array = getCurrentArray();
536 mCurrent = reinterpret_cast<unwrap_t<T> const*>(array->values()->data()) - (mFirstIndex >> SCALE_FACTOR);
537 mLast = mCurrent + array->length() + (mFirstIndex >> SCALE_FACTOR);
538 }
539
540 void prevChunk() const
541 {
542 auto previousArray = getCurrentArray();
543 mFirstIndex -= previousArray->length();
545 auto array = getCurrentArray();
546 mCurrent = reinterpret_cast<unwrap_t<T> const*>(array->values()->data()) - (mFirstIndex >> SCALE_FACTOR);
547 mLast = mCurrent + array->length() + (mFirstIndex >> SCALE_FACTOR);
548 }
549
550 void moveToChunk(int chunk)
551 {
552 if (mCurrentChunk < chunk) {
553 while (mCurrentChunk != chunk) {
554 nextChunk();
555 }
556 } else {
557 while (mCurrentChunk != chunk) {
558 prevChunk();
559 }
560 }
561 }
562
565 {
566 mCurrentChunk = mColumn->num_chunks() - 1;
567 auto array = getCurrentArray();
568 mFirstIndex = mColumn->length() - array->length();
569 mCurrent = reinterpret_cast<unwrap_t<T> const*>(array->values()->data()) - (mFirstIndex >> SCALE_FACTOR);
570 mLast = mCurrent + array->length() + (mFirstIndex >> SCALE_FACTOR);
571 }
572
573 auto operator*() const
574 requires std::same_as<bool, std::decay_t<T>>
575 {
576 checkSkipChunk();
577 return (*(mCurrent + ((*mCurrentPos + *mGlobalOffset) >> SCALE_FACTOR)) & (1 << ((*mCurrentPos + *mGlobalOffset) & ((1 << SCALE_FACTOR) - 1)))) != 0;
578 }
579
580 auto operator*() const
581 requires((!std::same_as<bool, std::decay_t<T>>) && std::same_as<arrow_array_for_t<T>, arrow::ListArray>)
582 {
583 checkSkipChunk();
584 auto list = std::static_pointer_cast<arrow::ListArray>(mColumn->chunk(mCurrentChunk));
585 auto offset = list->value_offset(*mCurrentPos + *mGlobalOffset - mFirstIndex);
586 auto length = list->value_length(*mCurrentPos + *mGlobalOffset - mFirstIndex);
587 return gsl::span<unwrap_t<T> const>{mCurrent + mFirstIndex + offset, mCurrent + mFirstIndex + (offset + length)};
588 }
589
590 decltype(auto) operator*() const
591 requires((!std::same_as<bool, std::decay_t<T>>) && std::same_as<arrow_array_for_t<T>, arrow::BinaryViewArray>)
592 {
593 checkSkipChunk();
594 auto array = std::static_pointer_cast<arrow::BinaryViewArray>(mColumn->chunk(mCurrentChunk));
595 return array->GetView(*mCurrentPos + *mGlobalOffset - mFirstIndex);
596 }
597
598 decltype(auto) operator*() const
599 requires((!std::same_as<bool, std::decay_t<T>>) && !std::same_as<arrow_array_for_t<T>, arrow::ListArray> && !std::same_as<arrow_array_for_t<T>, arrow::BinaryViewArray>)
600 {
601 checkSkipChunk();
602 return *(mCurrent + ((*mCurrentPos + *mGlobalOffset) >> SCALE_FACTOR));
603 }
604
605 // Move to the chunk which containts element pos
607 {
608 checkSkipChunk();
609 return *this;
610 }
611
612 mutable unwrap_t<T> const* mCurrent;
614 uint64_t const* mGlobalOffset;
615 mutable unwrap_t<T> const* mLast;
616 arrow::ChunkedArray const* mColumn;
617 mutable int mFirstIndex;
618 mutable int mCurrentChunk;
619
620 private:
621 void checkSkipChunk() const
622 requires((ChunkingPolicy::chunked == true) && std::same_as<arrow_array_for_t<T>, arrow::ListArray>)
623 {
624 auto list = std::static_pointer_cast<arrow::ListArray>(mColumn->chunk(mCurrentChunk));
625 if (O2_BUILTIN_UNLIKELY(*mCurrentPos + *mGlobalOffset - mFirstIndex >= list->length())) {
626 nextChunk();
627 }
628 }
629
630 void checkSkipChunk() const
631 requires((ChunkingPolicy::chunked == true) && !std::same_as<arrow_array_for_t<T>, arrow::ListArray>)
632 {
633 if (O2_BUILTIN_UNLIKELY(((mCurrent + ((*mCurrentPos + *mGlobalOffset) >> SCALE_FACTOR)) >= mLast))) {
634 nextChunk();
635 }
636 }
637
638 void checkSkipChunk() const
639 requires(ChunkingPolicy::chunked == false)
640 {
641 }
643 auto getCurrentArray() const
644 requires(std::same_as<arrow_array_for_t<T>, arrow::FixedSizeListArray>)
645 {
646 std::shared_ptr<arrow::Array> chunkToUse = mColumn->chunk(mCurrentChunk);
647 chunkToUse = std::dynamic_pointer_cast<arrow::FixedSizeListArray>(chunkToUse)->values();
648 return std::static_pointer_cast<arrow_array_for_t<value_for_t<T>>>(chunkToUse);
649 }
650
651 auto getCurrentArray() const
652 requires(std::same_as<arrow_array_for_t<T>, arrow::ListArray>)
653 {
654 std::shared_ptr<arrow::Array> chunkToUse = mColumn->chunk(mCurrentChunk);
655 chunkToUse = std::dynamic_pointer_cast<arrow::ListArray>(chunkToUse)->values();
656 return std::static_pointer_cast<arrow_array_for_t<value_for_t<T>>>(chunkToUse);
657 }
658
659 auto getCurrentArray() const
660 requires(!std::same_as<arrow_array_for_t<T>, arrow::FixedSizeListArray> && !std::same_as<arrow_array_for_t<T>, arrow::ListArray>)
661 {
662 std::shared_ptr<arrow::Array> chunkToUse = mColumn->chunk(mCurrentChunk);
663 return std::static_pointer_cast<arrow_array_for_t<T>>(chunkToUse);
664 }
665};
666
667template <typename T, typename INHERIT>
668struct Column {
669 static constexpr void isIteratableColumn() {};
670
671 using inherited_t = INHERIT;
673 : mColumnIterator{it}
674 {
675 }
676
677 Column() = default;
678 Column(Column const&) = default;
679 Column& operator=(Column const&) = default;
680
681 Column(Column&&) = default;
682 Column& operator=(Column&&) = default;
683
684 using type = T;
685 static constexpr const char* const& columnLabel() { return INHERIT::mLabel; }
687 {
688 return mColumnIterator;
689 }
690
691 static auto asArrowField()
692 {
693 return std::make_shared<arrow::Field>(inherited_t::mLabel, soa::asArrowDataType<type>());
694 }
695
699};
700
703template <typename F, typename INHERIT>
705 static constexpr void isDynamicColumn() {};
706 using inherited_t = INHERIT;
707
708 static constexpr const char* const& columnLabel() { return INHERIT::mLabel; }
709};
710
711template <typename INHERIT>
713 static constexpr void isEnumeratingColumn() {};
714 using inherited_t = INHERIT;
715 static constexpr const uint32_t hash = 0;
716
717 static constexpr const char* const& columnLabel() { return INHERIT::mLabel; }
718};
719
720template <typename INHERIT>
722 static constexpr void isMarkingColumn() {};
723 using inherited_t = INHERIT;
724 static constexpr const uint32_t hash = 0;
725
726 static constexpr const char* const& columnLabel() { return INHERIT::mLabel; }
727};
728
729template <size_t M = 0>
730struct Marker : o2::soa::MarkerColumn<Marker<M>> {
731 using type = size_t;
733 constexpr inline static auto value = M;
734
735 Marker() = default;
736 Marker(Marker const&) = default;
737 Marker(Marker&&) = default;
738
739 Marker& operator=(Marker const&) = default;
740 Marker& operator=(Marker&&) = default;
741
742 Marker(arrow::ChunkedArray const*) {}
743 constexpr inline auto mark()
744 {
745 return value;
746 }
747
748 static constexpr const char* mLabel = "Marker";
749};
750
751template <int64_t START = 0, int64_t END = -1>
752struct Index : o2::soa::IndexColumn<Index<START, END>> {
754 constexpr inline static int64_t start = START;
755 constexpr inline static int64_t end = END;
756
757 Index() = default;
758 Index(Index const&) = default;
759 Index(Index&&) = default;
760
761 Index& operator=(Index const&) = default;
762 Index& operator=(Index&&) = default;
763
764 Index(arrow::ChunkedArray const*)
765 {
766 }
767
768 constexpr inline int64_t rangeStart()
769 {
770 return START;
771 }
772
773 constexpr inline int64_t rangeEnd()
774 {
775 return END;
776 }
777
778 [[nodiscard]] int64_t index() const
779 {
780 return index<0>();
781 }
782
783 [[nodiscard]] int64_t filteredIndex() const
784 {
785 return index<1>();
786 }
787
788 [[nodiscard]] int64_t globalIndex() const
789 {
790 return index<0>() + offsets<0>();
791 }
792
793 template <int N = 0>
794 [[nodiscard]] int64_t index() const
795 {
796 return *std::get<N>(rowIndices);
797 }
798
799 template <int N = 0>
800 [[nodiscard]] int64_t offsets() const
801 {
802 return *std::get<N>(rowOffsets);
803 }
804
805 void setIndices(std::tuple<int64_t const*, int64_t const*> indices)
806 {
808 }
809
810 void setOffsets(std::tuple<uint64_t const*> offsets)
811 {
813 }
814
815 static constexpr const char* mLabel = "Index";
816 using type = int64_t;
817
818 std::tuple<int64_t const*, int64_t const*> rowIndices;
821 std::tuple<uint64_t const*> rowOffsets;
822};
823
828 uint64_t mOffset = 0;
829};
830
832 static constexpr void isRowViewSentinel() {};
834};
835
837 static constexpr void isFilteredIndexPolicy();
838 // We use -1 in the IndexPolicyBase to indicate that the index is
839 // invalid. What will validate the index is the this->setCursor()
840 // which happens below which will properly setup the first index
841 // by remapping the filtered index 0 to whatever unfiltered index
842 // it belongs to.
843 FilteredIndexPolicy(std::span<int64_t const> selection, int64_t rows, uint64_t offset = 0)
844 : IndexPolicyBase{-1, offset},
845 mSelectedRows(selection),
846 mMaxSelection(selection.size()),
847 nRows{rows}
848 {
849 this->setCursor(0);
850 }
851
852 void resetSelection(std::span<int64_t const> selection)
853 {
854 mSelectedRows = selection;
855 mMaxSelection = selection.size();
856 this->setCursor(0);
857 }
858
864
865 [[nodiscard]] std::tuple<int64_t const*, int64_t const*>
867 {
868 return std::make_tuple(&mRowIndex, &mSelectionRow);
869 }
870
871 [[nodiscard]] std::tuple<uint64_t const*>
873 {
874 return std::make_tuple(&mOffset);
875 }
876
878 {
879 this->setCursor(start);
880 if (end >= 0) {
881 mMaxSelection = std::min(end, mMaxSelection);
882 }
883 }
884
886 {
887 mSelectionRow = i;
888 updateRow();
889 }
890
892 {
893 mSelectionRow += i;
894 updateRow();
895 }
896
897 friend bool operator==(FilteredIndexPolicy const& lh, FilteredIndexPolicy const& rh)
898 {
899 return lh.mSelectionRow == rh.mSelectionRow;
900 }
901
902 bool operator==(RowViewSentinel const& sentinel) const
903 {
904 return O2_BUILTIN_UNLIKELY(mSelectionRow == sentinel.index);
905 }
906
911 {
912 this->mSelectionRow = this->mMaxSelection;
913 this->mRowIndex = -1;
914 }
915
916 [[nodiscard]] auto getSelectionRow() const
917 {
918 return mSelectionRow;
919 }
920
921 [[nodiscard]] auto size() const
922 {
923 return mMaxSelection;
924 }
925
926 [[nodiscard]] auto raw_size() const
927 {
928 return nRows;
929 }
930
931 private:
932 inline void updateRow()
933 {
934 this->mRowIndex = O2_BUILTIN_LIKELY(mSelectionRow < mMaxSelection) ? mSelectedRows[mSelectionRow] : -1;
935 }
936 std::span<int64_t const> mSelectedRows;
937 int64_t mSelectionRow = 0;
938 int64_t mMaxSelection = 0;
939 int64_t nRows = 0;
940};
941
943 static constexpr void isDefaultIndexPolicy() {};
950
956 mMaxRow(nRows)
957 {
958 }
959
965
967 {
968 this->setCursor(start);
969 if (end >= 0) {
970 mMaxRow = std::min(end, mMaxRow);
971 }
972 }
973
974 [[nodiscard]] std::tuple<int64_t const*, int64_t const*>
976 {
977 return std::make_tuple(&mRowIndex, &mRowIndex);
978 }
979
980 [[nodiscard]] std::tuple<uint64_t const*>
982 {
983 return std::make_tuple(&mOffset);
984 }
985
987 {
988 this->mRowIndex = i;
989 }
991 {
992 this->mRowIndex += i;
993 }
994
996 {
997 this->setCursor(mMaxRow);
998 }
999
1000 friend bool operator==(DefaultIndexPolicy const& lh, DefaultIndexPolicy const& rh)
1001 {
1002 return lh.mRowIndex == rh.mRowIndex;
1003 }
1004
1005 bool operator==(RowViewSentinel const& sentinel) const
1006 {
1007 return O2_BUILTIN_UNLIKELY(this->mRowIndex == sentinel.index);
1008 }
1009
1010 [[nodiscard]] auto size() const
1011 {
1012 return mMaxRow;
1013 }
1014
1016};
1017
1020template <typename C>
1023 arrow::ChunkedArray* second;
1024};
1025
1026template <typename C>
1027concept needs_ptr_rec = C::needs_ptr_rec;
1028
1029template <typename D, typename O, typename IP, typename... C>
1030struct TableIterator : IP, C... {
1031 public:
1032 static constexpr void isTableIterator() {};
1033 using self_t = TableIterator<D, O, IP, C...>;
1034 using policy_t = IP;
1039 using bindings_pack_t = decltype([]<typename... Cs>(framework::pack<Cs...>) -> framework::pack<typename Cs::binding_t...> {}(external_index_columns_t{})); // decltype(extractBindings(external_index_columns_t{}));
1040
1041 TableIterator(arrow::ChunkedArray* columnData[sizeof...(C)], IP&& policy)
1042 : IP{policy},
1043 C(columnData[framework::has_type_at_v<C>(all_columns{})])...
1044 {
1045 if (this->size() != 0) {
1046 bind();
1047 }
1048 }
1049
1050 TableIterator(arrow::ChunkedArray* columnData[sizeof...(C)], IP&& policy)
1051 requires(has_index<C...>)
1052 : IP{policy},
1053 C(columnData[framework::has_type_at_v<C>(all_columns{})])...
1054 {
1055 if (this->size() != 0) {
1056 bind();
1057 }
1058 // In case we have an index column might need to constrain the actual
1059 // number of rows in the view to the range provided by the index.
1060 // FIXME: we should really understand what happens to an index when we
1061 // have a RowViewFiltered.
1062 this->limitRange(this->rangeStart(), this->rangeEnd());
1063 }
1064
1065 TableIterator() = default;
1067 : IP{static_cast<IP const&>(other)},
1068 C(static_cast<C const&>(other))...
1069 {
1070 if (this->size() != 0) {
1071 bind();
1072 }
1073 }
1074
1076 {
1077 IP::operator=(static_cast<IP const&>(other));
1078 (void(static_cast<C&>(*this) = static_cast<C>(other)), ...);
1079 if (this->size() != 0) {
1080 bind();
1081 }
1082 return *this;
1083 }
1084
1086 requires std::same_as<IP, DefaultIndexPolicy>
1087 : IP{static_cast<IP const&>(other)},
1088 C(static_cast<C const&>(other))...
1089 {
1090 if (this->size() != 0) {
1091 bind();
1092 }
1093 }
1094
1096 {
1097 this->moveByIndex(1);
1098 return *this;
1099 }
1100
1102 {
1103 self_t copy = *this;
1104 this->operator++();
1105 return copy;
1106 }
1107
1109 {
1110 this->moveByIndex(-1);
1111 return *this;
1112 }
1113
1115 {
1116 self_t copy = *this;
1117 this->operator--();
1118 return copy;
1119 }
1120
1123 {
1124 TableIterator copy = *this;
1125 copy.moveByIndex(inc);
1126 return copy;
1127 }
1128
1130 {
1131 return operator+(-dec);
1132 }
1133
1135 {
1136 return *this;
1137 }
1138
1139 template <typename CL>
1140 auto getCurrent() const
1141 {
1142 return CL::getCurrentRaw();
1143 }
1144
1145 template <typename... Cs>
1147 {
1148 return std::vector<o2::soa::Binding>{static_cast<Cs const&>(*this).getCurrentRaw()...};
1149 }
1150
1151 auto getIndexBindings() const
1152 {
1154 }
1155
1156 template <typename... TA>
1157 void bindExternalIndices(TA*... current)
1158 {
1159 ([this]<soa::is_index_column... CCs>(TA* cur, framework::pack<CCs...>) {
1160 (CCs::setCurrent(cur), ...);
1161 }(current, external_index_columns_t{}),
1162 ...);
1163 }
1164
1165 template <typename TA>
1166 void bindExternalIndex(TA* current)
1167 {
1168 [this]<soa::is_index_column... CCs>(TA* cur, framework::pack<CCs...>) {
1169 (CCs::setCurrent(cur), ...);
1170 }(current, external_index_columns_t{});
1171 }
1172
1173 template <typename... Cs>
1174 void doSetCurrentIndexRaw(framework::pack<Cs...> p, std::vector<o2::soa::Binding>&& ptrs)
1175 {
1176 (Cs::setCurrentRaw(ptrs[framework::has_type_at_v<Cs>(p)]), ...);
1177 }
1178
1179 template <typename... Cs, typename I>
1181 {
1183 b.bind(ptr);
1184 (Cs::setCurrentRaw(b), ...);
1185 }
1186
1187 void bindExternalIndicesRaw(std::vector<o2::soa::Binding>&& ptrs)
1188 {
1189 doSetCurrentIndexRaw(external_index_columns_t{}, std::forward<std::vector<o2::soa::Binding>>(ptrs));
1190 }
1191
1192 template <typename I>
1193 void bindInternalIndices(I const* table)
1194 {
1196 }
1197
1199 {
1200 [&pointerReconstructor, this]<typename... Cs>(framework::pack<Cs...>) {
1201 ([&pointerReconstructor, this]<typename CC>() {
1202 if constexpr (needs_ptr_rec<CC>) {
1203 if (pointerReconstructor) {
1204 CC::ptrRec = &pointerReconstructor;
1205 }
1206 }
1207 }.template operator()<Cs>(),
1208 ...);
1209 }(all_columns{});
1210 }
1211
1212 private:
1214 template <typename... PC>
1215 void doMoveToEnd(framework::pack<PC...>)
1216 {
1217 (PC::mColumnIterator.moveToEnd(), ...);
1218 }
1219
1222 void bind()
1223 {
1224 using namespace o2::soa;
1225 auto f = framework::overloaded{
1226 [this]<soa::is_persistent_column T>(T*) -> void { T::mColumnIterator.mCurrentPos = &this->mRowIndex; T::mColumnIterator.mGlobalOffset = &this->mOffset; },
1227 [this]<soa::is_dynamic_column T>(T*) -> void { bindDynamicColumn<T>(typename T::bindings_t{}); },
1228 [this]<typename T>(T*) -> void {},
1229 };
1230 (f(static_cast<C*>(nullptr)), ...);
1231 if constexpr (has_index<C...>) {
1232 this->setIndices(this->getIndices());
1233 this->setOffsets(this->getOffsets());
1234 }
1235 }
1236
1237 template <typename DC, typename... B>
1238 auto bindDynamicColumn(framework::pack<B...>)
1239 {
1240 DC::boundIterators = std::make_tuple(getDynamicBinding<B>()...);
1241 }
1242
1243 // Sometimes dynamic columns are defined for tables in
1244 // the hope that it will be joined / extended with another one which provides
1245 // the full set of bindings. This is to avoid a compilation
1246 // error if constructor for the table or any other thing involving a missing
1247 // binding is preinstanciated.
1248 template <typename B>
1249 requires(can_bind<self_t, B>)
1250 decltype(auto) getDynamicBinding()
1251 {
1252 static_assert(std::same_as<decltype(&(static_cast<B*>(this)->mColumnIterator)), std::decay_t<decltype(B::mColumnIterator)>*>, "foo");
1253 return &(static_cast<B*>(this)->mColumnIterator);
1254 }
1255
1256 template <typename B>
1257 decltype(auto) getDynamicBinding()
1258 {
1259 return static_cast<std::decay_t<decltype(B::mColumnIterator)>*>(nullptr);
1260 }
1261};
1262
1264 static o2::soa::ArrowTableRef joinTables(std::vector<std::shared_ptr<arrow::Table>>&& tables);
1265 static o2::soa::ArrowTableRef joinTables(std::vector<o2::soa::ArrowTableRef>&& tables);
1266 static o2::soa::ArrowTableRef joinTables(std::vector<o2::soa::ArrowTableRef>&& tables, std::span<const char* const> labels);
1267 static o2::soa::ArrowTableRef joinTables(std::vector<o2::soa::ArrowTableRef>&& tables, std::span<const std::string> labels);
1268 static o2::soa::ArrowTableRef joinTables(std::vector<std::shared_ptr<arrow::Table>>&& tables, std::span<const char* const> labels);
1269 static o2::soa::ArrowTableRef joinTables(std::vector<std::shared_ptr<arrow::Table>>&& tables, std::span<const std::string> labels);
1270 static o2::soa::ArrowTableRef concatTables(std::vector<o2::soa::ArrowTableRef>&& tables);
1271 static o2::soa::ArrowTableRef concatTables(std::vector<std::shared_ptr<arrow::Table>>&& tables);
1272};
1273
1274template <size_t N1, std::array<TableRef, N1> os1, size_t N2, std::array<TableRef, N2> os2>
1275consteval bool is_compatible()
1276{
1277 return []<size_t... Is>(std::index_sequence<Is...>) {
1278 return ([]<size_t... Ks>(std::index_sequence<Ks...>) {
1279 constexpr auto h = os1[Is].desc_hash;
1280 using H = o2::aod::Hash<h>;
1281 return (((h == os2[Ks].desc_hash) || is_ng_index_equivalent_v<H, o2::aod::Hash<os2[Ks].desc_hash>>) || ...);
1282 }(std::make_index_sequence<N2>()) ||
1283 ...);
1284 }(std::make_index_sequence<N1>());
1285}
1286
1287template <with_originals T, with_originals B>
1289{
1290 return is_compatible<T::originals.size(), T::originals, B::originals.size(), B::originals>();
1291}
1292
1293template <typename T, typename B>
1294using is_binding_compatible = std::conditional_t<is_binding_compatible_v<T, typename B::binding_t>(), std::true_type, std::false_type>;
1295
1296template <soa::is_table T>
1297static constexpr std::string getLabelForTable()
1298{
1299 return std::string{aod::label<std::decay_t<T>::originals[0]>()};
1300}
1301
1302template <soa::is_table T>
1304static constexpr std::string getLabelFromType()
1305{
1306 return getLabelForTable<T>();
1307}
1308
1309template <soa::is_iterator T>
1310static constexpr std::string getLabelFromType()
1311{
1312 return getLabelForTable<typename std::decay_t<T>::parent_t>();
1313}
1314
1315template <soa::is_index_table T>
1316static constexpr std::string getLabelFromType()
1317{
1318 return getLabelForTable<typename std::decay_t<T>::first_t>();
1319}
1320template <soa::with_base_table T>
1321 requires(!soa::is_iterator<T>)
1322static constexpr std::string getLabelFromType()
1323{
1324 return getLabelForTable<typename aod::MetadataTrait<o2::aod::Hash<T::originals[T::originals.size() - 1].desc_hash>>::metadata::base_table_t>();
1325}
1326
1327template <typename... C>
1328static constexpr auto hasColumnForKey(framework::pack<C...>, std::string_view key)
1329{
1330 auto caseInsensitiveCompare = [](const std::string_view& str1, const std::string_view& str2) {
1331 return std::ranges::equal(
1332 str1, str2,
1333 [](char c1, char c2) {
1334 return asciiToLower(static_cast<unsigned char>(c1)) ==
1335 asciiToLower(static_cast<unsigned char>(c2));
1336 });
1337 };
1338 return (caseInsensitiveCompare(C::inherited_t::mLabel, key) || ...);
1339}
1340
1341template <TableRef ref>
1342static constexpr std::pair<bool, std::string> hasKey(std::string_view key)
1343{
1344 return {hasColumnForKey(typename aod::MetadataTrait<o2::aod::Hash<ref.desc_hash>>::metadata::columns{}, key), aod::label<ref>()};
1345}
1346
1347template <TableRef ref>
1348static constexpr std::pair<bool, framework::ConcreteDataMatcher> hasKeyM(std::string_view key)
1349{
1350 return {hasColumnForKey(typename aod::MetadataTrait<o2::aod::Hash<ref.desc_hash>>::metadata::columns{}, key), aod::matcher<ref>()};
1351}
1352
1353void notFoundColumn(const char* label, const char* key);
1354void missingOptionalPreslice(const char* label, const char* key);
1355
1356template <with_originals T, bool OPT = false>
1357static constexpr std::string getLabelFromTypeForKey(std::string_view key)
1358{
1359 auto locate = []<size_t... Is>(std::index_sequence<Is...>, std::string_view key) {
1360 return std::array{hasKey<T::originals[Is]>(key)...} |
1361 std::views::filter([](auto const& x) { return x.first; });
1362 }(std::make_index_sequence<T::originals.size()>{}, key);
1363 if (!locate.empty()) {
1364 return locate.front().second;
1365 }
1366
1367 if constexpr (!OPT) {
1368 notFoundColumn(getLabelFromType<std::decay_t<T>>().data(), key.data());
1369 } else {
1370 return "[MISSING]";
1371 }
1373}
1374
1375template <with_originals T, bool OPT = false>
1376static constexpr framework::ConcreteDataMatcher getMatcherFromTypeForKey(std::string_view key)
1377{
1378 auto locate = []<size_t... Is>(std::index_sequence<Is...>, std::string_view key) {
1379 return std::array{hasKeyM<T::originals[Is]>(key)...} |
1380 std::views::filter([](auto const& x) { return x.first; });
1381 }(std::make_index_sequence<T::originals.size()>{}, key);
1382 if (!locate.empty()) {
1383 return locate.front().second;
1384 }
1385
1386 if constexpr (!OPT) {
1387 notFoundColumn(getLabelFromType<std::decay_t<T>>().data(), key.data());
1388 } else {
1390 }
1392}
1393
1394template <typename B, typename... C>
1395consteval static bool hasIndexTo(framework::pack<C...>&&)
1396{
1397 return (o2::soa::is_binding_compatible_v<B, typename C::binding_t>() || ...);
1398}
1399
1400template <typename B, typename... C>
1401consteval static bool hasSortedIndexTo(framework::pack<C...>&&)
1402{
1403 return ((C::sorted && o2::soa::is_binding_compatible_v<B, typename C::binding_t>()) || ...);
1404}
1405
1406template <typename B, typename Z>
1407consteval static bool relatedByIndex()
1408{
1409 return hasIndexTo<B>(typename Z::table_t::external_index_columns_t{});
1410}
1411
1412template <typename B, typename Z>
1413consteval static bool relatedBySortedIndex()
1414{
1415 return hasSortedIndexTo<B>(typename Z::table_t::external_index_columns_t{});
1416}
1417} // namespace o2::soa
1418
1419namespace o2::framework
1420{
1423 static constexpr void isPreslicePolicy() {};
1424 const std::string binding;
1426
1427 bool isMissing() const;
1428 Entry const& getBindingKey() const;
1429};
1430
1437
1440
1442 std::span<const int64_t> getSliceFor(int value) const;
1443};
1444
1445template <soa::is_table T, is_preslice_policy Policy, bool OPT = false>
1446struct PresliceBase : public Policy {
1447 static constexpr void isPresliceContainer() {};
1448 constexpr static bool optional = OPT;
1449 using target_t = T;
1450 using policy_t = Policy;
1451 const std::string binding;
1452
1454 : Policy{PreslicePolicyBase{{o2::soa::getLabelFromTypeForKey<T, OPT>(std::string{index_.name})}, Entry(o2::soa::getLabelFromTypeForKey<T, OPT>(std::string{index_.name}), o2::soa::getMatcherFromTypeForKey<T, OPT>(std::string{index_.name}), std::string{index_.name})}, {}}
1455 {
1456 }
1457
1459 {
1460 if constexpr (OPT) {
1461 if (Policy::isMissing()) {
1462 return {nullptr, {0, 0}};
1463 }
1464 }
1465 return Policy::getSliceFor(value, input);
1466 }
1467
1468 std::span<const int64_t> getSliceFor(int value) const
1469 {
1470 if constexpr (OPT) {
1471 if (Policy::isMissing()) {
1472 return {};
1473 }
1474 }
1475 return Policy::getSliceFor(value);
1476 }
1477};
1478
1479template <soa::is_table T>
1481template <soa::is_table T>
1483template <soa::is_table T>
1485template <soa::is_table T>
1487
1501 static constexpr void isPresliceGroup() {};
1502};
1503} // namespace o2::framework
1504
1505namespace o2::soa
1506{
1507template <soa::is_table T>
1508class FilteredBase;
1509template <typename T>
1510class Filtered;
1511
1512// FIXME: compatbility declaration to be removed
1513template <typename T>
1515
1517template <typename... Is>
1518static consteval auto extractBindings(framework::pack<Is...>)
1519{
1520 return framework::pack<typename Is::binding_t...>{};
1521}
1522
1524
1525template <typename T, typename C, typename Policy, bool OPT>
1526 requires std::same_as<Policy, framework::PreslicePolicySorted> && (o2::soa::is_binding_compatible_v<C, T>())
1527auto doSliceBy(T const* table, o2::framework::PresliceBase<C, Policy, OPT> const& container, int value)
1528{
1529 if constexpr (OPT) {
1530 if (container.isMissing()) {
1531 missingOptionalPreslice(getLabelFromType<std::decay_t<T>>().data(), container.bindingKey.key.c_str());
1532 }
1533 }
1534 auto out = container.getSliceFor(value, table->asArrowTableRef());
1535 auto t = typename T::self_t({out});
1536 if (t.tableSize() != 0) {
1537 table->copyIndexBindings(t);
1538 t.bindInternalIndicesTo(table);
1539 }
1540 return t;
1541}
1542
1543template <soa::is_filtered_table T>
1544auto doSliceByHelper(T const* table, std::span<const int64_t> const& selection)
1545{
1546 auto t = soa::Filtered<typename T::base_t>({table->asArrowTableRef()}, selection);
1547 if (t.tableSize() != 0) {
1548 table->copyIndexBindings(t);
1549 t.bindInternalIndicesTo(table);
1550 t.intersectWithSelection(table->getSelectedRows()); // intersect filters
1551 }
1552 return t;
1553}
1554
1555template <soa::is_table T>
1556 requires(!soa::is_filtered_table<T>)
1557auto doSliceByHelper(T const* table, std::span<const int64_t> const& selection)
1558{
1559 auto t = soa::Filtered<T>({table->asArrowTableRef()}, selection);
1560 if (t.tableSize() != 0) {
1561 table->copyIndexBindings(t);
1562 t.bindInternalIndicesTo(table);
1563 }
1564 return t;
1565}
1566
1567template <typename T, typename C, typename Policy, bool OPT>
1568 requires std::same_as<Policy, framework::PreslicePolicyGeneral> && (o2::soa::is_binding_compatible_v<C, T>())
1569auto doSliceBy(T const* table, o2::framework::PresliceBase<C, Policy, OPT> const& container, int value)
1570{
1571 if constexpr (OPT) {
1572 if (container.isMissing()) {
1573 missingOptionalPreslice(getLabelFromType<std::decay_t<T>>().data(), container.bindingKey.key.c_str());
1574 }
1575 }
1576 auto selection = container.getSliceFor(value);
1577 return doSliceByHelper(table, selection);
1578}
1579
1580SelectionVector sliceSelection(std::span<int64_t const> const& mSelectedRows, int64_t nrows, uint64_t offset);
1581
1582template <soa::is_filtered_table T>
1584{
1585 if (slice.range.offset >= static_cast<uint64_t>(table->tableSize())) {
1587 if (fresult.tableSize() != 0) {
1588 table->copyIndexBindings(fresult);
1589 }
1590 return fresult;
1591 }
1592 auto slicedSelection = sliceSelection(table->getSelectedRows(), slice.range.size, slice.range.offset);
1593 Filtered<typename T::base_t> fresult{{slice}, std::move(slicedSelection)};
1594 if (fresult.tableSize() != 0) {
1595 table->copyIndexBindings(fresult);
1596 }
1597 return fresult;
1598}
1599
1600template <soa::is_filtered_table T, typename C, bool OPT>
1601 requires(o2::soa::is_binding_compatible_v<C, T>())
1603{
1604 if constexpr (OPT) {
1605 if (container.isMissing()) {
1606 missingOptionalPreslice(getLabelFromType<T>().data(), container.bindingKey.key.c_str());
1607 }
1608 }
1609 auto slice = container.getSliceFor(value, table->asArrowTableRef());
1610 return prepareFilteredSlice(table, slice);
1611}
1612
1614
1615template <soa::is_table T>
1617{
1618 auto localCache = cache.ptr->getCacheFor({"", originReplacement(cache.ptr->newOrigin)(o2::soa::getMatcherFromTypeForKey<T>(node.name)),
1619 node.name});
1620 auto [offset, count] = localCache.getSliceFor(value);
1621 auto t = typename T::self_t({table->asArrowTableRef().slice({static_cast<uint64_t>(offset), count})});
1622 if (t.tableSize() != 0) {
1623 table->copyIndexBindings(t);
1624 }
1625 return t;
1626}
1627
1628template <soa::is_filtered_table T>
1630{
1631 auto localCache = cache.ptr->getCacheFor({"", originReplacement(cache.ptr->newOrigin)(o2::soa::getMatcherFromTypeForKey<T>(node.name)),
1632 node.name});
1633 auto [offset, count] = localCache.getSliceFor(value);
1634 return prepareFilteredSlice(table, table->asArrowTableRef().slice({static_cast<uint64_t>(offset), count}));
1635}
1636
1637template <soa::is_table T>
1639{
1640 auto localCache = cache.ptr->getCacheUnsortedFor({"", originReplacement(cache.ptr->newOrigin)(o2::soa::getMatcherFromTypeForKey<T>(node.name)),
1641 node.name});
1642 if constexpr (soa::is_filtered_table<T>) {
1643 auto t = typename T::self_t({table->asArrowTableRef()}, localCache.getSliceFor(value));
1644 if (t.tableSize() != 0) {
1645 t.intersectWithSelection(table->getSelectedRows());
1646 table->copyIndexBindings(t);
1647 }
1648 return t;
1649 } else {
1650 auto t = Filtered<T>({table->asArrowTableRef()}, localCache.getSliceFor(value));
1651 if (t.tableSize() != 0) {
1652 table->copyIndexBindings(t);
1653 }
1654 return t;
1655 }
1656}
1657
1658template <with_originals T>
1660{
1661 return Filtered<T>({t.asArrowTableRef()}, selectionToVector(framework::expressions::createSelection(t.asArrowTable(), f)));
1662}
1663
1664arrow::ChunkedArray* getIndexFromLabel(arrow::Table* table, std::string_view label);
1665
1666template <typename D, typename O, typename IP, typename... C>
1667consteval auto base_iter(framework::pack<C...>&&) -> TableIterator<D, O, IP, C...>
1668{
1669}
1670template <TableRef ref, typename... Ts>
1671 requires((sizeof...(Ts) > 0) && (soa::is_column<Ts> && ...))
1672consteval auto getColumns()
1673{
1674 return framework::pack<Ts...>{};
1675}
1676
1677template <TableRef ref, typename... Ts>
1678 requires((sizeof...(Ts) > 0) && !(soa::is_column<Ts> || ...) && (ref.origin_hash == "CONC"_h))
1679consteval auto getColumns()
1680{
1681 return framework::full_intersected_pack_t<typename Ts::columns_t...>{};
1682}
1683
1684template <TableRef ref, typename... Ts>
1685 requires((sizeof...(Ts) > 0) && !(soa::is_column<Ts> || ...) && (ref.origin_hash != "CONC"_h))
1686consteval auto getColumns()
1687{
1688 return framework::concatenated_pack_unique_t<typename Ts::columns_t...>{};
1689}
1690
1691template <TableRef ref, typename... Ts>
1692 requires(sizeof...(Ts) == 0 && soa::has_metadata<aod::MetadataTrait<o2::aod::Hash<ref.desc_hash>>>)
1693consteval auto getColumns()
1694{
1695 return typename aod::MetadataTrait<o2::aod::Hash<ref.desc_hash>>::metadata::columns{};
1696}
1697
1698template <TableRef ref, typename... Ts>
1699 requires((sizeof...(Ts) == 0) || (o2::soa::is_column<Ts> && ...))
1700consteval auto computeOriginals()
1701{
1702 return std::array<TableRef, 1>{ref};
1703}
1704
1705template <TableRef ref, typename... Ts>
1706 requires((sizeof...(Ts) > 0) && (!(o2::soa::is_column<Ts> && ...)))
1707consteval auto computeOriginals()
1708{
1709 return o2::soa::mergeOriginals<Ts...>();
1710}
1711
1714template <aod::is_aod_hash L, aod::is_aod_hash D, aod::is_origin_hash O, typename... Ts>
1716{
1717 public:
1718 static constexpr void isSOATable() {};
1719 static constexpr const auto ref = TableRef{L::hash, D::hash, O::hash, o2::aod::version(D::str)};
1720 using self_t = Table<L, D, O, Ts...>;
1722
1723 static constexpr const auto originals = computeOriginals<ref, Ts...>();
1724 static constexpr const auto originalLabels = []<size_t N, std::array<TableRef, N> refs, size_t... Is>(std::index_sequence<Is...>) {
1725 return std::array<const char*, N>{o2::aod::label<refs[Is]>()...};
1726 }.template operator()<originals.size(), originals>(std::make_index_sequence<originals.size()>());
1727 static constexpr const uint32_t binding_origin = originals[0].origin_hash;
1729
1730 template <size_t N, std::array<TableRef, N> bindings>
1731 requires(ref.origin_hash == "CONC"_h)
1732 static consteval auto isIndexTargetOf()
1733 {
1734 return false;
1735 }
1736
1737 template <size_t N, std::array<TableRef, N> bindings>
1738 requires(ref.origin_hash == "JOIN"_h)
1739 static consteval auto isIndexTargetOf()
1740 {
1741 return std::ranges::any_of(self_t::originals,
1742 [](TableRef const& r) {
1743 return std::ranges::any_of(bindings, [&r](TableRef const& b) { return b == r; });
1744 });
1745 }
1746
1747 template <size_t N, std::array<TableRef, N> bindings>
1748 requires(!(ref.origin_hash == "CONC"_h || ref.origin_hash == "JOIN"_h))
1749 static consteval auto isIndexTargetOf()
1750 {
1751 return std::find(bindings.begin(), bindings.end(), self_t::ref) != bindings.end();
1752 }
1753
1754 template <TableRef r>
1755 static consteval bool hasOriginal()
1756 {
1757 return std::ranges::any_of(originals, [](TableRef const& o) { return o.desc_hash == r.desc_hash; });
1758 }
1759
1760 using columns_t = decltype(getColumns<ref, Ts...>());
1761
1762 static constexpr auto column_hashes = []<typename... C>(framework::pack<C...>) consteval {
1763 auto hashes = std::array{C::hash...};
1764 std::ranges::sort(hashes);
1765 return hashes;
1766 }(columns_t{});
1767
1770
1773 template <typename IP>
1774 using base_iterator = decltype(base_iter<D, O, IP>(columns_t{}));
1775
1776 template <typename IP, typename Parent, typename... T>
1778 using columns_t = typename Parent::columns_t;
1779 using external_index_columns_t = typename Parent::external_index_columns_t;
1781 static constexpr auto originals = Parent::originals;
1782 using policy_t = IP;
1783 using parent_t = Parent;
1784
1786
1787 TableIteratorBase(arrow::ChunkedArray* columnData[framework::pack_size(columns_t{})], IP&& policy)
1788 : base_iterator<IP>(columnData, std::forward<decltype(policy)>(policy))
1789 {
1790 }
1791
1792 template <typename P, typename... Os>
1794 requires(P::ref.desc_hash == Parent::ref.desc_hash)
1795 {
1796 static_cast<base_iterator<IP>&>(*this) = static_cast<base_iterator<IP>>(other);
1797 return *this;
1798 }
1799
1800 template <typename P>
1802 {
1803 static_cast<base_iterator<IP>&>(*this) = static_cast<base_iterator<IP>>(other);
1804 return *this;
1805 }
1806
1807 template <typename P>
1809 requires std::same_as<IP, DefaultIndexPolicy>
1810 {
1811 static_cast<base_iterator<IP>&>(*this) = static_cast<base_iterator<FilteredIndexPolicy>>(other);
1812 return *this;
1813 }
1814
1815 template <typename P, typename O1, typename... Os>
1817 requires(P::ref.desc_hash == Parent::ref.desc_hash)
1818 {
1819 *this = other;
1820 }
1821
1822 template <typename P, typename O1, typename... Os>
1824 requires(P::ref.desc_hash == Parent::ref.desc_hash)
1825 {
1826 *this = other;
1827 }
1828
1829 template <typename P>
1834
1835 template <typename P>
1837 {
1838 *this = other;
1839 }
1840
1841 template <typename P>
1843 requires std::same_as<IP, DefaultIndexPolicy>
1844 {
1845 *this = other;
1846 }
1847
1849 {
1850 this->mRowIndex = other.index;
1851 return *this;
1852 }
1853 template <typename P>
1855 {
1856 this->mRowIndex = other.mRowIndex;
1857 }
1858
1859 template <typename P, typename... Os>
1861 requires std::same_as<typename P::table_t, typename Parent::table_t>
1862 {
1863 this->mRowIndex = other.mRowIndex;
1864 }
1865
1866 template <typename TI>
1867 auto getId() const
1868 {
1869 using decayed = std::decay_t<TI>;
1870 if constexpr (framework::has_type<decayed>(bindings_pack_t{})) { // index to another table
1871 constexpr auto idx = framework::has_type_at_v<decayed>(bindings_pack_t{});
1873 } else if constexpr (std::same_as<decayed, Parent>) { // self index
1874 return this->globalIndex();
1875 } else if constexpr (is_indexing_column<decayed>) { // soa::Index<>
1876 return this->globalIndex();
1877 } else {
1878 return static_cast<int32_t>(-1);
1879 }
1880 }
1881
1882 template <typename CD, typename... CDArgs>
1883 auto getDynamicColumn() const
1884 {
1885 using decayed = std::decay_t<CD>;
1886 static_assert(is_dynamic_t<decayed>(), "Requested column is not a dynamic column");
1887 return static_cast<decayed>(*this).template getDynamicValue<CDArgs...>();
1888 }
1889
1890 template <typename B, typename CC>
1891 auto getValue() const
1892 {
1893 using COL = std::decay_t<CC>;
1894 static_assert(is_dynamic_t<COL>() || soa::is_persistent_column<COL>, "Should be persistent or dynamic column with no argument that has a return type convertable to float");
1895 return static_cast<B>(static_cast<COL>(*this).get());
1896 }
1897
1898 template <typename B, typename... CCs>
1899 std::array<B, sizeof...(CCs)> getValues() const
1900 {
1901 static_assert(std::same_as<B, float> || std::same_as<B, double>, "The common return type should be float or double");
1902 return {getValue<B, CCs>()...};
1903 }
1904
1905 using IP::size;
1906
1907 using base_iterator<IP>::operator++;
1908
1911 {
1912 TableIteratorBase copy = *this;
1913 copy.moveByIndex(inc);
1914 return copy;
1915 }
1916
1918 {
1919 return operator+(-dec);
1920 }
1921
1923 {
1924 return *this;
1925 }
1926 };
1927
1928 template <typename IP, typename Parent, typename... T>
1930
1931 template <typename IP, typename Parent>
1932 using iterator_template_o = decltype([]() {
1933 if constexpr (sizeof...(Ts) == 0) {
1935 } else {
1936 if constexpr ((o2::soa::is_column<Ts> && ...)) {
1937 return iterator_template<IP, Parent>{};
1938 } else {
1939 return iterator_template<IP, Parent, Ts...>{};
1940 }
1941 }
1942 }());
1943
1946
1950
1952 : mArrowTableRef(tableRef),
1953 mEnd{tableRef.range.size}
1954 {
1955 if (mArrowTableRef.tablePtr->num_rows() == 0) {
1956 for (size_t ci = 0; ci < framework::pack_size(columns_t{}); ++ci) {
1957 mColumnChunks[ci] = nullptr;
1958 }
1959 mBegin = mEnd;
1960 } else {
1961 auto lookups = [this]<typename... C>(framework::pack<C...>) -> std::array<arrow::ChunkedArray*, framework::pack_size(columns_t{})> { return {lookupColumn<C>()...}; }(columns_t{});
1962 for (size_t ci = 0; ci < framework::pack_size(columns_t{}); ++ci) {
1963 mColumnChunks[ci] = lookups[ci];
1964 }
1965 mBegin = unfiltered_iterator{mColumnChunks, {mEnd.index, mArrowTableRef.range.offset}};
1966 mBegin.bindInternalIndices(this);
1967 }
1968 }
1969
1970 Table(std::shared_ptr<arrow::Table> table)
1971 : Table(o2::soa::ArrowTableRef{table})
1972 {
1973 }
1974
1975 Table(std::vector<o2::soa::ArrowTableRef>&& tables)
1976 requires(ref.origin_hash != "CONC"_h)
1977 : Table(ArrowHelpers::joinTables(std::forward<std::vector<o2::soa::ArrowTableRef>>(tables), std::span{originalLabels}))
1978 {
1979 }
1980
1981 Table(std::vector<o2::soa::ArrowTableRef>&& tables)
1982 requires(ref.origin_hash == "CONC"_h)
1983 : Table(ArrowHelpers::concatTables(std::forward<std::vector<o2::soa::ArrowTableRef>>(tables)))
1984 {
1985 }
1986
1987 Table(std::vector<std::shared_ptr<arrow::Table>>&& tables)
1988 requires(ref.origin_hash != "CONC"_h)
1989 : Table(ArrowHelpers::joinTables(std::forward<std::vector<std::shared_ptr<arrow::Table>>>(tables)))
1990 {
1991 }
1992
1993 Table(std::vector<std::shared_ptr<arrow::Table>>&& tables)
1994 requires(ref.origin_hash == "CONC"_h)
1995 : Table(ArrowHelpers::concatTables(std::forward<std::vector<std::shared_ptr<arrow::Table>>>(tables)))
1996 {
1997 }
1998
1999 template <typename Key>
2000 inline arrow::ChunkedArray* getIndexToKey()
2001 {
2002 constexpr auto map = []<typename... Cs>(framework::pack<Cs...>) {
2003 return std::array<bool, sizeof...(Cs)>{[]() {
2004 if constexpr (requires { Cs::index_targets.size(); }) {
2005 return Key::template isIndexTargetOf<Cs::index_targets.size(), Cs::index_targets>();
2006 } else {
2007 return false;
2008 }
2009 }()...};
2011 constexpr auto pos = std::find(map.begin(), map.end(), true);
2012 if constexpr (pos != map.end()) {
2013 return mColumnChunks[std::distance(map.begin(), pos)];
2014 } else {
2015 static_assert(framework::always_static_assert_v<Key>, "This table does not have an index to given Key");
2016 }
2017 }
2018
2020 {
2021 return mBegin;
2022 }
2023
2024 auto const& cached_begin() const
2025 {
2026 return mBegin;
2027 }
2028
2030 {
2031 return unfiltered_iterator(mBegin);
2032 }
2033
2035 {
2036 return RowViewSentinel{mEnd};
2037 }
2038
2039 filtered_iterator filtered_begin(std::span<int64_t const> selection)
2040 {
2041 // Note that the FilteredIndexPolicy will never outlive the selection which
2042 // is held by the table, so we are safe passing the bare pointer. If it does it
2043 // means that the iterator on a table is outliving the table itself, which is
2044 // a bad idea.
2045 return filtered_iterator(mColumnChunks, {selection, mArrowTableRef.tablePtr->num_rows(), mArrowTableRef.range.offset});
2046 }
2047
2048 iterator iteratorAt(uint64_t i) const
2049 {
2050 return rawIteratorAt(i);
2051 }
2052
2054 {
2055 auto it = mBegin;
2056 it.setCursor(i);
2057 return it;
2058 }
2059
2061 {
2062 return unfiltered_const_iterator(mBegin);
2063 }
2064
2065 [[nodiscard]] RowViewSentinel end() const
2066 {
2067 return RowViewSentinel{mEnd};
2068 }
2069
2071 [[nodiscard]] std::shared_ptr<arrow::Table> asArrowTable() const
2072 {
2073 return mArrowTableRef.tablePtr;
2074 }
2075
2076 [[nodiscard]] std::shared_ptr<arrow::Table> asArrowTableConstrained() const
2077 {
2078 return mArrowTableRef.tablePtr->Slice(mArrowTableRef.range.offset, mArrowTableRef.range.size);
2079 }
2080
2081 [[nodiscard]] ArrowTableRef asArrowTableRef() const
2082 {
2083 return mArrowTableRef;
2084 }
2086 auto offset() const
2087 {
2088 return mArrowTableRef.range.offset;
2089 }
2091 [[nodiscard]] int64_t size() const
2092 {
2093 return mArrowTableRef.range.size;
2094 }
2095
2096 [[nodiscard]] int64_t tableSize() const
2097 {
2098 return size();
2099 }
2100
2103 template <typename... TA>
2104 void bindExternalIndices(TA*... current)
2105 {
2106 ([this](TA* cur) {
2107 if constexpr (binding_origin == TA::binding_origin) {
2108 mBegin.bindExternalIndex(cur);
2109 }
2110 }(current),
2111 ...);
2112 }
2113
2114 template <typename TA>
2115 void bindExternalIndex(TA* current)
2116 {
2117 mBegin.bindExternalIndex(current); // unchecked binding for the derived tables
2118 }
2119
2120 template <typename I>
2122 {
2123 mBegin.bindInternalIndices(ptr);
2124 }
2125
2130
2131 template <typename... Cs>
2133 {
2134 (static_cast<Cs>(mBegin).setCurrentRaw(binding), ...);
2135 }
2136
2137 void bindExternalIndicesRaw(std::vector<o2::soa::Binding>&& ptrs)
2138 {
2139 mBegin.bindExternalIndicesRaw(std::forward<std::vector<o2::soa::Binding>>(ptrs));
2140 }
2141
2142 template <typename T, typename... Cs>
2144 {
2145 dest.bindExternalIndicesRaw(mBegin.getIndexBindings());
2146 }
2147
2148 template <typename T>
2149 void copyIndexBindings(T& dest) const
2150 {
2152 }
2153
2155 {
2156 auto t = o2::soa::select(*this, f);
2158 return t;
2159 }
2160
2162 {
2163 return doSliceByCached(this, node, value, cache);
2164 }
2165
2170
2171 template <typename T1, typename Policy, bool OPT>
2173 {
2174 return doSliceBy(this, container, value);
2175 }
2176
2177 auto rawSlice(uint64_t start, uint64_t end) const
2178 {
2179 return self_t{mArrowTableRef.slice({start, static_cast<int64_t>(end - start + 1)})};
2180 }
2181
2182 auto emptySlice() const
2183 {
2184 return self_t{mArrowTableRef.makeEmpty()};
2185 }
2186
2188 {
2189 mBegin.setPointerReconstructor(pointerReconstructor);
2190 }
2191
2192 private:
2193 template <typename T>
2194 arrow::ChunkedArray* lookupColumn()
2195 {
2196 return nullptr;
2197 }
2198
2199 template <soa::is_persistent_column T>
2200 arrow::ChunkedArray* lookupColumn()
2201 {
2202 return getIndexFromLabel(mArrowTableRef.tablePtr.get(), T::columnLabel());
2203 }
2204
2205 ArrowTableRef mArrowTableRef;
2206 // std::shared_ptr<arrow::Table> mTable = nullptr;
2207 // uint64_t mOffset = 0;
2208 // Cached pointers to the ChunkedArray associated to a column
2209 arrow::ChunkedArray* mColumnChunks[framework::pack_size(columns_t{})];
2210 RowViewSentinel mEnd;
2211 iterator mBegin;
2212};
2213
2214template <uint32_t D, soa::is_column... C>
2216
2217void getterNotFound(const char* targetColumnLabel);
2218void emptyColumnLabel();
2219
2220namespace row_helpers
2221{
2222template <typename R, typename T, typename C>
2223R getColumnValue(const T& rowIterator)
2224{
2225 return static_cast<R>(static_cast<C>(rowIterator).get());
2226}
2227
2228namespace
2229{
2230template <typename R, typename T>
2231using ColumnGetterFunction = R (*)(const T&);
2232
2233template <typename T, typename R>
2235 // lambda is callable without additional free args
2236 framework::pack_size(typename T::bindings_t{}) == framework::pack_size(typename T::callable_t::args{}) &&
2237 requires(T t) {
2238 { t.get() } -> std::convertible_to<R>;
2239 };
2240
2241template <typename T, typename R>
2243 { t.get() } -> std::convertible_to<R>;
2244};
2245
2246template <typename R, typename T, persistent_with_common_getter<R> C>
2247ColumnGetterFunction<R, T> createGetterPtr(const std::string_view& targetColumnLabel)
2248{
2249 return targetColumnLabel == C::columnLabel() ? &getColumnValue<R, T, C> : nullptr;
2250}
2251
2252template <typename R, typename T, dynamic_with_common_getter<R> C>
2253ColumnGetterFunction<R, T> createGetterPtr(const std::string_view& targetColumnLabel)
2254{
2255 std::string_view columnLabel(C::columnLabel());
2256
2257 // allows user to use consistent formatting (with prefix) of all column labels
2258 // by default there isn't 'f' prefix for dynamic column labels
2259 if (targetColumnLabel.starts_with("f") && targetColumnLabel.substr(1) == columnLabel) {
2260 return &getColumnValue<R, T, C>;
2261 }
2262
2263 // check also exact match if user is aware of prefix missing
2264 if (targetColumnLabel == columnLabel) {
2265 return &getColumnValue<R, T, C>;
2266 }
2267
2268 return nullptr;
2269}
2270
2271template <typename R, typename T, typename... Cs>
2272ColumnGetterFunction<R, T> getColumnGetterByLabel(o2::framework::pack<Cs...>, const std::string_view& targetColumnLabel)
2273{
2274 ColumnGetterFunction<R, T> func;
2275
2276 (void)((func = createGetterPtr<R, T, Cs>(targetColumnLabel), func) || ...);
2277
2278 if (!func) {
2279 getterNotFound(targetColumnLabel.data());
2280 }
2281
2282 return func;
2283}
2284
2285template <typename T, typename R>
2286using with_common_getter_t = typename std::conditional<persistent_with_common_getter<T, R> || dynamic_with_common_getter<T, R>, std::true_type, std::false_type>::type;
2287} // namespace
2288
2289template <typename R, typename T>
2290ColumnGetterFunction<R, typename T::iterator> getColumnGetterByLabel(const std::string_view& targetColumnLabel)
2291{
2292 using TypesWithCommonGetter = o2::framework::selected_pack_multicondition<with_common_getter_t, framework::pack<R>, typename T::columns_t>;
2293
2294 if (targetColumnLabel.size() == 0) {
2296 }
2297
2298 return getColumnGetterByLabel<R, typename T::iterator>(TypesWithCommonGetter{}, targetColumnLabel);
2299}
2300} // namespace row_helpers
2301} // namespace o2::soa
2302
2303namespace o2::aod
2304{
2305// If you get an error about not satisfying is_origin_hash, you need to add
2306// an entry here.
2308O2ORIGIN("AOD1");
2309O2ORIGIN("AOD2");
2310
2311O2ORIGIN("JOIN");
2312O2HASH("JOIN/0");
2313
2314O2ORIGIN("CONC");
2315O2HASH("CONC/0");
2316
2317O2ORIGIN("TEST");
2318O2HASH("TEST/0");
2319} // namespace o2::aod
2320
2321namespace
2322{
2323template <typename T>
2324consteval static std::string_view namespace_prefix()
2325{
2326 constexpr auto name = o2::framework::type_name<T>();
2327 const auto pos = name.rfind(std::string_view{":"});
2328 return name.substr(0, pos + 1);
2329}
2330} // namespace
2331
2332#define DECLARE_EQUIVALENT_FOR_INDEX(_Base_, _Equiv_) \
2333 template <> \
2334 struct EquivalentIndexNG<o2::aod::Hash<_Base_::ref.desc_hash>, o2::aod::Hash<_Equiv_::ref.desc_hash>> { \
2335 constexpr static bool value = true; \
2336 }
2337
2338#define DECLARE_EQUIVALENT_FOR_INDEX_NG(_Base_, _Equiv_) \
2339 template <> \
2340 struct EquivalentIndexNG<o2::aod::Hash<_Base_ ""_h>, o2::aod::Hash<_Equiv_ ""_h>> { \
2341 constexpr static bool value = true; \
2342 }
2343
2344#define DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) \
2345 struct _Name_ : o2::soa::Column<_Type_, _Name_> { \
2346 static constexpr const char* mLabel = _Label_; \
2347 static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \
2348 static_assert(!((*(mLabel + 1) == 'I' && *(mLabel + 2) == 'n' && *(mLabel + 3) == 'd' && *(mLabel + 4) == 'e' && *(mLabel + 5) == 'x')), "Index is not a valid column name"); \
2349 using base = o2::soa::Column<_Type_, _Name_>; \
2350 using type = _Type_; \
2351 using column_t = _Name_; \
2352 _Name_(arrow::ChunkedArray const* column) \
2353 : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator<type>(column)) \
2354 { \
2355 } \
2356 \
2357 _Name_() = default; \
2358 _Name_(_Name_ const& other) = default; \
2359 _Name_& operator=(_Name_ const& other) = default; \
2360 \
2361 decltype(auto) _Getter_() const \
2362 { \
2363 return *mColumnIterator; \
2364 } \
2365 \
2366 decltype(auto) get() const \
2367 { \
2368 return _Getter_(); \
2369 } \
2370 }; \
2371 [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() }
2372
2373#define DECLARE_SOA_CCDB_COLUMN_FULL(_Name_, _Label_, _Getter_, _ConcreteType_, _CCDBQuery_, _RunDependent_, ...) \
2374 struct _Name_ : o2::soa::Column<int64_t[3], _Name_> { \
2375 static constexpr const char* mLabel = _Label_; \
2376 static constexpr const char* query = _CCDBQuery_; \
2377 /* How the object is keyed in CCDB: 0 queries by timestamp alone, 1 additionally sends */ \
2378 /* the run number as "runNumber" metadata (o2::ccdb run-dependent objects), 2 uses the */ \
2379 /* run number in place of the timestamp. A non-zero value needs the column's table to */ \
2380 /* be uniform in the run number, since that is where the run comes from. */ \
2381 static constexpr int run_dependent = _RunDependent_; \
2382 static constexpr const uint32_t hash = crc32(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \
2383 static constexpr bool needs_ptr_rec = true; \
2384 /* Post-deserialisation fixup for objects which are not usable straight out of the ROOT */ \
2385 /* streamer, e.g. FlatObjects whose internal pointers must be rectified first. Runs on */ \
2386 /* the receiving device, once per (re)deserialisation, before the object is ever handed */ \
2387 /* out. Returns the object to cache: a finaliser returning a different instance owns */ \
2388 /* disposing of the one it was given. */ \
2389 using finaliser_t = _ConcreteType_* (*)(_ConcreteType_*); \
2390 static constexpr finaliser_t finalise = __VA_ARGS__; \
2391 std::function<std::byte*(fair::mq::shmem::MetaHeader&&)> const* ptrRec = nullptr; \
2392 using base = o2::soa::Column<int64_t[3], _Name_>; \
2393 using type = int64_t[3]; \
2394 using column_t = _Name_; \
2395 _Name_(arrow::ChunkedArray const* column) \
2396 : o2::soa::Column<int64_t[3], _Name_>(o2::soa::ColumnIterator<int64_t[3]>(column)) \
2397 { \
2398 } \
2399 \
2400 _Name_() = default; \
2401 _Name_(_Name_ const& other) = default; \
2402 _Name_& operator=(_Name_ const& other) = default; \
2403 \
2404 decltype(auto) _Getter_() const \
2405 { \
2406 auto& [handle, segment, size] = *mColumnIterator; \
2407 auto span = std::span<std::byte>{(*ptrRec)(fair::mq::shmem::MetaHeader{ \
2408 static_cast<size_t>(size), \
2409 0, handle, 0, 0, \
2410 static_cast<uint16_t>(segment), true}), \
2411 static_cast<size_t>(size)}; \
2412 if constexpr (std::same_as<_ConcreteType_, std::span<std::byte>>) { \
2413 return span; \
2414 } else { \
2415 static std::byte* payload = nullptr; \
2416 static _ConcreteType_* deserialised = nullptr; \
2417 static TClass* c = TClass::GetClass(#_ConcreteType_); \
2418 if (payload != (std::byte*)span.data()) { \
2419 payload = (std::byte*)span.data(); \
2420 delete deserialised; \
2421 TBufferFile f(TBufferFile::EMode::kRead, span.size(), (char*)span.data(), kFALSE); \
2422 auto* streamed = (_ConcreteType_*)soa::extractCCDBPayload((char*)payload, span.size(), c, "ccdb_object"); \
2423 if (!streamed) { \
2424 LOGP(fatal, \
2425 "Could not deserialise a {} from the CCDB payload for {} ({} bytes). Check the configured " \
2426 "path (option \"ccdb:{}\") and that the object exists for this timestamp.", \
2427 #_ConcreteType_, _CCDBQuery_, span.size(), _Label_); \
2428 } \
2429 deserialised = finalise(streamed); \
2430 } \
2431 return *deserialised; \
2432 } \
2433 } \
2434 \
2435 decltype(auto) \
2436 get() const \
2437 { \
2438 return _Getter_(); \
2439 } \
2440 };
2441
2442/* Conventional label, and the object used exactly as the ROOT streamer produced it. Reach
2443 for DECLARE_SOA_CCDB_COLUMN_FULL when it needs finalising first — a FlatObject whose
2444 pointers must be rectified, say. Its finaliser is the trailing argument, so commas in a
2445 lambda body are absorbed by __VA_ARGS__. */
2446#define DECLARE_SOA_CCDB_COLUMN(_Name_, _Getter_, _ConcreteType_, _CCDBQuery_) \
2447 DECLARE_SOA_CCDB_COLUMN_FULL(_Name_, "f" #_Name_, _Getter_, _ConcreteType_, _CCDBQuery_, 0, \
2448 [](_ConcreteType_* ccdbObject) { return ccdbObject; })
2449
2450#define DECLARE_SOA_COLUMN(_Name_, _Getter_, _Type_) \
2451 DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, "f" #_Name_)
2452
2455#define MAKEINT(_Size_) uint##_Size_##_t
2456
2457#define DECLARE_SOA_BITMAP_COLUMN_FULL(_Name_, _Getter_, _Size_, _Label_) \
2458 struct _Name_ : o2::soa::Column<MAKEINT(_Size_), _Name_> { \
2459 static constexpr const char* mLabel = _Label_; \
2460 static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \
2461 static_assert(!((*(mLabel + 1) == 'I' && *(mLabel + 2) == 'n' && *(mLabel + 3) == 'd' && *(mLabel + 4) == 'e' && *(mLabel + 5) == 'x')), "Index is not a valid column name"); \
2462 using base = o2::soa::Column<MAKEINT(_Size_), _Name_>; \
2463 using type = MAKEINT(_Size_); \
2464 _Name_(arrow::ChunkedArray const* column) \
2465 : o2::soa::Column<type, _Name_>(o2::soa::ColumnIterator<type>(column)) \
2466 { \
2467 } \
2468 \
2469 _Name_() = default; \
2470 _Name_(_Name_ const& other) = default; \
2471 _Name_& operator=(_Name_ const& other) = default; \
2472 \
2473 decltype(auto) _Getter_##_raw() const \
2474 { \
2475 return *mColumnIterator; \
2476 } \
2477 \
2478 bool _Getter_##_bit(int bit) const \
2479 { \
2480 return (*mColumnIterator & (static_cast<type>(1) << bit)) >> bit; \
2481 } \
2482 }; \
2483 [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<MAKEINT(_Size_)>() }
2484
2485#define DECLARE_SOA_BITMAP_COLUMN(_Name_, _Getter_, _Size_) \
2486 DECLARE_SOA_BITMAP_COLUMN_FULL(_Name_, _Getter_, _Size_, "f" #_Name_)
2487
2490#define DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_, _Expression_) \
2491 struct _Name_ : o2::soa::Column<_Type_, _Name_> { \
2492 static constexpr const char* mLabel = _Label_; \
2493 static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \
2494 using base = o2::soa::Column<_Type_, _Name_>; \
2495 using type = _Type_; \
2496 using column_t = _Name_; \
2497 using spawnable_t = std::true_type; \
2498 _Name_(arrow::ChunkedArray const* column) \
2499 : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator<type>(column)) \
2500 { \
2501 } \
2502 \
2503 _Name_() = default; \
2504 _Name_(_Name_ const& other) = default; \
2505 _Name_& operator=(_Name_ const& other) = default; \
2506 \
2507 decltype(auto) _Getter_() const \
2508 { \
2509 return *mColumnIterator; \
2510 } \
2511 \
2512 decltype(auto) get() const \
2513 { \
2514 return _Getter_(); \
2515 } \
2516 \
2517 static o2::framework::expressions::Projector Projector() \
2518 { \
2519 return _Expression_; \
2520 } \
2521 }; \
2522 [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() }
2523
2524#define DECLARE_SOA_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Expression_) \
2525 DECLARE_SOA_EXPRESSION_COLUMN_FULL(_Name_, _Getter_, _Type_, "f" #_Name_, _Expression_);
2526
2529#define DECLARE_SOA_CONFIGURABLE_EXPRESSION_COLUMN(_Name_, _Getter_, _Type_, _Label_) \
2530 struct _Name_ : o2::soa::Column<_Type_, _Name_> { \
2531 static constexpr const char* mLabel = _Label_; \
2532 static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_>(), std::string_view{#_Getter_}); \
2533 static constexpr const int32_t mHash = _Label_ ""_h; \
2534 using base = o2::soa::Column<_Type_, _Name_>; \
2535 using type = _Type_; \
2536 using column_t = _Name_; \
2537 using spawnable_t = std::true_type; \
2538 _Name_(arrow::ChunkedArray const* column) \
2539 : o2::soa::Column<_Type_, _Name_>(o2::soa::ColumnIterator<type>(column)) \
2540 { \
2541 } \
2542 \
2543 _Name_() = default; \
2544 _Name_(_Name_ const& other) = default; \
2545 _Name_& operator=(_Name_ const& other) = default; \
2546 \
2547 decltype(auto) _Getter_() const \
2548 { \
2549 return *mColumnIterator; \
2550 } \
2551 \
2552 decltype(auto) get() const \
2553 { \
2554 return _Getter_(); \
2555 } \
2556 }; \
2557 [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_ { _Label_, _Name_::hash, o2::framework::expressions::selectArrowType<_Type_>() }
2558
2577
2579
2580template <o2::soa::is_table T>
2581consteval auto getIndexTargets()
2582{
2583 return T::originals;
2584}
2585
2586#define DECLARE_SOA_SLICE_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, _Label_, _Suffix_) \
2587 struct _Name_##IdSlice : o2::soa::Column<_Type_[2], _Name_##IdSlice> { \
2588 static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \
2589 static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \
2590 static constexpr const char* mLabel = "fIndexSlice" _Label_ _Suffix_; \
2591 static constexpr const uint32_t hash = 0; \
2592 using base = o2::soa::Column<_Type_[2], _Name_##IdSlice>; \
2593 using type = _Type_[2]; \
2594 using column_t = _Name_##IdSlice; \
2595 using binding_t = _Table_; \
2596 static constexpr auto index_targets = getIndexTargets<_Table_>(); \
2597 _Name_##IdSlice(arrow::ChunkedArray const* column) \
2598 : o2::soa::Column<_Type_[2], _Name_##IdSlice>(o2::soa::ColumnIterator<type>(column)) \
2599 { \
2600 } \
2601 \
2602 _Name_##IdSlice() = default; \
2603 _Name_##IdSlice(_Name_##IdSlice const& other) = default; \
2604 _Name_##IdSlice& operator=(_Name_##IdSlice const& other) = default; \
2605 std::array<_Type_, 2> inline getIds() const \
2606 { \
2607 return _Getter_##Ids(); \
2608 } \
2609 \
2610 bool has_##_Getter_() const \
2611 { \
2612 auto a = *mColumnIterator; \
2613 return a[0] >= 0 && a[1] >= 0; \
2614 } \
2615 \
2616 std::array<_Type_, 2> _Getter_##Ids() const \
2617 { \
2618 auto a = *mColumnIterator; \
2619 return std::array{a[0], a[1]}; \
2620 } \
2621 \
2622 template <typename T> \
2623 auto _Getter_##_as() const \
2624 { \
2625 if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \
2626 o2::soa::notBoundTable(#_Table_); \
2627 } \
2628 auto t = mBinding.get<T>(); \
2629 if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \
2630 o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \
2631 } \
2632 if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \
2633 return t->emptySlice(); \
2634 } \
2635 auto a = *mColumnIterator; \
2636 auto r = t->rawSlice(a[0], a[1]); \
2637 t->copyIndexBindings(r); \
2638 r.bindInternalIndicesTo(t); \
2639 return r; \
2640 } \
2641 \
2642 auto _Getter_() const \
2643 { \
2644 return _Getter_##_as<binding_t>(); \
2645 } \
2646 \
2647 template <typename T> \
2648 bool setCurrent(T const* current) \
2649 { \
2650 if constexpr (o2::soa::is_binding_compatible_v<T, binding_t>()) { \
2651 assert(current != nullptr); \
2652 this->mBinding.bind(current); \
2653 return true; \
2654 } \
2655 return false; \
2656 } \
2657 \
2658 bool setCurrentRaw(o2::soa::Binding current) \
2659 { \
2660 this->mBinding = current; \
2661 return true; \
2662 } \
2663 binding_t const* getCurrent() const { return mBinding.get<binding_t>(); } \
2664 o2::soa::Binding getCurrentRaw() const { return mBinding; } \
2665 o2::soa::Binding mBinding; \
2666 };
2667
2668#define DECLARE_SOA_SLICE_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_) DECLARE_SOA_SLICE_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, #_Table_, _Suffix_)
2669#define DECLARE_SOA_SLICE_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_SLICE_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, _Name_##s, "")
2670#define DECLARE_SOA_SLICE_INDEX_COLUMN_CUSTOM(_Name_, _Getter_, _Label_) DECLARE_SOA_SLICE_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, int32_t, _Name_##s, _Label_, "")
2671
2673#define DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, _Label_, _Suffix_) \
2674 struct _Name_##Ids : o2::soa::Column<std::vector<_Type_>, _Name_##Ids> { \
2675 static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \
2676 static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \
2677 static constexpr const char* mLabel = "fIndexArray" _Label_ _Suffix_; \
2678 static constexpr const uint32_t hash = 0; \
2679 using base = o2::soa::Column<std::vector<_Type_>, _Name_##Ids>; \
2680 using type = std::vector<_Type_>; \
2681 using column_t = _Name_##Ids; \
2682 using binding_t = _Table_; \
2683 static constexpr auto index_targets = getIndexTargets<_Table_>(); \
2684 _Name_##Ids(arrow::ChunkedArray const* column) \
2685 : o2::soa::Column<std::vector<_Type_>, _Name_##Ids>(o2::soa::ColumnIterator<type>(column)) \
2686 { \
2687 } \
2688 \
2689 _Name_##Ids() = default; \
2690 _Name_##Ids(_Name_##Ids const& other) = default; \
2691 _Name_##Ids& operator=(_Name_##Ids const& other) = default; \
2692 \
2693 gsl::span<const _Type_> inline getIds() const \
2694 { \
2695 return _Getter_##Ids(); \
2696 } \
2697 \
2698 gsl::span<const _Type_> _Getter_##Ids() const \
2699 { \
2700 return *mColumnIterator; \
2701 } \
2702 \
2703 bool has_##_Getter_() const \
2704 { \
2705 return !(*mColumnIterator).empty(); \
2706 } \
2707 \
2708 template <soa::is_table T> \
2709 auto _Getter_##_as() const \
2710 { \
2711 if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \
2712 o2::soa::notBoundTable(#_Table_); \
2713 } \
2714 auto t = mBinding.get<T>(); \
2715 if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \
2716 o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \
2717 } \
2718 auto result = std::vector<typename T::unfiltered_iterator>(); \
2719 result.reserve((*mColumnIterator).size()); \
2720 for (auto& i : *mColumnIterator) { \
2721 result.emplace_back(t->rawIteratorAt(i)); \
2722 } \
2723 return result; \
2724 } \
2725 \
2726 template <soa::is_filtered_table T> \
2727 auto filtered_##_Getter_##_as() const \
2728 { \
2729 if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \
2730 o2::soa::notBoundTable(#_Table_); \
2731 } \
2732 auto t = mBinding.get<T>(); \
2733 if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \
2734 o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \
2735 } \
2736 auto result = std::vector<typename T::iterator>(); \
2737 result.reserve((*mColumnIterator).size()); \
2738 for (auto const& i : *mColumnIterator) { \
2739 auto pos = t->isInSelectedRows(i); \
2740 if (pos > 0) { \
2741 result.emplace_back(t->iteratorAt(pos)); \
2742 } \
2743 } \
2744 return result; \
2745 } \
2746 \
2747 auto _Getter_() const \
2748 { \
2749 return _Getter_##_as<binding_t>(); \
2750 } \
2751 \
2752 template <typename T> \
2753 auto _Getter_##_first_as() const \
2754 { \
2755 if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \
2756 o2::soa::notBoundTable(#_Table_); \
2757 } \
2758 auto t = mBinding.get<T>(); \
2759 if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \
2760 o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \
2761 } \
2762 return t->rawIteratorAt((*mColumnIterator)[0]); \
2763 } \
2764 \
2765 template <typename T> \
2766 auto _Getter_##_last_as() const \
2767 { \
2768 if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \
2769 o2::soa::notBoundTable(#_Table_); \
2770 } \
2771 auto t = mBinding.get<T>(); \
2772 if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \
2773 o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \
2774 } \
2775 return t->rawIteratorAt((*mColumnIterator).back()); \
2776 } \
2777 \
2778 auto _Getter_first() const \
2779 { \
2780 return _Getter_##_first_as<binding_t>(); \
2781 } \
2782 \
2783 auto _Getter_last() const \
2784 { \
2785 return _Getter_##_last_as<binding_t>(); \
2786 } \
2787 \
2788 template <typename T> \
2789 bool setCurrent(T const* current) \
2790 { \
2791 if constexpr (o2::soa::is_binding_compatible_v<T, binding_t>()) { \
2792 assert(current != nullptr); \
2793 this->mBinding.bind(current); \
2794 return true; \
2795 } \
2796 return false; \
2797 } \
2798 \
2799 bool setCurrentRaw(o2::soa::Binding current) \
2800 { \
2801 this->mBinding = current; \
2802 return true; \
2803 } \
2804 binding_t const* getCurrent() const { return mBinding.get<binding_t>(); } \
2805 o2::soa::Binding getCurrentRaw() const { return mBinding; } \
2806 o2::soa::Binding mBinding; \
2807 };
2808
2809#define DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_) DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, #_Table_, _Suffix_)
2810#define DECLARE_SOA_ARRAY_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, _Name_##s, "")
2811#define DECLARE_SOA_ARRAY_INDEX_COLUMN_CUSTOM(_Name_, _Getter_, _Label_) DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, int32_t, _Name_##s, _Label_, "")
2812
2814#define DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, _Label_, _Suffix_) \
2815 struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \
2816 static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \
2817 static_assert((*_Suffix_ == '\0') || (*_Suffix_ == '_'), "Suffix has to begin with _"); \
2818 static constexpr const char* mLabel = "fIndex" _Label_ _Suffix_; \
2819 static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \
2820 using base = o2::soa::Column<_Type_, _Name_##Id>; \
2821 using type = _Type_; \
2822 using column_t = _Name_##Id; \
2823 using binding_t = _Table_; \
2824 static constexpr auto index_targets = getIndexTargets<_Table_>(); \
2825 _Name_##Id(arrow::ChunkedArray const* column) \
2826 : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator<type>(column)) \
2827 { \
2828 } \
2829 \
2830 _Name_##Id() = default; \
2831 _Name_##Id(_Name_##Id const& other) = default; \
2832 _Name_##Id& operator=(_Name_##Id const& other) = default; \
2833 type inline getId() const \
2834 { \
2835 return _Getter_##Id(); \
2836 } \
2837 \
2838 type _Getter_##Id() const \
2839 { \
2840 return *mColumnIterator; \
2841 } \
2842 \
2843 bool has_##_Getter_() const \
2844 { \
2845 return *mColumnIterator >= 0; \
2846 } \
2847 \
2848 template <typename T> \
2849 auto _Getter_##_as() const \
2850 { \
2851 if (O2_BUILTIN_UNLIKELY(mBinding.ptr == nullptr)) { \
2852 o2::soa::notBoundTable(#_Table_); \
2853 } \
2854 if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \
2855 o2::soa::accessingInvalidIndexFor(#_Getter_); \
2856 } \
2857 auto t = mBinding.get<T>(); \
2858 if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \
2859 o2::soa::dereferenceWithWrongType(#_Getter_, #_Table_); \
2860 } \
2861 return t->rawIteratorAt(*mColumnIterator); \
2862 } \
2863 \
2864 auto _Getter_() const \
2865 { \
2866 return _Getter_##_as<binding_t>(); \
2867 } \
2868 \
2869 template <typename T> \
2870 bool setCurrent(T* current) \
2871 { \
2872 if constexpr (o2::soa::is_binding_compatible_v<T, binding_t>()) { \
2873 assert(current != nullptr); \
2874 this->mBinding.bind(current); \
2875 return true; \
2876 } \
2877 return false; \
2878 } \
2879 \
2880 bool setCurrentRaw(o2::soa::Binding current) \
2881 { \
2882 this->mBinding = current; \
2883 return true; \
2884 } \
2885 binding_t const* getCurrent() const { return mBinding.get<binding_t>(); } \
2886 o2::soa::Binding getCurrentRaw() const { return mBinding; } \
2887 o2::soa::Binding mBinding; \
2888 }; \
2889 [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_ _Suffix_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() }
2890
2891#define DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Table_, _Suffix_) DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, _Type_, _Table_, #_Table_, _Suffix_)
2892#define DECLARE_SOA_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, _Name_##s, "")
2893#define DECLARE_SOA_INDEX_COLUMN_CUSTOM(_Name_, _Getter_, _Label_) DECLARE_SOA_INDEX_COLUMN_FULL_CUSTOM(_Name_, _Getter_, int32_t, _Name_##s, _Label_, "")
2894
2896#define DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, _IndexTarget_) \
2897 struct _Name_##Id : o2::soa::Column<_Type_, _Name_##Id> { \
2898 static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \
2899 static constexpr const char* mLabel = "fIndex" _Label_; \
2900 static constexpr const uint32_t hash = compile_time_hash(namespace_prefix<_Name_##Id>(), std::string_view{#_Getter_ "Id"}); \
2901 using base = o2::soa::Column<_Type_, _Name_##Id>; \
2902 using type = _Type_; \
2903 using column_t = _Name_##Id; \
2904 using self_index_t = std::true_type; \
2905 using compatible_signature = std::conditional<aod::is_aod_hash<_IndexTarget_>, _IndexTarget_, void>; \
2906 _Name_##Id(arrow::ChunkedArray const* column) \
2907 : o2::soa::Column<_Type_, _Name_##Id>(o2::soa::ColumnIterator<type>(column)) \
2908 { \
2909 } \
2910 \
2911 _Name_##Id() = default; \
2912 _Name_##Id(_Name_##Id const& other) = default; \
2913 _Name_##Id& operator=(_Name_##Id const& other) = default; \
2914 type inline getId() const \
2915 { \
2916 return _Getter_##Id(); \
2917 } \
2918 \
2919 type _Getter_##Id() const \
2920 { \
2921 return *mColumnIterator; \
2922 } \
2923 \
2924 bool has_##_Getter_() const \
2925 { \
2926 return *mColumnIterator >= 0; \
2927 } \
2928 \
2929 template <typename T> \
2930 auto _Getter_##_as() const \
2931 { \
2932 if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \
2933 o2::soa::accessingInvalidIndexFor(#_Getter_); \
2934 } \
2935 auto t = mBinding.get<T>(); \
2936 if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \
2937 o2::soa::dereferenceWithWrongType(#_Getter_, "self"); \
2938 } \
2939 return t->rawIteratorAt(*mColumnIterator); \
2940 } \
2941 \
2942 bool setCurrentRaw(o2::soa::Binding current) \
2943 { \
2944 this->mBinding = current; \
2945 return true; \
2946 } \
2947 o2::soa::Binding getCurrentRaw() const { return mBinding; } \
2948 o2::soa::Binding mBinding; \
2949 }; \
2950 [[maybe_unused]] static constexpr o2::framework::expressions::BindingNode _Getter_##Id { "fIndex" _Label_, _Name_##Id::hash, o2::framework::expressions::selectArrowType<_Type_>() }
2951
2952#define DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) DECLARE_SOA_SELF_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, void)
2953#define DECLARE_SOA_SELF_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_SELF_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, #_Name_)
2955#define DECLARE_SOA_SELF_SLICE_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, _IndexTarget_) \
2956 struct _Name_##IdSlice : o2::soa::Column<_Type_[2], _Name_##IdSlice> { \
2957 static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \
2958 static constexpr const char* mLabel = "fIndexSlice" _Label_; \
2959 static constexpr const uint32_t hash = 0; \
2960 using base = o2::soa::Column<_Type_[2], _Name_##IdSlice>; \
2961 using type = _Type_[2]; \
2962 using column_t = _Name_##IdSlice; \
2963 using self_index_t = std::true_type; \
2964 using compatible_signature = std::conditional<aod::is_aod_hash<_IndexTarget_>, _IndexTarget_, void>; \
2965 _Name_##IdSlice(arrow::ChunkedArray const* column) \
2966 : o2::soa::Column<_Type_[2], _Name_##IdSlice>(o2::soa::ColumnIterator<type>(column)) \
2967 { \
2968 } \
2969 \
2970 _Name_##IdSlice() = default; \
2971 _Name_##IdSlice(_Name_##IdSlice const& other) = default; \
2972 _Name_##IdSlice& operator=(_Name_##IdSlice const& other) = default; \
2973 std::array<_Type_, 2> inline getIds() const \
2974 { \
2975 return _Getter_##Ids(); \
2976 } \
2977 \
2978 bool has_##_Getter_() const \
2979 { \
2980 auto a = *mColumnIterator; \
2981 return a[0] >= 0 && a[1] >= 0; \
2982 } \
2983 \
2984 std::array<_Type_, 2> _Getter_##Ids() const \
2985 { \
2986 auto a = *mColumnIterator; \
2987 return std::array{a[0], a[1]}; \
2988 } \
2989 \
2990 template <typename T> \
2991 auto _Getter_##_as() const \
2992 { \
2993 auto t = mBinding.get<T>(); \
2994 if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \
2995 o2::soa::dereferenceWithWrongType(#_Getter_, "self"); \
2996 } \
2997 if (O2_BUILTIN_UNLIKELY(!has_##_Getter_())) { \
2998 return t->emptySlice(); \
2999 } \
3000 auto a = *mColumnIterator; \
3001 auto r = t->rawSlice(a[0], a[1]); \
3002 t->copyIndexBindings(r); \
3003 r.bindInternalIndicesTo(t); \
3004 return r; \
3005 } \
3006 \
3007 bool setCurrentRaw(o2::soa::Binding current) \
3008 { \
3009 this->mBinding = current; \
3010 return true; \
3011 } \
3012 o2::soa::Binding getCurrentRaw() const { return mBinding; } \
3013 o2::soa::Binding mBinding; \
3014 };
3015
3016#define DECLARE_SOA_SELF_SLICE_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) DECLARE_SOA_SELF_SLICE_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, void)
3017#define DECLARE_SOA_SELF_SLICE_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_SELF_SLICE_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, "_" #_Name_)
3019#define DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, _IndexTarget_) \
3020 struct _Name_##Ids : o2::soa::Column<std::vector<_Type_>, _Name_##Ids> { \
3021 static_assert(std::is_integral_v<_Type_>, "Index type must be integral"); \
3022 static constexpr const char* mLabel = "fIndexArray" _Label_; \
3023 static constexpr const uint32_t hash = 0; \
3024 using base = o2::soa::Column<std::vector<_Type_>, _Name_##Ids>; \
3025 using type = std::vector<_Type_>; \
3026 using column_t = _Name_##Ids; \
3027 using self_index_t = std::true_type; \
3028 using compatible_signature = std::conditional<aod::is_aod_hash<_IndexTarget_>, _IndexTarget_, void>; \
3029 _Name_##Ids(arrow::ChunkedArray const* column) \
3030 : o2::soa::Column<std::vector<_Type_>, _Name_##Ids>(o2::soa::ColumnIterator<type>(column)) \
3031 { \
3032 } \
3033 \
3034 _Name_##Ids() = default; \
3035 _Name_##Ids(_Name_##Ids const& other) = default; \
3036 _Name_##Ids& operator=(_Name_##Ids const& other) = default; \
3037 gsl::span<const _Type_> inline getIds() const \
3038 { \
3039 return _Getter_##Ids(); \
3040 } \
3041 \
3042 gsl::span<const _Type_> _Getter_##Ids() const \
3043 { \
3044 return *mColumnIterator; \
3045 } \
3046 \
3047 bool has_##_Getter_() const \
3048 { \
3049 return !(*mColumnIterator).empty(); \
3050 } \
3051 \
3052 template <typename T> \
3053 auto _Getter_##_as() const \
3054 { \
3055 auto t = mBinding.get<T>(); \
3056 if (O2_BUILTIN_UNLIKELY(t == nullptr)) { \
3057 o2::soa::dereferenceWithWrongType(#_Getter_, "self"); \
3058 } \
3059 auto result = std::vector<typename T::unfiltered_iterator>(); \
3060 for (auto& i : *mColumnIterator) { \
3061 result.push_back(t->rawIteratorAt(i)); \
3062 } \
3063 return result; \
3064 } \
3065 \
3066 template <typename T> \
3067 auto _Getter_##_first_as() const \
3068 { \
3069 return mBinding.get<T>()->rawIteratorAt((*mColumnIterator)[0]); \
3070 } \
3071 \
3072 template <typename T> \
3073 auto _Getter_##_last_as() const \
3074 { \
3075 return mBinding.get<T>()->rawIteratorAt((*mColumnIterator).back()); \
3076 } \
3077 \
3078 bool setCurrentRaw(o2::soa::Binding current) \
3079 { \
3080 this->mBinding = current; \
3081 return true; \
3082 } \
3083 o2::soa::Binding getCurrentRaw() const { return mBinding; } \
3084 o2::soa::Binding mBinding; \
3085 };
3086
3087#define DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_) DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN_COMPLETE(_Name_, _Getter_, _Type_, _Label_, void)
3088#define DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(_Name_, _Getter_) DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN_FULL(_Name_, _Getter_, int32_t, "_" #_Name_)
3089
3118#define DECLARE_SOA_DYNAMIC_COLUMN(_Name_, _Getter_, ...) \
3119 struct _Name_##Callback { \
3120 static inline constexpr auto getLambda() { return __VA_ARGS__; } \
3121 }; \
3122 \
3123 struct _Name_##Helper { \
3124 using callable_t = decltype(o2::framework::FunctionMetadata(std::declval<decltype(_Name_##Callback::getLambda())>())); \
3125 using return_type = typename callable_t::return_type; \
3126 }; \
3127 template <typename... Bindings> \
3128 struct _Name_ : o2::soa::DynamicColumn<typename _Name_##Helper::callable_t::type, _Name_<Bindings...>> { \
3129 using base = o2::soa::DynamicColumn<typename _Name_##Helper::callable_t::type, _Name_<Bindings...>>; \
3130 using helper = _Name_##Helper; \
3131 using callback_holder_t = _Name_##Callback; \
3132 using callable_t = helper::callable_t; \
3133 using callback_t = callable_t::type; \
3134 static constexpr const uint32_t hash = 0; \
3135 \
3136 _Name_(arrow::ChunkedArray const*) \
3137 { \
3138 } \
3139 _Name_() = default; \
3140 _Name_(_Name_ const& other) = default; \
3141 _Name_& operator=(_Name_ const& other) = default; \
3142 static constexpr const char* mLabel = #_Name_; \
3143 using type = typename callable_t::return_type; \
3144 \
3145 template <typename... FreeArgs> \
3146 type _Getter_(FreeArgs... freeArgs) const \
3147 { \
3148 return boundGetter(std::make_index_sequence<std::tuple_size_v<decltype(boundIterators)>>{}, freeArgs...); \
3149 } \
3150 template <typename... FreeArgs> \
3151 type getDynamicValue(FreeArgs... freeArgs) const \
3152 { \
3153 return boundGetter(std::make_index_sequence<std::tuple_size_v<decltype(boundIterators)>>{}, freeArgs...); \
3154 } \
3155 \
3156 type get() const \
3157 { \
3158 return _Getter_(); \
3159 } \
3160 \
3161 template <size_t... Is, typename... FreeArgs> \
3162 type boundGetter(std::integer_sequence<size_t, Is...>&&, FreeArgs... freeArgs) const \
3163 { \
3164 return __VA_ARGS__((**std::get<Is>(boundIterators))..., freeArgs...); \
3165 } \
3166 \
3167 using bindings_t = typename o2::framework::pack<Bindings...>; \
3168 std::tuple<o2::soa::ColumnIterator<typename Bindings::type> const*...> boundIterators; \
3169 }
3170
3171#define DECLARE_SOA_TABLE_METADATA(_Name_, _Desc_, _Version_, ...) \
3172 using _Name_##Metadata = TableMetadata<Hash<_Desc_ "/" #_Version_ ""_h>, __VA_ARGS__>;
3173
3174#define DECLARE_SOA_TABLE_METADATA_TRAIT(_Name_, _Desc_, _Version_) \
3175 template <> \
3176 struct MetadataTrait<Hash<_Desc_ "/" #_Version_ ""_h>> { \
3177 static constexpr void isMetadataTrait() {}; \
3178 using metadata = _Name_##Metadata; \
3179 };
3180
3181#define DECLARE_SOA_TABLE_FULL_VERSIONED_(_Name_, _Label_, _Origin_, _Desc_, _Version_) \
3182 O2HASH(_Desc_ "/" #_Version_); \
3183 template <typename O> \
3184 using _Name_##From = o2::soa::Table<Hash<_Label_ ""_h>, Hash<_Desc_ "/" #_Version_ ""_h>, O>; \
3185 using _Name_ = _Name_##From<Hash<_Origin_ ""_h>>; \
3186 template <> \
3187 struct MetadataTrait<Hash<_Desc_ "/" #_Version_ ""_h>> { \
3188 static constexpr void isMetadataTrait() {}; \
3189 using metadata = _Name_##Metadata; \
3190 };
3191
3192#define DECLARE_SOA_STAGE(_Name_, _Origin_, _Desc_, _Version_) \
3193 template <typename O> \
3194 using _Name_##From = o2::soa::Table<Hash<#_Name_ ""_h>, Hash<_Desc_ "/" #_Version_ ""_h>, O>; \
3195 using _Name_ = _Name_##From<Hash<_Origin_ ""_h>>;
3196
3197#define DECLARE_SOA_TABLE_FULL_VERSIONED(_Name_, _Label_, _Origin_, _Desc_, _Version_, ...) \
3198 DECLARE_SOA_TABLE_METADATA(_Name_, _Desc_, _Version_, __VA_ARGS__); \
3199 DECLARE_SOA_TABLE_FULL_VERSIONED_(_Name_, _Label_, _Origin_, _Desc_, _Version_);
3200
3201#define DECLARE_SOA_TABLE_FULL(_Name_, _Label_, _Origin_, _Desc_, ...) \
3202 O2HASH(_Label_); \
3203 DECLARE_SOA_TABLE_METADATA(_Name_, _Desc_, 0, __VA_ARGS__); \
3204 DECLARE_SOA_TABLE_FULL_VERSIONED_(_Name_, _Label_, _Origin_, _Desc_, 0)
3205
3206#define DECLARE_SOA_TABLE(_Name_, _Origin_, _Desc_, ...) \
3207 DECLARE_SOA_TABLE_FULL(_Name_, #_Name_, _Origin_, _Desc_, __VA_ARGS__)
3208
3209#define DECLARE_SOA_TABLE_VERSIONED(_Name_, _Origin_, _Desc_, _Version_, ...) \
3210 O2HASH(#_Name_); \
3211 DECLARE_SOA_TABLE_METADATA(_Name_, _Desc_, _Version_, __VA_ARGS__); \
3212 DECLARE_SOA_TABLE_FULL_VERSIONED_(_Name_, #_Name_, _Origin_, _Desc_, _Version_)
3213
3214#define DECLARE_SOA_TABLE_STAGED_VERSIONED(_BaseName_, _Desc_, _Version_, ...) \
3215 O2HASH(_Desc_ "/" #_Version_); \
3216 O2HASH(#_BaseName_); \
3217 O2HASH("Stored" #_BaseName_); \
3218 DECLARE_SOA_TABLE_METADATA(_BaseName_, _Desc_, _Version_, __VA_ARGS__); \
3219 using Stored##_BaseName_##Metadata = _BaseName_##Metadata; \
3220 DECLARE_SOA_TABLE_METADATA_TRAIT(_BaseName_, _Desc_, _Version_); \
3221 DECLARE_SOA_STAGE(_BaseName_, "AOD", _Desc_, _Version_); \
3222 DECLARE_SOA_STAGE(Stored##_BaseName_, "AOD1", _Desc_, _Version_);
3223
3224#define DECLARE_SOA_TABLE_STAGED(_BaseName_, _Desc_, ...) \
3225 DECLARE_SOA_TABLE_STAGED_VERSIONED(_BaseName_, _Desc_, 0, __VA_ARGS__);
3226
3227#define DECLARE_SOA_EXTENDED_TABLE_NG(_Name_, _OriginalTable_, _Desc_, _Version_, ...) \
3228 O2HASH(_Desc_ "/" #_Version_); \
3229 O2HASH(#_Name_ "Extension"); \
3230 template <typename O> \
3231 using _Name_##ExtensionFrom = soa::Table<o2::aod::Hash<#_Name_ "Extension"_h>, o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>, O>; \
3232 using _Name_##Extension = _Name_##ExtensionFrom<o2::aod::Hash<"AOD"_h>>; \
3233 struct _Name_##ExtensionMetadata : TableMetadata<o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>, __VA_ARGS__> { \
3234 using base_table_t = _OriginalTable_; \
3235 template <o2::aod::is_origin_hash O> \
3236 using extension_table_t_from = _Name_##ExtensionFrom<O>; \
3237 using extension_table_t = _Name_##Extension; \
3238 using expression_pack_t = framework::pack<__VA_ARGS__>; \
3239 static constexpr auto N = _OriginalTable_::originals.size(); \
3240 template <o2::aod::is_origin_hash O = o2::aod::Hash<"AOD"_h>> \
3241 static consteval auto generateSources() \
3242 { \
3243 return _OriginalTable_##From<O>::originals; \
3244 } \
3245 }; \
3246 template <> \
3247 struct MetadataTrait<o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>> { \
3248 static constexpr void isMetadataTrait() {}; \
3249 using metadata = _Name_##ExtensionMetadata; \
3250 }; \
3251 template <typename O> \
3252 using _Name_##From = o2::soa::Join<_OriginalTable_##From<O>, _Name_##ExtensionFrom<O>>; \
3253 using _Name_ = _Name_##From<o2::aod::Hash<"AOD"_h>>;
3254
3255#define DECLARE_SOA_EXTENDED_TABLE(_Name_, _Table_, _Description_, _Version_, ...) \
3256 DECLARE_SOA_EXTENDED_TABLE_NG(_Name_, _Table_, _Description_, _Version_, __VA_ARGS__)
3257
3258#define DECLARE_SOA_EXTENDED_TABLE_USER(_Name_, _Table_, _Description_, ...) \
3259 DECLARE_SOA_EXTENDED_TABLE_NG(_Name_, _Table_, "EX" _Description_, 0, __VA_ARGS__)
3260
3261#define DECLARE_SOA_CONFIGURABLE_EXTENDED_TABLE_NG(_Name_, _OriginalTable_, _Desc_, _Version_, ...) \
3262 O2HASH(_Desc_ "/" #_Version_); \
3263 O2HASH(#_Name_ "CfgExtension"); \
3264 template <typename O> \
3265 using _Name_##CfgExtensionFrom = soa::Table<o2::aod::Hash<#_Name_ "CfgExtension"_h>, o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>, O>; \
3266 using _Name_##CfgExtension = _Name_##CfgExtensionFrom<o2::aod::Hash<"AOD"_h>>; \
3267 struct _Name_##CfgExtensionMetadata : TableMetadata<o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>, __VA_ARGS__> { \
3268 using base_table_t = _OriginalTable_; \
3269 template <o2::aod::is_origin_hash O> \
3270 using extension_table_t_from = _Name_##CfgExtensionFrom<O>; \
3271 using extension_table_t = _Name_##CfgExtension; \
3272 using placeholders_pack_t = framework::pack<__VA_ARGS__>; \
3273 using configurable_t = std::true_type; \
3274 static constexpr auto N = _OriginalTable_::originals.size(); \
3275 template <o2::aod::is_origin_hash O = o2::aod::Hash<"AOD"_h>> \
3276 static consteval auto generateSources() \
3277 { \
3278 return _OriginalTable_##From<O>::originals; \
3279 } \
3280 }; \
3281 template <> \
3282 struct MetadataTrait<o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>> { \
3283 static constexpr void isMetadataTrait() {}; \
3284 using metadata = _Name_##CfgExtensionMetadata; \
3285 }; \
3286 template <typename O> \
3287 using _Name_##From = o2::soa::Join<_OriginalTable_##From<O>, _Name_##CfgExtensionFrom<O>>; \
3288 using _Name_ = _Name_##From<o2::aod::Hash<"AOD"_h>>;
3289
3290#define DECLARE_SOA_CONFIGURABLE_EXTENDED_TABLE(_Name_, _OriginalTable_, _Description_, ...) \
3291 DECLARE_SOA_CONFIGURABLE_EXTENDED_TABLE_NG(_Name_, _OriginalTable_, "EX" _Description_, 0, __VA_ARGS__)
3292
3293#define DECLARE_SOA_INDEX_TABLE_NG(_Name_, _Key_, _Version_, _Desc_, _Exclusive_, ...) \
3294 O2HASH(#_Name_); \
3295 O2HASH(_Desc_ "/" #_Version_); \
3296 struct _Name_##Metadata : o2::aod::TableMetadata<o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>, soa::Index<>, __VA_ARGS__> { \
3297 static constexpr bool exclusive = _Exclusive_; \
3298 template <o2::aod::is_origin_hash O> \
3299 using KeyFrom = _Key_##From<O>; \
3300 using Key = _Key_; \
3301 using index_pack_t = framework::pack<__VA_ARGS__>; \
3302 template <o2::aod::is_origin_hash O = o2::aod::Hash<"AOD"_h>> \
3303 static consteval auto generateSources() \
3304 { \
3305 return []<soa::is_index_column... Cs>(framework::pack<Cs...>) { \
3306 constexpr auto first = o2::soa::mergeOriginals<typename Cs::binding_t...>(); \
3307 constexpr auto second = o2::aod::filterForKey<first.size(), first, Key>(); \
3308 return o2::aod::replaceOrigin<second.size(), second, O>(); \
3309 }(framework::pack<__VA_ARGS__>{}); \
3310 } \
3311 static constexpr auto N = []<typename... Cs>(framework::pack<Cs...>) { \
3312 constexpr auto a = o2::soa::mergeOriginals<typename Cs::binding_t...>(); \
3313 return o2::aod::filterForKey<a.size(), a, Key>(); \
3314 }(framework::pack<__VA_ARGS__>{}) \
3315 .size(); \
3316 }; \
3317 template <> \
3318 struct MetadataTrait<o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>> { \
3319 static constexpr void isMetadataTrait() {}; \
3320 using metadata = _Name_##Metadata; \
3321 }; \
3322 template <o2::aod::is_origin_hash O> \
3323 using _Name_##From = o2::soa::IndexTable<o2::aod::Hash<#_Name_ ""_h>, o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>, O, _Key_##From<O>, __VA_ARGS__>; \
3324 using _Name_ = _Name_##From<o2::aod::Hash<"AOD"_h>>;
3325
3326#define DECLARE_SOA_INDEX_TABLE(_Name_, _Key_, _Description_, ...) \
3327 DECLARE_SOA_INDEX_TABLE_NG(_Name_, _Key_, 0, _Description_, false, __VA_ARGS__)
3328
3329#define DECLARE_SOA_INDEX_TABLE_EXCLUSIVE(_Name_, _Key_, _Description_, ...) \
3330 DECLARE_SOA_INDEX_TABLE_NG(_Name_, _Key_, 0, _Description_, true, __VA_ARGS__)
3331
3332#define DECLARE_SOA_INDEX_TABLE_USER(_Name_, _Key_, _Description_, ...) \
3333 DECLARE_SOA_INDEX_TABLE_NG(_Name_, _Key_, 0, _Description_, false, __VA_ARGS__)
3334
3335#define DECLARE_SOA_INDEX_TABLE_EXCLUSIVE_USER(_Name_, _Key_, _Description_, ...) \
3336 DECLARE_SOA_INDEX_TABLE_NG(_Name_, _Key_, 0, _Description_, true, __VA_ARGS__)
3337
3338// Declare were each row is associated to a timestamp column of an _TimestampSource_
3339// table.
3340//
3341// The columns of this table have to be CCDB_COLUMNS so that for each timestamp, we get a row
3342// which points to the specified CCDB objectes described by those columns.
3343#define DECLARE_SOA_TIMESTAMPED_TABLE_FULL(_Name_, _Label_, _TimestampSource_, _TimestampColumn_, _UniformitySource_, _UniformityColumn_, _Version_, _Desc_, ...) \
3344 O2HASH(_Desc_ "/" #_Version_); \
3345 template <typename O> \
3346 using _Name_##TimestampFrom = soa::Table<o2::aod::Hash<_Label_ ""_h>, o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>, O>; \
3347 using _Name_##Timestamp = _Name_##TimestampFrom<o2::aod::Hash< \
3348 "AOD" \
3349 ""_h>>; \
3350 struct _Name_##TimestampMetadata : TableMetadata<o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>, __VA_ARGS__> { \
3351 template <typename O = o2::aod::Hash<"AOD" \
3352 ""_h>> \
3353 using base_table_t = _TimestampSource_##From<O>; \
3354 template <typename O = o2::aod::Hash<"AOD" \
3355 ""_h>> \
3356 using extension_table_t = _Name_##TimestampFrom<O>; \
3357 static constexpr const auto ccdb_urls = []<typename... Cs>(framework::pack<Cs...>) { \
3358 return std::array<std::string_view, sizeof...(Cs)>{Cs::query...}; \
3359 }(framework::pack<__VA_ARGS__>{}); \
3360 static constexpr const auto ccdb_bindings = []<typename... Cs>(framework::pack<Cs...>) { \
3361 return std::array<std::string_view, sizeof...(Cs)>{Cs::mLabel...}; \
3362 }(framework::pack<__VA_ARGS__>{}); \
3363 static constexpr const auto ccdb_run_dependent = []<typename... Cs>(framework::pack<Cs...>) { \
3364 return std::array<int, sizeof...(Cs)>{Cs::run_dependent...}; \
3365 }(framework::pack<__VA_ARGS__>{}); \
3366 /* The uniformity column may live in a table other than the timestamp source (the run */ \
3367 /* number is on aod::BCs, the timestamp on aod::Timestamps). Both are handed to the */ \
3368 /* fetcher, which reads them positionally — sound because the two are row-aligned. */ \
3369 /* Row alignment cannot be checked here: ASoA encodes no type-level relation between */ \
3370 /* two tables that happen to have equal row counts (aod::BCs and aod::Timestamps have */ \
3371 /* disjoint originals). The CCDB fetcher verifies the lengths match before reading. */ \
3372 static constexpr auto N = o2::soa::mergeOriginals<_TimestampSource_, _UniformitySource_>().size(); \
3373 template <o2::aod::is_origin_hash O = o2::aod::Hash<"AOD"_h>> \
3374 static consteval auto generateSources() \
3375 { \
3376 return o2::soa::mergeOriginals<_TimestampSource_##From<O>, _UniformitySource_##From<O>>(); \
3377 } \
3378 static constexpr auto timestamp_column_label = _TimestampColumn_::mLabel; \
3379 /* Rows sharing a uniformity value resolve to the same CCDB object, so the fetcher */ \
3380 /* need only query once per distinct value. Defaults to the timestamp column, i.e. */ \
3381 /* every distinct timestamp may yield a different object — the pre-existing behaviour.*/ \
3382 static constexpr auto uniformity_column_label = _UniformityColumn_::mLabel; \
3383 /*static constexpr auto timestampColumn = _TimestampColumn_;*/ \
3384 }; \
3385 template <> \
3386 struct MetadataTrait<o2::aod::Hash<_Desc_ "/" #_Version_ ""_h>> { \
3387 static constexpr void isMetadataTrait() {}; \
3388 using metadata = _Name_##TimestampMetadata; \
3389 }; \
3390 template <typename O> \
3391 using _Name_##From = o2::soa::Join<_TimestampSource_, _Name_##TimestampFrom<O>>; \
3392 using _Name_ = _Name_##From<o2::aod::Hash< \
3393 "AOD" \
3394 ""_h>>;
3395
3396/* Uniformity defaults to the timestamp column of the timestamp source: each distinct
3397 timestamp may resolve to a different object, which is the pre-existing behaviour.
3398 Pass an explicit uniformity source + column (e.g. aod::BCs / aod::bc::RunNumber) when
3399 the object is constant across a coarser key: the fetcher then queries once per distinct
3400 value instead of once per row. The uniformity source must be row-aligned with the
3401 timestamp source, which is checked. */
3402#define DECLARE_SOA_TIMESTAMPED_TABLE(_Name_, _TimestampSource_, _TimestampColumn_, _Version_, _Desc_, ...) \
3403 O2HASH(#_Name_ "Timestamped"); \
3404 DECLARE_SOA_TIMESTAMPED_TABLE_FULL(_Name_, #_Name_ "Timestamped", _TimestampSource_, _TimestampColumn_, _TimestampSource_, _TimestampColumn_, _Version_, _Desc_, __VA_ARGS__)
3405
3406/* Short form for a table with a coarser uniformity key; unlike the CCDB column macros the
3407 short form is worth keeping, because going through _FULL would also make every caller
3408 hand-write the O2HASH of the label. */
3409#define DECLARE_SOA_UNIFORM_TABLE(_Name_, _TimestampSource_, _TimestampColumn_, _UniformitySource_, _UniformityColumn_, _Version_, _Desc_, ...) \
3410 O2HASH(#_Name_ "Timestamped"); \
3411 DECLARE_SOA_TIMESTAMPED_TABLE_FULL(_Name_, #_Name_ "Timestamped", _TimestampSource_, _TimestampColumn_, _UniformitySource_, _UniformityColumn_, _Version_, _Desc_, __VA_ARGS__)
3412
3413namespace o2::soa
3414{
3415template <typename... Ts>
3416struct Join : Table<o2::aod::Hash<"JOIN"_h>, o2::aod::Hash<"JOIN/0"_h>, o2::aod::Hash<"JOIN"_h>, Ts...> {
3417 static constexpr void isJoin() {};
3418 using base = Table<o2::aod::Hash<"JOIN"_h>, o2::aod::Hash<"JOIN/0"_h>, o2::aod::Hash<"JOIN"_h>, Ts...>;
3419
3420 Join(std::vector<ArrowTableRef>&& tables)
3421 : base{ArrowHelpers::joinTables(std::move(tables))}
3422 {
3423 if (this->tableSize() != 0) {
3425 }
3426 }
3427
3430 static constexpr const uint32_t binding_origin = base::binding_origin;
3432
3433 template <typename... TA>
3434 void bindExternalIndices(TA*... current)
3435 {
3436 ([this](TA* cur) {
3437 if constexpr (binding_origin == TA::binding_origin) {
3438 this->bindExternalIndex(cur);
3439 }
3440 }(current),
3441 ...);
3442 }
3443
3444 using self_t = Join<Ts...>;
3445 using table_t = base;
3446 static constexpr const auto originals = base::originals;
3447 static constexpr const auto originalLabels = base::originalLabels;
3450 using iterator = table_t::template iterator_template<DefaultIndexPolicy, self_t, Ts...>;
3456
3458 {
3459 return iterator{this->cached_begin()};
3460 }
3461
3463 {
3464 return const_iterator{this->cached_begin()};
3465 }
3466
3468 {
3469 return doSliceByCached(this, node, value, cache);
3470 }
3471
3476
3477 template <typename T1, typename Policy, bool OPT>
3479 {
3480 return doSliceBy(this, container, value);
3481 }
3482
3483 iterator rawIteratorAt(uint64_t i) const
3484 {
3485 auto it = iterator{this->cached_begin()};
3486 it.setCursor(i);
3487 return it;
3488 }
3489
3490 iterator iteratorAt(uint64_t i) const
3491 {
3492 return rawIteratorAt(i);
3493 }
3494
3495 auto rawSlice(uint64_t start, uint64_t end) const
3496 {
3497 return self_t{{this->asArrowTableRef().slice({start, static_cast<int64_t>(end - start + 1)})}};
3498 }
3499
3500 auto emptySlice() const
3501 {
3502 return self_t{{this->asArrowTableRef().slice({0, 0})}};
3503 }
3504
3505 template <typename T>
3506 static consteval bool contains()
3507 {
3508 return []<size_t... Is>(std::index_sequence<Is...>) {
3509 return (std::ranges::any_of(originals, [](TableRef const& ref) { return ref.desc_hash == T::originals[Is].desc_hash; }) && ...);
3510 }(std::make_index_sequence<T::originals.size()>());
3511 }
3512};
3513
3514template <typename... Ts>
3515constexpr auto join(Ts const&... t)
3516{
3517 return Join<Ts...>({ArrowHelpers::joinTables({t.asArrowTableRef()...}, std::span{Join<Ts...>::base::originalLabels})});
3518}
3519
3520template <typename T>
3521constexpr bool is_soa_join_v = is_join<T>;
3522
3523template <typename... Ts>
3524struct Concat : Table<o2::aod::Hash<"CONC"_h>, o2::aod::Hash<"CONC/0"_h>, o2::aod::Hash<"CONC"_h>, Ts...> {
3525 using base = Table<o2::aod::Hash<"CONC"_h>, o2::aod::Hash<"CONC/0"_h>, o2::aod::Hash<"CONC"_h>, Ts...>;
3526 using self_t = Concat<Ts...>;
3527
3529 : base{table}
3530 {
3532 }
3533
3534 Concat(std::shared_ptr<arrow::Table> table)
3535 : Concat{ArrowTableRef{table}}
3536 {
3537 }
3538
3539 Concat(std::vector<ArrowTableRef>&& tables)
3540 : Concat{ArrowHelpers::concatTables(std::move(tables))}
3541 {
3542 }
3543
3544 Concat(Ts const&... t)
3545 : Concat{ArrowHelpers::concatTables({t.asArrowTableRef()...})}
3546 {
3547 }
3548
3549 using base::originals;
3550
3551 using base::bindExternalIndices;
3552 using base::bindInternalIndicesTo;
3553
3554 using table_t = base;
3557
3558 using iterator = table_t::template iterator_template<DefaultIndexPolicy, self_t, Ts...>;
3564};
3565
3566template <typename... Ts>
3567constexpr auto concat(Ts const&... t)
3568{
3569 return Concat<Ts...>{t...};
3570}
3571
3572template <typename S>
3573concept is_a_selection = std::same_as<std::decay_t<S>, gandiva::Selection> || std::same_as<std::decay_t<S>, SelectionVector> || std::same_as<std::decay_t<S>, std::span<int64_t const>>;
3574
3575template <soa::is_table T>
3576class FilteredBase : public T
3577{
3578 public:
3579 static constexpr void isFilteredBase() {};
3581 using table_t = typename T::table_t;
3582 using T::originals;
3583 static constexpr const uint32_t binding_origin = T::binding_origin;
3584 static constexpr const header::DataOrigin binding_origin_ = T::binding_origin_;
3585 template <typename... TA>
3586 void bindExternalIndices(TA*... current)
3587 {
3588 ([this](TA* cur) {
3589 if constexpr (binding_origin == TA::binding_origin) {
3590 this->bindExternalIndex(cur);
3591 mFilteredBegin.bindExternalIndex(cur);
3592 }
3593 }(current),
3594 ...);
3595 }
3596 using columns_t = typename T::columns_t;
3597 using persistent_columns_t = typename T::persistent_columns_t;
3598 using external_index_columns_t = typename T::external_index_columns_t;
3599
3600 using iterator = T::template iterator_template_o<FilteredIndexPolicy, self_t>;
3601 using unfiltered_iterator = T::template iterator_template_o<DefaultIndexPolicy, self_t>;
3603
3604 FilteredBase(std::vector<ArrowTableRef>&& tables, is_a_selection auto selection)
3605 : T{std::move(tables)}
3606 {
3607 adoptSelection(selection);
3608 if (this->tableSize() != 0) {
3609 mFilteredBegin = table_t::filtered_begin(mSelectedRows);
3610 }
3611 resetRanges();
3612 mFilteredBegin.bindInternalIndices(this);
3613 }
3614
3616 {
3617 return iterator(mFilteredBegin);
3618 }
3619
3621 {
3622 return const_iterator(mFilteredBegin);
3623 }
3624
3626 {
3627 auto it = unfiltered_iterator{mFilteredBegin};
3628 it.setCursor(i);
3629 return it;
3630 }
3631
3632 [[nodiscard]] RowViewSentinel end() const
3633 {
3634 return RowViewSentinel{*mFilteredEnd};
3635 }
3636
3638 {
3639 return mFilteredBegin;
3640 }
3641
3642 auto const& cached_begin() const
3643 {
3644 return mFilteredBegin;
3645 }
3646
3647 iterator iteratorAt(uint64_t i) const
3648 {
3649 return mFilteredBegin + i;
3650 }
3651
3652 [[nodiscard]] int64_t size() const
3653 {
3654 return mSelectedRows.size();
3655 }
3656
3657 [[nodiscard]] int64_t tableSize() const
3658 {
3659 return this->asArrowTableRef().range.size;
3660 }
3661
3662 auto const& getSelectedRows() const
3663 {
3664 return mSelectedRows;
3665 }
3666
3667 auto rawSlice(uint64_t start, uint64_t end) const
3668 {
3669 SelectionVector newSelection;
3670 newSelection.resize(static_cast<int64_t>(end - start + 1));
3671 std::iota(newSelection.begin(), newSelection.end(), start);
3672 return self_t{{this->asArrowTableRef()}, std::move(newSelection)};
3673 }
3674
3675 auto emptySlice() const
3676 {
3677 return self_t{{this->asArrowTableRef()}, SelectionVector{}};
3678 }
3679
3680 static inline auto getSpan(gandiva::Selection const& sel)
3681 {
3682 if (sel == nullptr) {
3683 return std::span<int64_t const>{};
3684 }
3685 auto array = std::static_pointer_cast<arrow::Int64Array>(sel->ToArray());
3686 auto start = array->raw_values();
3687 auto stop = start + array->length();
3688 return std::span{start, stop};
3689 }
3690
3693 void bindExternalIndicesRaw(std::vector<o2::soa::Binding>&& ptrs)
3694 {
3695 mFilteredBegin.bindExternalIndicesRaw(std::forward<std::vector<o2::soa::Binding>>(ptrs));
3696 }
3697
3698 template <typename I>
3700 {
3701 mFilteredBegin.bindInternalIndices(ptr);
3702 }
3703
3704 template <typename T1, typename... Cs>
3706 {
3707 dest.bindExternalIndicesRaw(mFilteredBegin.getIndexBindings());
3708 }
3709
3710 template <typename T1>
3711 void copyIndexBindings(T1& dest) const
3712 {
3713 doCopyIndexBindings(external_index_columns_t{}, dest);
3714 }
3715
3716 template <typename T1>
3717 auto rawSliceBy(o2::framework::Preslice<T1> const& container, int value) const
3718 {
3719 return (table_t)this->sliceBy(container, value);
3720 }
3721
3723 {
3724 return doFilteredSliceByCached(this, node, value, cache);
3725 }
3726
3731
3732 template <typename T1, bool OPT>
3734 {
3735 return doFilteredSliceBy(this, container, value);
3736 }
3737
3738 template <typename T1, bool OPT>
3740 {
3741 return doSliceBy(this, container, value);
3742 }
3743
3745 {
3746 auto t = o2::soa::select(*this, f);
3747 copyIndexBindings(t);
3748 return t;
3749 }
3750
3751 int isInSelectedRows(int i) const
3752 {
3753 auto locate = std::find(mSelectedRows.begin(), mSelectedRows.end(), i);
3754 if (locate == mSelectedRows.end()) {
3755 return -1;
3756 }
3757 return static_cast<int>(std::distance(mSelectedRows.begin(), locate));
3758 }
3759
3761 {
3762 mCached = true;
3763 SelectionVector rowsUnion;
3764 std::ranges::set_union(mSelectedRows, selection, std::back_inserter(rowsUnion));
3765 mSelectedRowsCache.clear();
3766 mSelectedRowsCache = rowsUnion;
3767 resetRanges();
3768 }
3769
3771 {
3772 mCached = true;
3773 SelectionVector intersection;
3774 std::ranges::set_intersection(mSelectedRows, selection, std::back_inserter(intersection));
3775 mSelectedRowsCache.clear();
3776 mSelectedRowsCache = intersection;
3777 resetRanges();
3778 }
3779
3780 bool isCached() const
3781 {
3782 return mCached;
3783 }
3784
3786 {
3787 mFilteredBegin.setPointerReconstructor(pointerReconstructor);
3788 }
3789
3790 private:
3791 void resetRanges()
3792 {
3793 if (mCached) {
3794 mSelectedRows = std::span{mSelectedRowsCache};
3795 }
3796 mFilteredEnd.reset(new RowViewSentinel{static_cast<int64_t>(mSelectedRows.size())});
3797 if (tableSize() == 0) {
3798 mFilteredBegin = *mFilteredEnd;
3799 } else {
3800 mFilteredBegin.resetSelection(mSelectedRows);
3801 }
3802 }
3803
3804 template <typename S>
3805 inline void adoptSelection(S)
3806 {
3807 }
3808
3809 template <typename S>
3810 requires(std::same_as<std::decay_t<S>, gandiva::Selection>)
3811 inline void adoptSelection(S selection)
3812 {
3813 mSelectedRows = getSpan(selection);
3814 mCached = false;
3815 }
3816
3817 template <typename S>
3818 requires(std::same_as<std::decay_t<S>, SelectionVector>)
3819 inline void adoptSelection(S selection)
3820 {
3821 mSelectedRowsCache = std::move(selection);
3822 mSelectedRows = std::span{mSelectedRowsCache};
3823 mCached = true;
3824 }
3825
3826 template <typename S>
3827 requires(std::same_as<std::decay_t<S>, std::span<int64_t const>>)
3828 inline void adoptSelection(S selection)
3829 {
3830 mSelectedRows = selection;
3831 mCached = false;
3832 }
3833
3834 std::span<int64_t const> mSelectedRows;
3835 SelectionVector mSelectedRowsCache;
3836 bool mCached = false;
3837 iterator mFilteredBegin;
3838 std::shared_ptr<RowViewSentinel> mFilteredEnd;
3839};
3840
3841template <typename T>
3842class Filtered : public FilteredBase<T>
3843{
3844 public:
3845 using base_t = T;
3847 using table_t = typename T::table_t;
3848 using columns_t = typename T::columns_t;
3849
3850 using iterator = T::template iterator_template_o<FilteredIndexPolicy, self_t>;
3851 using unfiltered_iterator = T::template iterator_template_o<DefaultIndexPolicy, self_t>;
3853
3855 {
3856 return iterator(this->cached_begin());
3857 }
3858
3860 {
3861 return const_iterator(this->cached_begin());
3862 }
3863
3864 Filtered(std::vector<ArrowTableRef>&& tables, is_a_selection auto selection)
3865 : FilteredBase<T>{std::move(tables), std::forward<decltype(selection)>(selection)} {}
3866
3868 {
3869 Filtered<T> copy(*this);
3870 copy.sumWithSelection(selection);
3871 return copy;
3872 }
3873
3875 {
3876 return operator+(other.getSelectedRows());
3877 }
3878
3880 {
3881 this->sumWithSelection(selection);
3882 return *this;
3883 }
3884
3886 {
3887 return operator+=(other.getSelectedRows());
3888 }
3889
3891 {
3892 Filtered<T> copy(*this);
3893 copy.intersectWithSelection(selection);
3894 return copy;
3895 }
3896
3898 {
3899 return operator*(other.getSelectedRows());
3900 }
3901
3903 {
3904 this->intersectWithSelection(selection);
3905 return *this;
3906 }
3907
3909 {
3910 return operator*=(other.getSelectedRows());
3911 }
3912
3914 {
3915 auto it = unfiltered_iterator{this->cached_begin()};
3916 it.setCursor(i);
3917 return it;
3918 }
3919
3920 using FilteredBase<T>::getSelectedRows;
3921
3922 auto rawSlice(uint64_t start, uint64_t end) const
3923 {
3924 SelectionVector newSelection;
3925 newSelection.resize(static_cast<int64_t>(end - start + 1));
3926 std::iota(newSelection.begin(), newSelection.end(), start);
3927 return self_t{{this->asArrowTableRef()}, std::move(newSelection)};
3928 }
3929
3930 auto emptySlice() const
3931 {
3932 return self_t{{this->asArrowTableRef()}, SelectionVector{}};
3933 }
3934
3935 template <typename T1>
3936 auto rawSliceBy(o2::framework::Preslice<T1> const& container, int value) const
3937 {
3938 return (table_t)this->sliceBy(container, value);
3939 }
3940
3942 {
3943 return doFilteredSliceByCached(this, node, value, cache);
3944 }
3945
3950
3951 template <typename T1, bool OPT>
3953 {
3954 return doFilteredSliceBy(this, container, value);
3955 }
3956
3957 template <typename T1, bool OPT>
3959 {
3960 return doSliceBy(this, container, value);
3961 }
3962
3964 {
3965 auto t = o2::soa::select(*this, f);
3966 copyIndexBindings(t);
3967 return t;
3968 }
3969};
3970
3971template <typename T>
3972class Filtered<Filtered<T>> : public FilteredBase<typename T::table_t>
3973{
3974 public:
3976 using base_t = T;
3978 using columns_t = typename T::columns_t;
3979
3980 using iterator = typename T::template iterator_template_o<FilteredIndexPolicy, self_t>;
3981 using unfiltered_iterator = typename T::template iterator_template_o<DefaultIndexPolicy, self_t>;
3983
3985 {
3986 return iterator(this->cached_begin());
3987 }
3988
3990 {
3991 return const_iterator(this->cached_begin());
3992 }
3993
3994 Filtered(std::vector<Filtered<T>>&& tables, is_a_selection auto selection)
3995 : FilteredBase<typename T::table_t>(std::move(extractTablesFromFiltered(tables)), std::forward<decltype(selection)>(selection))
3996 {
3997 for (auto& table : tables) {
3998 *this *= table;
3999 }
4000 }
4001
4003 {
4004 Filtered<Filtered<T>> copy(*this);
4005 copy.sumWithSelection(selection);
4006 return copy;
4007 }
4008
4010 {
4011 return operator+(other.getSelectedRows());
4012 }
4013
4015 {
4016 this->sumWithSelection(selection);
4017 return *this;
4018 }
4019
4021 {
4022 return operator+=(other.getSelectedRows());
4023 }
4024
4026 {
4027 Filtered<Filtered<T>> copy(*this);
4028 copy.intersectionWithSelection(selection);
4029 return copy;
4030 }
4031
4033 {
4034 return operator*(other.getSelectedRows());
4035 }
4036
4038 {
4039 this->intersectWithSelection(selection);
4040 return *this;
4041 }
4042
4044 {
4045 return operator*=(other.getSelectedRows());
4046 }
4047
4049 {
4050 auto it = unfiltered_iterator{this->cached_begin()};
4051 it.setCursor(i);
4052 return it;
4053 }
4054
4055 auto rawSlice(uint64_t start, uint64_t end) const
4056 {
4057 SelectionVector newSelection;
4058 newSelection.resize(static_cast<int64_t>(end - start + 1));
4059 std::iota(newSelection.begin(), newSelection.end(), start);
4060 return self_t{{this->asArrowTableRef()}, std::move(newSelection)};
4061 }
4062
4063 auto emptySlice() const
4064 {
4065 return self_t{{this->asArrowTableRef()}, SelectionVector{}};
4066 }
4067
4069 {
4070 return doFilteredSliceByCached(this, node, value, cache);
4071 }
4072
4077
4078 template <typename T1, bool OPT>
4080 {
4081 return doFilteredSliceBy(this, container, value);
4082 }
4083
4084 template <typename T1, bool OPT>
4086 {
4087 return doSliceBy(this, container, value);
4088 }
4089
4090 private:
4091 std::vector<ArrowTableRef> extractTablesFromFiltered(std::vector<Filtered<T>>& tables)
4092 {
4093 std::vector<ArrowTableRef> outTables;
4094 for (auto& table : tables) {
4095 outTables.push_back(table.asArrowTableRef());
4096 }
4097 return outTables;
4098 }
4099};
4100
4106template <typename L, typename D, typename O, typename Key, typename H, typename... Ts>
4107struct IndexTable : Table<L, D, O> {
4108 static constexpr void isIndexTable() {};
4109 using self_t = IndexTable<L, D, O, Key, H, Ts...>;
4114 using first_t = typename H::binding_t;
4115 using rest_t = framework::pack<typename Ts::binding_t...>;
4116
4117 static constexpr const uint32_t binding_origin = Key::binding_origin;
4118 static constexpr const header::DataOrigin binding_origin_ = Key::binding_origin_;
4119
4120 template <typename... TA>
4121 void bindExternalIndices(TA*... current)
4122 {
4123 ([this](TA* cur) {
4124 if constexpr (binding_origin == TA::binding_origin) {
4125 this->bindExternalIndex(cur);
4126 }
4127 }(current),
4128 ...);
4129 }
4130
4132 : base_t{table} {}
4133
4136 IndexTable(std::vector<ArrowTableRef>&& tables)
4137 : base_t{tables[0]} {}
4138
4139 IndexTable(IndexTable const&) = default;
4141 IndexTable& operator=(IndexTable const&) = default;
4143
4148};
4149
4150template <typename T, bool APPLY>
4151struct SmallGroupsBase : public Filtered<T> {
4152 static constexpr void isSmallGroups() {};
4153 static constexpr bool applyFilters = APPLY;
4154
4155 SmallGroupsBase(std::vector<ArrowTableRef>&& tables, is_a_selection auto selection)
4156 : Filtered<T>(std::move(tables), selection) {}
4157};
4158
4159template <typename T>
4161
4162template <typename T>
4164} // namespace o2::soa
4165
4166#endif // O2_FRAMEWORK_ASOA_H_
header::DataDescription description
std::vector< std::string > labels
std::string binding
#define O2HASH(_Str_)
Pre-declare Hash specialization for a generic string.
Definition ASoA.h:299
#define O2ORIGIN(_Str_)
Pre-declare Hash specialization for an origin string.
Definition ASoA.h:308
consteval auto getIndexTargets()
SLICE.
Definition ASoA.h:2581
o2::monitoring::tags::Key Key
#define O2_BUILTIN_UNREACHABLE
#define O2_BUILTIN_LIKELY(x)
#define O2_BUILTIN_UNLIKELY(x)
Hit operator+(const Hit &lhs, const Hit &rhs)
Definition Hit.cxx:46
uint32_t hash
std::unique_ptr< expressions::Node > node
int32_t i
std::string columnLabel
uint16_t pos
Definition RawData.h:3
uint32_t res
Definition RawData.h:0
uint32_t c
Definition RawData.h:2
uint32_t version
Definition RawData.h:8
TBranch * ptr
void merge(Options const &options)
StringRef key
Definition B.h:16
Class for time synchronization of RawReader instances.
int64_t const * mCurrentPos
Definition ASoA.h:613
ColumnIterator(arrow::ChunkedArray const *column)
Definition ASoA.h:508
ColumnIterator(ColumnIterator< T, ChunkingPolicy > const &)=default
uint64_t const * mGlobalOffset
Definition ASoA.h:614
void moveToEnd()
Move the iterator to the end of the column.
Definition ASoA.h:564
ColumnIterator< T > & moveToPos()
Definition ASoA.h:606
auto operator*() const
Definition ASoA.h:580
ColumnIterator< T, ChunkingPolicy > & operator=(ColumnIterator< T, ChunkingPolicy > const &)=default
unwrap_t< T > const * mCurrent
Definition ASoA.h:612
unwrap_t< T > const * mLast
Definition ASoA.h:615
ColumnIterator(ColumnIterator< T, ChunkingPolicy > &&)=default
void prevChunk() const
Definition ASoA.h:540
arrow::ChunkedArray const * mColumn
Definition ASoA.h:616
auto operator*() const
Definition ASoA.h:573
ColumnIterator< T, ChunkingPolicy > & operator=(ColumnIterator< T, ChunkingPolicy > &&)=default
void moveToChunk(int chunk)
Definition ASoA.h:550
void nextChunk() const
Move the iterator to the next chunk.
Definition ASoA.h:530
bool isCached() const
Definition ASoA.h:3780
auto sliceByCachedUnsorted(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:3727
int64_t tableSize() const
Definition ASoA.h:3657
auto & cached_begin()
Definition ASoA.h:3637
typename T::external_index_columns_t external_index_columns_t
Definition ASoA.h:3598
auto select(framework::expressions::Filter const &f) const
Definition ASoA.h:3744
static auto getSpan(gandiva::Selection const &sel)
Definition ASoA.h:3680
int64_t size() const
Definition ASoA.h:3652
T::template iterator_template_o< FilteredIndexPolicy, self_t > iterator
Definition ASoA.h:3600
auto rawSliceBy(o2::framework::Preslice< T1 > const &container, int value) const
Definition ASoA.h:3717
T::template iterator_template_o< DefaultIndexPolicy, self_t > unfiltered_iterator
Definition ASoA.h:3601
void copyIndexBindings(T1 &dest) const
Definition ASoA.h:3711
auto const & getSelectedRows() const
Definition ASoA.h:3662
void setPointerReconstructor(framework::PointerReconstructor const &pointerReconstructor)
Definition ASoA.h:3785
typename T::columns_t columns_t
Definition ASoA.h:3596
auto emptySlice() const
Definition ASoA.h:3675
void bindExternalIndices(TA *... current)
Definition ASoA.h:3586
void sumWithSelection(is_a_selection auto selection)
Definition ASoA.h:3760
void bindInternalIndicesTo(I const *ptr)
Definition ASoA.h:3699
FilteredBase(std::vector< ArrowTableRef > &&tables, is_a_selection auto selection)
Definition ASoA.h:3604
auto sliceBy(o2::framework::PresliceBase< T1, framework::PreslicePolicyGeneral, OPT > const &container, int value) const
Definition ASoA.h:3739
auto rawSlice(uint64_t start, uint64_t end) const
Definition ASoA.h:3667
auto sliceBy(o2::framework::PresliceBase< T1, framework::PreslicePolicySorted, OPT > const &container, int value) const
Definition ASoA.h:3733
iterator iteratorAt(uint64_t i) const
Definition ASoA.h:3647
iterator const_iterator
Definition ASoA.h:3602
typename T::table_t table_t
Definition ASoA.h:3581
typename T::persistent_columns_t persistent_columns_t
Definition ASoA.h:3597
static constexpr void isFilteredBase()
Definition ASoA.h:3579
RowViewSentinel end() const
Definition ASoA.h:3632
void intersectWithSelection(is_a_selection auto selection)
Definition ASoA.h:3770
void bindExternalIndicesRaw(std::vector< o2::soa::Binding > &&ptrs)
Definition ASoA.h:3693
const_iterator begin() const
Definition ASoA.h:3620
unfiltered_iterator rawIteratorAt(uint64_t i) const
Definition ASoA.h:3625
int isInSelectedRows(int i) const
Definition ASoA.h:3751
auto sliceByCached(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:3722
void doCopyIndexBindings(framework::pack< Cs... >, T1 &dest) const
Definition ASoA.h:3705
iterator begin()
Definition ASoA.h:3615
auto const & cached_begin() const
Definition ASoA.h:3642
auto sliceBy(o2::framework::PresliceBase< T1, framework::PreslicePolicySorted, OPT > const &container, int value) const
Definition ASoA.h:4079
Filtered(std::vector< Filtered< T > > &&tables, is_a_selection auto selection)
Definition ASoA.h:3994
typename FilteredBase< typename T::table_t >::table_t table_t
Definition ASoA.h:3977
typename T::template iterator_template_o< DefaultIndexPolicy, self_t > unfiltered_iterator
Definition ASoA.h:3981
auto sliceBy(o2::framework::PresliceBase< T1, framework::PreslicePolicyGeneral, OPT > const &container, int value) const
Definition ASoA.h:4085
typename T::template iterator_template_o< FilteredIndexPolicy, self_t > iterator
Definition ASoA.h:3980
typename T::columns_t columns_t
Definition ASoA.h:3978
const_iterator begin() const
Definition ASoA.h:3989
Filtered< Filtered< T > > operator+=(is_a_selection auto selection)
Definition ASoA.h:4014
Filtered< Filtered< T > > operator*(is_a_selection auto selection)
Definition ASoA.h:4025
Filtered< Filtered< T > > operator+(is_a_selection auto selection)
Definition ASoA.h:4002
unfiltered_iterator rawIteratorAt(uint64_t i) const
Definition ASoA.h:4048
Filtered< Filtered< T > > operator*=(is_a_selection auto selection)
Definition ASoA.h:4037
Filtered< Filtered< T > > operator+=(Filtered< T > const &other)
Definition ASoA.h:4020
auto rawSlice(uint64_t start, uint64_t end) const
Definition ASoA.h:4055
Filtered< Filtered< T > > operator+(Filtered< T > const &other)
Definition ASoA.h:4009
Filtered< Filtered< T > > operator*=(Filtered< T > const &other)
Definition ASoA.h:4043
auto sliceByCached(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:4068
Filtered< Filtered< T > > operator*(Filtered< T > const &other)
Definition ASoA.h:4032
auto sliceByCachedUnsorted(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:4073
Filtered< T > operator+=(Filtered< T > const &other)
Definition ASoA.h:3885
Filtered(std::vector< ArrowTableRef > &&tables, is_a_selection auto selection)
Definition ASoA.h:3864
auto sliceBy(o2::framework::PresliceBase< T1, framework::PreslicePolicyGeneral, OPT > const &container, int value) const
Definition ASoA.h:3958
iterator const_iterator
Definition ASoA.h:3852
iterator begin()
Definition ASoA.h:3854
auto sliceByCachedUnsorted(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:3946
Filtered< T > operator+(Filtered< T > const &other)
Definition ASoA.h:3874
auto emptySlice() const
Definition ASoA.h:3930
const_iterator begin() const
Definition ASoA.h:3859
Filtered< T > operator+(is_a_selection auto selection)
Definition ASoA.h:3867
T::template iterator_template_o< FilteredIndexPolicy, self_t > iterator
Definition ASoA.h:3850
auto sliceByCached(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:3941
auto select(framework::expressions::Filter const &f) const
Definition ASoA.h:3963
Filtered< T > operator*(is_a_selection auto selection)
Definition ASoA.h:3890
T::template iterator_template_o< DefaultIndexPolicy, self_t > unfiltered_iterator
Definition ASoA.h:3851
unfiltered_iterator rawIteratorAt(uint64_t i) const
Definition ASoA.h:3913
Filtered< T > operator*=(Filtered< T > const &other)
Definition ASoA.h:3908
Filtered< T > operator*(Filtered< T > const &other)
Definition ASoA.h:3897
auto rawSliceBy(o2::framework::Preslice< T1 > const &container, int value) const
Definition ASoA.h:3936
auto rawSlice(uint64_t start, uint64_t end) const
Definition ASoA.h:3922
auto sliceBy(o2::framework::PresliceBase< T1, framework::PreslicePolicySorted, OPT > const &container, int value) const
Definition ASoA.h:3952
typename T::table_t table_t
Definition ASoA.h:3847
typename T::columns_t columns_t
Definition ASoA.h:3848
Filtered< T > operator+=(is_a_selection auto selection)
Definition ASoA.h:3879
Filtered< T > operator*=(is_a_selection auto selection)
Definition ASoA.h:3902
decltype([]< typename... C >(framework::pack< C... > &&) -> framework::selected_pack< soa::is_self_index_t, C... > {}(columns_t{})) internal_index_columns_t
Definition ASoA.h:1772
void bindInternalIndicesExplicit(o2::soa::Binding binding)
Definition ASoA.h:2126
void setPointerReconstructor(framework::PointerReconstructor const &pointerReconstructor)
Definition ASoA.h:2187
auto & cached_begin()
Definition ASoA.h:2019
iterator iteratorAt(uint64_t i) const
Definition ASoA.h:2048
decltype([]< typename... C >(framework::pack< C... > &&) -> framework::selected_pack< soa::is_persistent_column_t, C... > {}(columns_t{})) persistent_columns_t
Definition ASoA.h:1768
static constexpr const auto ref
Definition ASoA.h:1719
auto offset() const
Return offset.
Definition ASoA.h:2086
static consteval bool hasOriginal()
Definition ASoA.h:1755
unfiltered_iterator begin()
Definition ASoA.h:2029
int64_t tableSize() const
Definition ASoA.h:2096
auto rawSlice(uint64_t start, uint64_t end) const
Definition ASoA.h:2177
Table(std::vector< o2::soa::ArrowTableRef > &&tables)
Definition ASoA.h:1975
void bindExternalIndices(TA *... current)
Definition ASoA.h:2104
auto select(framework::expressions::Filter const &f) const
Definition ASoA.h:2154
unfiltered_iterator unfiltered_const_iterator
Definition ASoA.h:1949
decltype([]() { if constexpr(sizeof...(Ts)==0) { return iterator_template< IP, Parent >{} iterator_template_o
Definition ASoA.h:1934
auto const & cached_begin() const
Definition ASoA.h:2024
auto emptySlice() const
Definition ASoA.h:2182
auto sliceByCachedUnsorted(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:2166
TableIteratorBase< IP, Parent, T... > iterator_template
Definition ASoA.h:1929
static constexpr header::DataOrigin binding_origin_
Definition ASoA.h:1728
void bindExternalIndicesRaw(std::vector< o2::soa::Binding > &&ptrs)
Definition ASoA.h:2137
auto sliceBy(o2::framework::PresliceBase< T1, Policy, OPT > const &container, int value) const
Definition ASoA.h:2172
iterator unfiltered_iterator
Definition ASoA.h:1947
void bindExternalIndex(TA *current)
Definition ASoA.h:2115
std::shared_ptr< arrow::Table > asArrowTable() const
Return a type erased arrow table backing store for / the type safe table.
Definition ASoA.h:2071
filtered_iterator filtered_begin(std::span< int64_t const > selection)
Definition ASoA.h:2039
void doCopyIndexBindings(framework::pack< Cs... >, T &dest) const
Definition ASoA.h:2143
int64_t size() const
Size of the table, in rows.
Definition ASoA.h:2091
static constexpr auto column_hashes
Definition ASoA.h:1762
decltype(getColumns< ref, Ts... >()) columns_t
Definition ASoA.h:1760
arrow::ChunkedArray * getIndexToKey()
Definition ASoA.h:2000
RowViewSentinel end()
Definition ASoA.h:2034
ArrowTableRef asArrowTableRef() const
Definition ASoA.h:2081
decltype([]< typename... C >(framework::pack< C... >) -> framework::pack< typename C::type... > {}(persistent_columns_t{})) column_types
Definition ASoA.h:1769
static constexpr const uint32_t binding_origin
Definition ASoA.h:1727
static consteval auto isIndexTargetOf()
Definition ASoA.h:1732
std::shared_ptr< arrow::Table > asArrowTableConstrained() const
Definition ASoA.h:2076
iterator_template_o< FilteredIndexPolicy, table_t > filtered_iterator
Definition ASoA.h:1945
unfiltered_const_iterator begin() const
Definition ASoA.h:2060
void copyIndexBindings(T &dest) const
Definition ASoA.h:2149
static constexpr const auto originalLabels
Definition ASoA.h:1724
Table< L, D, O, Ts... > self_t
Definition ASoA.h:1720
static consteval auto isIndexTargetOf()
Definition ASoA.h:1739
void doBindInternalIndicesExplicit(framework::pack< Cs... >, o2::soa::Binding binding)
Definition ASoA.h:2132
static constexpr const auto originals
Definition ASoA.h:1723
Table(std::vector< std::shared_ptr< arrow::Table > > &&tables)
Definition ASoA.h:1987
Table(std::shared_ptr< arrow::Table > table)
Definition ASoA.h:1970
Table(o2::soa::ArrowTableRef tableRef)
Definition ASoA.h:1951
Table(std::vector< std::shared_ptr< arrow::Table > > &&tables)
Definition ASoA.h:1993
decltype([]< typename... C >(framework::pack< C... > &&) -> framework::selected_pack< soa::is_external_index_t, C... > {}(columns_t{})) external_index_columns_t
Definition ASoA.h:1771
RowViewSentinel end() const
Definition ASoA.h:2065
static constexpr void isSOATable()
Definition ASoA.h:1718
auto sliceByCached(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:2161
void bindInternalIndicesTo(I const *ptr)
Definition ASoA.h:2121
unfiltered_iterator rawIteratorAt(uint64_t i) const
Definition ASoA.h:2053
Table(std::vector< o2::soa::ArrowTableRef > &&tables)
Definition ASoA.h:1981
iterator_template_o< DefaultIndexPolicy, table_t > iterator
Definition ASoA.h:1944
GLint GLenum GLint x
Definition glcorearb.h:403
GLenum func
Definition glcorearb.h:778
GLint GLsizei count
Definition glcorearb.h:399
GLsizeiptr size
Definition glcorearb.h:659
GLuint GLsizei const GLuint const GLintptr * offsets
Definition glcorearb.h:2595
GLuint GLuint end
Definition glcorearb.h:469
GLenum array
Definition glcorearb.h:4274
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLenum GLint * range
Definition glcorearb.h:1899
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLenum target
Definition glcorearb.h:1641
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLboolean * data
Definition glcorearb.h:298
GLintptr offset
Definition glcorearb.h:660
GLuint GLsizei GLsizei * length
Definition glcorearb.h:790
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
GLsizei GLenum const void * indices
Definition glcorearb.h:400
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean r
Definition glcorearb.h:1233
GLuint start
Definition glcorearb.h:469
GLenum GLenum GLsizei len
Definition glcorearb.h:4232
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLint ref
Definition glcorearb.h:291
std::shared_ptr< gandiva::SelectionVector > Selection
Definition Expressions.h:45
consteval const char * origin_str()
Definition ASoA.h:370
consteval const char * signature()
Definition ASoA.h:382
consteval auto replaceOrigin()
Replace origins in the TableRef array.
Definition ASoA.h:402
constexpr framework::ConcreteDataMatcher matcher()
Definition ASoA.h:388
consteval auto filterForKey()
Filter TableRef array for compatibility with Key table.
Definition ASoA.h:287
consteval const char * label()
Definition ASoA.h:364
consteval header::DataOrigin origin()
Definition ASoA.h:376
gandiva::Selection createSelection(std::shared_ptr< arrow::Table > const &table, Filter const &expression)
Function for creating gandiva selection from our internal filter tree.
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::decay_t< decltype(select_pack< Condition >(pack<>{}, Pack{}, CondPack{}))> selected_pack_multicondition
Definition Pack.h:181
std::decay_t< decltype(prune_voids_pack(pack<>{}, with_condition_pack< Condition, Types... >{}))> selected_pack
Definition Pack.h:179
std::function< std::byte *(fair::mq::shmem::MetaHeader &&)> PointerReconstructor
Definition ASoA.h:52
decltype(intersected_pack(Ps{}...)) full_intersected_pack_t
Definition Pack.h:283
typename pack_element< I, T >::type pack_element_t
Definition Pack.h:56
consteval size_t has_type_at_v(pack< Ts... >)
Definition Pack.h:228
constexpr std::size_t pack_size(pack< Ts... > const &)
template function to determine number of types in a pack
Definition Pack.h:28
decltype(concatenate_pack_unique(Ps{}...)) concatenated_pack_unique_t
Definition Pack.h:319
std::string strToUpper(std::string &&str)
Definition ASoA.cxx:322
typename pack_element< 0, T >::type pack_head_t
Definition Pack.h:59
std::string cutString(std::string &&str)
Definition ASoA.cxx:313
std::vector< std::vector< int64_t > > ListVector
Descriptor< gSizeDataDescriptionString > DataDescription
Definition DataHeader.h:551
const int tableSize
R getColumnValue(const T &rowIterator)
Definition ASoA.h:2223
ColumnGetterFunction< R, typename T::iterator > getColumnGetterByLabel(const std::string_view &targetColumnLabel)
Definition ASoA.h:2290
void * extractCCDBPayload(char *payload, size_t size, TClass const *cl, const char *what)
Definition ASoA.cxx:243
consteval auto computeOriginals()
Definition ASoA.h:1700
auto createFieldsFromColumns(framework::pack< C... >)
Definition ASoA.h:77
SelectionVector selectionToVector(gandiva::Selection const &sel)
Definition ASoA.cxx:48
constexpr bool is_persistent_v
column identification
Definition ASoA.h:209
constexpr bool is_ng_index_equivalent_v
Definition ASoA.h:460
consteval auto remove_if(L l)
Definition ASoA.h:155
constexpr auto join(Ts const &... t)
Definition ASoA.h:3515
auto doSliceBy(T const *table, o2::framework::PresliceBase< C, Policy, OPT > const &container, int value)
Definition ASoA.h:1527
void notBoundTable(const char *tableName)
Definition ASoA.cxx:228
SelectionVector sliceSelection(std::span< int64_t const > const &mSelectedRows, int64_t nrows, uint64_t offset)
Definition ASoA.cxx:58
auto doFilteredSliceBy(T const *table, o2::framework::PresliceBase< C, framework::PreslicePolicySorted, OPT > const &container, int value)
Definition ASoA.h:1602
constexpr auto concat(Ts const &... t)
Definition ASoA.h:3567
consteval auto intersectOriginals()
Definition ASoA.h:190
consteval auto getColumns()
Definition ASoA.h:1672
std::vector< int64_t > SelectionVector
Definition ASoA.h:444
std::conditional_t< is_binding_compatible_v< T, typename B::binding_t >(), std::true_type, std::false_type > is_binding_compatible
Definition ASoA.h:1294
consteval auto mergeOriginals()
Definition ASoA.h:173
constexpr bool is_soa_filtered_v
Definition ASoA.h:1514
typename std::conditional_t< is_index_column< C >, std::true_type, std::false_type > is_external_index_t
Definition ASoA.h:215
void missingFilterDeclaration(int hash, int ai)
Definition ASoA.cxx:33
auto doSliceByCachedUnsorted(T const *table, framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache)
Definition ASoA.h:1638
auto doSliceByCached(T const *table, framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache)
Definition ASoA.h:1616
void accessingInvalidIndexFor(const char *getter)
Definition ASoA.cxx:25
auto select(T const &t, framework::expressions::Filter const &f)
Definition ASoA.h:1659
consteval auto base_iter(framework::pack< C... > &&) -> TableIterator< D, O, IP, C... >
Definition ASoA.h:1667
constexpr bool is_index_equivalent_v
Definition ASoA.h:457
constexpr bool is_soa_join_v
Definition ASoA.h:3521
void dereferenceWithWrongType(const char *getter, const char *target)
Definition ASoA.cxx:29
consteval bool is_binding_compatible_v()
Definition ASoA.h:1288
void emptyColumnLabel()
Definition ASoA.cxx:43
typename unwrap< T >::type unwrap_t
Definition ASoA.h:492
auto prepareFilteredSlice(T const *table, o2::soa::ArrowTableRef slice)
Definition ASoA.h:1583
void getterNotFound(const char *targetColumnLabel)
Definition ASoA.cxx:38
auto doFilteredSliceByCached(T const *table, framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache)
Definition ASoA.h:1629
void missingOptionalPreslice(const char *label, const char *key)
Definition ASoA.cxx:238
constexpr char asciiToLower(char c)
Definition ASoA.h:71
auto doSliceByHelper(T const *table, std::span< const int64_t > const &selection)
Definition ASoA.h:1544
std::function< framework::ConcreteDataMatcher(framework::ConcreteDataMatcher &&)> originReplacement(header::DataOrigin newOrigin)
Definition ASoA.cxx:299
consteval bool is_compatible()
Definition ASoA.h:1275
arrow::ChunkedArray * getIndexFromLabel(arrow::Table *table, std::string_view label)
Definition ASoA.cxx:210
consteval auto merge()
Helpers to manipulate TableRef arrays.
Definition ASoA.h:132
consteval auto merge_if(L l)
Definition ASoA.h:143
std::conditional_t< is_persistent_column< C >, std::true_type, std::false_type > is_persistent_column_t
Definition ASoA.h:212
typename arrow_array_for< T >::type arrow_array_for_t
Definition ArrowTypes.h:166
void notFoundColumn(const char *label, const char *key)
Definition ASoA.cxx:233
std::conditional_t< is_dynamic_column< T >, std::true_type, std::false_type > is_dynamic_t
pack filtering helpers
Definition Concepts.h:95
typename std::conditional_t< is_self_index_column< C >, std::true_type, std::false_type > is_self_index_t
Definition ASoA.h:218
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
FIXME: do not use data model tables.
static constexpr uint32_t hash
Definition ASoA.h:281
static constexpr char const *const str
Definition ASoA.h:282
static constexpr void isHash()
Definition ASoA.h:280
static constexpr void isMetadataTrait()
Definition ASoA.h:272
Base type for table metadata.
Definition ASoA.h:239
static consteval int getIndexPosToKey()
Definition ASoA.h:259
framework::selected_pack< soa::is_self_index_t, Cs... > internal_index_columns_t
Definition ASoA.h:244
framework::selected_pack< soa::is_persistent_column_t, Cs... > persistent_columns_t
Definition ASoA.h:242
static std::shared_ptr< arrow::Schema > getSchema()
Definition ASoA.h:264
framework::selected_pack< soa::is_external_index_t, Cs... > external_index_columns_t
Definition ASoA.h:243
static consteval std::array< bool, sizeof...(PCs)> getMap(framework::pack< PCs... >)
Definition ASoA.h:247
static constexpr void isTableMetadata()
Definition ASoA.h:240
SliceInfoUnsortedPtr getCacheUnsortedFor(Entry const &bindingKey) const
SliceInfoPtr getCacheFor(Entry const &bindingKey) const
static constexpr bool optional
Definition ASoA.h:1448
PresliceBase(expressions::BindingNode index_)
Definition ASoA.h:1453
std::span< const int64_t > getSliceFor(int value) const
Definition ASoA.h:1468
const std::string binding
Definition ASoA.h:1451
o2::soa::ArrowTableRef getSliceFor(int value, o2::soa::ArrowTableRef const &input) const
Definition ASoA.h:1458
static constexpr void isPresliceContainer()
Definition ASoA.h:1447
static constexpr void isPresliceGroup()
Definition ASoA.h:1501
tracks origin in bindingKey matcher to handle the correct arguments
Definition ASoA.h:1422
const std::string binding
Definition ASoA.h:1424
Entry const & getBindingKey() const
Definition ASoA.cxx:333
static constexpr void isPreslicePolicy()
Definition ASoA.h:1423
SliceInfoUnsortedPtr sliceInfo
Definition ASoA.h:1441
std::span< const int64_t > getSliceFor(int value) const
Definition ASoA.cxx:354
void updateSliceInfo(SliceInfoUnsortedPtr &&si)
Definition ASoA.cxx:343
o2::soa::ArrowTableRef getSliceFor(int value, o2::soa::ArrowTableRef const &input) const
Definition ASoA.cxx:348
void updateSliceInfo(SliceInfoPtr &&si)
Definition ASoA.cxx:338
ArrowTableSlicingCache * ptr
Definition SliceCache.h:22
std::pair< int64_t, int64_t > getSliceFor(int value) const
An expression tree node corresponding to a column binding.
A struct, containing the root of the expression tree.
From https://en.cppreference.com/w/cpp/utility/variant/visit.
static o2::soa::ArrowTableRef concatTables(std::vector< std::shared_ptr< arrow::Table > > &&tables)
static o2::soa::ArrowTableRef joinTables(std::vector< std::shared_ptr< arrow::Table > > &&tables)
Definition ASoA.cxx:140
static o2::soa::ArrowTableRef concatTables(std::vector< o2::soa::ArrowTableRef > &&tables)
Definition ASoA.cxx:174
ArrowTableRef makeEmpty() const
Definition ArrowTypes.h:47
std::shared_ptr< arrow::Table > tablePtr
Definition ArrowTypes.h:32
ArrowTableRef slice(ArrowRange newRange) const
Definition ArrowTypes.h:52
Type-checking index column binding.
Definition ASoA.h:421
uint32_t hash
Definition ASoA.h:423
void const * ptr
Definition ASoA.h:422
void bind(T const *table)
Definition ASoA.h:427
T const * get() const
Definition ASoA.h:435
static constexpr bool chunked
Definition ASoA.h:466
arrow::ChunkedArray * second
Definition ASoA.h:1023
Column(ColumnIterator< T > const &it)
Definition ASoA.h:672
Column()=default
static constexpr const char *const & columnLabel()
Definition ASoA.h:685
ColumnIterator< T > const & getIterator() const
Definition ASoA.h:686
Column & operator=(Column const &)=default
INHERIT inherited_t
Definition ASoA.h:671
Column(Column &&)=default
static auto asArrowField()
Definition ASoA.h:691
Column & operator=(Column &&)=default
Column(Column const &)=default
static constexpr void isIteratableColumn()
Definition ASoA.h:669
ColumnIterator< T > mColumnIterator
Definition ASoA.h:698
Concat(std::shared_ptr< arrow::Table > table)
Definition ASoA.h:3534
table_t::template iterator_template< DefaultIndexPolicy, self_t, Ts... > iterator
Definition ASoA.h:3558
typename table_t::persistent_columns_t persistent_columns_t
Definition ASoA.h:3556
typename table_t::columns_t columns_t
Definition ASoA.h:3555
Concat(std::vector< ArrowTableRef > &&tables)
Definition ASoA.h:3539
iterator const_iterator
Definition ASoA.h:3559
const_iterator unfiltered_const_iterator
Definition ASoA.h:3561
Concat(Ts const &... t)
Definition ASoA.h:3544
iterator unfiltered_iterator
Definition ASoA.h:3560
table_t::template iterator_template< FilteredIndexPolicy, self_t, Ts... > filtered_iterator
Definition ASoA.h:3562
Concat(ArrowTableRef table)
Definition ASoA.h:3528
filtered_iterator filtered_const_iterator
Definition ASoA.h:3563
DefaultIndexPolicy(int64_t nRows, uint64_t offset)
Definition ASoA.h:954
friend bool operator==(DefaultIndexPolicy const &lh, DefaultIndexPolicy const &rh)
Definition ASoA.h:1000
bool operator==(RowViewSentinel const &sentinel) const
Definition ASoA.h:1005
static constexpr void isDefaultIndexPolicy()
Definition ASoA.h:943
DefaultIndexPolicy(FilteredIndexPolicy const &other)
Definition ASoA.h:960
std::tuple< uint64_t const * > getOffsets() const
Definition ASoA.h:981
DefaultIndexPolicy & operator=(DefaultIndexPolicy &&)=default
void setCursor(int64_t i)
Definition ASoA.h:986
void limitRange(int64_t start, int64_t end)
Definition ASoA.h:966
DefaultIndexPolicy(DefaultIndexPolicy &&)=default
DefaultIndexPolicy(DefaultIndexPolicy const &)=default
DefaultIndexPolicy & operator=(DefaultIndexPolicy const &)=default
std::tuple< int64_t const *, int64_t const * > getIndices() const
Definition ASoA.h:975
DefaultIndexPolicy()=default
Needed to be able to copy the policy.
void moveByIndex(int64_t i)
Definition ASoA.h:990
static constexpr const char *const & columnLabel()
Definition ASoA.h:708
INHERIT inherited_t
Definition ASoA.h:706
static constexpr void isDynamicColumn()
Definition ASoA.h:705
FilteredIndexPolicy & operator=(FilteredIndexPolicy &&)=default
std::tuple< int64_t const *, int64_t const * > getIndices() const
Definition ASoA.h:866
FilteredIndexPolicy & operator=(FilteredIndexPolicy const &)=default
auto getSelectionRow() const
Definition ASoA.h:916
FilteredIndexPolicy(std::span< int64_t const > selection, int64_t rows, uint64_t offset=0)
Definition ASoA.h:843
friend bool operator==(FilteredIndexPolicy const &lh, FilteredIndexPolicy const &rh)
Definition ASoA.h:897
void resetSelection(std::span< int64_t const > selection)
Definition ASoA.h:852
void setCursor(int64_t i)
Definition ASoA.h:885
static constexpr void isFilteredIndexPolicy()
FilteredIndexPolicy(FilteredIndexPolicy const &)=default
auto raw_size() const
Definition ASoA.h:926
bool operator==(RowViewSentinel const &sentinel) const
Definition ASoA.h:902
std::tuple< uint64_t const * > getOffsets() const
Definition ASoA.h:872
void limitRange(int64_t start, int64_t end)
Definition ASoA.h:877
FilteredIndexPolicy(FilteredIndexPolicy &&)=default
void moveByIndex(int64_t i)
Definition ASoA.h:891
static constexpr bool chunked
Definition ASoA.h:472
static constexpr const char *const & columnLabel()
Definition ASoA.h:717
static constexpr void isEnumeratingColumn()
Definition ASoA.h:713
INHERIT inherited_t
Definition ASoA.h:714
static constexpr const uint32_t hash
Definition ASoA.h:715
uint64_t mOffset
Offset within a larger table.
Definition ASoA.h:828
int64_t mRowIndex
Position inside the current table.
Definition ASoA.h:826
static constexpr void isIndexTable()
Definition ASoA.h:4108
void bindExternalIndices(TA *... current)
Definition ASoA.h:4121
IndexTable(ArrowTableRef table)
Definition ASoA.h:4131
typename base_t::template iterator_template_o< DefaultIndexPolicy, self_t > iterator
Definition ASoA.h:4144
filtered_iterator const_filtered_iterator
Definition ASoA.h:4147
IndexTable(IndexTable &&)=default
IndexTable(std::vector< ArrowTableRef > &&tables)
Definition ASoA.h:4136
IndexTable & operator=(IndexTable const &)=default
iterator const_iterator
Definition ASoA.h:4145
IndexTable & operator=(IndexTable &&)=default
typename H::binding_t first_t
Definition ASoA.h:4114
typename base_t::template iterator_template_o< FilteredIndexPolicy, self_t > filtered_iterator
Definition ASoA.h:4146
IndexTable(IndexTable const &)=default
Index(Index const &)=default
void setIndices(std::tuple< int64_t const *, int64_t const * > indices)
Definition ASoA.h:805
Index & operator=(Index &&)=default
int64_t index() const
Definition ASoA.h:778
Index()=default
Index(arrow::ChunkedArray const *)
Definition ASoA.h:764
int64_t filteredIndex() const
Definition ASoA.h:783
constexpr int64_t rangeEnd()
Definition ASoA.h:773
constexpr int64_t rangeStart()
Definition ASoA.h:768
Index(Index &&)=default
Index & operator=(Index const &)=default
int64_t index() const
Definition ASoA.h:794
int64_t globalIndex() const
Definition ASoA.h:788
std::tuple< int64_t const *, int64_t const * > rowIndices
Definition ASoA.h:818
int64_t offsets() const
Definition ASoA.h:800
void setOffsets(std::tuple< uint64_t const * > offsets)
Definition ASoA.h:810
static constexpr const char * mLabel
Definition ASoA.h:815
std::tuple< uint64_t const * > rowOffsets
Definition ASoA.h:821
auto sliceBy(o2::framework::PresliceBase< T1, Policy, OPT > const &container, int value) const
Definition ASoA.h:3478
static constexpr const auto originalLabels
Definition ASoA.h:3447
iterator const_iterator
Definition ASoA.h:3451
static constexpr const auto originals
Definition ASoA.h:3446
iterator rawIteratorAt(uint64_t i) const
Definition ASoA.h:3483
static constexpr const uint32_t binding_origin
Definition ASoA.h:3430
auto sliceByCached(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:3467
const_iterator unfiltered_const_iterator
Definition ASoA.h:3453
typename table_t::columns_t columns_t
Definition ASoA.h:3448
auto emptySlice() const
Definition ASoA.h:3500
Table< o2::aod::Hash<"JOIN"_h >, o2::aod::Hash<"JOIN/0"_h >, o2::aod::Hash<"JOIN"_h >, Ts... > base
Definition ASoA.h:3418
iterator iteratorAt(uint64_t i) const
Definition ASoA.h:3490
typename table_t::persistent_columns_t persistent_columns_t
Definition ASoA.h:3449
Join< Ts... > self_t
Definition ASoA.h:3444
const_iterator begin() const
Definition ASoA.h:3462
void bindExternalIndices(TA *... current)
Definition ASoA.h:3434
table_t::template iterator_template< DefaultIndexPolicy, self_t, Ts... > iterator
Definition ASoA.h:3450
static consteval bool contains()
Definition ASoA.h:3506
static constexpr void isJoin()
Definition ASoA.h:3417
Join(std::vector< ArrowTableRef > &&tables)
Definition ASoA.h:3420
iterator begin()
Definition ASoA.h:3457
table_t::template iterator_template< FilteredIndexPolicy, self_t, Ts... > filtered_iterator
Definition ASoA.h:3454
auto sliceByCachedUnsorted(framework::expressions::BindingNode const &node, int value, o2::framework::SliceCache &cache) const
Definition ASoA.h:3472
auto rawSlice(uint64_t start, uint64_t end) const
Definition ASoA.h:3495
static constexpr const header::DataOrigin binding_origin_
Definition ASoA.h:3431
iterator unfiltered_iterator
Definition ASoA.h:3452
filtered_iterator filtered_const_iterator
Definition ASoA.h:3455
static constexpr const uint32_t hash
Definition ASoA.h:724
static constexpr const char *const & columnLabel()
Definition ASoA.h:726
static constexpr void isMarkingColumn()
Definition ASoA.h:722
INHERIT inherited_t
Definition ASoA.h:723
constexpr auto mark()
Definition ASoA.h:743
Marker & operator=(Marker const &)=default
size_t type
Definition ASoA.h:731
static constexpr auto value
Definition ASoA.h:733
static constexpr const char * mLabel
Definition ASoA.h:748
Marker(arrow::ChunkedArray const *)
Definition ASoA.h:742
Marker()=default
Marker(Marker const &)=default
Marker & operator=(Marker &&)=default
Marker(Marker &&)=default
int64_t const index
Definition ASoA.h:833
static constexpr void isRowViewSentinel()
Definition ASoA.h:832
SmallGroupsBase(std::vector< ArrowTableRef > &&tables, is_a_selection auto selection)
Definition ASoA.h:4155
static constexpr void isSmallGroups()
Definition ASoA.h:4152
framework::selected_pack< soa::is_persistent_column_t, C... > persistent_columns_t
Definition ASoA.h:1036
void doSetCurrentIndexRaw(framework::pack< Cs... > p, std::vector< o2::soa::Binding > &&ptrs)
Definition ASoA.h:1174
void bindInternalIndices(I const *table)
Definition ASoA.h:1193
TableIterator(TableIterator< D, O, FilteredIndexPolicy, C... > const &other)
Definition ASoA.h:1085
TableIterator(self_t const &other)
Definition ASoA.h:1066
TableIterator operator-(int64_t dec) const
Definition ASoA.h:1129
TableIterator(arrow::ChunkedArray *columnData[sizeof...(C)], IP &&policy)
Definition ASoA.h:1050
TableIterator & operator=(TableIterator other)
Definition ASoA.h:1075
TableIterator & operator++()
Definition ASoA.h:1095
void bindExternalIndex(TA *current)
Definition ASoA.h:1166
void doSetCurrentInternal(framework::pack< Cs... >, I const *ptr)
Definition ASoA.h:1180
auto getIndexBindingsImpl(framework::pack< Cs... >) const
Definition ASoA.h:1146
TableIterator operator--(int)
Definition ASoA.h:1114
void bindExternalIndicesRaw(std::vector< o2::soa::Binding > &&ptrs)
Definition ASoA.h:1187
TableIterator(arrow::ChunkedArray *columnData[sizeof...(C)], IP &&policy)
Definition ASoA.h:1041
decltype([]< typename... Cs >(framework::pack< Cs... >) -> framework::pack< typename Cs::binding_t... > {}(external_index_columns_t{})) bindings_pack_t
Definition ASoA.h:1039
void bindExternalIndices(TA *... current)
Definition ASoA.h:1157
auto getCurrent() const
Definition ASoA.h:1140
TableIterator & operator--()
Definition ASoA.h:1108
framework::selected_pack< soa::is_external_index_t, C... > external_index_columns_t
Definition ASoA.h:1037
TableIterator const & operator*() const
Definition ASoA.h:1134
static constexpr void isTableIterator()
Definition ASoA.h:1032
TableIterator operator++(int)
Definition ASoA.h:1101
framework::selected_pack< soa::is_self_index_t, C... > internal_index_columns_t
Definition ASoA.h:1038
auto getIndexBindings() const
Definition ASoA.h:1151
void setPointerReconstructor(framework::PointerReconstructor const &pointerReconstructor)
Definition ASoA.h:1198
TableIterator operator+(int64_t inc) const
Allow incrementing by more than one the iterator.
Definition ASoA.h:1122
Generic identifier for a table type.
Definition ASoA.h:86
constexpr TableRef & operator=(TableRef const &)=default
consteval TableRef()
Definition ASoA.h:87
uint32_t label_hash
Definition ASoA.h:101
constexpr bool descriptionCompatible(uint32_t _desc_hash) const noexcept
Definition ASoA.h:119
constexpr bool operator==(TableRef const &other) const noexcept
Definition ASoA.h:106
constexpr TableRef(TableRef &&)=default
uint32_t version
Definition ASoA.h:104
constexpr TableRef(TableRef const &)=default
consteval TableRef(uint32_t _label, uint32_t _desc, uint32_t _origin, uint32_t _version)
Definition ASoA.h:94
constexpr bool descriptionCompatible(TableRef const &other) const noexcept
Definition ASoA.h:114
uint32_t desc_hash
Definition ASoA.h:102
uint32_t origin_hash
Definition ASoA.h:103
constexpr TableRef & operator=(TableRef &&)=default
TableIteratorBase const & operator*() const
Definition ASoA.h:1922
TableIteratorBase(TableIteratorBase< IP, P, T... > const &other)
Definition ASoA.h:1830
typename Parent::columns_t columns_t
Definition ASoA.h:1778
TableIteratorBase(TableIteratorBase< IP, P, O1, Os... > const &other)
Definition ASoA.h:1816
typename Parent::external_index_columns_t external_index_columns_t
Definition ASoA.h:1779
TableIteratorBase operator-(int64_t dec) const
Definition ASoA.h:1917
void matchTo(TableIteratorBase< IP, P, T... > const &other)
Definition ASoA.h:1854
void matchTo(TableIteratorBase< IP, P, Os... > const &other)
Definition ASoA.h:1860
TableIteratorBase(TableIteratorBase< FilteredIndexPolicy, P, T... > other)
Definition ASoA.h:1842
std::array< B, sizeof...(CCs)> getValues() const
Definition ASoA.h:1899
static constexpr auto originals
Definition ASoA.h:1781
TableIteratorBase(TableIteratorBase< IP, P, T... > &&other) noexcept
Definition ASoA.h:1836
decltype([]< typename... C >(framework::pack< C... >) -> framework::pack< typename C::binding_t... > {}(external_index_columns_t{})) bindings_pack_t
Definition ASoA.h:1780
TableIteratorBase & operator=(TableIteratorBase< IP, P, Os... > other)
Definition ASoA.h:1793
TableIteratorBase(TableIteratorBase< IP, P, O1, Os... > &&other) noexcept
Definition ASoA.h:1823
TableIteratorBase & operator=(RowViewSentinel const &other)
Definition ASoA.h:1848
TableIteratorBase(arrow::ChunkedArray *columnData[framework::pack_size(columns_t{})], IP &&policy)
Definition ASoA.h:1787
TableIteratorBase & operator=(TableIteratorBase< IP, P, T... > other)
Definition ASoA.h:1801
TableIteratorBase operator+(int64_t inc) const
Allow incrementing by more than one the iterator.
Definition ASoA.h:1910
TableIteratorBase & operator=(TableIteratorBase< FilteredIndexPolicy, P, T... > other)
Definition ASoA.h:1808
unwrapper
Definition ASoA.h:477
VectorOfTObjectPtrs other
std::vector< ReadoutWindowData > rows
const std::string str