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
19// Apparently needs to be on top of the arrow includes.
20
21#include <arrow/chunked_array.h>
22#include <arrow/status.h>
23#include <arrow/memory_pool.h>
24#include <arrow/stl.h>
25#include <arrow/type_traits.h>
26#include <arrow/table.h>
27#include <arrow/builder.h>
28#include <arrow/util/key_value_metadata.h>
29
30#include <vector>
31#include <string>
32#include <memory>
33#include <tuple>
34#include <type_traits>
35#include <concepts>
36
37namespace arrow
38{
39class ArrayBuilder;
40class Table;
41class Array;
42} // namespace arrow
43
44extern template class arrow::NumericBuilder<arrow::UInt8Type>;
45extern template class arrow::NumericBuilder<arrow::UInt32Type>;
46extern template class arrow::NumericBuilder<arrow::FloatType>;
47extern template class arrow::NumericBuilder<arrow::Int32Type>;
48extern template class arrow::NumericBuilder<arrow::Int8Type>;
49
50namespace o2::framework
51{
52namespace detail
53{
55template <typename T>
57};
58
59template <typename T, int N>
60struct ConversionTraits<T (&)[N]> {
61 using ArrowType = ::arrow::FixedSizeListType;
62};
63
64template <typename T, int N>
65struct ConversionTraits<T[N]> {
66 using ArrowType = ::arrow::FixedSizeListType;
67};
68
69template <typename T, int N>
70struct ConversionTraits<std::array<T, N>> {
71 using ArrowType = ::arrow::FixedSizeListType;
72};
73
74template <typename T>
75struct ConversionTraits<std::vector<T>> {
76 using ArrowType = ::arrow::ListType;
77};
78
79#define O2_ARROW_STL_CONVERSION(c_type, ArrowType_) \
80 template <> \
81 struct ConversionTraits<c_type> { \
82 using ArrowType = ::arrow::ArrowType_; \
83 };
84
85// FIXME: for now we use Int8 to store booleans
86O2_ARROW_STL_CONVERSION(bool, BooleanType)
87O2_ARROW_STL_CONVERSION(int8_t, Int8Type)
88O2_ARROW_STL_CONVERSION(int16_t, Int16Type)
89O2_ARROW_STL_CONVERSION(int32_t, Int32Type)
90O2_ARROW_STL_CONVERSION(long long, Int64Type)
91O2_ARROW_STL_CONVERSION(long, Int64Type)
92O2_ARROW_STL_CONVERSION(uint8_t, UInt8Type)
93O2_ARROW_STL_CONVERSION(uint16_t, UInt16Type)
94O2_ARROW_STL_CONVERSION(uint32_t, UInt32Type)
95O2_ARROW_STL_CONVERSION(long long unsigned, UInt64Type)
96O2_ARROW_STL_CONVERSION(long unsigned, UInt64Type)
97O2_ARROW_STL_CONVERSION(float, FloatType)
98O2_ARROW_STL_CONVERSION(double, DoubleType)
99O2_ARROW_STL_CONVERSION(std::string, StringType)
100O2_ARROW_STL_CONVERSION(std::span<std::byte>, BinaryViewType)
101} // namespace detail
102
103void addLabelToSchema(std::shared_ptr<arrow::Schema>& schema, const char* label);
104
106 template <typename T>
107 static arrow::Status appendToList(std::unique_ptr<arrow::FixedSizeListBuilder>& builder, const T* data, int size = 1)
108 {
109 using ArrowType = typename detail::ConversionTraits<std::decay_t<T>>::ArrowType;
110 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
111 size_t numElements = static_cast<const arrow::FixedSizeListType*>(builder->type().get())->list_size();
112
113 auto status = builder->AppendValues(size);
114 auto ValueBuilder = static_cast<BuilderType*>(builder->value_builder());
115 status &= ValueBuilder->AppendValues(data, numElements * size, nullptr);
116
117 return status;
118 }
119
120 template <typename HolderType, typename T>
121 static arrow::Status append(HolderType& holder, T value)
122 {
123 return static_cast<typename HolderType::Policy&>(holder).append(holder.builder, value);
124 }
125
126 template <typename HolderType>
127 static arrow::Status flush(HolderType& holder)
128 {
129 return static_cast<typename HolderType::Policy&>(holder).flush(holder.builder);
130 }
131
135 template <typename HolderType, typename T>
136 static arrow::Status append(HolderType& holder, const T* data)
137 {
138 if constexpr (std::is_same_v<decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) {
139 return appendToList<T>(holder.builder, data);
140 } else {
141 return holder.builder->Append(reinterpret_cast<const uint8_t*>(data));
142 }
143 }
145 template <typename HolderType, typename T, int N>
146 static arrow::Status append(HolderType& holder, const T (&data)[N])
147 {
148 return holder.builder->Append(reinterpret_cast<const uint8_t*>(data));
149 }
150
152 template <typename HolderType, typename T, int N>
153 static arrow::Status append(HolderType& holder, std::array<const T, N> const& data)
154 {
155 return holder.builder->Append(reinterpret_cast<const uint8_t*>(data.data()));
156 }
157
159 template <typename HolderType, typename T>
160 static arrow::Status append(HolderType& holder, std::span<const T> data)
161 {
162 using ArrowType = typename detail::ConversionTraits<T>::ArrowType;
163 using ValueBuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
164 auto status = holder.builder->Reserve(data.size());
165 status &= holder.builder->Append();
166 auto vbuilder = static_cast<ValueBuilderType*>(holder.builder->value_builder());
167 status &= vbuilder->AppendValues(data.begin(), data.end());
168
169 return status;
170 }
171
172 template <typename HolderType, typename T>
173 static void unsafeAppend(HolderType& holder, std::span<const T> value)
174 {
175 auto status = append(holder, value);
176 if (!status.ok()) {
177 throw runtime_error("Unable to append to column");
178 }
179 }
180
181 template <typename HolderType, typename T>
182 static void unsafeAppend(HolderType& holder, T value)
183 {
184 return holder.builder->UnsafeAppend(value);
185 }
186
187 template <typename HolderType, typename T>
188 static void unsafeAppend(HolderType& holder, T* value)
189 {
190 if constexpr (std::is_same_v<decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) {
191 auto status = appendToList<T>(holder.builder, value);
192 } else {
193 return holder.builder->UnsafeAppend(reinterpret_cast<const uint8_t*>(value));
194 }
195 }
196
197 template <typename HolderType, typename ITERATOR>
198 static arrow::Status append(HolderType& holder, std::pair<ITERATOR, ITERATOR> ip)
199 {
201 using ValueBuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
202 // FIXME: for the moment we do not fill things.
203 auto status = holder.builder->Append();
204 auto valueBuilder = reinterpret_cast<ValueBuilderType*>(holder.builder->value_builder());
205 return status & valueBuilder->AppendValues(&*ip.first, std::distance(ip.first, ip.second));
206 }
207
208 // Lists do not have UnsafeAppend so we need to use the slow path in any case.
209 template <typename HolderType, typename ITERATOR>
210 static void unsafeAppend(HolderType& holder, std::pair<ITERATOR, ITERATOR> ip)
211 {
213 using ValueBuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
214 // FIXME: for the moment we do not fill things.
215 auto status = holder.builder->Append();
216 auto valueBuilder = reinterpret_cast<ValueBuilderType*>(holder.builder->value_builder());
217 status &= valueBuilder->AppendValues(&*ip.first, std::distance(ip.first, ip.second));
218 if (!status.ok()) {
219 throw runtime_error("Unable to append values to valueBuilder!");
220 }
221 return;
222 }
223};
224
225template <typename T>
227 using FillType = T;
228 using STLValueType = T;
230 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
231
232 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
233 {
234 return std::make_unique<BuilderType>(pool);
235 }
236
237 static std::shared_ptr<arrow::DataType> make_datatype()
238 {
239 return arrow::TypeTraits<ArrowType>::type_singleton();
240 }
241
242 static arrow::Status append(BuilderType& builder, T value)
243 {
244 return builder.Append(value);
245 }
246
247 template <int N>
248 static arrow::Status append(BuilderType& builder, std::array<T, N>& value)
249 {
250 return builder.Append(value);
251 }
252};
253
254template <>
255struct BuilderMaker<bool> {
256 using FillType = bool;
257 using STLValueType = bool;
259 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
260
261 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
262 {
263 return std::make_unique<BuilderType>(pool);
264 }
265
266 static std::shared_ptr<arrow::DataType> make_datatype()
267 {
268 return arrow::TypeTraits<ArrowType>::type_singleton();
269 }
270
271 static arrow::Status append(BuilderType& builder, bool value)
272 {
273 return builder.Append(value);
274 }
275};
276
277template <>
278struct BuilderMaker<std::span<std::byte>> {
279 using FillType = std::span<std::byte>;
280 using STLValueType = std::span<std::byte>;
282 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
283
284 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
285 {
286 return std::make_unique<BuilderType>(pool);
287 }
288
289 static std::shared_ptr<arrow::DataType> make_datatype()
290 {
291 return arrow::TypeTraits<ArrowType>::type_singleton();
292 }
293
294 static arrow::Status append(BuilderType& builder, std::span<std::byte> value)
295 {
296 return builder.Append((char*)value.data(), (int64_t)value.size());
297 }
298};
299
300template <typename ITERATOR>
301struct BuilderMaker<std::pair<ITERATOR, ITERATOR>> {
302 using FillType = std::pair<ITERATOR, ITERATOR> const&;
303 using STLValueType = typename ITERATOR::value_type;
304 using ArrowType = arrow::ListType;
306 using BuilderType = arrow::ListBuilder;
307 using ValueBuilder = typename arrow::TypeTraits<ValueType>::BuilderType;
308
309 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
310 {
311 auto valueBuilder = std::make_shared<ValueBuilder>(pool);
312 return std::make_unique<arrow::ListBuilder>(pool, valueBuilder);
313 }
314
315 static std::shared_ptr<arrow::DataType> make_datatype()
316 {
317 return arrow::list(arrow::TypeTraits<ValueType>::type_singleton());
318 }
319};
320
321template <typename T, int N>
322struct BuilderMaker<T (&)[N]> {
323 using FillType = const T*;
324 using STLValueType = T;
325 using BuilderType = arrow::FixedSizeListBuilder;
326 using ArrowType = arrow::FixedSizeListType;
328
329 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
330 {
331 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
332 auto status =
333 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
334 return std::make_unique<BuilderType>(pool, std::move(valueBuilder), N);
335 }
336
337 static std::shared_ptr<arrow::DataType> make_datatype()
338 {
339 return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N);
340 }
341};
342
343template <typename T, int N>
344struct BuilderMaker<T[N]> {
345 using FillType = const T*;
346 using BuilderType = arrow::FixedSizeListBuilder;
347 using ArrowType = arrow::FixedSizeListType;
349
350 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
351 {
352 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
353 auto status =
354 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
355 return std::make_unique<BuilderType>(pool, std::move(valueBuilder), N);
356 }
357
358 static std::shared_ptr<arrow::DataType> make_datatype()
359 {
360 return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N);
361 }
362};
363
364template <typename T, int N>
365struct BuilderMaker<std::array<T, N>> {
366 using FillType = const T*;
367 using BuilderType = arrow::FixedSizeListBuilder;
368 using ArrowType = arrow::FixedSizeListType;
370
371 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
372 {
373 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
374 auto status =
375 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
376 return std::make_unique<BuilderType>(pool, std::move(valueBuilder), N);
377 }
378
379 static std::shared_ptr<arrow::DataType> make_datatype()
380 {
381 return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N);
382 }
383};
384
385template <typename T>
386struct BuilderMaker<std::vector<T>> {
387 using FillType = std::span<const T>;
388 using BuilderType = arrow::ListBuilder;
389 using ArrowType = arrow::ListType;
391
392 static std::unique_ptr<BuilderType> make(arrow::MemoryPool* pool)
393 {
394 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
395 auto status =
396 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
397 return std::make_unique<BuilderType>(pool, std::move(valueBuilder));
398 }
399
400 static std::shared_ptr<arrow::DataType> make_datatype()
401 {
402 return arrow::list(arrow::TypeTraits<ElementType>::type_singleton());
403 }
404};
405
406template <typename... ARGS>
408{
409 return std::make_tuple(std::make_unique<ARGS>()...);
410}
411
412template <typename T>
415 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
416};
417
418// Support for building tables where each entry is an iterator pair.
419// We map them to an arrow::list for now.
420template <typename ITERATOR>
421struct BuilderTraits<std::pair<ITERATOR, ITERATOR>> {
422 using ArrowType = arrow::ListType;
423 using BuilderType = arrow::ListBuilder;
424};
425
426// Support for building array columns
427// FIXME: move to use FixedSizeList<T> once we move to 0.16.1
428template <typename T, int N>
429struct BuilderTraits<T[N]> {
430 using ArrowType = arrow::FixedSizeListType;
431 using BuilderType = arrow::FixedSizeListBuilder;
432};
433
434template <typename T>
435struct BuilderTraits<std::vector<T>> {
436 using ArrowType = arrow::ListType;
437 using BuilderType = arrow::ListBuilder;
438};
439
440template <typename T>
442 template <typename BUILDER>
443 arrow::Status append(BUILDER& builder, T value)
444 {
445 return builder->Append(value);
446 }
447
448 template <typename BUILDER>
449 requires std::same_as<std::span<std::byte>, T>
450 arrow::Status append(BUILDER& builder, T value)
451 {
452 return builder->Append((char*)value.data(), (int64_t)value.size());
453 }
454
455 template <typename BUILDER>
456 arrow::Status flush(BUILDER&)
457 {
458 return arrow::Status::OK();
459 }
460};
461
462template <typename T>
464 static constexpr int CHUNK_SIZE = 256;
465
466 template <typename BUILDER>
467 arrow::Status append(BUILDER& builder, T value)
468 {
469 cache[pos % CHUNK_SIZE] = value;
470 ++pos;
471 if (pos % CHUNK_SIZE == 0) {
472 return builder->AppendValues(cache, CHUNK_SIZE, nullptr);
473 }
474 return arrow::Status::OK();
475 }
476
477 template <typename BUILDER>
478 arrow::Status flush(BUILDER& builder)
479 {
480 if (pos % CHUNK_SIZE != 0) {
481 return builder->AppendValues(cache, pos % CHUNK_SIZE, nullptr);
482 }
483 return arrow::Status::OK();
484 }
485 T cache[CHUNK_SIZE];
486 int pos = 0;
487};
488
489template <typename T>
491 static consteval DirectInsertion<T> policy();
492 using Policy = decltype(policy());
493};
494
495template <size_t I, typename T>
496struct BuilderHolder : InsertionTrait<T>::Policy {
497 static constexpr size_t index = I;
500 using BuilderType = typename arrow::TypeTraits<ArrowType>::BuilderType;
501
502 BuilderHolder(arrow::MemoryPool* pool, size_t nRows = 0)
503 : builder{BuilderMaker<T>::make(pool)}
504 {
505 if (nRows > 0) {
506 auto s = builder->Reserve(nRows);
507 if (!s.ok()) {
508 throw runtime_error_f("Unable to reserve %ll rows", nRows);
509 }
510 }
511 }
512
513 std::unique_ptr<BuilderType> builder;
514};
515
517 template <typename... ARGS, size_t NCOLUMNS>
518 static std::array<arrow::DataType, NCOLUMNS> makeArrowColumnTypes()
519 {
521 }
522
524 template <typename... Ts, typename VALUES>
525 static bool append(std::tuple<Ts...>& holders, VALUES&& values)
526 {
527 return (BuilderUtils::append(std::get<Ts::index>(holders), std::get<Ts::index>(values)).ok() && ...);
528 }
529
533 template <typename... Ts, typename VALUES>
534 static void unsafeAppend(std::tuple<Ts...>& holders, VALUES&& values)
535 {
536 (BuilderUtils::unsafeAppend(std::get<Ts::index>(holders), std::get<Ts::index>(values)), ...);
537 }
538
540 template <typename... Ts>
541 static bool finalize(std::vector<std::shared_ptr<arrow::Array>>& arrays, std::tuple<Ts...>& holders)
542 {
543 return (finalize(arrays[Ts::index], std::get<Ts::index>(holders)) && ...);
544 }
545
546 template <typename HOLDER>
547 static bool finalize(std::shared_ptr<arrow::Array>& array, HOLDER& holder)
548 {
549 return BuilderUtils::flush(holder).ok() && holder.builder->Finish(&array).ok();
550 }
551};
552
553template <typename... ARGS>
554constexpr auto tuple_to_pack(std::tuple<ARGS...>&&)
555{
556 return framework::pack<ARGS...>{};
557}
558
561template <class T>
562auto constexpr to_tuple(T&& object) noexcept
563{
564 using type = std::decay_t<T>;
566 auto&& [p0, p1, p2, p3] = object;
567 return std::make_tuple(p0, p1, p2, p3);
569 auto&& [p0, p1, p2] = object;
570 return std::make_tuple(p0, p1, p2);
572 auto&& [p0, p1] = object;
573 return std::make_tuple(p0, p1);
574 } else if constexpr (is_braces_constructible<type, any_type>{}) {
575 auto&& [p0] = object;
576 return std::make_tuple(p0);
577 } else {
578 return std::make_tuple();
579 }
580}
581
582template <typename... ARGS>
583constexpr auto makeHolderTypes()
584{
585 return []<std::size_t... Is>(std::index_sequence<Is...>) {
586 return std::tuple(BuilderHolder<Is, ARGS>(arrow::default_memory_pool())...);
587 }(std::make_index_sequence<sizeof...(ARGS)>{});
588}
589
590template <typename... ARGS>
591auto makeHolders(arrow::MemoryPool* pool, size_t nRows)
592{
593 return [pool, nRows]<std::size_t... Is>(std::index_sequence<Is...>) {
594 return new std::tuple(BuilderHolder<Is, ARGS>(pool, nRows)...);
595 }(std::make_index_sequence<sizeof...(ARGS)>{});
596}
597
598template <typename... ARGS>
599using IndexedHoldersTuple = decltype(makeHolderTypes<ARGS...>());
600
601template <typename T>
602concept 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>;
603
608{
609 static void throwError(RuntimeErrorRef const& ref);
610
611 template <typename... ARGS>
612 using HoldersTuple = typename std::tuple<BuilderHolder<0, ARGS>...>;
613
614 template <typename... ARGS>
615 using HoldersTupleIndexed = decltype(makeHolderTypes<ARGS...>());
616
619 template <typename... ARGS>
620 auto getBuilders(o2::framework::pack<ARGS...>)
621 {
622 return (HoldersTupleIndexed<ARGS...>*)mHolders;
623 }
624
625 void validate() const;
626
627 template <typename... ARGS, size_t I = sizeof...(ARGS)>
628 auto makeBuilders(std::array<char const*, I> const& columnNames, size_t nRows)
629 {
630 char const* const* names_ptr = columnNames.data();
631 mSchema = std::make_shared<arrow::Schema>(
632 std::vector<std::shared_ptr<arrow::Field>>({std::make_shared<arrow::Field>(*names_ptr++, BuilderMaker<ARGS>::make_datatype(), true, nullptr)...}));
633
634 mHolders = makeHolders<ARGS...>(mMemoryPool, nRows);
635 mFinalizer = [](std::vector<std::shared_ptr<arrow::Array>>& arrays, void* holders) -> bool {
636 return TableBuilderHelpers::finalize(arrays, *(HoldersTupleIndexed<ARGS...>*)holders);
637 };
638 mDestructor = [](void* holders) mutable -> void {
639 delete (HoldersTupleIndexed<ARGS...>*)holders;
640 };
641 }
642
643 public:
644 template <typename ARG0, typename... ARGS>
645 requires(sizeof...(ARGS) == 0) && (!ShouldNotDeconstruct<ARG0>)
646 static constexpr int countColumns()
647 {
648 using argsPack_t = decltype(tuple_to_pack(framework::to_tuple(std::declval<ARG0>())));
649 return framework::pack_size(argsPack_t{});
650 }
651
652 template <typename ARG0, typename... ARGS>
653 requires(sizeof...(ARGS) > 0) || ShouldNotDeconstruct<ARG0>
654 static constexpr int countColumns()
655 {
656 return 1 + sizeof...(ARGS);
657 }
658
659 void setLabel(const char* label);
660
661 TableBuilder(arrow::MemoryPool* pool = arrow::default_memory_pool())
662 : mHolders{nullptr},
663 mMemoryPool{pool}
664 {
665 }
666
668 {
669 mDestructor(mHolders);
670 }
671
674 template <typename ARG0, typename... ARGS>
675 requires(sizeof...(ARGS) > 0) || ShouldNotDeconstruct<ARG0>
676 auto persist(std::array<char const*, sizeof...(ARGS) + 1> const& columnNames)
677 {
678 auto persister = persistTuple(framework::pack<ARG0, ARGS...>{}, columnNames);
679 // Callback used to fill the builders
680 return [persister = persister](unsigned int slot, typename BuilderMaker<ARG0>::FillType arg, typename BuilderMaker<ARGS>::FillType... args) -> void {
681 persister(slot, std::forward_as_tuple(arg, args...));
682 };
683 }
684
685 // Special case for a single parameter to handle the serialization of struct
686 // which can be decomposed
687 template <typename ARG0, typename... ARGS>
688 requires(sizeof...(ARGS) == 0) && (!ShouldNotDeconstruct<ARG0>)
689 auto persist(std::array<char const*, countColumns<ARG0, ARGS...>()> const& columnNames)
690 {
691 using argsPack_t = decltype(tuple_to_pack(framework::to_tuple(std::declval<ARG0>())));
692 auto persister = persistTuple(argsPack_t{}, columnNames);
693 return [persister = persister](unsigned int slot, ARG0 const& obj) -> void {
694 auto t = to_tuple(obj);
695 persister(slot, t);
696 };
697 }
698
700 template <typename... ARGS>
701 auto persistTuple(framework::pack<ARGS...>, std::array<char const*, sizeof...(ARGS)> const& columnNames)
702 {
703 constexpr int nColumns = sizeof...(ARGS);
704 validate();
705 mArrays.resize(nColumns);
706 makeBuilders<ARGS...>(columnNames, 10);
707
708 // Callback used to fill the builders
709 using FillTuple = std::tuple<typename BuilderMaker<ARGS>::FillType...>;
710 return [holders = mHolders](unsigned int /*slot*/, FillTuple const& t) -> void {
711 auto status = TableBuilderHelpers::append(*(HoldersTupleIndexed<ARGS...>*)holders, t);
712 if (status == false) {
713 throwError(runtime_error("Unable to append"));
714 }
715 };
716 }
717
718 // Same as above, but starting from a o2::soa::Table, which has all the
719 // information already available.
720 template <typename T>
721 auto cursor()
722 {
723 return [this]<typename... Cs>(pack<Cs...>) {
724 return this->template persist<typename Cs::type...>({Cs::columnLabel()...});
725 }(typename T::table_t::persistent_columns_t{});
726 }
727
728 template <typename... Cs>
730 {
731 return this->template persist<typename Cs::type...>({Cs::columnLabel()...});
732 }
733
734 template <typename T, typename E>
735 auto cursor()
736 {
737 return [this]<typename... Cs>(pack<Cs...>) {
738 return this->template persist<E>({Cs::columnLabel()...});
739 }(typename T::table_t::persistent_columns_t{});
740 }
741
743 template <typename... Ts>
744 auto reserveArrays(std::tuple<Ts...>& holders, int s)
745 {
746 return (std::get<Ts::index>(holders).builder->Reserve(s).ok() && ...);
747 }
748
749 template <typename... ARGS>
751 {
752 reserveArrays(*(HoldersTupleIndexed<ARGS...>*)mHolders, s);
753 }
754
756 void extracted(bool& status);
757 std::shared_ptr<arrow::Table> finalize();
758
759 private:
760 bool (*mFinalizer)(std::vector<std::shared_ptr<arrow::Array>>& arrays, void* holders);
761 void (*mDestructor)(void* holders);
762 void* mHolders;
763 arrow::MemoryPool* mMemoryPool;
764 std::shared_ptr<arrow::Schema> mSchema;
765 std::vector<std::shared_ptr<arrow::Array>> mArrays;
766};
767} // namespace o2::framework
768#endif // FRAMEWORK_TABLEBUILDER_H
std::shared_ptr< arrow::Schema > schema
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
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.
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
constexpr auto tuple_to_pack(std::tuple< ARGS... > &&)
auto makeHolders(arrow::MemoryPool *pool, size_t nRows)
decltype(makeHolderTypes< ARGS... >()) IndexedHoldersTuple
auto make_builders()
RuntimeErrorRef runtime_error_f(const char *,...)
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.