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