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