Conversion of range of std::tuple
-like to Table
instances¶
While the above example shows a quite manual approach of a row to columnar
conversion, Arrow also provides some template logic to convert ranges of
std::tuple<..>
-like objects to tables.
In the most simple case, you only need to provide the input data and the type conversion is then inferred at compile time.
std::vector<std::tuple<double, std::string>> rows = ..
std::shared_ptr<Table> table;
if (!arrow::stl::TableFromTupleRange(
arrow::default_memory_pool(),
rows, names, &table).ok()
) {
// Error handling code should go here.
}
In reverse, you can use TupleRangeFromTable
to fill an already
pre-allocated range with the data from a Table
instance.
// An important aspect here is that the table columns need to be in the
// same order as the columns will later appear in the tuple. As the tuple
// is unnamed, matching is done on positions.
std::shared_ptr<Table> table = ..
// The range needs to be pre-allocated to the respective amount of rows.
// This allows us to pass in an arbitrary range object, not only
// `std::vector`.
std::vector<std::tuple<double, std::string>> rows(2);
if (!arrow::stl::TupleRangeFromTable(*table, &rows).ok()) {
// Error handling code should go here.
}
Arrow itself already supports some C(++) data types for this conversion. If you
want to support additional data types, you need to implement a specialization
of arrow::stl::ConversionTraits<T>
and the more general
arrow::CTypeTraits<T>
.
namespace arrow {
template<>
struct CTypeTraits<boost::posix_time::ptime> {
using ArrowType = ::arrow::TimestampType;
static std::shared_ptr<::arrow::DataType> type_singleton() {
return ::arrow::timestamp(::arrow::TimeUnit::MICRO);
}
};
}
namespace arrow { namespace stl {
template <>
struct ConversionTraits<boost::posix_time::ptime> : public CTypeTraits<boost::posix_time::ptime> {
constexpr static bool nullable = false;
// This is the specialization to load a scalar value into an Arrow builder.
static Status AppendRow(
typename TypeTraits<TimestampType>::BuilderType& builder,
boost::posix_time::ptime cell) {
boost::posix_time::ptime const epoch({1970, 1, 1}, {0, 0, 0, 0});
return builder.Append((cell - epoch).total_microseconds());
}
// Specify how we can fill the tuple from the values stored in the Arrow
// array.
static boost::posix_time::ptime GetEntry(
const TimestampArray& array, size_t j) {
return psapp::arrow::internal::timestamp_epoch
+ boost::posix_time::time_duration(0, 0, 0, array.Value(j));
}
};
}}