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