Project
Loading...
Searching...
No Matches
TableBuilder.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_TABLEBUILDER_H_
13#define O2_FRAMEWORK_TABLEBUILDER_H_
14
15#include "Framework/ASoA.h"
18#include "arrow/type_traits.h"
19
20// Apparently needs to be on top of the arrow includes.
21#include <sstream>
22
23#include <arrow/chunked_array.h>
24#include <arrow/status.h>
25#include <arrow/memory_pool.h>
26#include <arrow/stl.h>
27#include <arrow/type_traits.h>
28#include <arrow/table.h>
29#include <arrow/builder.h>
30
31#include <vector>
32#include <string>
33#include <memory>
34#include <tuple>
35#include <type_traits>
36#include <concepts>
37
38namespace arrow
39{
40class ArrayBuilder;
41class Table;
42class Array;
43} // namespace arrow
44
45extern template class arrow::NumericBuilder<arrow::UInt8Type>;
46extern template class arrow::NumericBuilder<arrow::UInt32Type>;
47extern template class arrow::NumericBuilder<arrow::FloatType>;
48extern template class arrow::NumericBuilder<arrow::Int32Type>;
49extern template class arrow::NumericBuilder<arrow::Int8Type>;
50
51namespace o2::framework
52{
53namespace detail
54{
56template <typename T>
58};
59
60template <typename T, int N>
61struct ConversionTraits<T (&)[N]> {
62 using ArrowType = ::arrow::FixedSizeListType;
63};
64
65template <typename T, int N>
66struct ConversionTraits<T[N]> {
67 using ArrowType = ::arrow::FixedSizeListType;
68};
69
70template <typename T, int N>
71struct ConversionTraits<std::array<T, N>> {
72 using ArrowType = ::arrow::FixedSizeListType;
73};
74
75template <typename T>
76struct ConversionTraits<std::vector<T>> {
77 using ArrowType = ::arrow::ListType;
78};
79
80#define O2_ARROW_STL_CONVERSION(c_type, ArrowType_) \
81 template <> \
82 struct ConversionTraits<c_type> { \
83 using ArrowType = ::arrow::ArrowType_; \
84 };
85
86// FIXME: for now we use Int8 to store booleans
87O2_ARROW_STL_CONVERSION(bool, BooleanType)
88O2_ARROW_STL_CONVERSION(int8_t, Int8Type)
89O2_ARROW_STL_CONVERSION(int16_t, Int16Type)
90O2_ARROW_STL_CONVERSION(int32_t, Int32Type)
91O2_ARROW_STL_CONVERSION(long long, Int64Type)
92O2_ARROW_STL_CONVERSION(long, Int64Type)
93O2_ARROW_STL_CONVERSION(uint8_t, UInt8Type)
94O2_ARROW_STL_CONVERSION(uint16_t, UInt16Type)
95O2_ARROW_STL_CONVERSION(uint32_t, UInt32Type)
96O2_ARROW_STL_CONVERSION(long long unsigned, UInt64Type)
97O2_ARROW_STL_CONVERSION(long unsigned, UInt64Type)
98O2_ARROW_STL_CONVERSION(float, FloatType)
99O2_ARROW_STL_CONVERSION(double, DoubleType)
100O2_ARROW_STL_CONVERSION(std::string, StringType)
101O2_ARROW_STL_CONVERSION(std::span<std::byte>, BinaryViewType)
102} // namespace detail
103
104void addLabelToSchema(std::shared_ptr<arrow::Schema>& schema, const char* label);
105
107 template <typename T>
108 static arrow::Status appendToList(std::unique_ptr<arrow::FixedSizeListBuilder>& builder, const T* data, int size = 1)
109 {
110 using ArrowType = typename detail::ConversionTraits<std::decay_t<T>>::ArrowType;
111 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
112 size_t numElements = static_cast<const arrow::FixedSizeListType*>(builder->type().get())->list_size();
113
114 auto status = builder->AppendValues(size);
115 auto ValueBuilder = static_cast<BuilderType*>(builder->value_builder());
116 status &= ValueBuilder->AppendValues(data, numElements * size, nullptr);
117
118 return status;
119 }
120
121 template <typename HolderType, typename T>
122 static arrow::Status append(HolderType& holder, T value)
123 {
124 return static_cast<typename HolderType::Policy&>(holder).append(holder.builder, value);
125 }
126
127 template <typename HolderType>
128 static arrow::Status flush(HolderType& holder)
129 {
130 return static_cast<typename HolderType::Policy&>(holder).flush(holder.builder);
131 }
132
136 template <typename HolderType, typename T>
137 static arrow::Status append(HolderType& holder, const T* data)
138 {
139 if constexpr (std::is_same_v<decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) {
140 return appendToList<T>(holder.builder, data);
141 } else {
142 return holder.builder->Append(reinterpret_cast<const uint8_t*>(data));
143 }
144 }
146 template <typename HolderType, typename T, int N>
147 static arrow::Status append(HolderType& holder, const T (&data)[N])
148 {
149 return holder.builder->Append(reinterpret_cast<const uint8_t*>(data));
150 }
151
153 template <typename HolderType, typename T, int N>
154 static arrow::Status append(HolderType& holder, std::array<const T, N> const& data)
155 {
156 return holder.builder->Append(reinterpret_cast<const uint8_t*>(data.data()));
157 }
158
160 template <typename HolderType, typename T>
161 static arrow::Status append(HolderType& holder, std::span<const T> data)
162 {
163 using ArrowType = typename detail::ConversionTraits<T>::ArrowType;
164 using ValueBuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
165 auto status = holder.builder->Reserve(data.size());
166 status &= holder.builder->Append();
167 auto vbuilder = static_cast<ValueBuilderType*>(holder.builder->value_builder());
168 status &= vbuilder->AppendValues(data.begin(), data.end());
169
170 return status;
171 }
172
173 template <typename HolderType, typename T>
174 static void unsafeAppend(HolderType& holder, std::span<const T> value)
175 {
176 auto status = append(holder, value);
177 if (!status.ok()) {
178 throw runtime_error("Unable to append to column");
179 }
180 }
181
182 template <typename HolderType, typename T>
183 static void unsafeAppend(HolderType& holder, T value)
184 {
185 return holder.builder->UnsafeAppend(value);
186 }
187
188 template <typename HolderType, typename T>
189 static void unsafeAppend(HolderType& holder, T* value)
190 {
191 if constexpr (std::is_same_v<decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) {
192 auto status = appendToList<T>(holder.builder, value);
193 } else {
194 return holder.builder->UnsafeAppend(reinterpret_cast<const uint8_t*>(value));
195 }
196 }
197
198 template <typename HolderType, typename ITERATOR>
199 static arrow::Status append(HolderType& holder, std::pair<ITERATOR, ITERATOR> ip)
200 {
202 using ValueBuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
203 // FIXME: for the moment we do not fill things.
204 auto status = holder.builder->Append();
205 auto valueBuilder = reinterpret_cast<ValueBuilderType*>(holder.builder->value_builder());
206 return status & valueBuilder->AppendValues(&*ip.first, std::distance(ip.first, ip.second));
207 }
208
209 // Lists do not have UnsafeAppend so we need to use the slow path in any case.
210 template <typename HolderType, typename ITERATOR>
211 static void unsafeAppend(HolderType& holder, std::pair<ITERATOR, ITERATOR> ip)
212 {
214 using ValueBuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
215 // FIXME: for the moment we do not fill things.
216 auto status = holder.builder->Append();
217 auto valueBuilder = reinterpret_cast<ValueBuilderType*>(holder.builder->value_builder());
218 status &= valueBuilder->AppendValues(&*ip.first, std::distance(ip.first, ip.second));
219 if (!status.ok()) {
220 throw runtime_error("Unable to append values to valueBuilder!");
221 }
222 return;
223 }
224};
225
226template <typename T>
228 using FillType = T;
229 using STLValueType = T;
231 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
232
233 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
234 {
235 return std::make_unique<BuilderType>(pool);
236 }
237
238 static std::shared_ptr<arrow::DataType> make_datatype()
239 {
240 return arrow::TypeTraits<ArrowType>::type_singleton();
241 }
242
243 static arrow::Status append(BuilderType& builder, T value)
244 {
245 return builder.Append(value);
246 }
247
248 template <int N>
249 static arrow::Status append(BuilderType& builder, std::array<T, N>& value)
250 {
251 return builder.Append(value);
252 }
253};
254
255template <>
256struct BuilderMaker<bool> {
257 using FillType = bool;
258 using STLValueType = bool;
260 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
261
262 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
263 {
264 return std::make_unique<BuilderType>(pool);
265 }
266
267 static std::shared_ptr<arrow::DataType> make_datatype()
268 {
269 return arrow::TypeTraits<ArrowType>::type_singleton();
270 }
271
272 static arrow::Status append(BuilderType& builder, bool value)
273 {
274 return builder.Append(value);
275 }
276};
277
278template <>
279struct BuilderMaker<std::span<std::byte>> {
280 using FillType = std::span<std::byte>;
281 using STLValueType = std::span<std::byte>;
283 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
284
285 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
286 {
287 return std::make_unique<BuilderType>(pool);
288 }
289
290 static std::shared_ptr<arrow::DataType> make_datatype()
291 {
292 return arrow::TypeTraits<ArrowType>::type_singleton();
293 }
294
295 static arrow::Status append(BuilderType& builder, std::span<std::byte> value)
296 {
297 return builder.Append((char*)value.data(), (int64_t)value.size());
298 }
299};
300
301template <typename ITERATOR>
302struct BuilderMaker<std::pair<ITERATOR, ITERATOR>> {
303 using FillType = std::pair<ITERATOR, ITERATOR> const&;
304 using STLValueType = typename ITERATOR::value_type;
305 using ArrowType = arrow::ListType;
307 using BuilderType = arrow::ListBuilder;
308 using ValueBuilder = typename arrow::TypeTraits<ValueType>::BuilderType;
309
310 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
311 {
312 auto valueBuilder = std::make_shared<ValueBuilder>(pool);
313 return std::make_unique<arrow::ListBuilder>(pool, valueBuilder);
314 }
315
316 static std::shared_ptr<arrow::DataType> make_datatype()
317 {
318 return arrow::list(arrow::TypeTraits<ValueType>::type_singleton());
319 }
320};
321
322template <typename T, int N>
323struct BuilderMaker<T (&)[N]> {
324 using FillType = const T*;
325 using STLValueType = T;
326 using BuilderType = arrow::FixedSizeListBuilder;
327 using ArrowType = arrow::FixedSizeListType;
329
330 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
331 {
332 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
333 auto status =
334 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
335 return std::make_unique<BuilderType>(pool, std::move(valueBuilder), N);
336 }
337
338 static std::shared_ptr<arrow::DataType> make_datatype()
339 {
340 return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N);
341 }
342};
343
344template <typename T, int N>
345struct BuilderMaker<T[N]> {
346 using FillType = const T*;
347 using BuilderType = arrow::FixedSizeListBuilder;
348 using ArrowType = arrow::FixedSizeListType;
350
351 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
352 {
353 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
354 auto status =
355 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
356 return std::make_unique<BuilderType>(pool, std::move(valueBuilder), N);
357 }
358
359 static std::shared_ptr<arrow::DataType> make_datatype()
360 {
361 return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N);
362 }
363};
364
365template <typename T, int N>
366struct BuilderMaker<std::array<T, N>> {
367 using FillType = const T*;
368 using BuilderType = arrow::FixedSizeListBuilder;
369 using ArrowType = arrow::FixedSizeListType;
371
372 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
373 {
374 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
375 auto status =
376 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
377 return std::make_unique<BuilderType>(pool, std::move(valueBuilder), N);
378 }
379
380 static std::shared_ptr<arrow::DataType> make_datatype()
381 {
382 return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N);
383 }
384};
385
386template <typename T>
387struct BuilderMaker<std::vector<T>> {
388 using FillType = std::span<const T>;
389 using BuilderType = arrow::ListBuilder;
390 using ArrowType = arrow::ListType;
392
393 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
394 {
395 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
396 auto status =
397 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
398 return std::make_unique<BuilderType>(pool, std::move(valueBuilder));
399 }
400
401 static std::shared_ptr<arrow::DataType> make_datatype()
402 {
403 return arrow::list(arrow::TypeTraits<ElementType>::type_singleton());
404 }
405};
406
407template <typename... ARGS>
409{
410 return std::make_tuple(std::make_unique<ARGS>()...);
411}
412
413template <typename T>
416 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
417};
418
419// Support for building tables where each entry is an iterator pair.
420// We map them to an arrow::list for now.
421template <typename ITERATOR>
422struct BuilderTraits<std::pair<ITERATOR, ITERATOR>> {
423 using ArrowType = arrow::ListType;
424 using BuilderType = arrow::ListBuilder;
425};
426
427// Support for building array columns
428// FIXME: move to use FixedSizeList<T> once we move to 0.16.1
429template <typename T, int N>
430struct BuilderTraits<T[N]> {
431 using ArrowType = arrow::FixedSizeListType;
432 using BuilderType = arrow::FixedSizeListBuilder;
433};
434
435template <typename T>
436struct BuilderTraits<std::vector<T>> {
437 using ArrowType = arrow::ListType;
438 using BuilderType = arrow::ListBuilder;
439};
440
441template <typename T>
443 template <typename BUILDER>
444 arrow::Status append(BUILDER& builder, T value)
445 {
446 return builder->Append(value);
447 }
448
449 template <typename BUILDER>
450 requires std::same_as<std::span<std::byte>, T>
451 arrow::Status append(BUILDER& builder, T value)
452 {
453 return builder->Append((char*)value.data(), (int64_t)value.size());
454 }
455
456 template <typename BUILDER>
457 arrow::Status flush(BUILDER&)
458 {
459 return arrow::Status::OK();
460 }
461};
462
463template <typename T>
465 static constexpr int CHUNK_SIZE = 256;
466
467 template <typename BUILDER>
468 arrow::Status append(BUILDER& builder, T value)
469 {
470 cache[pos % CHUNK_SIZE] = value;
471 ++pos;
472 if (pos % CHUNK_SIZE == 0) {
473 return builder->AppendValues(cache, CHUNK_SIZE, nullptr);
474 }
475 return arrow::Status::OK();
476 }
477
478 template <typename BUILDER>
479 arrow::Status flush(BUILDER& builder)
480 {
481 if (pos % CHUNK_SIZE != 0) {
482 return builder->AppendValues(cache, pos % CHUNK_SIZE, nullptr);
483 }
484 return arrow::Status::OK();
485 }
486 T cache[CHUNK_SIZE];
487 int pos = 0;
488};
489
490template <typename T>
492 static consteval DirectInsertion<T> policy();
493 using Policy = decltype(policy());
494};
495
496template <size_t I, typename T>
497struct BuilderHolder : InsertionTrait<T>::Policy {
498 static constexpr size_t index = I;
501 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
502
503 BuilderHolder(arrow::MemoryPool* pool, size_t nRows = 0)
504 : builder{BuilderMaker<T>::make(pool)}
505 {
506 if (nRows > 0) {
507 auto s = builder->Reserve(nRows);
508 if (!s.ok()) {
509 throw runtime_error_f("Unable to reserve %ll rows", nRows);
510 }
511 }
512 }
513
514 std::unique_ptr<BuilderType> builder;
515};
516
518 template <typename... ARGS, size_t NCOLUMNS>
519 static std::array<arrow::DataType, NCOLUMNS> makeArrowColumnTypes()
520 {
522 }
523
525 template <typename... Ts, typename VALUES>
526 static bool append(std::tuple<Ts...>& holders, VALUES&& values)
527 {
528 return (BuilderUtils::append(std::get<Ts::index>(holders), std::get<Ts::index>(values)).ok() && ...);
529 }
530
534 template <typename... Ts, typename VALUES>
535 static void unsafeAppend(std::tuple<Ts...>& holders, VALUES&& values)
536 {
537 (BuilderUtils::unsafeAppend(std::get<Ts::index>(holders), std::get<Ts::index>(values)), ...);
538 }
539
541 template <typename... Ts>
542 static bool finalize(std::vector<std::shared_ptr<arrow::Array>>& arrays, std::tuple<Ts...>& holders)
543 {
544 return (finalize(arrays[Ts::index], std::get<Ts::index>(holders)) && ...);
545 }
546
547 template <typename HOLDER>
548 static bool finalize(std::shared_ptr<arrow::Array>& array, HOLDER& holder)
549 {
550 return BuilderUtils::flush(holder).ok() && holder.builder->Finish(&array).ok();
551 }
552};
553
554template <typename... ARGS>
555constexpr auto tuple_to_pack(std::tuple<ARGS...>&&)
556{
557 return framework::pack<ARGS...>{};
558}
559
562template <class T>
563auto constexpr to_tuple(T&& object) noexcept
564{
565 using type = std::decay_t<T>;
567 auto&& [p0, p1, p2, p3] = object;
568 return std::make_tuple(p0, p1, p2, p3);
570 auto&& [p0, p1, p2] = object;
571 return std::make_tuple(p0, p1, p2);
573 auto&& [p0, p1] = object;
574 return std::make_tuple(p0, p1);
575 } else if constexpr (is_braces_constructible<type, any_type>{}) {
576 auto&& [p0] = object;
577 return std::make_tuple(p0);
578 } else {
579 return std::make_tuple();
580 }
581}
582
583template <typename... ARGS>
584constexpr auto makeHolderTypes()
585{
586 return []<std::size_t... Is>(std::index_sequence<Is...>) {
587 return std::tuple(BuilderHolder<Is, ARGS>(arrow::default_memory_pool())...);
588 }(std::make_index_sequence<sizeof...(ARGS)>{});
589}
590
591template <typename... ARGS>
592auto makeHolders(arrow::MemoryPool* pool, size_t nRows)
593{
594 return [pool, nRows]<std::size_t... Is>(std::index_sequence<Is...>) {
595 return new std::tuple(BuilderHolder<Is, ARGS>(pool, nRows)...);
596 }(std::make_index_sequence<sizeof...(ARGS)>{});
597}
598
599template <typename... ARGS>
600using IndexedHoldersTuple = decltype(makeHolderTypes<ARGS...>());
601
602template <typename T>
603concept ShouldNotDeconstruct = std::is_bounded_array_v<T> || std::is_arithmetic_v<T> || framework::is_base_of_template_v<std::vector, T> || std::same_as<std::span<std::byte>, T>;
604
609{
610 static void throwError(RuntimeErrorRef const& ref);
611
612 template <typename... ARGS>
613 using HoldersTuple = typename std::tuple<BuilderHolder<0, ARGS>...>;
614
615 template <typename... ARGS>
616 using HoldersTupleIndexed = decltype(makeHolderTypes<ARGS...>());
617
620 template <typename... ARGS>
621 auto getBuilders(o2::framework::pack<ARGS...>)
622 {
623 return (HoldersTupleIndexed<ARGS...>*)mHolders;
624 }
625
626 void validate() const;
627
628 template <typename... ARGS, size_t I = sizeof...(ARGS)>
629 auto makeBuilders(std::array<char const*, I> const& columnNames, size_t nRows)
630 {
631 char const* const* names_ptr = columnNames.data();
632 mSchema = std::make_shared<arrow::Schema>(
633 std::vector<std::shared_ptr<arrow::Field>>({std::make_shared<arrow::Field>(*names_ptr++, BuilderMaker<ARGS>::make_datatype(), true, nullptr)...}));
634
635 mHolders = makeHolders<ARGS...>(mMemoryPool, nRows);
636 mFinalizer = [](std::vector<std::shared_ptr<arrow::Array>>& arrays, void* holders) -> bool {
637 return TableBuilderHelpers::finalize(arrays, *(HoldersTupleIndexed<ARGS...>*)holders);
638 };
639 mDestructor = [](void* holders) mutable -> void {
640 delete (HoldersTupleIndexed<ARGS...>*)holders;
641 };
642 }
643
644 public:
645 template <typename ARG0, typename... ARGS>
646 requires(sizeof...(ARGS) == 0) && (!ShouldNotDeconstruct<ARG0>)
647 static constexpr int countColumns()
648 {
649 using argsPack_t = decltype(tuple_to_pack(framework::to_tuple(std::declval<ARG0>())));
650 return framework::pack_size(argsPack_t{});
651 }
652
653 template <typename ARG0, typename... ARGS>
654 requires(sizeof...(ARGS) > 0) || ShouldNotDeconstruct<ARG0>
655 static constexpr int countColumns()
656 {
657 return 1 + sizeof...(ARGS);
658 }
659
660 void setLabel(const char* label);
661
662 TableBuilder(arrow::MemoryPool* pool = arrow::default_memory_pool())
663 : mHolders{nullptr},
664 mMemoryPool{pool}
665 {
666 }
667
669 {
670 mDestructor(mHolders);
671 }
672
675 template <typename ARG0, typename... ARGS>
676 requires(sizeof...(ARGS) > 0) || ShouldNotDeconstruct<ARG0>
677 auto persist(std::array<char const*, sizeof...(ARGS) + 1> const& columnNames)
678 {
679 auto persister = persistTuple(framework::pack<ARG0, ARGS...>{}, columnNames);
680 // Callback used to fill the builders
681 return [persister = persister](unsigned int slot, typename BuilderMaker<ARG0>::FillType arg, typename BuilderMaker<ARGS>::FillType... args) -> void {
682 persister(slot, std::forward_as_tuple(arg, args...));
683 };
684 }
685
686 // Special case for a single parameter to handle the serialization of struct
687 // which can be decomposed
688 template <typename ARG0, typename... ARGS>
689 requires(sizeof...(ARGS) == 0) && (!ShouldNotDeconstruct<ARG0>)
690 auto persist(std::array<char const*, countColumns<ARG0, ARGS...>()> const& columnNames)
691 {
692 using argsPack_t = decltype(tuple_to_pack(framework::to_tuple(std::declval<ARG0>())));
693 auto persister = persistTuple(argsPack_t{}, columnNames);
694 return [persister = persister](unsigned int slot, ARG0 const& obj) -> void {
695 auto t = to_tuple(obj);
696 persister(slot, t);
697 };
698 }
699
701 template <typename... ARGS>
702 auto persistTuple(framework::pack<ARGS...>, std::array<char const*, sizeof...(ARGS)> const& columnNames)
703 {
704 constexpr int nColumns = sizeof...(ARGS);
705 validate();
706 mArrays.resize(nColumns);
707 makeBuilders<ARGS...>(columnNames, 10);
708
709 // Callback used to fill the builders
710 using FillTuple = std::tuple<typename BuilderMaker<ARGS>::FillType...>;
711 return [holders = mHolders](unsigned int /*slot*/, FillTuple const& t) -> void {
712 auto status = TableBuilderHelpers::append(*(HoldersTupleIndexed<ARGS...>*)holders, t);
713 if (status == false) {
714 throwError(runtime_error("Unable to append"));
715 }
716 };
717 }
718
719 // Same as above, but starting from a o2::soa::Table, which has all the
720 // information already available.
721 template <typename T>
722 auto cursor()
723 {
724 return [this]<typename... Cs>(pack<Cs...>) {
725 return this->template persist<typename Cs::type...>({Cs::columnLabel()...});
726 }(typename T::table_t::persistent_columns_t{});
727 }
728
729 template <typename... Cs>
731 {
732 return this->template persist<typename Cs::type...>({Cs::columnLabel()...});
733 }
734
735 template <typename T, typename E>
736 auto cursor()
737 {
738 return [this]<typename... Cs>(pack<Cs...>) {
739 return this->template persist<E>({Cs::columnLabel()...});
740 }(typename T::table_t::persistent_columns_t{});
741 }
742
744 template <typename... Ts>
745 auto reserveArrays(std::tuple<Ts...>& holders, int s)
746 {
747 return (std::get<Ts::index>(holders).builder->Reserve(s).ok() && ...);
748 }
749
750 template <typename... ARGS>
752 {
753 reserveArrays(*(HoldersTupleIndexed<ARGS...>*)mHolders, s);
754 }
755
757 void extracted(bool& status);
758 std::shared_ptr<arrow::Table> finalize();
759
760 private:
761 bool (*mFinalizer)(std::vector<std::shared_ptr<arrow::Array>>& arrays, void* holders);
762 void (*mDestructor)(void* holders);
763 void* mHolders;
764 arrow::MemoryPool* mMemoryPool;
765 std::shared_ptr<arrow::Schema> mSchema;
766 std::vector<std::shared_ptr<arrow::Array>> mArrays;
767};
768
769template <typename T>
770auto makeEmptyTable(const char* name)
771{
773 [[maybe_unused]] auto writer = b.cursor<T>();
774 b.setLabel(name);
775 return b.finalize();
776}
777
778template <soa::TableRef R>
780{
782 [[maybe_unused]] auto writer = b.cursor(typename aod::MetadataTrait<aod::Hash<R.desc_hash>>::metadata::persistent_columns_t{});
783 b.setLabel(aod::label<R>());
784 return b.finalize();
785}
786
787template <typename... Cs>
789{
791 [[maybe_unused]] auto writer = b.cursor(p);
792 b.setLabel(name);
793 return b.finalize();
794}
795
796std::shared_ptr<arrow::Table> spawnerHelper(std::shared_ptr<arrow::Table> const& fullTable, std::shared_ptr<arrow::Schema> newSchema, size_t nColumns,
797 expressions::Projector* projectors, const char* name, std::shared_ptr<gandiva::Projector>& projector);
798
800template <aod::is_aod_hash D>
802auto spawner(std::shared_ptr<arrow::Table> const& fullTable, const char* name, o2::framework::expressions::Projector* projectors, std::shared_ptr<gandiva::Projector>& projector, std::shared_ptr<arrow::Schema> const& schema)
803{
804 using placeholders_pack_t = typename o2::aod::MetadataTrait<D>::metadata::placeholders_pack_t;
805 if (fullTable->num_rows() == 0) {
806 return makeEmptyTable(name, placeholders_pack_t{});
807 }
808 return spawnerHelper(fullTable, schema, framework::pack_size(placeholders_pack_t{}), projectors, name, projector);
809}
810
811template <aod::is_aod_hash D>
813auto spawner(std::vector<std::shared_ptr<arrow::Table>>&& tables, const char* name, o2::framework::expressions::Projector* projectors, std::shared_ptr<gandiva::Projector>& projector, std::shared_ptr<arrow::Schema> const& schema)
814{
815 auto fullTable = soa::ArrowHelpers::joinTables(std::move(tables), std::span{o2::aod::MetadataTrait<D>::metadata::base_table_t::originalLabels});
816 return spawner<D>(fullTable, name, projectors, projector, schema);
817}
818
819template <aod::is_aod_hash D>
821auto spawner(std::shared_ptr<arrow::Table> const& fullTable, const char* name, expressions::Projector* projectors, std::shared_ptr<gandiva::Projector>& projector, std::shared_ptr<arrow::Schema> const& schema)
822{
823 using expression_pack_t = typename o2::aod::MetadataTrait<D>::metadata::expression_pack_t;
824 if (fullTable->num_rows() == 0) {
825 return makeEmptyTable(name, expression_pack_t{});
826 }
827 return spawnerHelper(fullTable, schema, framework::pack_size(expression_pack_t{}), projectors, name, projector);
828}
829
830template <aod::is_aod_hash D>
832auto spawner(std::vector<std::shared_ptr<arrow::Table>>&& tables, const char* name, expressions::Projector* projectors, std::shared_ptr<gandiva::Projector>& projector, std::shared_ptr<arrow::Schema> const& schema)
833{
834 auto fullTable = soa::ArrowHelpers::joinTables(std::move(tables), std::span{o2::aod::MetadataTrait<D>::metadata::base_table_t::originalLabels});
835 return spawner<D>(fullTable, name, projectors, projector, schema);
836}
837
838template <typename... C>
839auto spawner(framework::pack<C...>, std::vector<std::shared_ptr<arrow::Table>>&& tables, const char* name, expressions::Projector* projectors, std::shared_ptr<gandiva::Projector>& projector, std::shared_ptr<arrow::Schema> const& schema)
840{
841 std::array<const char*, 1> labels{"original"};
842 auto fullTable = soa::ArrowHelpers::joinTables(std::move(tables), std::span<const char* const>{labels});
843 if (fullTable->num_rows() == 0) {
845 }
846 return spawnerHelper(fullTable, schema, sizeof...(C), projectors, name, projector);
847}
848
849template <typename... T>
850using iterator_tuple_t = std::tuple<typename T::iterator...>;
851} // namespace o2::framework
852#endif // FRAMEWORK_TABLEBUILDER_H
constexpr int p2()
constexpr int p1()
constexpr to accelerate the coordinates changing
uint16_t pos
Definition RawData.h:3
#define O2_ARROW_STL_CONVERSION(c_type, ArrowType_)
auto cursor(framework::pack< Cs... >)
auto persist(std::array< char const *, countColumns< ARG0, ARGS... >()> const &columnNames)
auto persistTuple(framework::pack< ARGS... >, std::array< char const *, sizeof...(ARGS)> const &columnNames)
Same a the above, but use a tuple to persist stuff.
static constexpr int countColumns()
void extracted(bool &status)
Actually creates the arrow::Table from the builders.
static constexpr int countColumns()
auto reserve(o2::framework::pack< ARGS... > &&, int s)
TableBuilder(arrow::MemoryPool *pool=arrow::default_memory_pool())
auto reserveArrays(std::tuple< Ts... > &holders, int s)
Reserve method to expand the columns as needed.
auto persist(std::array< char const *, sizeof...(ARGS)+1 > const &columnNames)
GLsizeiptr size
Definition glcorearb.h:659
GLenum array
Definition glcorearb.h:4274
GLuint index
Definition glcorearb.h:781
GLuint const GLchar * name
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLenum GLsizei GLsizei GLint * values
Definition glcorearb.h:1576
GLboolean * data
Definition glcorearb.h:298
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLuint object
Definition glcorearb.h:4041
const GLuint * arrays
Definition glcorearb.h:1314
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
void addLabelToSchema(std::shared_ptr< arrow::Schema > &schema, const char *label)
RuntimeErrorRef runtime_error(const char *)
constexpr auto makeHolderTypes()
auto constexpr to_tuple(T &&object) noexcept
auto makeEmptyTable(const char *name)
auto spawner(std::shared_ptr< arrow::Table > const &fullTable, const char *name, o2::framework::expressions::Projector *projectors, std::shared_ptr< gandiva::Projector > &projector, std::shared_ptr< arrow::Schema > const &schema)
Expression-based column generator to materialize columns.
constexpr auto tuple_to_pack(std::tuple< ARGS... > &&)
auto makeHolders(arrow::MemoryPool *pool, size_t nRows)
std::shared_ptr< arrow::Table > spawnerHelper(std::shared_ptr< arrow::Table > const &fullTable, std::shared_ptr< arrow::Schema > newSchema, size_t nColumns, expressions::Projector *projectors, const char *name, std::shared_ptr< gandiva::Projector > &projector)
decltype(makeHolderTypes< ARGS... >()) IndexedHoldersTuple
auto make_builders()
RuntimeErrorRef runtime_error_f(const char *,...)
std::tuple< typename T::iterator... > iterator_tuple_t
Defining DataPointCompositeObject explicitly as copiable.
typename detail::ConversionTraits< T >::ArrowType ArrowType
std::unique_ptr< BuilderType > builder
typename arrow::TypeTraits< ArrowType >::BuilderType BuilderType
typename InsertionTrait< T >::Policy Policy
BuilderHolder(arrow::MemoryPool *pool, size_t nRows=0)
typename detail::ConversionTraits< T >::ArrowType ElementType
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
arrow::FixedSizeListBuilder BuilderType
arrow::FixedSizeListType ArrowType
static std::shared_ptr< arrow::DataType > make_datatype()
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
typename detail::ConversionTraits< T >::ArrowType ElementType
arrow::FixedSizeListType ArrowType
static std::shared_ptr< arrow::DataType > make_datatype()
arrow::FixedSizeListBuilder BuilderType
typename arrow::TypeTraits< ArrowType >::BuilderType BuilderType
static arrow::Status append(BuilderType &builder, bool value)
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
static std::shared_ptr< arrow::DataType > make_datatype()
typename detail::ConversionTraits< bool >::ArrowType ArrowType
typename detail::ConversionTraits< T >::ArrowType ElementType
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
static std::shared_ptr< arrow::DataType > make_datatype()
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
typename detail::ConversionTraits< typename ITERATOR::value_type >::ArrowType ValueType
typename arrow::TypeTraits< ValueType >::BuilderType ValueBuilder
static std::shared_ptr< arrow::DataType > make_datatype()
static arrow::Status append(BuilderType &builder, std::span< std::byte > value)
typename arrow::TypeTraits< ArrowType >::BuilderType BuilderType
typename detail::ConversionTraits< std::span< std::byte > >::ArrowType ArrowType
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
static std::shared_ptr< arrow::DataType > make_datatype()
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
typename detail::ConversionTraits< T >::ArrowType ElementType
static std::shared_ptr< arrow::DataType > make_datatype()
typename arrow::TypeTraits< ArrowType >::BuilderType BuilderType
static arrow::Status append(BuilderType &builder, std::array< T, N > &value)
static arrow::Status append(BuilderType &builder, T value)
typename detail::ConversionTraits< T >::ArrowType ArrowType
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
static std::shared_ptr< arrow::DataType > make_datatype()
arrow::FixedSizeListBuilder BuilderType
arrow::FixedSizeListType ArrowType
typename arrow::TypeTraits< ArrowType >::BuilderType BuilderType
typename detail::ConversionTraits< T >::ArrowType ArrowType
static arrow::Status flush(HolderType &holder)
static arrow::Status appendToList(std::unique_ptr< arrow::FixedSizeListBuilder > &builder, const T *data, int size=1)
static arrow::Status append(HolderType &holder, const T(&data)[N])
Appender for the array case.
static arrow::Status append(HolderType &holder, T value)
static void unsafeAppend(HolderType &holder, std::span< const T > value)
static arrow::Status append(HolderType &holder, std::span< const T > data)
Appender for the vector case.
static arrow::Status append(HolderType &holder, const T *data)
static arrow::Status append(HolderType &holder, std::pair< ITERATOR, ITERATOR > ip)
static arrow::Status append(HolderType &holder, std::array< const T, N > const &data)
Appender for the array case.
static void unsafeAppend(HolderType &holder, T *value)
static void unsafeAppend(HolderType &holder, std::pair< ITERATOR, ITERATOR > ip)
static void unsafeAppend(HolderType &holder, T value)
arrow::Status append(BUILDER &builder, T value)
arrow::Status flush(BUILDER &builder)
arrow::Status append(BUILDER &builder, T value)
arrow::Status append(BUILDER &builder, T value)
arrow::Status flush(BUILDER &)
static consteval DirectInsertion< T > policy()
static bool finalize(std::shared_ptr< arrow::Array > &array, HOLDER &holder)
static bool append(std::tuple< Ts... > &holders, VALUES &&values)
Invokes the append method for each entry in the tuple.
static std::array< arrow::DataType, NCOLUMNS > makeArrowColumnTypes()
static bool finalize(std::vector< std::shared_ptr< arrow::Array > > &arrays, std::tuple< Ts... > &holders)
Invokes the append method for each entry in the tuple.
static void unsafeAppend(std::tuple< Ts... > &holders, VALUES &&values)
FIXME: adapt type conversion to new arrow.
A struct, containing the root of the expression tree.