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