12#ifndef O2_FRAMEWORK_TABLEBUILDER_H_
13#define O2_FRAMEWORK_TABLEBUILDER_H_
21#include <arrow/chunked_array.h>
22#include <arrow/status.h>
23#include <arrow/memory_pool.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>
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>;
59template <
typename T,
int N>
64template <
typename T,
int N>
69template <
typename T,
int N>
79#define O2_ARROW_STL_CONVERSION(c_type, ArrowType_) \
81 struct ConversionTraits<c_type> { \
82 using ArrowType = ::arrow::ArrowType_; \
106 template <
typename T>
107 static arrow::Status
appendToList(std::unique_ptr<arrow::FixedSizeListBuilder>& builder,
const T*
data,
int size = 1)
110 using BuilderType =
typename arrow::TypeTraits<ArrowType>::BuilderType;
111 size_t numElements =
static_cast<const arrow::FixedSizeListType*
>(builder->type().get())->
list_size();
113 auto status = builder->AppendValues(
size);
114 auto ValueBuilder =
static_cast<BuilderType*
>(builder->value_builder());
115 status &= ValueBuilder->AppendValues(
data, numElements *
size,
nullptr);
120 template <
typename HolderType,
typename T>
123 return static_cast<typename HolderType::Policy&
>(holder).append(holder.builder,
value);
126 template <
typename HolderType>
127 static arrow::Status
flush(HolderType& holder)
129 return static_cast<typename HolderType::Policy&
>(holder).flush(holder.builder);
135 template <
typename HolderType,
typename T>
136 static arrow::Status
append(HolderType& holder,
const T*
data)
138 if constexpr (std::is_same_v<
decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) {
139 return appendToList<T>(holder.builder,
data);
141 return holder.builder->Append(
reinterpret_cast<const uint8_t*
>(
data));
145 template <
typename HolderType,
typename T,
int N>
146 static arrow::Status
append(HolderType& holder,
const T (&
data)[N])
148 return holder.builder->Append(
reinterpret_cast<const uint8_t*
>(
data));
152 template <
typename HolderType,
typename T,
int N>
153 static arrow::Status
append(HolderType& holder, std::array<const T, N>
const&
data)
155 return holder.builder->Append(
reinterpret_cast<const uint8_t*
>(
data.data()));
159 template <
typename HolderType,
typename T>
160 static arrow::Status
append(HolderType& holder, std::span<const T>
data)
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());
172 template <
typename HolderType,
typename T>
175 auto status = append(holder,
value);
181 template <
typename HolderType,
typename T>
184 return holder.builder->UnsafeAppend(
value);
187 template <
typename HolderType,
typename T>
190 if constexpr (std::is_same_v<
decltype(holder.builder), std::unique_ptr<arrow::FixedSizeListBuilder>>) {
191 auto status = appendToList<T>(holder.builder,
value);
193 return holder.builder->UnsafeAppend(
reinterpret_cast<const uint8_t*
>(
value));
197 template <
typename HolderType,
typename ITERATOR>
198 static arrow::Status
append(HolderType& holder, std::pair<ITERATOR, ITERATOR> ip)
201 using ValueBuilderType =
typename arrow::TypeTraits<ArrowType>::BuilderType;
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));
209 template <
typename HolderType,
typename ITERATOR>
210 static void unsafeAppend(HolderType& holder, std::pair<ITERATOR, ITERATOR> ip)
213 using ValueBuilderType =
typename arrow::TypeTraits<ArrowType>::BuilderType;
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));
219 throw runtime_error(
"Unable to append values to valueBuilder!");
230 using BuilderType =
typename arrow::TypeTraits<ArrowType>::BuilderType;
232 static std::unique_ptr<BuilderType>
make(arrow::MemoryPool* pool)
234 return std::make_unique<BuilderType>(pool);
239 return arrow::TypeTraits<ArrowType>::type_singleton();
244 return builder.Append(
value);
250 return builder.Append(
value);
259 using BuilderType =
typename arrow::TypeTraits<ArrowType>::BuilderType;
261 static std::unique_ptr<BuilderType>
make(arrow::MemoryPool* pool)
263 return std::make_unique<BuilderType>(pool);
268 return arrow::TypeTraits<ArrowType>::type_singleton();
273 return builder.Append(
value);
282 using BuilderType =
typename arrow::TypeTraits<ArrowType>::BuilderType;
284 static std::unique_ptr<BuilderType>
make(arrow::MemoryPool* pool)
286 return std::make_unique<BuilderType>(pool);
291 return arrow::TypeTraits<ArrowType>::type_singleton();
296 return builder.Append((
char*)
value.data(), (int64_t)
value.size());
300template <
typename ITERATOR>
302 using FillType = std::pair<ITERATOR, ITERATOR>
const&;
307 using ValueBuilder =
typename arrow::TypeTraits<ValueType>::BuilderType;
309 static std::unique_ptr<BuilderType>
make(arrow::MemoryPool* pool)
311 auto valueBuilder = std::make_shared<ValueBuilder>(pool);
312 return std::make_unique<arrow::ListBuilder>(pool, valueBuilder);
317 return arrow::list(arrow::TypeTraits<ValueType>::type_singleton());
321template <
typename T,
int N>
329 static std::unique_ptr<BuilderType>
make(arrow::MemoryPool* pool)
331 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
333 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
334 return std::make_unique<BuilderType>(pool, std::move(valueBuilder), N);
339 return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N);
343template <
typename T,
int N>
350 static std::unique_ptr<BuilderType>
make(arrow::MemoryPool* pool)
352 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
354 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
355 return std::make_unique<BuilderType>(pool, std::move(valueBuilder), N);
360 return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N);
364template <
typename T,
int N>
371 static std::unique_ptr<BuilderType>
make(arrow::MemoryPool* pool)
373 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
375 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
376 return std::make_unique<BuilderType>(pool, std::move(valueBuilder), N);
381 return arrow::fixed_size_list(arrow::TypeTraits<ElementType>::type_singleton(), N);
392 static std::unique_ptr<BuilderType>
make(arrow::MemoryPool* pool)
394 std::unique_ptr<arrow::ArrayBuilder> valueBuilder;
396 arrow::MakeBuilder(pool, arrow::TypeTraits<ElementType>::type_singleton(), &valueBuilder);
397 return std::make_unique<BuilderType>(pool, std::move(valueBuilder));
402 return arrow::list(arrow::TypeTraits<ElementType>::type_singleton());
406template <
typename... ARGS>
409 return std::make_tuple(std::make_unique<ARGS>()...);
415 using BuilderType =
typename arrow::TypeTraits<ArrowType>::BuilderType;
420template <
typename ITERATOR>
428template <
typename T,
int N>
442 template <
typename BUILDER>
445 return builder->Append(
value);
448 template <
typename BUILDER>
449 requires std::same_as<std::span<std::byte>, T>
452 return builder->Append((
char*)
value.data(), (int64_t)
value.size());
455 template <
typename BUILDER>
458 return arrow::Status::OK();
464 static constexpr int CHUNK_SIZE = 256;
466 template <
typename BUILDER>
471 if (
pos % CHUNK_SIZE == 0) {
472 return builder->AppendValues(cache, CHUNK_SIZE,
nullptr);
474 return arrow::Status::OK();
477 template <
typename BUILDER>
478 arrow::Status
flush(BUILDER& builder)
480 if (
pos % CHUNK_SIZE != 0) {
481 return builder->AppendValues(cache,
pos % CHUNK_SIZE,
nullptr);
483 return arrow::Status::OK();
495template <
size_t I,
typename T>
500 using BuilderType =
typename arrow::TypeTraits<ArrowType>::BuilderType;
506 auto s = builder->Reserve(nRows);
517 template <
typename... ARGS,
size_t NCOLUMNS>
524 template <
typename...
Ts,
typename VALUES>
527 return (BuilderUtils::append(std::get<Ts::index>(holders), std::get<Ts::index>(
values)).ok() && ...);
533 template <
typename...
Ts,
typename VALUES>
536 (BuilderUtils::unsafeAppend(std::get<Ts::index>(holders), std::get<Ts::index>(
values)), ...);
540 template <
typename...
Ts>
541 static bool finalize(std::vector<std::shared_ptr<arrow::Array>>&
arrays, std::tuple<Ts...>& holders)
543 return (finalize(
arrays[Ts::index], std::get<Ts::index>(holders)) && ...);
546 template <
typename HOLDER>
549 return BuilderUtils::flush(holder).ok() && holder.builder->Finish(&
array).ok();
553template <
typename... ARGS>
564 using type = std::decay_t<T>;
567 return std::make_tuple(p0,
p1,
p2, p3);
570 return std::make_tuple(p0,
p1,
p2);
573 return std::make_tuple(p0,
p1);
576 return std::make_tuple(p0);
578 return std::make_tuple();
582template <
typename... ARGS>
585 return []<std::size_t... Is>(std::index_sequence<Is...>) {
587 }(std::make_index_sequence<
sizeof...(ARGS)>{});
590template <
typename... ARGS>
593 return [pool, nRows]<std::size_t... Is>(std::index_sequence<Is...>) {
595 }(std::make_index_sequence<
sizeof...(ARGS)>{});
598template <
typename... ARGS>
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>;
611 template <
typename... ARGS>
612 using HoldersTuple =
typename std::tuple<BuilderHolder<0, ARGS>...>;
614 template <
typename... ARGS>
619 template <
typename... ARGS>
622 return (HoldersTupleIndexed<ARGS...>*)mHolders;
625 void validate()
const;
627 template <
typename... ARGS,
size_t I =
sizeof...(ARGS)>
628 auto makeBuilders(std::array<char const*, I>
const& columnNames,
size_t nRows)
630 char const*
const* names_ptr = columnNames.data();
631 mSchema = std::make_shared<arrow::Schema>(
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);
638 mDestructor = [](
void* holders)
mutable ->
void {
639 delete (HoldersTupleIndexed<ARGS...>*)holders;
644 template <
typename ARG0,
typename... ARGS>
648 using argsPack_t =
decltype(
tuple_to_pack(framework::to_tuple(std::declval<ARG0>())));
649 return framework::pack_size(argsPack_t{});
652 template <
typename ARG0,
typename... ARGS>
656 return 1 +
sizeof...(ARGS);
659 void setLabel(
const char*
label);
669 mDestructor(mHolders);
674 template <
typename ARG0,
typename... ARGS>
676 auto persist(std::array<
char const*,
sizeof...(ARGS) + 1>
const& columnNames)
681 persister(slot, std::forward_as_tuple(arg, args...));
687 template <
typename ARG0,
typename... ARGS>
689 auto persist(std::array<
char const*, countColumns<ARG0, ARGS...>()>
const& columnNames)
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 {
700 template <
typename... ARGS>
703 constexpr int nColumns =
sizeof...(ARGS);
705 mArrays.resize(nColumns);
706 makeBuilders<ARGS...>(columnNames, 10);
709 using FillTuple = std::tuple<typename BuilderMaker<ARGS>::FillType...>;
710 return [holders = mHolders](
unsigned int , FillTuple
const& t) ->
void {
711 auto status = TableBuilderHelpers::append(*(HoldersTupleIndexed<ARGS...>*)holders, t);
712 if (status ==
false) {
720 template <
typename T>
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{});
728 template <
typename... Cs>
731 return this->
template persist<
typename Cs::type...>({Cs::columnLabel()...});
734 template <
typename T,
typename E>
737 return [
this]<
typename... Cs>(
pack<Cs...>) {
738 return this->
template persist<E>({Cs::columnLabel()...});
739 }(
typename T::table_t::persistent_columns_t{});
743 template <
typename...
Ts>
746 return (std::get<Ts::index>(holders).builder->Reserve(s).ok() && ...);
749 template <
typename... ARGS>
752 reserveArrays(*(HoldersTupleIndexed<ARGS...>*)mHolders, s);
757 std::shared_ptr<arrow::Table> finalize();
760 bool (*mFinalizer)(std::vector<std::shared_ptr<arrow::Array>>&
arrays,
void* holders);
761 void (*mDestructor)(
void* holders);
763 arrow::MemoryPool* mMemoryPool;
764 std::shared_ptr<arrow::Schema> mSchema;
765 std::vector<std::shared_ptr<arrow::Array>> mArrays;
std::shared_ptr< arrow::Schema > schema
constexpr int p1()
constexpr to accelerate the coordinates changing
#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)
GLsizei const GLfloat * value
GLint GLint GLsizei GLint GLenum GLenum type
GLenum GLsizei GLsizei GLint * values
GLuint GLsizei const GLchar * label
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
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
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)
arrow::FixedSizeListType ArrowType
arrow::FixedSizeListBuilder BuilderType
static std::shared_ptr< arrow::DataType > make_datatype()
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
arrow::ListType ArrowType
arrow::ListBuilder BuilderType
typename detail::ConversionTraits< typename ITERATOR::value_type >::ArrowType ValueType
typename ITERATOR::value_type STLValueType
std::pair< ITERATOR, ITERATOR > const & FillType
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
std::span< std::byte > STLValueType
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()
std::span< std::byte > FillType
std::span< const T > FillType
arrow::ListType ArrowType
static std::unique_ptr< BuilderType > make(arrow::MemoryPool *pool)
typename detail::ConversionTraits< T >::ArrowType ElementType
arrow::ListBuilder BuilderType
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
arrow::ListType ArrowType
arrow::ListBuilder BuilderType
arrow::ListType ArrowType
arrow::ListBuilder BuilderType
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()
decltype(policy()) 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)
::arrow::FixedSizeListType ArrowType
::arrow::FixedSizeListType ArrowType
::arrow::FixedSizeListType ArrowType
::arrow::ListType ArrowType
FIXME: adapt type conversion to new arrow.