mirror of
https://github.com/apache/arrow.git
synced 2026-10-29 00:56:31 +08:00
Consolidate Array and Builder classes in array.h, builder.h. Remove arrow/types subdirectory
Change-Id: I1d84f714b02a2e1abc0171663ca183b682be5907
This commit is contained in:
1 parent
73fe55683c
commit
8cdf059d5d
43 files changed
+1506
-2035
No files matched your search
@@ -750,14 +750,6 @@ set(ARROW_SRCS
|
||||
src/arrow/table.cc
|
||||
src/arrow/type.cc
|
||||
|
||||
src/arrow/types/construct.cc
|
||||
src/arrow/types/decimal.cc
|
||||
src/arrow/types/list.cc
|
||||
src/arrow/types/primitive.cc
|
||||
src/arrow/types/string.cc
|
||||
src/arrow/types/struct.cc
|
||||
src/arrow/types/union.cc
|
||||
|
||||
src/arrow/util/bit-util.cc
|
||||
src/arrow/util/buffer.cc
|
||||
src/arrow/util/memory-pool.cc
|
||||
@@ -823,7 +815,6 @@ endif()
|
||||
add_subdirectory(src/arrow)
|
||||
add_subdirectory(src/arrow/io)
|
||||
add_subdirectory(src/arrow/util)
|
||||
add_subdirectory(src/arrow/types)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# IPC library
|
||||
|
||||
@@ -37,6 +37,12 @@ install(FILES
|
||||
set(ARROW_TEST_LINK_LIBS ${ARROW_MIN_TEST_LIBS})
|
||||
|
||||
ADD_ARROW_TEST(array-test)
|
||||
ADD_ARROW_TEST(array-decimal-test)
|
||||
ADD_ARROW_TEST(array-list-test)
|
||||
ADD_ARROW_TEST(array-primitive-test)
|
||||
ADD_ARROW_TEST(array-string-test)
|
||||
ADD_ARROW_TEST(array-struct-test)
|
||||
|
||||
ADD_ARROW_TEST(column-test)
|
||||
ADD_ARROW_TEST(pretty_print-test)
|
||||
ADD_ARROW_TEST(schema-test)
|
||||
|
||||
@@ -27,12 +27,6 @@
|
||||
#include "arrow/table.h"
|
||||
#include "arrow/type.h"
|
||||
|
||||
#include "arrow/types/construct.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/memory-pool.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "arrow/types/decimal.h"
|
||||
#include "arrow/type.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
@@ -27,10 +27,6 @@
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/construct.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/test-common.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
using std::shared_ptr;
|
||||
@@ -22,13 +22,11 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/type_traits.h"
|
||||
#include "arrow/types/construct.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/test-common.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/status.h"
|
||||
@@ -24,11 +24,9 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/test-common.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
@@ -25,11 +25,6 @@
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/construct.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/struct.h"
|
||||
#include "arrow/types/test-common.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
using std::shared_ptr;
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/memory-pool.h"
|
||||
|
||||
|
||||
@@ -19,9 +19,12 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
#include "arrow/type_traits.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/logging.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
namespace arrow {
|
||||
@@ -85,4 +88,440 @@ Status NullArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Primitive array base
|
||||
|
||||
PrimitiveArray::PrimitiveArray(const TypePtr& type, int32_t length,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: Array(type, length, null_count, null_bitmap) {
|
||||
data_ = data;
|
||||
raw_data_ = data == nullptr ? nullptr : data_->data();
|
||||
}
|
||||
|
||||
bool PrimitiveArray::EqualsExact(const PrimitiveArray& other) const {
|
||||
if (this == &other) { return true; }
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
if (null_count_ > 0) {
|
||||
bool equal_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::CeilByte(length_) / 8);
|
||||
if (!equal_bitmap) { return false; }
|
||||
|
||||
const uint8_t* this_data = raw_data_;
|
||||
const uint8_t* other_data = other.raw_data_;
|
||||
|
||||
auto size_meta = dynamic_cast<const FixedWidthType*>(type_.get());
|
||||
int value_byte_size = size_meta->bit_width() / 8;
|
||||
DCHECK_GT(value_byte_size, 0);
|
||||
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (!IsNull(i) && memcmp(this_data, other_data, value_byte_size)) { return false; }
|
||||
this_data += value_byte_size;
|
||||
other_data += value_byte_size;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (length_ == 0 && other.length_ == 0) { return true; }
|
||||
return data_->Equals(*other.data_, length_);
|
||||
}
|
||||
}
|
||||
|
||||
bool PrimitiveArray::Equals(const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
return EqualsExact(*static_cast<const PrimitiveArray*>(arr.get()));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status NumericArray<T>::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
template class NumericArray<UInt8Type>;
|
||||
template class NumericArray<UInt16Type>;
|
||||
template class NumericArray<UInt32Type>;
|
||||
template class NumericArray<UInt64Type>;
|
||||
template class NumericArray<Int8Type>;
|
||||
template class NumericArray<Int16Type>;
|
||||
template class NumericArray<Int32Type>;
|
||||
template class NumericArray<Int64Type>;
|
||||
template class NumericArray<TimestampType>;
|
||||
template class NumericArray<HalfFloatType>;
|
||||
template class NumericArray<FloatType>;
|
||||
template class NumericArray<DoubleType>;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// BooleanArray
|
||||
|
||||
BooleanArray::BooleanArray(int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count, const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: PrimitiveArray(
|
||||
std::make_shared<BooleanType>(), length, data, null_count, null_bitmap) {}
|
||||
|
||||
BooleanArray::BooleanArray(const TypePtr& type, int32_t length,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: PrimitiveArray(type, length, data, null_count, null_bitmap) {}
|
||||
|
||||
bool BooleanArray::EqualsExact(const BooleanArray& other) const {
|
||||
if (this == &other) return true;
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
if (null_count_ > 0) {
|
||||
bool equal_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::BytesForBits(length_));
|
||||
if (!equal_bitmap) { return false; }
|
||||
|
||||
const uint8_t* this_data = raw_data_;
|
||||
const uint8_t* other_data = other.raw_data_;
|
||||
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (!IsNull(i) && BitUtil::GetBit(this_data, i) != BitUtil::GetBit(other_data, i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return data_->Equals(*other.data_, BitUtil::BytesForBits(length_));
|
||||
}
|
||||
}
|
||||
|
||||
bool BooleanArray::Equals(const ArrayPtr& arr) const {
|
||||
if (this == arr.get()) return true;
|
||||
if (Type::BOOL != arr->type_enum()) { return false; }
|
||||
return EqualsExact(*static_cast<const BooleanArray*>(arr.get()));
|
||||
}
|
||||
|
||||
bool BooleanArray::RangeEquals(int32_t start_idx, int32_t end_idx,
|
||||
int32_t other_start_idx, const ArrayPtr& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<BooleanArray*>(arr.get());
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
const bool is_null = IsNull(i);
|
||||
if (is_null != arr->IsNull(o_i) || (!is_null && Value(i) != other->Value(o_i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Status BooleanArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// ListArray
|
||||
|
||||
bool ListArray::EqualsExact(const ListArray& other) const {
|
||||
if (this == &other) { return true; }
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
bool equal_offsets =
|
||||
offset_buffer_->Equals(*other.offset_buffer_, (length_ + 1) * sizeof(int32_t));
|
||||
if (!equal_offsets) { return false; }
|
||||
bool equal_null_bitmap = true;
|
||||
if (null_count_ > 0) {
|
||||
equal_null_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::BytesForBits(length_));
|
||||
}
|
||||
|
||||
if (!equal_null_bitmap) { return false; }
|
||||
|
||||
return values()->Equals(other.values());
|
||||
}
|
||||
|
||||
bool ListArray::Equals(const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
return EqualsExact(*static_cast<const ListArray*>(arr.get()));
|
||||
}
|
||||
|
||||
bool ListArray::RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<ListArray*>(arr.get());
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
const bool is_null = IsNull(i);
|
||||
if (is_null != arr->IsNull(o_i)) { return false; }
|
||||
if (is_null) continue;
|
||||
const int32_t begin_offset = offset(i);
|
||||
const int32_t end_offset = offset(i + 1);
|
||||
const int32_t other_begin_offset = other->offset(o_i);
|
||||
const int32_t other_end_offset = other->offset(o_i + 1);
|
||||
// Underlying can't be equal if the size isn't equal
|
||||
if (end_offset - begin_offset != other_end_offset - other_begin_offset) {
|
||||
return false;
|
||||
}
|
||||
if (!values_->RangeEquals(
|
||||
begin_offset, end_offset, other_begin_offset, other->values())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Status ListArray::Validate() const {
|
||||
if (length_ < 0) { return Status::Invalid("Length was negative"); }
|
||||
if (!offset_buffer_) { return Status::Invalid("offset_buffer_ was null"); }
|
||||
if (offset_buffer_->size() / static_cast<int>(sizeof(int32_t)) < length_) {
|
||||
std::stringstream ss;
|
||||
ss << "offset buffer size (bytes): " << offset_buffer_->size()
|
||||
<< " isn't large enough for length: " << length_;
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
const int32_t last_offset = offset(length_);
|
||||
if (last_offset > 0) {
|
||||
if (!values_) {
|
||||
return Status::Invalid("last offset was non-zero and values was null");
|
||||
}
|
||||
if (values_->length() != last_offset) {
|
||||
std::stringstream ss;
|
||||
ss << "Final offset invariant not equal to values length: " << last_offset
|
||||
<< "!=" << values_->length();
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
|
||||
const Status child_valid = values_->Validate();
|
||||
if (!child_valid.ok()) {
|
||||
std::stringstream ss;
|
||||
ss << "Child array invalid: " << child_valid.ToString();
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
int32_t prev_offset = offset(0);
|
||||
if (prev_offset != 0) { return Status::Invalid("The first offset wasn't zero"); }
|
||||
for (int32_t i = 1; i <= length_; ++i) {
|
||||
int32_t current_offset = offset(i);
|
||||
if (IsNull(i - 1) && current_offset != prev_offset) {
|
||||
std::stringstream ss;
|
||||
ss << "Offset invariant failure at: " << i << " inconsistent offsets for null slot"
|
||||
<< current_offset << "!=" << prev_offset;
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
if (current_offset < prev_offset) {
|
||||
std::stringstream ss;
|
||||
ss << "Offset invariant failure: " << i
|
||||
<< " inconsistent offset for non-null slot: " << current_offset << "<"
|
||||
<< prev_offset;
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
prev_offset = current_offset;
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status ListArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// String and binary
|
||||
|
||||
static std::shared_ptr<DataType> kBinary = std::make_shared<BinaryType>();
|
||||
static std::shared_ptr<DataType> kString = std::make_shared<StringType>();
|
||||
|
||||
BinaryArray::BinaryArray(int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: BinaryArray(kBinary, length, offsets, data, null_count, null_bitmap) {}
|
||||
|
||||
BinaryArray::BinaryArray(const TypePtr& type, int32_t length,
|
||||
const std::shared_ptr<Buffer>& offsets, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count, const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: Array(type, length, null_count, null_bitmap),
|
||||
offset_buffer_(offsets),
|
||||
offsets_(reinterpret_cast<const int32_t*>(offset_buffer_->data())),
|
||||
data_buffer_(data),
|
||||
data_(nullptr) {
|
||||
if (data_buffer_ != nullptr) { data_ = data_buffer_->data(); }
|
||||
}
|
||||
|
||||
Status BinaryArray::Validate() const {
|
||||
// TODO(wesm): what to do here?
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
bool BinaryArray::EqualsExact(const BinaryArray& other) const {
|
||||
if (!Array::EqualsExact(other)) { return false; }
|
||||
|
||||
bool equal_offsets =
|
||||
offset_buffer_->Equals(*other.offset_buffer_, (length_ + 1) * sizeof(int32_t));
|
||||
if (!equal_offsets) { return false; }
|
||||
|
||||
if (!data_buffer_ && !(other.data_buffer_)) { return true; }
|
||||
|
||||
return data_buffer_->Equals(*other.data_buffer_, data_buffer_->size());
|
||||
}
|
||||
|
||||
bool BinaryArray::Equals(const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
return EqualsExact(*static_cast<const BinaryArray*>(arr.get()));
|
||||
}
|
||||
|
||||
bool BinaryArray::RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<const BinaryArray*>(arr.get());
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
const bool is_null = IsNull(i);
|
||||
if (is_null != arr->IsNull(o_i)) { return false; }
|
||||
if (is_null) continue;
|
||||
const int32_t begin_offset = offset(i);
|
||||
const int32_t end_offset = offset(i + 1);
|
||||
const int32_t other_begin_offset = other->offset(o_i);
|
||||
const int32_t other_end_offset = other->offset(o_i + 1);
|
||||
// Underlying can't be equal if the size isn't equal
|
||||
if (end_offset - begin_offset != other_end_offset - other_begin_offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::memcmp(data_ + begin_offset, other->data_ + other_begin_offset,
|
||||
end_offset - begin_offset)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Status BinaryArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
StringArray::StringArray(int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: BinaryArray(kString, length, offsets, data, null_count, null_bitmap) {}
|
||||
|
||||
Status StringArray::Validate() const {
|
||||
// TODO(emkornfield) Validate proper UTF8 code points?
|
||||
return BinaryArray::Validate();
|
||||
}
|
||||
|
||||
Status StringArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Struct
|
||||
|
||||
std::shared_ptr<Array> StructArray::field(int32_t pos) const {
|
||||
DCHECK_GT(field_arrays_.size(), 0);
|
||||
return field_arrays_[pos];
|
||||
}
|
||||
|
||||
bool StructArray::Equals(const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
if (null_count_ != arr->null_count()) { return false; }
|
||||
return RangeEquals(0, length_, 0, arr);
|
||||
}
|
||||
|
||||
bool StructArray::RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (Type::STRUCT != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<StructArray*>(arr.get());
|
||||
|
||||
bool equal_fields = true;
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
if (IsNull(i) != arr->IsNull(o_i)) { return false; }
|
||||
if (IsNull(i)) continue;
|
||||
for (size_t j = 0; j < field_arrays_.size(); ++j) {
|
||||
// TODO: really we should be comparing stretches of non-null data rather
|
||||
// than looking at one value at a time.
|
||||
equal_fields = field(j)->RangeEquals(i, i + 1, o_i, other->field(j));
|
||||
if (!equal_fields) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Status StructArray::Validate() const {
|
||||
if (length_ < 0) { return Status::Invalid("Length was negative"); }
|
||||
|
||||
if (null_count() > length_) {
|
||||
return Status::Invalid("Null count exceeds the length of this struct");
|
||||
}
|
||||
|
||||
if (field_arrays_.size() > 0) {
|
||||
// Validate fields
|
||||
int32_t array_length = field_arrays_[0]->length();
|
||||
size_t idx = 0;
|
||||
for (auto it : field_arrays_) {
|
||||
if (it->length() != array_length) {
|
||||
std::stringstream ss;
|
||||
ss << "Length is not equal from field " << it->type()->ToString()
|
||||
<< " at position {" << idx << "}";
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
|
||||
const Status child_valid = it->Validate();
|
||||
if (!child_valid.ok()) {
|
||||
std::stringstream ss;
|
||||
ss << "Child array invalid: " << child_valid.ToString() << " at position {" << idx
|
||||
<< "}";
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
|
||||
if (array_length > 0 && array_length != length_) {
|
||||
return Status::Invalid("Struct's length is not equal to its child arrays");
|
||||
}
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status StructArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
#define MAKE_PRIMITIVE_ARRAY_CASE(ENUM, ArrayType) \
|
||||
case Type::ENUM: \
|
||||
out->reset(new ArrayType(type, length, data, null_count, null_bitmap)); \
|
||||
break;
|
||||
|
||||
Status MakePrimitiveArray(const TypePtr& type, int32_t length,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap, ArrayPtr* out) {
|
||||
switch (type->type) {
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(BOOL, BooleanArray);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(UINT8, UInt8Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(INT8, Int8Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(UINT16, UInt16Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(INT16, Int16Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(UINT32, UInt32Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(INT32, Int32Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(UINT64, UInt64Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(INT64, Int64Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(FLOAT, FloatArray);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(DOUBLE, DoubleArray);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(TIME, Int64Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(TIMESTAMP, TimestampArray);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(TIMESTAMP_DOUBLE, DoubleArray);
|
||||
default:
|
||||
return Status::NotImplemented(type->ToString());
|
||||
}
|
||||
#ifdef NDEBUG
|
||||
return Status::OK();
|
||||
#else
|
||||
return (*out)->Validate();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
+370
-1
@@ -23,12 +23,12 @@
|
||||
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/macros.h"
|
||||
#include "arrow/util/visibility.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
class Buffer;
|
||||
class MemoryPool;
|
||||
class MutableBuffer;
|
||||
class Status;
|
||||
@@ -110,6 +110,375 @@ typedef std::shared_ptr<Array> ArrayPtr;
|
||||
Status ARROW_EXPORT GetEmptyBitmap(
|
||||
MemoryPool* pool, int32_t length, std::shared_ptr<MutableBuffer>* result);
|
||||
|
||||
// Base class for fixed-size logical types. See MakePrimitiveArray
|
||||
// (types/construct.h) for constructing a specific subclass.
|
||||
class ARROW_EXPORT PrimitiveArray : public Array {
|
||||
public:
|
||||
virtual ~PrimitiveArray() {}
|
||||
|
||||
std::shared_ptr<Buffer> data() const { return data_; }
|
||||
|
||||
bool EqualsExact(const PrimitiveArray& other) const;
|
||||
bool Equals(const std::shared_ptr<Array>& arr) const override;
|
||||
|
||||
protected:
|
||||
PrimitiveArray(const TypePtr& type, int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
std::shared_ptr<Buffer> data_;
|
||||
const uint8_t* raw_data_;
|
||||
};
|
||||
|
||||
template <typename TYPE>
|
||||
class ARROW_EXPORT NumericArray : public PrimitiveArray {
|
||||
public:
|
||||
using TypeClass = TYPE;
|
||||
using value_type = typename TypeClass::c_type;
|
||||
NumericArray(int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr)
|
||||
: PrimitiveArray(
|
||||
std::make_shared<TypeClass>(), length, data, null_count, null_bitmap) {}
|
||||
NumericArray(const TypePtr& type, int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr)
|
||||
: PrimitiveArray(type, length, data, null_count, null_bitmap) {}
|
||||
|
||||
bool EqualsExact(const NumericArray<TypeClass>& other) const {
|
||||
return PrimitiveArray::EqualsExact(static_cast<const PrimitiveArray&>(other));
|
||||
}
|
||||
|
||||
bool ApproxEquals(const std::shared_ptr<Array>& arr) const { return Equals(arr); }
|
||||
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const ArrayPtr& arr) const override {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<NumericArray<TypeClass>*>(arr.get());
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
const bool is_null = IsNull(i);
|
||||
if (is_null != arr->IsNull(o_i) || (!is_null && Value(i) != other->Value(o_i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const value_type* raw_data() const {
|
||||
return reinterpret_cast<const value_type*>(raw_data_);
|
||||
}
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
value_type Value(int i) const { return raw_data()[i]; }
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool NumericArray<FloatType>::ApproxEquals(
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
|
||||
const auto& other = *static_cast<NumericArray<FloatType>*>(arr.get());
|
||||
|
||||
if (this == &other) { return true; }
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
auto this_data = reinterpret_cast<const float*>(raw_data_);
|
||||
auto other_data = reinterpret_cast<const float*>(other.raw_data_);
|
||||
|
||||
static constexpr float EPSILON = 1E-5;
|
||||
|
||||
if (length_ == 0 && other.length_ == 0) { return true; }
|
||||
|
||||
if (null_count_ > 0) {
|
||||
bool equal_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::CeilByte(length_) / 8);
|
||||
if (!equal_bitmap) { return false; }
|
||||
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (IsNull(i)) continue;
|
||||
if (fabs(this_data[i] - other_data[i]) > EPSILON) { return false; }
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (fabs(this_data[i] - other_data[i]) > EPSILON) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool NumericArray<DoubleType>::ApproxEquals(
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
|
||||
const auto& other = *static_cast<NumericArray<DoubleType>*>(arr.get());
|
||||
|
||||
if (this == &other) { return true; }
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
auto this_data = reinterpret_cast<const double*>(raw_data_);
|
||||
auto other_data = reinterpret_cast<const double*>(other.raw_data_);
|
||||
|
||||
if (length_ == 0 && other.length_ == 0) { return true; }
|
||||
|
||||
static constexpr double EPSILON = 1E-5;
|
||||
|
||||
if (null_count_ > 0) {
|
||||
bool equal_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::CeilByte(length_) / 8);
|
||||
if (!equal_bitmap) { return false; }
|
||||
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (IsNull(i)) continue;
|
||||
if (fabs(this_data[i] - other_data[i]) > EPSILON) { return false; }
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (fabs(this_data[i] - other_data[i]) > EPSILON) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class ARROW_EXPORT BooleanArray : public PrimitiveArray {
|
||||
public:
|
||||
using TypeClass = BooleanType;
|
||||
|
||||
BooleanArray(int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
BooleanArray(const TypePtr& type, int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
|
||||
bool EqualsExact(const BooleanArray& other) const;
|
||||
bool Equals(const ArrayPtr& arr) const override;
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const ArrayPtr& arr) const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
const uint8_t* raw_data() const { return reinterpret_cast<const uint8_t*>(raw_data_); }
|
||||
|
||||
bool Value(int i) const { return BitUtil::GetBit(raw_data(), i); }
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// ListArray
|
||||
|
||||
class ARROW_EXPORT ListArray : public Array {
|
||||
public:
|
||||
using TypeClass = ListType;
|
||||
|
||||
ListArray(const TypePtr& type, int32_t length, std::shared_ptr<Buffer> offsets,
|
||||
const ArrayPtr& values, int32_t null_count = 0,
|
||||
std::shared_ptr<Buffer> null_bitmap = nullptr)
|
||||
: Array(type, length, null_count, null_bitmap) {
|
||||
offset_buffer_ = offsets;
|
||||
offsets_ = offsets == nullptr ? nullptr : reinterpret_cast<const int32_t*>(
|
||||
offset_buffer_->data());
|
||||
values_ = values;
|
||||
}
|
||||
|
||||
Status Validate() const override;
|
||||
|
||||
virtual ~ListArray() = default;
|
||||
|
||||
// Return a shared pointer in case the requestor desires to share ownership
|
||||
// with this array.
|
||||
std::shared_ptr<Array> values() const { return values_; }
|
||||
std::shared_ptr<Buffer> offsets() const {
|
||||
return std::static_pointer_cast<Buffer>(offset_buffer_);
|
||||
}
|
||||
|
||||
std::shared_ptr<DataType> value_type() const { return values_->type(); }
|
||||
|
||||
const int32_t* raw_offsets() const { return offsets_; }
|
||||
|
||||
int32_t offset(int i) const { return offsets_[i]; }
|
||||
|
||||
// Neither of these functions will perform boundschecking
|
||||
int32_t value_offset(int i) const { return offsets_[i]; }
|
||||
int32_t value_length(int i) const { return offsets_[i + 1] - offsets_[i]; }
|
||||
|
||||
bool EqualsExact(const ListArray& other) const;
|
||||
bool Equals(const std::shared_ptr<Array>& arr) const override;
|
||||
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const ArrayPtr& arr) const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Buffer> offset_buffer_;
|
||||
const int32_t* offsets_;
|
||||
ArrayPtr values_;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Binary and String
|
||||
|
||||
class ARROW_EXPORT BinaryArray : public Array {
|
||||
public:
|
||||
using TypeClass = BinaryType;
|
||||
|
||||
BinaryArray(int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count = 0,
|
||||
const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
|
||||
// Constructor that allows sub-classes/builders to propagate there logical type up the
|
||||
// class hierarchy.
|
||||
BinaryArray(const TypePtr& type, int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count = 0,
|
||||
const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
|
||||
// Return the pointer to the given elements bytes
|
||||
// TODO(emkornfield) introduce a StringPiece or something similar to capture zero-copy
|
||||
// pointer + offset
|
||||
const uint8_t* GetValue(int i, int32_t* out_length) const {
|
||||
const int32_t pos = offsets_[i];
|
||||
*out_length = offsets_[i + 1] - pos;
|
||||
return data_ + pos;
|
||||
}
|
||||
|
||||
std::shared_ptr<Buffer> data() const { return data_buffer_; }
|
||||
std::shared_ptr<Buffer> offsets() const { return offset_buffer_; }
|
||||
|
||||
const int32_t* raw_offsets() const { return offsets_; }
|
||||
|
||||
int32_t offset(int i) const { return offsets_[i]; }
|
||||
|
||||
// Neither of these functions will perform boundschecking
|
||||
int32_t value_offset(int i) const { return offsets_[i]; }
|
||||
int32_t value_length(int i) const { return offsets_[i + 1] - offsets_[i]; }
|
||||
|
||||
bool EqualsExact(const BinaryArray& other) const;
|
||||
bool Equals(const std::shared_ptr<Array>& arr) const override;
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const ArrayPtr& arr) const override;
|
||||
|
||||
Status Validate() const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Buffer> offset_buffer_;
|
||||
const int32_t* offsets_;
|
||||
|
||||
std::shared_ptr<Buffer> data_buffer_;
|
||||
const uint8_t* data_;
|
||||
};
|
||||
|
||||
class ARROW_EXPORT StringArray : public BinaryArray {
|
||||
public:
|
||||
using TypeClass = StringType;
|
||||
|
||||
StringArray(int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count = 0,
|
||||
const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
|
||||
// Construct a std::string
|
||||
// TODO: std::bad_alloc possibility
|
||||
std::string GetString(int i) const {
|
||||
int32_t nchars;
|
||||
const uint8_t* str = GetValue(i, &nchars);
|
||||
return std::string(reinterpret_cast<const char*>(str), nchars);
|
||||
}
|
||||
|
||||
Status Validate() const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Struct
|
||||
|
||||
class ARROW_EXPORT StructArray : public Array {
|
||||
public:
|
||||
using TypeClass = StructType;
|
||||
|
||||
StructArray(const TypePtr& type, int32_t length, std::vector<ArrayPtr>& field_arrays,
|
||||
int32_t null_count = 0, std::shared_ptr<Buffer> null_bitmap = nullptr)
|
||||
: Array(type, length, null_count, null_bitmap) {
|
||||
type_ = type;
|
||||
field_arrays_ = field_arrays;
|
||||
}
|
||||
|
||||
Status Validate() const override;
|
||||
|
||||
virtual ~StructArray() {}
|
||||
|
||||
// Return a shared pointer in case the requestor desires to share ownership
|
||||
// with this array.
|
||||
std::shared_ptr<Array> field(int32_t pos) const;
|
||||
|
||||
const std::vector<ArrayPtr>& fields() const { return field_arrays_; }
|
||||
|
||||
bool EqualsExact(const StructArray& other) const;
|
||||
bool Equals(const std::shared_ptr<Array>& arr) const override;
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const std::shared_ptr<Array>& arr) const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
protected:
|
||||
// The child arrays corresponding to each field of the struct data type.
|
||||
std::vector<ArrayPtr> field_arrays_;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Union
|
||||
|
||||
class UnionArray : public Array {
|
||||
protected:
|
||||
// The data are types encoded as int16
|
||||
Buffer* types_;
|
||||
std::vector<std::shared_ptr<Array>> children_;
|
||||
};
|
||||
|
||||
class DenseUnionArray : public UnionArray {
|
||||
protected:
|
||||
Buffer* offset_buf_;
|
||||
};
|
||||
|
||||
class SparseUnionArray : public UnionArray {};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// extern templates and other details
|
||||
|
||||
// gcc and clang disagree about how to handle template visibility when you have
|
||||
// explicit specializations https://llvm.org/bugs/show_bug.cgi?id=24815
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wattributes"
|
||||
#endif
|
||||
|
||||
// Only instantiate these templates once
|
||||
extern template class ARROW_EXPORT NumericArray<Int8Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<UInt8Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<Int16Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<UInt16Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<Int32Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<UInt32Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<Int64Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<UInt64Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<HalfFloatType>;
|
||||
extern template class ARROW_EXPORT NumericArray<FloatType>;
|
||||
extern template class ARROW_EXPORT NumericArray<DoubleType>;
|
||||
extern template class ARROW_EXPORT NumericArray<TimestampType>;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Helper functions
|
||||
|
||||
// Create new arrays for logical types that are backed by primitive arrays.
|
||||
Status ARROW_EXPORT MakePrimitiveArray(const std::shared_ptr<DataType>& type,
|
||||
int32_t length, const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap, std::shared_ptr<Array>* out);
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif
|
||||
@@ -19,8 +19,12 @@
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/type_traits.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/logging.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
namespace arrow {
|
||||
@@ -123,4 +127,323 @@ void ArrayBuilder::UnsafeSetNotNull(int32_t length) {
|
||||
length_ = new_length;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status PrimitiveBuilder<T>::Init(int32_t capacity) {
|
||||
RETURN_NOT_OK(ArrayBuilder::Init(capacity));
|
||||
data_ = std::make_shared<PoolBuffer>(pool_);
|
||||
|
||||
int64_t nbytes = TypeTraits<T>::bytes_required(capacity);
|
||||
RETURN_NOT_OK(data_->Resize(nbytes));
|
||||
// TODO(emkornfield) valgrind complains without this
|
||||
memset(data_->mutable_data(), 0, nbytes);
|
||||
|
||||
raw_data_ = reinterpret_cast<value_type*>(data_->mutable_data());
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status PrimitiveBuilder<T>::Resize(int32_t capacity) {
|
||||
// XXX: Set floor size for now
|
||||
if (capacity < kMinBuilderCapacity) { capacity = kMinBuilderCapacity; }
|
||||
|
||||
if (capacity_ == 0) {
|
||||
RETURN_NOT_OK(Init(capacity));
|
||||
} else {
|
||||
RETURN_NOT_OK(ArrayBuilder::Resize(capacity));
|
||||
const int64_t old_bytes = data_->size();
|
||||
const int64_t new_bytes = TypeTraits<T>::bytes_required(capacity);
|
||||
RETURN_NOT_OK(data_->Resize(new_bytes));
|
||||
raw_data_ = reinterpret_cast<value_type*>(data_->mutable_data());
|
||||
memset(data_->mutable_data() + old_bytes, 0, new_bytes - old_bytes);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status PrimitiveBuilder<T>::Append(
|
||||
const value_type* values, int32_t length, const uint8_t* valid_bytes) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
|
||||
if (length > 0) {
|
||||
memcpy(raw_data_ + length_, values, TypeTraits<T>::bytes_required(length));
|
||||
}
|
||||
|
||||
// length_ is update by these
|
||||
ArrayBuilder::UnsafeAppendToBitmap(valid_bytes, length);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status PrimitiveBuilder<T>::Finish(std::shared_ptr<Array>* out) {
|
||||
const int64_t bytes_required = TypeTraits<T>::bytes_required(length_);
|
||||
if (bytes_required > 0 && bytes_required < data_->size()) {
|
||||
// Trim buffers
|
||||
RETURN_NOT_OK(data_->Resize(bytes_required));
|
||||
}
|
||||
*out = std::make_shared<typename TypeTraits<T>::ArrayType>(
|
||||
type_, length_, data_, null_count_, null_bitmap_);
|
||||
|
||||
data_ = null_bitmap_ = nullptr;
|
||||
capacity_ = length_ = null_count_ = 0;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template class PrimitiveBuilder<UInt8Type>;
|
||||
template class PrimitiveBuilder<UInt16Type>;
|
||||
template class PrimitiveBuilder<UInt32Type>;
|
||||
template class PrimitiveBuilder<UInt64Type>;
|
||||
template class PrimitiveBuilder<Int8Type>;
|
||||
template class PrimitiveBuilder<Int16Type>;
|
||||
template class PrimitiveBuilder<Int32Type>;
|
||||
template class PrimitiveBuilder<Int64Type>;
|
||||
template class PrimitiveBuilder<TimestampType>;
|
||||
template class PrimitiveBuilder<HalfFloatType>;
|
||||
template class PrimitiveBuilder<FloatType>;
|
||||
template class PrimitiveBuilder<DoubleType>;
|
||||
|
||||
Status BooleanBuilder::Init(int32_t capacity) {
|
||||
RETURN_NOT_OK(ArrayBuilder::Init(capacity));
|
||||
data_ = std::make_shared<PoolBuffer>(pool_);
|
||||
|
||||
int64_t nbytes = BitUtil::BytesForBits(capacity);
|
||||
RETURN_NOT_OK(data_->Resize(nbytes));
|
||||
// TODO(emkornfield) valgrind complains without this
|
||||
memset(data_->mutable_data(), 0, nbytes);
|
||||
|
||||
raw_data_ = reinterpret_cast<uint8_t*>(data_->mutable_data());
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status BooleanBuilder::Resize(int32_t capacity) {
|
||||
// XXX: Set floor size for now
|
||||
if (capacity < kMinBuilderCapacity) { capacity = kMinBuilderCapacity; }
|
||||
|
||||
if (capacity_ == 0) {
|
||||
RETURN_NOT_OK(Init(capacity));
|
||||
} else {
|
||||
RETURN_NOT_OK(ArrayBuilder::Resize(capacity));
|
||||
const int64_t old_bytes = data_->size();
|
||||
const int64_t new_bytes = BitUtil::BytesForBits(capacity);
|
||||
|
||||
RETURN_NOT_OK(data_->Resize(new_bytes));
|
||||
raw_data_ = reinterpret_cast<uint8_t*>(data_->mutable_data());
|
||||
memset(data_->mutable_data() + old_bytes, 0, new_bytes - old_bytes);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status BooleanBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
const int64_t bytes_required = BitUtil::BytesForBits(length_);
|
||||
|
||||
if (bytes_required > 0 && bytes_required < data_->size()) {
|
||||
// Trim buffers
|
||||
RETURN_NOT_OK(data_->Resize(bytes_required));
|
||||
}
|
||||
*out = std::make_shared<BooleanArray>(type_, length_, data_, null_count_, null_bitmap_);
|
||||
|
||||
data_ = null_bitmap_ = nullptr;
|
||||
capacity_ = length_ = null_count_ = 0;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status BooleanBuilder::Append(
|
||||
const uint8_t* values, int32_t length, const uint8_t* valid_bytes) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
// Skip reading from unitialised memory
|
||||
// TODO: This actually is only to keep valgrind happy but may or may not
|
||||
// have a performance impact.
|
||||
if ((valid_bytes != nullptr) && !valid_bytes[i]) continue;
|
||||
|
||||
if (values[i] > 0) {
|
||||
BitUtil::SetBit(raw_data_, length_ + i);
|
||||
} else {
|
||||
BitUtil::ClearBit(raw_data_, length_ + i);
|
||||
}
|
||||
}
|
||||
|
||||
// this updates length_
|
||||
ArrayBuilder::UnsafeAppendToBitmap(valid_bytes, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// ListBuilder
|
||||
|
||||
ListBuilder::ListBuilder(
|
||||
MemoryPool* pool, std::shared_ptr<ArrayBuilder> value_builder, const TypePtr& type)
|
||||
: ArrayBuilder(
|
||||
pool, type ? type : std::static_pointer_cast<DataType>(
|
||||
std::make_shared<ListType>(value_builder->type()))),
|
||||
offset_builder_(pool),
|
||||
value_builder_(value_builder) {}
|
||||
|
||||
ListBuilder::ListBuilder(
|
||||
MemoryPool* pool, std::shared_ptr<Array> values, const TypePtr& type)
|
||||
: ArrayBuilder(pool, type ? type : std::static_pointer_cast<DataType>(
|
||||
std::make_shared<ListType>(values->type()))),
|
||||
offset_builder_(pool),
|
||||
values_(values) {}
|
||||
|
||||
Status ListBuilder::Init(int32_t elements) {
|
||||
DCHECK_LT(elements, std::numeric_limits<int32_t>::max());
|
||||
RETURN_NOT_OK(ArrayBuilder::Init(elements));
|
||||
// one more then requested for offsets
|
||||
return offset_builder_.Resize((elements + 1) * sizeof(int32_t));
|
||||
}
|
||||
|
||||
Status ListBuilder::Resize(int32_t capacity) {
|
||||
DCHECK_LT(capacity, std::numeric_limits<int32_t>::max());
|
||||
// one more then requested for offsets
|
||||
RETURN_NOT_OK(offset_builder_.Resize((capacity + 1) * sizeof(int32_t)));
|
||||
return ArrayBuilder::Resize(capacity);
|
||||
}
|
||||
|
||||
Status ListBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
std::shared_ptr<Array> items = values_;
|
||||
if (!items) { RETURN_NOT_OK(value_builder_->Finish(&items)); }
|
||||
|
||||
RETURN_NOT_OK(offset_builder_.Append<int32_t>(items->length()));
|
||||
std::shared_ptr<Buffer> offsets = offset_builder_.Finish();
|
||||
|
||||
*out = std::make_shared<ListArray>(
|
||||
type_, length_, offsets, items, null_count_, null_bitmap_);
|
||||
|
||||
Reset();
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
void ListBuilder::Reset() {
|
||||
capacity_ = length_ = null_count_ = 0;
|
||||
null_bitmap_ = nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<ArrayBuilder> ListBuilder::value_builder() const {
|
||||
DCHECK(!values_) << "Using value builder is pointless when values_ is set";
|
||||
return value_builder_;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// String and binary
|
||||
|
||||
// This used to be a static member variable of BinaryBuilder, but it can cause
|
||||
// valgrind to report a (spurious?) memory leak when needed in other shared
|
||||
// libraries. The problem came up while adding explicit visibility to libarrow
|
||||
// and libparquet_arrow
|
||||
static TypePtr kBinaryValueType = TypePtr(new UInt8Type());
|
||||
|
||||
BinaryBuilder::BinaryBuilder(MemoryPool* pool, const TypePtr& type)
|
||||
: ListBuilder(pool, std::make_shared<UInt8Builder>(pool, kBinaryValueType), type) {
|
||||
byte_builder_ = static_cast<UInt8Builder*>(value_builder_.get());
|
||||
}
|
||||
|
||||
Status BinaryBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
std::shared_ptr<Array> result;
|
||||
RETURN_NOT_OK(ListBuilder::Finish(&result));
|
||||
|
||||
const auto list = std::dynamic_pointer_cast<ListArray>(result);
|
||||
auto values = std::dynamic_pointer_cast<UInt8Array>(list->values());
|
||||
|
||||
*out = std::make_shared<BinaryArray>(list->length(), list->offsets(), values->data(),
|
||||
list->null_count(), list->null_bitmap());
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status StringBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
std::shared_ptr<Array> result;
|
||||
RETURN_NOT_OK(ListBuilder::Finish(&result));
|
||||
|
||||
const auto list = std::dynamic_pointer_cast<ListArray>(result);
|
||||
auto values = std::dynamic_pointer_cast<UInt8Array>(list->values());
|
||||
|
||||
*out = std::make_shared<StringArray>(list->length(), list->offsets(), values->data(),
|
||||
list->null_count(), list->null_bitmap());
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Struct
|
||||
|
||||
Status StructBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
std::vector<std::shared_ptr<Array>> fields(field_builders_.size());
|
||||
for (size_t i = 0; i < field_builders_.size(); ++i) {
|
||||
RETURN_NOT_OK(field_builders_[i]->Finish(&fields[i]));
|
||||
}
|
||||
|
||||
*out = std::make_shared<StructArray>(type_, length_, fields, null_count_, null_bitmap_);
|
||||
|
||||
null_bitmap_ = nullptr;
|
||||
capacity_ = length_ = null_count_ = 0;
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
std::shared_ptr<ArrayBuilder> StructBuilder::field_builder(int pos) const {
|
||||
DCHECK_GT(field_builders_.size(), 0);
|
||||
return field_builders_[pos];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Helper functions
|
||||
|
||||
#define BUILDER_CASE(ENUM, BuilderType) \
|
||||
case Type::ENUM: \
|
||||
out->reset(new BuilderType(pool, type)); \
|
||||
return Status::OK();
|
||||
|
||||
// Initially looked at doing this with vtables, but shared pointers makes it
|
||||
// difficult
|
||||
//
|
||||
// TODO(wesm): come up with a less monolithic strategy
|
||||
Status MakeBuilder(MemoryPool* pool, const std::shared_ptr<DataType>& type,
|
||||
std::shared_ptr<ArrayBuilder>* out) {
|
||||
switch (type->type) {
|
||||
BUILDER_CASE(UINT8, UInt8Builder);
|
||||
BUILDER_CASE(INT8, Int8Builder);
|
||||
BUILDER_CASE(UINT16, UInt16Builder);
|
||||
BUILDER_CASE(INT16, Int16Builder);
|
||||
BUILDER_CASE(UINT32, UInt32Builder);
|
||||
BUILDER_CASE(INT32, Int32Builder);
|
||||
BUILDER_CASE(UINT64, UInt64Builder);
|
||||
BUILDER_CASE(INT64, Int64Builder);
|
||||
BUILDER_CASE(TIMESTAMP, TimestampBuilder);
|
||||
|
||||
BUILDER_CASE(BOOL, BooleanBuilder);
|
||||
|
||||
BUILDER_CASE(FLOAT, FloatBuilder);
|
||||
BUILDER_CASE(DOUBLE, DoubleBuilder);
|
||||
|
||||
BUILDER_CASE(STRING, StringBuilder);
|
||||
BUILDER_CASE(BINARY, BinaryBuilder);
|
||||
|
||||
case Type::LIST: {
|
||||
std::shared_ptr<ArrayBuilder> value_builder;
|
||||
std::shared_ptr<DataType> value_type =
|
||||
static_cast<ListType*>(type.get())->value_type();
|
||||
RETURN_NOT_OK(MakeBuilder(pool, value_type, &value_builder));
|
||||
out->reset(new ListBuilder(pool, value_builder));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
case Type::STRUCT: {
|
||||
std::vector<FieldPtr>& fields = type->children_;
|
||||
std::vector<std::shared_ptr<ArrayBuilder>> values_builder;
|
||||
|
||||
for (auto it : fields) {
|
||||
std::shared_ptr<ArrayBuilder> builder;
|
||||
RETURN_NOT_OK(MakeBuilder(pool, it->type, &builder));
|
||||
values_builder.push_back(builder);
|
||||
}
|
||||
out->reset(new StructBuilder(pool, type, values_builder));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
default:
|
||||
return Status::NotImplemented(type->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
+311
-1
@@ -23,6 +23,8 @@
|
||||
#include <vector>
|
||||
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/macros.h"
|
||||
#include "arrow/util/status.h"
|
||||
#include "arrow/util/visibility.h"
|
||||
@@ -31,7 +33,6 @@ namespace arrow {
|
||||
|
||||
class Array;
|
||||
class MemoryPool;
|
||||
class PoolBuffer;
|
||||
|
||||
static constexpr int32_t kMinBuilderCapacity = 1 << 5;
|
||||
|
||||
@@ -130,6 +131,315 @@ class ARROW_EXPORT ArrayBuilder {
|
||||
DISALLOW_COPY_AND_ASSIGN(ArrayBuilder);
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
class ARROW_EXPORT PrimitiveBuilder : public ArrayBuilder {
|
||||
public:
|
||||
using value_type = typename Type::c_type;
|
||||
|
||||
explicit PrimitiveBuilder(MemoryPool* pool, const TypePtr& type)
|
||||
: ArrayBuilder(pool, type), data_(nullptr) {}
|
||||
|
||||
virtual ~PrimitiveBuilder() {}
|
||||
|
||||
using ArrayBuilder::Advance;
|
||||
|
||||
// Write nulls as uint8_t* (0 value indicates null) into pre-allocated memory
|
||||
Status AppendNulls(const uint8_t* valid_bytes, int32_t length) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
UnsafeAppendToBitmap(valid_bytes, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status AppendNull() {
|
||||
RETURN_NOT_OK(Reserve(1));
|
||||
UnsafeAppendToBitmap(false);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
std::shared_ptr<Buffer> data() const { return data_; }
|
||||
|
||||
// Vector append
|
||||
//
|
||||
// If passed, valid_bytes is of equal length to values, and any zero byte
|
||||
// will be considered as a null for that slot
|
||||
Status Append(
|
||||
const value_type* values, int32_t length, const uint8_t* valid_bytes = nullptr);
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
Status Init(int32_t capacity) override;
|
||||
|
||||
// Increase the capacity of the builder to accommodate at least the indicated
|
||||
// number of elements
|
||||
Status Resize(int32_t capacity) override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<PoolBuffer> data_;
|
||||
value_type* raw_data_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ARROW_EXPORT NumericBuilder : public PrimitiveBuilder<T> {
|
||||
public:
|
||||
using typename PrimitiveBuilder<T>::value_type;
|
||||
using PrimitiveBuilder<T>::PrimitiveBuilder;
|
||||
|
||||
using PrimitiveBuilder<T>::Append;
|
||||
using PrimitiveBuilder<T>::Init;
|
||||
using PrimitiveBuilder<T>::Resize;
|
||||
using PrimitiveBuilder<T>::Reserve;
|
||||
|
||||
// Scalar append.
|
||||
Status Append(value_type val) {
|
||||
RETURN_NOT_OK(ArrayBuilder::Reserve(1));
|
||||
UnsafeAppend(val);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Does not capacity-check; make sure to call Reserve beforehand
|
||||
void UnsafeAppend(value_type val) {
|
||||
BitUtil::SetBit(null_bitmap_data_, length_);
|
||||
raw_data_[length_++] = val;
|
||||
}
|
||||
|
||||
protected:
|
||||
using PrimitiveBuilder<T>::length_;
|
||||
using PrimitiveBuilder<T>::null_bitmap_data_;
|
||||
using PrimitiveBuilder<T>::raw_data_;
|
||||
};
|
||||
|
||||
// Builders
|
||||
|
||||
using UInt8Builder = NumericBuilder<UInt8Type>;
|
||||
using UInt16Builder = NumericBuilder<UInt16Type>;
|
||||
using UInt32Builder = NumericBuilder<UInt32Type>;
|
||||
using UInt64Builder = NumericBuilder<UInt64Type>;
|
||||
|
||||
using Int8Builder = NumericBuilder<Int8Type>;
|
||||
using Int16Builder = NumericBuilder<Int16Type>;
|
||||
using Int32Builder = NumericBuilder<Int32Type>;
|
||||
using Int64Builder = NumericBuilder<Int64Type>;
|
||||
using TimestampBuilder = NumericBuilder<TimestampType>;
|
||||
|
||||
using HalfFloatBuilder = NumericBuilder<HalfFloatType>;
|
||||
using FloatBuilder = NumericBuilder<FloatType>;
|
||||
using DoubleBuilder = NumericBuilder<DoubleType>;
|
||||
|
||||
class ARROW_EXPORT BooleanBuilder : public ArrayBuilder {
|
||||
public:
|
||||
explicit BooleanBuilder(MemoryPool* pool, const TypePtr& type)
|
||||
: ArrayBuilder(pool, type), data_(nullptr) {}
|
||||
|
||||
virtual ~BooleanBuilder() {}
|
||||
|
||||
using ArrayBuilder::Advance;
|
||||
|
||||
// Write nulls as uint8_t* (0 value indicates null) into pre-allocated memory
|
||||
Status AppendNulls(const uint8_t* valid_bytes, int32_t length) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
UnsafeAppendToBitmap(valid_bytes, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status AppendNull() {
|
||||
RETURN_NOT_OK(Reserve(1));
|
||||
UnsafeAppendToBitmap(false);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
std::shared_ptr<Buffer> data() const { return data_; }
|
||||
|
||||
// Scalar append
|
||||
Status Append(bool val) {
|
||||
Reserve(1);
|
||||
BitUtil::SetBit(null_bitmap_data_, length_);
|
||||
if (val) {
|
||||
BitUtil::SetBit(raw_data_, length_);
|
||||
} else {
|
||||
BitUtil::ClearBit(raw_data_, length_);
|
||||
}
|
||||
++length_;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Vector append
|
||||
//
|
||||
// If passed, valid_bytes is of equal length to values, and any zero byte
|
||||
// will be considered as a null for that slot
|
||||
Status Append(
|
||||
const uint8_t* values, int32_t length, const uint8_t* valid_bytes = nullptr);
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
Status Init(int32_t capacity) override;
|
||||
|
||||
// Increase the capacity of the builder to accommodate at least the indicated
|
||||
// number of elements
|
||||
Status Resize(int32_t capacity) override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<PoolBuffer> data_;
|
||||
uint8_t* raw_data_;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// List builder
|
||||
|
||||
// Builder class for variable-length list array value types
|
||||
//
|
||||
// To use this class, you must append values to the child array builder and use
|
||||
// the Append function to delimit each distinct list value (once the values
|
||||
// have been appended to the child array) or use the bulk API to append
|
||||
// a sequence of offests and null values.
|
||||
//
|
||||
// A note on types. Per arrow/type.h all types in the c++ implementation are
|
||||
// logical so even though this class always builds list array, this can
|
||||
// represent multiple different logical types. If no logical type is provided
|
||||
// at construction time, the class defaults to List<T> where t is taken from the
|
||||
// value_builder/values that the object is constructed with.
|
||||
class ARROW_EXPORT ListBuilder : public ArrayBuilder {
|
||||
public:
|
||||
// Use this constructor to incrementally build the value array along with offsets and
|
||||
// null bitmap.
|
||||
ListBuilder(MemoryPool* pool, std::shared_ptr<ArrayBuilder> value_builder,
|
||||
const TypePtr& type = nullptr);
|
||||
|
||||
// Use this constructor to build the list with a pre-existing values array
|
||||
ListBuilder(
|
||||
MemoryPool* pool, std::shared_ptr<Array> values, const TypePtr& type = nullptr);
|
||||
|
||||
virtual ~ListBuilder() {}
|
||||
|
||||
Status Init(int32_t elements) override;
|
||||
Status Resize(int32_t capacity) override;
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
|
||||
// Vector append
|
||||
//
|
||||
// If passed, valid_bytes is of equal length to values, and any zero byte
|
||||
// will be considered as a null for that slot
|
||||
Status Append(
|
||||
const int32_t* offsets, int32_t length, const uint8_t* valid_bytes = nullptr) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
UnsafeAppendToBitmap(valid_bytes, length);
|
||||
offset_builder_.UnsafeAppend<int32_t>(offsets, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Start a new variable-length list slot
|
||||
//
|
||||
// This function should be called before beginning to append elements to the
|
||||
// value builder
|
||||
Status Append(bool is_valid = true) {
|
||||
RETURN_NOT_OK(Reserve(1));
|
||||
UnsafeAppendToBitmap(is_valid);
|
||||
RETURN_NOT_OK(offset_builder_.Append<int32_t>(value_builder_->length()));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status AppendNull() { return Append(false); }
|
||||
|
||||
std::shared_ptr<ArrayBuilder> value_builder() const;
|
||||
|
||||
protected:
|
||||
BufferBuilder offset_builder_;
|
||||
std::shared_ptr<ArrayBuilder> value_builder_;
|
||||
std::shared_ptr<Array> values_;
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Binary and String
|
||||
|
||||
// BinaryBuilder : public ListBuilder
|
||||
class ARROW_EXPORT BinaryBuilder : public ListBuilder {
|
||||
public:
|
||||
explicit BinaryBuilder(MemoryPool* pool, const TypePtr& type);
|
||||
virtual ~BinaryBuilder() {}
|
||||
|
||||
Status Append(const uint8_t* value, int32_t length) {
|
||||
RETURN_NOT_OK(ListBuilder::Append());
|
||||
return byte_builder_->Append(value, length);
|
||||
}
|
||||
|
||||
Status Append(const char* value, int32_t length) {
|
||||
return Append(reinterpret_cast<const uint8_t*>(value), length);
|
||||
}
|
||||
|
||||
Status Append(const std::string& value) { return Append(value.c_str(), value.size()); }
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
|
||||
protected:
|
||||
UInt8Builder* byte_builder_;
|
||||
};
|
||||
|
||||
// String builder
|
||||
class ARROW_EXPORT StringBuilder : public BinaryBuilder {
|
||||
public:
|
||||
explicit StringBuilder(MemoryPool* pool, const TypePtr& type)
|
||||
: BinaryBuilder(pool, type) {}
|
||||
|
||||
using BinaryBuilder::Append;
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
|
||||
Status Append(const std::vector<std::string>& values, uint8_t* null_bytes);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Struct
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// StructArray builder
|
||||
// Append, Resize and Reserve methods are acting on StructBuilder.
|
||||
// Please make sure all these methods of all child-builders' are consistently
|
||||
// called to maintain data-structure consistency.
|
||||
class ARROW_EXPORT StructBuilder : public ArrayBuilder {
|
||||
public:
|
||||
StructBuilder(MemoryPool* pool, const std::shared_ptr<DataType>& type,
|
||||
const std::vector<std::shared_ptr<ArrayBuilder>>& field_builders)
|
||||
: ArrayBuilder(pool, type) {
|
||||
field_builders_ = field_builders;
|
||||
}
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
|
||||
// Null bitmap is of equal length to every child field, and any zero byte
|
||||
// will be considered as a null for that field, but users must using app-
|
||||
// end methods or advance methods of the child builders' independently to
|
||||
// insert data.
|
||||
Status Append(int32_t length, const uint8_t* valid_bytes) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
UnsafeAppendToBitmap(valid_bytes, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Append an element to the Struct. All child-builders' Append method must
|
||||
// be called independently to maintain data-structure consistency.
|
||||
Status Append(bool is_valid = true) {
|
||||
RETURN_NOT_OK(Reserve(1));
|
||||
UnsafeAppendToBitmap(is_valid);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status AppendNull() { return Append(false); }
|
||||
|
||||
std::shared_ptr<ArrayBuilder> field_builder(int pos) const;
|
||||
|
||||
const std::vector<std::shared_ptr<ArrayBuilder>>& field_builders() const {
|
||||
return field_builders_;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<ArrayBuilder>> field_builders_;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Helper functions
|
||||
|
||||
Status ARROW_EXPORT MakeBuilder(MemoryPool* pool, const std::shared_ptr<DataType>& type,
|
||||
std::shared_ptr<ArrayBuilder>* out);
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_BUILDER_H_
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/util/memory-pool.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "arrow/schema.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
|
||||
using std::shared_ptr;
|
||||
using std::vector;
|
||||
|
||||
@@ -33,10 +33,6 @@
|
||||
#include "arrow/table.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/construct.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/logging.h"
|
||||
|
||||
@@ -31,10 +31,6 @@
|
||||
#include "arrow/ipc/util.h"
|
||||
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/memory-pool.h"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/io/memory.h"
|
||||
#include "arrow/io/test-common.h"
|
||||
#include "arrow/ipc/adapter.h"
|
||||
@@ -32,10 +33,6 @@
|
||||
#include "arrow/ipc/util.h"
|
||||
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/memory-pool.h"
|
||||
|
||||
@@ -26,15 +26,13 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/ipc/json-internal.h"
|
||||
#include "arrow/ipc/json.h"
|
||||
#include "arrow/table.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/type_traits.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
#include "arrow/util/memory-pool.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
@@ -147,7 +145,7 @@ TEST(TestJsonArrayWriter, NestedTypes) {
|
||||
std::vector<int32_t> values = {0, 1, 2, 3, 4, 5, 6};
|
||||
|
||||
std::shared_ptr<Array> values_array;
|
||||
MakeArray<Int32Type, int32_t>(int32(), values_is_valid, values, &values_array);
|
||||
ArrayFromVector<Int32Type, int32_t>(int32(), values_is_valid, values, &values_array);
|
||||
|
||||
// List
|
||||
std::vector<bool> list_is_valid = {true, false, true, true, true};
|
||||
@@ -188,10 +186,10 @@ void MakeBatchArrays(const std::shared_ptr<Schema>& schema, const int num_rows,
|
||||
test::randint<int32_t>(num_rows, 0, 100, &v2_values);
|
||||
|
||||
std::shared_ptr<Array> v1;
|
||||
MakeArray<Int8Type, int8_t>(schema->field(0)->type, is_valid, v1_values, &v1);
|
||||
ArrayFromVector<Int8Type, int8_t>(schema->field(0)->type, is_valid, v1_values, &v1);
|
||||
|
||||
std::shared_ptr<Array> v2;
|
||||
MakeArray<Int32Type, int32_t>(schema->field(1)->type, is_valid, v2_values, &v2);
|
||||
ArrayFromVector<Int32Type, int32_t>(schema->field(1)->type, is_valid, v2_values, &v2);
|
||||
|
||||
static const int kBufferSize = 10;
|
||||
static uint8_t buffer[kBufferSize];
|
||||
@@ -323,13 +321,13 @@ TEST(TestJsonFileReadWrite, MinimalFormatExample) {
|
||||
std::vector<bool> foo_valid = {true, false, true, true, true};
|
||||
std::vector<int32_t> foo_values = {1, 2, 3, 4, 5};
|
||||
std::shared_ptr<Array> foo;
|
||||
MakeArray<Int32Type, int32_t>(int32(), foo_valid, foo_values, &foo);
|
||||
ArrayFromVector<Int32Type, int32_t>(int32(), foo_valid, foo_values, &foo);
|
||||
ASSERT_TRUE(batch->column(0)->Equals(foo));
|
||||
|
||||
std::vector<bool> bar_valid = {true, false, false, true, true};
|
||||
std::vector<double> bar_values = {1, 2, 3, 4, 5};
|
||||
std::shared_ptr<Array> bar;
|
||||
MakeArray<DoubleType, double>(float64(), bar_valid, bar_values, &bar);
|
||||
ArrayFromVector<DoubleType, double>(float64(), bar_valid, bar_values, &bar);
|
||||
ASSERT_TRUE(batch->column(1)->Equals(bar));
|
||||
}
|
||||
|
||||
|
||||
@@ -28,14 +28,12 @@
|
||||
#include "rapidjson/writer.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/schema.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/type_traits.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/logging.h"
|
||||
#include "arrow/util/memory-pool.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
|
||||
@@ -25,13 +25,10 @@
|
||||
#include <vector>
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/table.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/memory-pool.h"
|
||||
|
||||
@@ -26,14 +26,11 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/pretty_print.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/type_traits.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
|
||||
@@ -25,9 +25,6 @@
|
||||
#include "arrow/table.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/type_traits.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/column.h"
|
||||
#include "arrow/schema.h"
|
||||
#include "arrow/table.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/column.h"
|
||||
#include "arrow/schema.h"
|
||||
#include "arrow/table.h"
|
||||
@@ -253,8 +254,9 @@ Status MakeRandomBytePoolBuffer(int32_t length, MemoryPool* pool,
|
||||
} // namespace test
|
||||
|
||||
template <typename TYPE, typename C_TYPE>
|
||||
void MakeArray(const std::shared_ptr<DataType>& type, const std::vector<bool>& is_valid,
|
||||
const std::vector<C_TYPE>& values, std::shared_ptr<Array>* out) {
|
||||
void ArrayFromVector(const std::shared_ptr<DataType>& type,
|
||||
const std::vector<bool>& is_valid, const std::vector<C_TYPE>& values,
|
||||
std::shared_ptr<Array>* out) {
|
||||
std::shared_ptr<Buffer> values_buffer;
|
||||
std::shared_ptr<Buffer> values_bitmap;
|
||||
|
||||
@@ -272,6 +274,37 @@ void MakeArray(const std::shared_ptr<DataType>& type, const std::vector<bool>& i
|
||||
values_buffer, null_count, values_bitmap);
|
||||
}
|
||||
|
||||
class TestBuilder : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() {
|
||||
pool_ = default_memory_pool();
|
||||
type_ = TypePtr(new UInt8Type());
|
||||
builder_.reset(new UInt8Builder(pool_, type_));
|
||||
builder_nn_.reset(new UInt8Builder(pool_, type_));
|
||||
}
|
||||
|
||||
protected:
|
||||
MemoryPool* pool_;
|
||||
|
||||
TypePtr type_;
|
||||
std::unique_ptr<ArrayBuilder> builder_;
|
||||
std::unique_ptr<ArrayBuilder> builder_nn_;
|
||||
};
|
||||
|
||||
template <class T, class Builder>
|
||||
Status MakeArray(const std::vector<uint8_t>& valid_bytes, const std::vector<T>& values,
|
||||
int size, Builder* builder, ArrayPtr* out) {
|
||||
// Append the first 1000
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (valid_bytes[i] > 0) {
|
||||
RETURN_NOT_OK(builder->Append(values[i]));
|
||||
} else {
|
||||
RETURN_NOT_OK(builder->AppendNull());
|
||||
}
|
||||
}
|
||||
return builder->Finish(out);
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_TEST_UTIL_H_
|
||||
@@ -220,6 +220,12 @@ std::vector<BufferDescr> UnionType::GetBufferLayout() const {
|
||||
}
|
||||
}
|
||||
|
||||
std::string DecimalType::ToString() const {
|
||||
std::stringstream s;
|
||||
s << "decimal(" << precision << ", " << scale << ")";
|
||||
return s.str();
|
||||
}
|
||||
|
||||
std::vector<BufferDescr> DecimalType::GetBufferLayout() const {
|
||||
// TODO(wesm)
|
||||
return {};
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
#######################################
|
||||
# arrow_types
|
||||
#######################################
|
||||
|
||||
# Headers: top level
|
||||
install(FILES
|
||||
construct.h
|
||||
datetime.h
|
||||
decimal.h
|
||||
list.h
|
||||
primitive.h
|
||||
string.h
|
||||
struct.h
|
||||
union.h
|
||||
DESTINATION include/arrow/types)
|
||||
|
||||
|
||||
ADD_ARROW_TEST(decimal-test)
|
||||
ADD_ARROW_TEST(list-test)
|
||||
ADD_ARROW_TEST(primitive-test)
|
||||
ADD_ARROW_TEST(string-test)
|
||||
ADD_ARROW_TEST(struct-test)
|
||||
@@ -1,124 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#include "arrow/types/construct.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/types/string.h"
|
||||
#include "arrow/types/struct.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/status.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
class ArrayBuilder;
|
||||
|
||||
#define BUILDER_CASE(ENUM, BuilderType) \
|
||||
case Type::ENUM: \
|
||||
out->reset(new BuilderType(pool, type)); \
|
||||
return Status::OK();
|
||||
|
||||
// Initially looked at doing this with vtables, but shared pointers makes it
|
||||
// difficult
|
||||
//
|
||||
// TODO(wesm): come up with a less monolithic strategy
|
||||
Status MakeBuilder(MemoryPool* pool, const std::shared_ptr<DataType>& type,
|
||||
std::shared_ptr<ArrayBuilder>* out) {
|
||||
switch (type->type) {
|
||||
BUILDER_CASE(UINT8, UInt8Builder);
|
||||
BUILDER_CASE(INT8, Int8Builder);
|
||||
BUILDER_CASE(UINT16, UInt16Builder);
|
||||
BUILDER_CASE(INT16, Int16Builder);
|
||||
BUILDER_CASE(UINT32, UInt32Builder);
|
||||
BUILDER_CASE(INT32, Int32Builder);
|
||||
BUILDER_CASE(UINT64, UInt64Builder);
|
||||
BUILDER_CASE(INT64, Int64Builder);
|
||||
BUILDER_CASE(TIMESTAMP, TimestampBuilder);
|
||||
|
||||
BUILDER_CASE(BOOL, BooleanBuilder);
|
||||
|
||||
BUILDER_CASE(FLOAT, FloatBuilder);
|
||||
BUILDER_CASE(DOUBLE, DoubleBuilder);
|
||||
|
||||
BUILDER_CASE(STRING, StringBuilder);
|
||||
BUILDER_CASE(BINARY, BinaryBuilder);
|
||||
|
||||
case Type::LIST: {
|
||||
std::shared_ptr<ArrayBuilder> value_builder;
|
||||
std::shared_ptr<DataType> value_type =
|
||||
static_cast<ListType*>(type.get())->value_type();
|
||||
RETURN_NOT_OK(MakeBuilder(pool, value_type, &value_builder));
|
||||
out->reset(new ListBuilder(pool, value_builder));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
case Type::STRUCT: {
|
||||
std::vector<FieldPtr>& fields = type->children_;
|
||||
std::vector<std::shared_ptr<ArrayBuilder>> values_builder;
|
||||
|
||||
for (auto it : fields) {
|
||||
std::shared_ptr<ArrayBuilder> builder;
|
||||
RETURN_NOT_OK(MakeBuilder(pool, it->type, &builder));
|
||||
values_builder.push_back(builder);
|
||||
}
|
||||
out->reset(new StructBuilder(pool, type, values_builder));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
default:
|
||||
return Status::NotImplemented(type->ToString());
|
||||
}
|
||||
}
|
||||
|
||||
#define MAKE_PRIMITIVE_ARRAY_CASE(ENUM, ArrayType) \
|
||||
case Type::ENUM: \
|
||||
out->reset(new ArrayType(type, length, data, null_count, null_bitmap)); \
|
||||
break;
|
||||
|
||||
Status MakePrimitiveArray(const TypePtr& type, int32_t length,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap, ArrayPtr* out) {
|
||||
switch (type->type) {
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(BOOL, BooleanArray);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(UINT8, UInt8Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(INT8, Int8Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(UINT16, UInt16Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(INT16, Int16Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(UINT32, UInt32Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(INT32, Int32Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(UINT64, UInt64Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(INT64, Int64Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(FLOAT, FloatArray);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(DOUBLE, DoubleArray);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(TIME, Int64Array);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(TIMESTAMP, TimestampArray);
|
||||
MAKE_PRIMITIVE_ARRAY_CASE(TIMESTAMP_DOUBLE, DoubleArray);
|
||||
default:
|
||||
return Status::NotImplemented(type->ToString());
|
||||
}
|
||||
#ifdef NDEBUG
|
||||
return Status::OK();
|
||||
#else
|
||||
return (*out)->Validate();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
@@ -1,47 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#ifndef ARROW_TYPES_CONSTRUCT_H
|
||||
#define ARROW_TYPES_CONSTRUCT_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "arrow/util/visibility.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
class Array;
|
||||
class ArrayBuilder;
|
||||
class Buffer;
|
||||
struct DataType;
|
||||
struct Field;
|
||||
class MemoryPool;
|
||||
class Status;
|
||||
|
||||
Status ARROW_EXPORT MakeBuilder(MemoryPool* pool, const std::shared_ptr<DataType>& type,
|
||||
std::shared_ptr<ArrayBuilder>* out);
|
||||
|
||||
// Create new arrays for logical types that are backed by primitive arrays.
|
||||
Status ARROW_EXPORT MakePrimitiveArray(const std::shared_ptr<DataType>& type,
|
||||
int32_t length, const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap, std::shared_ptr<Array>* out);
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_BUILDER_H_
|
||||
@@ -1,27 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#ifndef ARROW_TYPES_DATETIME_H
|
||||
#define ARROW_TYPES_DATETIME_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "arrow/type.h"
|
||||
|
||||
namespace arrow {} // namespace arrow
|
||||
|
||||
#endif // ARROW_TYPES_DATETIME_H
|
||||
@@ -1,31 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#include "arrow/types/decimal.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace arrow {
|
||||
|
||||
std::string DecimalType::ToString() const {
|
||||
std::stringstream s;
|
||||
s << "decimal(" << precision << ", " << scale << ")";
|
||||
return s.str();
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
@@ -1,28 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#ifndef ARROW_TYPES_DECIMAL_H
|
||||
#define ARROW_TYPES_DECIMAL_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/util/visibility.h"
|
||||
|
||||
namespace arrow {} // namespace arrow
|
||||
|
||||
#endif // ARROW_TYPES_DECIMAL_H
|
||||
@@ -1,162 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
#include "arrow/types/list.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace arrow {
|
||||
|
||||
bool ListArray::EqualsExact(const ListArray& other) const {
|
||||
if (this == &other) { return true; }
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
bool equal_offsets =
|
||||
offset_buffer_->Equals(*other.offset_buffer_, (length_ + 1) * sizeof(int32_t));
|
||||
if (!equal_offsets) { return false; }
|
||||
bool equal_null_bitmap = true;
|
||||
if (null_count_ > 0) {
|
||||
equal_null_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::BytesForBits(length_));
|
||||
}
|
||||
|
||||
if (!equal_null_bitmap) { return false; }
|
||||
|
||||
return values()->Equals(other.values());
|
||||
}
|
||||
|
||||
bool ListArray::Equals(const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
return EqualsExact(*static_cast<const ListArray*>(arr.get()));
|
||||
}
|
||||
|
||||
bool ListArray::RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<ListArray*>(arr.get());
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
const bool is_null = IsNull(i);
|
||||
if (is_null != arr->IsNull(o_i)) { return false; }
|
||||
if (is_null) continue;
|
||||
const int32_t begin_offset = offset(i);
|
||||
const int32_t end_offset = offset(i + 1);
|
||||
const int32_t other_begin_offset = other->offset(o_i);
|
||||
const int32_t other_end_offset = other->offset(o_i + 1);
|
||||
// Underlying can't be equal if the size isn't equal
|
||||
if (end_offset - begin_offset != other_end_offset - other_begin_offset) {
|
||||
return false;
|
||||
}
|
||||
if (!values_->RangeEquals(
|
||||
begin_offset, end_offset, other_begin_offset, other->values())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Status ListArray::Validate() const {
|
||||
if (length_ < 0) { return Status::Invalid("Length was negative"); }
|
||||
if (!offset_buffer_) { return Status::Invalid("offset_buffer_ was null"); }
|
||||
if (offset_buffer_->size() / static_cast<int>(sizeof(int32_t)) < length_) {
|
||||
std::stringstream ss;
|
||||
ss << "offset buffer size (bytes): " << offset_buffer_->size()
|
||||
<< " isn't large enough for length: " << length_;
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
const int32_t last_offset = offset(length_);
|
||||
if (last_offset > 0) {
|
||||
if (!values_) {
|
||||
return Status::Invalid("last offset was non-zero and values was null");
|
||||
}
|
||||
if (values_->length() != last_offset) {
|
||||
std::stringstream ss;
|
||||
ss << "Final offset invariant not equal to values length: " << last_offset
|
||||
<< "!=" << values_->length();
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
|
||||
const Status child_valid = values_->Validate();
|
||||
if (!child_valid.ok()) {
|
||||
std::stringstream ss;
|
||||
ss << "Child array invalid: " << child_valid.ToString();
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
int32_t prev_offset = offset(0);
|
||||
if (prev_offset != 0) { return Status::Invalid("The first offset wasn't zero"); }
|
||||
for (int32_t i = 1; i <= length_; ++i) {
|
||||
int32_t current_offset = offset(i);
|
||||
if (IsNull(i - 1) && current_offset != prev_offset) {
|
||||
std::stringstream ss;
|
||||
ss << "Offset invariant failure at: " << i << " inconsistent offsets for null slot"
|
||||
<< current_offset << "!=" << prev_offset;
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
if (current_offset < prev_offset) {
|
||||
std::stringstream ss;
|
||||
ss << "Offset invariant failure: " << i
|
||||
<< " inconsistent offset for non-null slot: " << current_offset << "<"
|
||||
<< prev_offset;
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
prev_offset = current_offset;
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status ListBuilder::Init(int32_t elements) {
|
||||
DCHECK_LT(elements, std::numeric_limits<int32_t>::max());
|
||||
RETURN_NOT_OK(ArrayBuilder::Init(elements));
|
||||
// one more then requested for offsets
|
||||
return offset_builder_.Resize((elements + 1) * sizeof(int32_t));
|
||||
}
|
||||
|
||||
Status ListBuilder::Resize(int32_t capacity) {
|
||||
DCHECK_LT(capacity, std::numeric_limits<int32_t>::max());
|
||||
// one more then requested for offsets
|
||||
RETURN_NOT_OK(offset_builder_.Resize((capacity + 1) * sizeof(int32_t)));
|
||||
return ArrayBuilder::Resize(capacity);
|
||||
}
|
||||
|
||||
Status ListBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
std::shared_ptr<Array> items = values_;
|
||||
if (!items) { RETURN_NOT_OK(value_builder_->Finish(&items)); }
|
||||
|
||||
RETURN_NOT_OK(offset_builder_.Append<int32_t>(items->length()));
|
||||
std::shared_ptr<Buffer> offsets = offset_builder_.Finish();
|
||||
|
||||
*out = std::make_shared<ListArray>(
|
||||
type_, length_, offsets, items, null_count_, null_bitmap_);
|
||||
|
||||
Reset();
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
void ListBuilder::Reset() {
|
||||
capacity_ = length_ = null_count_ = 0;
|
||||
null_bitmap_ = nullptr;
|
||||
}
|
||||
|
||||
Status ListArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
@@ -1,170 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#ifndef ARROW_TYPES_LIST_H
|
||||
#define ARROW_TYPES_LIST_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/logging.h"
|
||||
#include "arrow/util/status.h"
|
||||
#include "arrow/util/visibility.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
class MemoryPool;
|
||||
|
||||
class ARROW_EXPORT ListArray : public Array {
|
||||
public:
|
||||
using TypeClass = ListType;
|
||||
|
||||
ListArray(const TypePtr& type, int32_t length, std::shared_ptr<Buffer> offsets,
|
||||
const ArrayPtr& values, int32_t null_count = 0,
|
||||
std::shared_ptr<Buffer> null_bitmap = nullptr)
|
||||
: Array(type, length, null_count, null_bitmap) {
|
||||
offset_buffer_ = offsets;
|
||||
offsets_ = offsets == nullptr ? nullptr : reinterpret_cast<const int32_t*>(
|
||||
offset_buffer_->data());
|
||||
values_ = values;
|
||||
}
|
||||
|
||||
Status Validate() const override;
|
||||
|
||||
virtual ~ListArray() = default;
|
||||
|
||||
// Return a shared pointer in case the requestor desires to share ownership
|
||||
// with this array.
|
||||
std::shared_ptr<Array> values() const { return values_; }
|
||||
std::shared_ptr<Buffer> offsets() const {
|
||||
return std::static_pointer_cast<Buffer>(offset_buffer_);
|
||||
}
|
||||
|
||||
std::shared_ptr<DataType> value_type() const { return values_->type(); }
|
||||
|
||||
const int32_t* raw_offsets() const { return offsets_; }
|
||||
|
||||
int32_t offset(int i) const { return offsets_[i]; }
|
||||
|
||||
// Neither of these functions will perform boundschecking
|
||||
int32_t value_offset(int i) const { return offsets_[i]; }
|
||||
int32_t value_length(int i) const { return offsets_[i + 1] - offsets_[i]; }
|
||||
|
||||
bool EqualsExact(const ListArray& other) const;
|
||||
bool Equals(const std::shared_ptr<Array>& arr) const override;
|
||||
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const ArrayPtr& arr) const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Buffer> offset_buffer_;
|
||||
const int32_t* offsets_;
|
||||
ArrayPtr values_;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Array builder
|
||||
|
||||
// Builder class for variable-length list array value types
|
||||
//
|
||||
// To use this class, you must append values to the child array builder and use
|
||||
// the Append function to delimit each distinct list value (once the values
|
||||
// have been appended to the child array) or use the bulk API to append
|
||||
// a sequence of offests and null values.
|
||||
//
|
||||
// A note on types. Per arrow/type.h all types in the c++ implementation are
|
||||
// logical so even though this class always builds list array, this can
|
||||
// represent multiple different logical types. If no logical type is provided
|
||||
// at construction time, the class defaults to List<T> where t is taken from the
|
||||
// value_builder/values that the object is constructed with.
|
||||
class ARROW_EXPORT ListBuilder : public ArrayBuilder {
|
||||
public:
|
||||
// Use this constructor to incrementally build the value array along with offsets and
|
||||
// null bitmap.
|
||||
ListBuilder(MemoryPool* pool, std::shared_ptr<ArrayBuilder> value_builder,
|
||||
const TypePtr& type = nullptr)
|
||||
: ArrayBuilder(
|
||||
pool, type ? type : std::static_pointer_cast<DataType>(
|
||||
std::make_shared<ListType>(value_builder->type()))),
|
||||
offset_builder_(pool),
|
||||
value_builder_(value_builder) {}
|
||||
|
||||
// Use this constructor to build the list with a pre-existing values array
|
||||
ListBuilder(
|
||||
MemoryPool* pool, std::shared_ptr<Array> values, const TypePtr& type = nullptr)
|
||||
: ArrayBuilder(pool, type ? type : std::static_pointer_cast<DataType>(
|
||||
std::make_shared<ListType>(values->type()))),
|
||||
offset_builder_(pool),
|
||||
values_(values) {}
|
||||
|
||||
virtual ~ListBuilder() {}
|
||||
|
||||
Status Init(int32_t elements) override;
|
||||
Status Resize(int32_t capacity) override;
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
|
||||
// Vector append
|
||||
//
|
||||
// If passed, valid_bytes is of equal length to values, and any zero byte
|
||||
// will be considered as a null for that slot
|
||||
Status Append(
|
||||
const int32_t* offsets, int32_t length, const uint8_t* valid_bytes = nullptr) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
UnsafeAppendToBitmap(valid_bytes, length);
|
||||
offset_builder_.UnsafeAppend<int32_t>(offsets, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Start a new variable-length list slot
|
||||
//
|
||||
// This function should be called before beginning to append elements to the
|
||||
// value builder
|
||||
Status Append(bool is_valid = true) {
|
||||
RETURN_NOT_OK(Reserve(1));
|
||||
UnsafeAppendToBitmap(is_valid);
|
||||
RETURN_NOT_OK(offset_builder_.Append<int32_t>(value_builder_->length()));
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status AppendNull() { return Append(false); }
|
||||
|
||||
std::shared_ptr<ArrayBuilder> value_builder() const {
|
||||
DCHECK(!values_) << "Using value builder is pointless when values_ is set";
|
||||
return value_builder_;
|
||||
}
|
||||
|
||||
protected:
|
||||
BufferBuilder offset_builder_;
|
||||
std::shared_ptr<ArrayBuilder> value_builder_;
|
||||
std::shared_ptr<Array> values_;
|
||||
|
||||
void Reset();
|
||||
};
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_TYPES_LIST_H
|
||||
@@ -1,294 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#include "arrow/types/primitive.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <memory>
|
||||
|
||||
#include "arrow/type_traits.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/logging.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Primitive array base
|
||||
|
||||
PrimitiveArray::PrimitiveArray(const TypePtr& type, int32_t length,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: Array(type, length, null_count, null_bitmap) {
|
||||
data_ = data;
|
||||
raw_data_ = data == nullptr ? nullptr : data_->data();
|
||||
}
|
||||
|
||||
bool PrimitiveArray::EqualsExact(const PrimitiveArray& other) const {
|
||||
if (this == &other) { return true; }
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
if (null_count_ > 0) {
|
||||
bool equal_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::CeilByte(length_) / 8);
|
||||
if (!equal_bitmap) { return false; }
|
||||
|
||||
const uint8_t* this_data = raw_data_;
|
||||
const uint8_t* other_data = other.raw_data_;
|
||||
|
||||
auto size_meta = dynamic_cast<const FixedWidthType*>(type_.get());
|
||||
int value_byte_size = size_meta->bit_width() / 8;
|
||||
DCHECK_GT(value_byte_size, 0);
|
||||
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (!IsNull(i) && memcmp(this_data, other_data, value_byte_size)) { return false; }
|
||||
this_data += value_byte_size;
|
||||
other_data += value_byte_size;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (length_ == 0 && other.length_ == 0) { return true; }
|
||||
return data_->Equals(*other.data_, length_);
|
||||
}
|
||||
}
|
||||
|
||||
bool PrimitiveArray::Equals(const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
return EqualsExact(*static_cast<const PrimitiveArray*>(arr.get()));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status NumericArray<T>::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
template class NumericArray<UInt8Type>;
|
||||
template class NumericArray<UInt16Type>;
|
||||
template class NumericArray<UInt32Type>;
|
||||
template class NumericArray<UInt64Type>;
|
||||
template class NumericArray<Int8Type>;
|
||||
template class NumericArray<Int16Type>;
|
||||
template class NumericArray<Int32Type>;
|
||||
template class NumericArray<Int64Type>;
|
||||
template class NumericArray<TimestampType>;
|
||||
template class NumericArray<HalfFloatType>;
|
||||
template class NumericArray<FloatType>;
|
||||
template class NumericArray<DoubleType>;
|
||||
|
||||
template <typename T>
|
||||
Status PrimitiveBuilder<T>::Init(int32_t capacity) {
|
||||
RETURN_NOT_OK(ArrayBuilder::Init(capacity));
|
||||
data_ = std::make_shared<PoolBuffer>(pool_);
|
||||
|
||||
int64_t nbytes = TypeTraits<T>::bytes_required(capacity);
|
||||
RETURN_NOT_OK(data_->Resize(nbytes));
|
||||
// TODO(emkornfield) valgrind complains without this
|
||||
memset(data_->mutable_data(), 0, nbytes);
|
||||
|
||||
raw_data_ = reinterpret_cast<value_type*>(data_->mutable_data());
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status PrimitiveBuilder<T>::Resize(int32_t capacity) {
|
||||
// XXX: Set floor size for now
|
||||
if (capacity < kMinBuilderCapacity) { capacity = kMinBuilderCapacity; }
|
||||
|
||||
if (capacity_ == 0) {
|
||||
RETURN_NOT_OK(Init(capacity));
|
||||
} else {
|
||||
RETURN_NOT_OK(ArrayBuilder::Resize(capacity));
|
||||
const int64_t old_bytes = data_->size();
|
||||
const int64_t new_bytes = TypeTraits<T>::bytes_required(capacity);
|
||||
RETURN_NOT_OK(data_->Resize(new_bytes));
|
||||
raw_data_ = reinterpret_cast<value_type*>(data_->mutable_data());
|
||||
memset(data_->mutable_data() + old_bytes, 0, new_bytes - old_bytes);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status PrimitiveBuilder<T>::Append(
|
||||
const value_type* values, int32_t length, const uint8_t* valid_bytes) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
|
||||
if (length > 0) {
|
||||
memcpy(raw_data_ + length_, values, TypeTraits<T>::bytes_required(length));
|
||||
}
|
||||
|
||||
// length_ is update by these
|
||||
ArrayBuilder::UnsafeAppendToBitmap(valid_bytes, length);
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Status PrimitiveBuilder<T>::Finish(std::shared_ptr<Array>* out) {
|
||||
const int64_t bytes_required = TypeTraits<T>::bytes_required(length_);
|
||||
if (bytes_required > 0 && bytes_required < data_->size()) {
|
||||
// Trim buffers
|
||||
RETURN_NOT_OK(data_->Resize(bytes_required));
|
||||
}
|
||||
*out = std::make_shared<typename TypeTraits<T>::ArrayType>(
|
||||
type_, length_, data_, null_count_, null_bitmap_);
|
||||
|
||||
data_ = null_bitmap_ = nullptr;
|
||||
capacity_ = length_ = null_count_ = 0;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
template class PrimitiveBuilder<UInt8Type>;
|
||||
template class PrimitiveBuilder<UInt16Type>;
|
||||
template class PrimitiveBuilder<UInt32Type>;
|
||||
template class PrimitiveBuilder<UInt64Type>;
|
||||
template class PrimitiveBuilder<Int8Type>;
|
||||
template class PrimitiveBuilder<Int16Type>;
|
||||
template class PrimitiveBuilder<Int32Type>;
|
||||
template class PrimitiveBuilder<Int64Type>;
|
||||
template class PrimitiveBuilder<TimestampType>;
|
||||
template class PrimitiveBuilder<HalfFloatType>;
|
||||
template class PrimitiveBuilder<FloatType>;
|
||||
template class PrimitiveBuilder<DoubleType>;
|
||||
|
||||
Status BooleanBuilder::Init(int32_t capacity) {
|
||||
RETURN_NOT_OK(ArrayBuilder::Init(capacity));
|
||||
data_ = std::make_shared<PoolBuffer>(pool_);
|
||||
|
||||
int64_t nbytes = BitUtil::BytesForBits(capacity);
|
||||
RETURN_NOT_OK(data_->Resize(nbytes));
|
||||
// TODO(emkornfield) valgrind complains without this
|
||||
memset(data_->mutable_data(), 0, nbytes);
|
||||
|
||||
raw_data_ = reinterpret_cast<uint8_t*>(data_->mutable_data());
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status BooleanBuilder::Resize(int32_t capacity) {
|
||||
// XXX: Set floor size for now
|
||||
if (capacity < kMinBuilderCapacity) { capacity = kMinBuilderCapacity; }
|
||||
|
||||
if (capacity_ == 0) {
|
||||
RETURN_NOT_OK(Init(capacity));
|
||||
} else {
|
||||
RETURN_NOT_OK(ArrayBuilder::Resize(capacity));
|
||||
const int64_t old_bytes = data_->size();
|
||||
const int64_t new_bytes = BitUtil::BytesForBits(capacity);
|
||||
|
||||
RETURN_NOT_OK(data_->Resize(new_bytes));
|
||||
raw_data_ = reinterpret_cast<uint8_t*>(data_->mutable_data());
|
||||
memset(data_->mutable_data() + old_bytes, 0, new_bytes - old_bytes);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status BooleanBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
const int64_t bytes_required = BitUtil::BytesForBits(length_);
|
||||
|
||||
if (bytes_required > 0 && bytes_required < data_->size()) {
|
||||
// Trim buffers
|
||||
RETURN_NOT_OK(data_->Resize(bytes_required));
|
||||
}
|
||||
*out = std::make_shared<BooleanArray>(type_, length_, data_, null_count_, null_bitmap_);
|
||||
|
||||
data_ = null_bitmap_ = nullptr;
|
||||
capacity_ = length_ = null_count_ = 0;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status BooleanBuilder::Append(
|
||||
const uint8_t* values, int32_t length, const uint8_t* valid_bytes) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
// Skip reading from unitialised memory
|
||||
// TODO: This actually is only to keep valgrind happy but may or may not
|
||||
// have a performance impact.
|
||||
if ((valid_bytes != nullptr) && !valid_bytes[i]) continue;
|
||||
|
||||
if (values[i] > 0) {
|
||||
BitUtil::SetBit(raw_data_, length_ + i);
|
||||
} else {
|
||||
BitUtil::ClearBit(raw_data_, length_ + i);
|
||||
}
|
||||
}
|
||||
|
||||
// this updates length_
|
||||
ArrayBuilder::UnsafeAppendToBitmap(valid_bytes, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
BooleanArray::BooleanArray(int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count, const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: PrimitiveArray(
|
||||
std::make_shared<BooleanType>(), length, data, null_count, null_bitmap) {}
|
||||
|
||||
BooleanArray::BooleanArray(const TypePtr& type, int32_t length,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: PrimitiveArray(type, length, data, null_count, null_bitmap) {}
|
||||
|
||||
bool BooleanArray::EqualsExact(const BooleanArray& other) const {
|
||||
if (this == &other) return true;
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
if (null_count_ > 0) {
|
||||
bool equal_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::BytesForBits(length_));
|
||||
if (!equal_bitmap) { return false; }
|
||||
|
||||
const uint8_t* this_data = raw_data_;
|
||||
const uint8_t* other_data = other.raw_data_;
|
||||
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (!IsNull(i) && BitUtil::GetBit(this_data, i) != BitUtil::GetBit(other_data, i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return data_->Equals(*other.data_, BitUtil::BytesForBits(length_));
|
||||
}
|
||||
}
|
||||
|
||||
bool BooleanArray::Equals(const ArrayPtr& arr) const {
|
||||
if (this == arr.get()) return true;
|
||||
if (Type::BOOL != arr->type_enum()) { return false; }
|
||||
return EqualsExact(*static_cast<const BooleanArray*>(arr.get()));
|
||||
}
|
||||
|
||||
bool BooleanArray::RangeEquals(int32_t start_idx, int32_t end_idx,
|
||||
int32_t other_start_idx, const ArrayPtr& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<BooleanArray*>(arr.get());
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
const bool is_null = IsNull(i);
|
||||
if (is_null != arr->IsNull(o_i) || (!is_null && Value(i) != other->Value(o_i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Status BooleanArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
@@ -1,371 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#ifndef ARROW_TYPES_PRIMITIVE_H
|
||||
#define ARROW_TYPES_PRIMITIVE_H
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/type_fwd.h"
|
||||
#include "arrow/types/datetime.h"
|
||||
#include "arrow/util/bit-util.h"
|
||||
#include "arrow/util/buffer.h"
|
||||
#include "arrow/util/status.h"
|
||||
#include "arrow/util/visibility.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
class MemoryPool;
|
||||
|
||||
// Base class for fixed-size logical types. See MakePrimitiveArray
|
||||
// (types/construct.h) for constructing a specific subclass.
|
||||
class ARROW_EXPORT PrimitiveArray : public Array {
|
||||
public:
|
||||
virtual ~PrimitiveArray() {}
|
||||
|
||||
std::shared_ptr<Buffer> data() const { return data_; }
|
||||
|
||||
bool EqualsExact(const PrimitiveArray& other) const;
|
||||
bool Equals(const std::shared_ptr<Array>& arr) const override;
|
||||
|
||||
protected:
|
||||
PrimitiveArray(const TypePtr& type, int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
std::shared_ptr<Buffer> data_;
|
||||
const uint8_t* raw_data_;
|
||||
};
|
||||
|
||||
template <typename TYPE>
|
||||
class ARROW_EXPORT NumericArray : public PrimitiveArray {
|
||||
public:
|
||||
using TypeClass = TYPE;
|
||||
using value_type = typename TypeClass::c_type;
|
||||
NumericArray(int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr)
|
||||
: PrimitiveArray(
|
||||
std::make_shared<TypeClass>(), length, data, null_count, null_bitmap) {}
|
||||
NumericArray(const TypePtr& type, int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr)
|
||||
: PrimitiveArray(type, length, data, null_count, null_bitmap) {}
|
||||
|
||||
bool EqualsExact(const NumericArray<TypeClass>& other) const {
|
||||
return PrimitiveArray::EqualsExact(static_cast<const PrimitiveArray&>(other));
|
||||
}
|
||||
|
||||
bool ApproxEquals(const std::shared_ptr<Array>& arr) const { return Equals(arr); }
|
||||
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const ArrayPtr& arr) const override {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<NumericArray<TypeClass>*>(arr.get());
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
const bool is_null = IsNull(i);
|
||||
if (is_null != arr->IsNull(o_i) || (!is_null && Value(i) != other->Value(o_i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const value_type* raw_data() const {
|
||||
return reinterpret_cast<const value_type*>(raw_data_);
|
||||
}
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
value_type Value(int i) const { return raw_data()[i]; }
|
||||
};
|
||||
|
||||
template <>
|
||||
inline bool NumericArray<FloatType>::ApproxEquals(
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
|
||||
const auto& other = *static_cast<NumericArray<FloatType>*>(arr.get());
|
||||
|
||||
if (this == &other) { return true; }
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
auto this_data = reinterpret_cast<const float*>(raw_data_);
|
||||
auto other_data = reinterpret_cast<const float*>(other.raw_data_);
|
||||
|
||||
static constexpr float EPSILON = 1E-5;
|
||||
|
||||
if (length_ == 0 && other.length_ == 0) { return true; }
|
||||
|
||||
if (null_count_ > 0) {
|
||||
bool equal_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::CeilByte(length_) / 8);
|
||||
if (!equal_bitmap) { return false; }
|
||||
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (IsNull(i)) continue;
|
||||
if (fabs(this_data[i] - other_data[i]) > EPSILON) { return false; }
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (fabs(this_data[i] - other_data[i]) > EPSILON) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool NumericArray<DoubleType>::ApproxEquals(
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
|
||||
const auto& other = *static_cast<NumericArray<DoubleType>*>(arr.get());
|
||||
|
||||
if (this == &other) { return true; }
|
||||
if (null_count_ != other.null_count_) { return false; }
|
||||
|
||||
auto this_data = reinterpret_cast<const double*>(raw_data_);
|
||||
auto other_data = reinterpret_cast<const double*>(other.raw_data_);
|
||||
|
||||
if (length_ == 0 && other.length_ == 0) { return true; }
|
||||
|
||||
static constexpr double EPSILON = 1E-5;
|
||||
|
||||
if (null_count_ > 0) {
|
||||
bool equal_bitmap =
|
||||
null_bitmap_->Equals(*other.null_bitmap_, BitUtil::CeilByte(length_) / 8);
|
||||
if (!equal_bitmap) { return false; }
|
||||
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (IsNull(i)) continue;
|
||||
if (fabs(this_data[i] - other_data[i]) > EPSILON) { return false; }
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (fabs(this_data[i] - other_data[i]) > EPSILON) { return false; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
class ARROW_EXPORT PrimitiveBuilder : public ArrayBuilder {
|
||||
public:
|
||||
using value_type = typename Type::c_type;
|
||||
|
||||
explicit PrimitiveBuilder(MemoryPool* pool, const TypePtr& type)
|
||||
: ArrayBuilder(pool, type), data_(nullptr) {}
|
||||
|
||||
virtual ~PrimitiveBuilder() {}
|
||||
|
||||
using ArrayBuilder::Advance;
|
||||
|
||||
// Write nulls as uint8_t* (0 value indicates null) into pre-allocated memory
|
||||
Status AppendNulls(const uint8_t* valid_bytes, int32_t length) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
UnsafeAppendToBitmap(valid_bytes, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status AppendNull() {
|
||||
RETURN_NOT_OK(Reserve(1));
|
||||
UnsafeAppendToBitmap(false);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
std::shared_ptr<Buffer> data() const { return data_; }
|
||||
|
||||
// Vector append
|
||||
//
|
||||
// If passed, valid_bytes is of equal length to values, and any zero byte
|
||||
// will be considered as a null for that slot
|
||||
Status Append(
|
||||
const value_type* values, int32_t length, const uint8_t* valid_bytes = nullptr);
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
Status Init(int32_t capacity) override;
|
||||
|
||||
// Increase the capacity of the builder to accommodate at least the indicated
|
||||
// number of elements
|
||||
Status Resize(int32_t capacity) override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<PoolBuffer> data_;
|
||||
value_type* raw_data_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class ARROW_EXPORT NumericBuilder : public PrimitiveBuilder<T> {
|
||||
public:
|
||||
using typename PrimitiveBuilder<T>::value_type;
|
||||
using PrimitiveBuilder<T>::PrimitiveBuilder;
|
||||
|
||||
using PrimitiveBuilder<T>::Append;
|
||||
using PrimitiveBuilder<T>::Init;
|
||||
using PrimitiveBuilder<T>::Resize;
|
||||
using PrimitiveBuilder<T>::Reserve;
|
||||
|
||||
// Scalar append.
|
||||
Status Append(value_type val) {
|
||||
RETURN_NOT_OK(ArrayBuilder::Reserve(1));
|
||||
UnsafeAppend(val);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Does not capacity-check; make sure to call Reserve beforehand
|
||||
void UnsafeAppend(value_type val) {
|
||||
BitUtil::SetBit(null_bitmap_data_, length_);
|
||||
raw_data_[length_++] = val;
|
||||
}
|
||||
|
||||
protected:
|
||||
using PrimitiveBuilder<T>::length_;
|
||||
using PrimitiveBuilder<T>::null_bitmap_data_;
|
||||
using PrimitiveBuilder<T>::raw_data_;
|
||||
};
|
||||
|
||||
// Builders
|
||||
|
||||
using UInt8Builder = NumericBuilder<UInt8Type>;
|
||||
using UInt16Builder = NumericBuilder<UInt16Type>;
|
||||
using UInt32Builder = NumericBuilder<UInt32Type>;
|
||||
using UInt64Builder = NumericBuilder<UInt64Type>;
|
||||
|
||||
using Int8Builder = NumericBuilder<Int8Type>;
|
||||
using Int16Builder = NumericBuilder<Int16Type>;
|
||||
using Int32Builder = NumericBuilder<Int32Type>;
|
||||
using Int64Builder = NumericBuilder<Int64Type>;
|
||||
using TimestampBuilder = NumericBuilder<TimestampType>;
|
||||
|
||||
using HalfFloatBuilder = NumericBuilder<HalfFloatType>;
|
||||
using FloatBuilder = NumericBuilder<FloatType>;
|
||||
using DoubleBuilder = NumericBuilder<DoubleType>;
|
||||
|
||||
class ARROW_EXPORT BooleanArray : public PrimitiveArray {
|
||||
public:
|
||||
using TypeClass = BooleanType;
|
||||
|
||||
BooleanArray(int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
BooleanArray(const TypePtr& type, int32_t length, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count = 0, const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
|
||||
bool EqualsExact(const BooleanArray& other) const;
|
||||
bool Equals(const ArrayPtr& arr) const override;
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const ArrayPtr& arr) const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
const uint8_t* raw_data() const { return reinterpret_cast<const uint8_t*>(raw_data_); }
|
||||
|
||||
bool Value(int i) const { return BitUtil::GetBit(raw_data(), i); }
|
||||
};
|
||||
|
||||
class ARROW_EXPORT BooleanBuilder : public ArrayBuilder {
|
||||
public:
|
||||
explicit BooleanBuilder(MemoryPool* pool, const TypePtr& type)
|
||||
: ArrayBuilder(pool, type), data_(nullptr) {}
|
||||
|
||||
virtual ~BooleanBuilder() {}
|
||||
|
||||
using ArrayBuilder::Advance;
|
||||
|
||||
// Write nulls as uint8_t* (0 value indicates null) into pre-allocated memory
|
||||
Status AppendNulls(const uint8_t* valid_bytes, int32_t length) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
UnsafeAppendToBitmap(valid_bytes, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status AppendNull() {
|
||||
RETURN_NOT_OK(Reserve(1));
|
||||
UnsafeAppendToBitmap(false);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
std::shared_ptr<Buffer> data() const { return data_; }
|
||||
|
||||
// Scalar append
|
||||
Status Append(bool val) {
|
||||
Reserve(1);
|
||||
BitUtil::SetBit(null_bitmap_data_, length_);
|
||||
if (val) {
|
||||
BitUtil::SetBit(raw_data_, length_);
|
||||
} else {
|
||||
BitUtil::ClearBit(raw_data_, length_);
|
||||
}
|
||||
++length_;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Vector append
|
||||
//
|
||||
// If passed, valid_bytes is of equal length to values, and any zero byte
|
||||
// will be considered as a null for that slot
|
||||
Status Append(
|
||||
const uint8_t* values, int32_t length, const uint8_t* valid_bytes = nullptr);
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
Status Init(int32_t capacity) override;
|
||||
|
||||
// Increase the capacity of the builder to accommodate at least the indicated
|
||||
// number of elements
|
||||
Status Resize(int32_t capacity) override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<PoolBuffer> data_;
|
||||
uint8_t* raw_data_;
|
||||
};
|
||||
|
||||
// gcc and clang disagree about how to handle template visibility when you have
|
||||
// explicit specializations https://llvm.org/bugs/show_bug.cgi?id=24815
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wattributes"
|
||||
#endif
|
||||
|
||||
// Only instantiate these templates once
|
||||
extern template class ARROW_EXPORT NumericArray<Int8Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<UInt8Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<Int16Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<UInt16Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<Int32Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<UInt32Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<Int64Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<UInt64Type>;
|
||||
extern template class ARROW_EXPORT NumericArray<HalfFloatType>;
|
||||
extern template class ARROW_EXPORT NumericArray<FloatType>;
|
||||
extern template class ARROW_EXPORT NumericArray<DoubleType>;
|
||||
extern template class ARROW_EXPORT NumericArray<TimestampType>;
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_TYPES_PRIMITIVE_H
|
||||
@@ -1,150 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#include "arrow/types/string.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "arrow/type.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
static std::shared_ptr<DataType> kBinary = std::make_shared<BinaryType>();
|
||||
static std::shared_ptr<DataType> kString = std::make_shared<StringType>();
|
||||
|
||||
BinaryArray::BinaryArray(int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: BinaryArray(kBinary, length, offsets, data, null_count, null_bitmap) {}
|
||||
|
||||
BinaryArray::BinaryArray(const TypePtr& type, int32_t length,
|
||||
const std::shared_ptr<Buffer>& offsets, const std::shared_ptr<Buffer>& data,
|
||||
int32_t null_count, const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: Array(type, length, null_count, null_bitmap),
|
||||
offset_buffer_(offsets),
|
||||
offsets_(reinterpret_cast<const int32_t*>(offset_buffer_->data())),
|
||||
data_buffer_(data),
|
||||
data_(nullptr) {
|
||||
if (data_buffer_ != nullptr) { data_ = data_buffer_->data(); }
|
||||
}
|
||||
|
||||
Status BinaryArray::Validate() const {
|
||||
// TODO(wesm): what to do here?
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
bool BinaryArray::EqualsExact(const BinaryArray& other) const {
|
||||
if (!Array::EqualsExact(other)) { return false; }
|
||||
|
||||
bool equal_offsets =
|
||||
offset_buffer_->Equals(*other.offset_buffer_, (length_ + 1) * sizeof(int32_t));
|
||||
if (!equal_offsets) { return false; }
|
||||
|
||||
if (!data_buffer_ && !(other.data_buffer_)) { return true; }
|
||||
|
||||
return data_buffer_->Equals(*other.data_buffer_, data_buffer_->size());
|
||||
}
|
||||
|
||||
bool BinaryArray::Equals(const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
return EqualsExact(*static_cast<const BinaryArray*>(arr.get()));
|
||||
}
|
||||
|
||||
bool BinaryArray::RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<const BinaryArray*>(arr.get());
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
const bool is_null = IsNull(i);
|
||||
if (is_null != arr->IsNull(o_i)) { return false; }
|
||||
if (is_null) continue;
|
||||
const int32_t begin_offset = offset(i);
|
||||
const int32_t end_offset = offset(i + 1);
|
||||
const int32_t other_begin_offset = other->offset(o_i);
|
||||
const int32_t other_end_offset = other->offset(o_i + 1);
|
||||
// Underlying can't be equal if the size isn't equal
|
||||
if (end_offset - begin_offset != other_end_offset - other_begin_offset) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (std::memcmp(data_ + begin_offset, other->data_ + other_begin_offset,
|
||||
end_offset - begin_offset)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Status BinaryArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
StringArray::StringArray(int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count,
|
||||
const std::shared_ptr<Buffer>& null_bitmap)
|
||||
: BinaryArray(kString, length, offsets, data, null_count, null_bitmap) {}
|
||||
|
||||
Status StringArray::Validate() const {
|
||||
// TODO(emkornfield) Validate proper UTF8 code points?
|
||||
return BinaryArray::Validate();
|
||||
}
|
||||
|
||||
Status StringArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
// This used to be a static member variable of BinaryBuilder, but it can cause
|
||||
// valgrind to report a (spurious?) memory leak when needed in other shared
|
||||
// libraries. The problem came up while adding explicit visibility to libarrow
|
||||
// and libparquet_arrow
|
||||
static TypePtr kBinaryValueType = TypePtr(new UInt8Type());
|
||||
|
||||
BinaryBuilder::BinaryBuilder(MemoryPool* pool, const TypePtr& type)
|
||||
: ListBuilder(pool, std::make_shared<UInt8Builder>(pool, kBinaryValueType), type) {
|
||||
byte_builder_ = static_cast<UInt8Builder*>(value_builder_.get());
|
||||
}
|
||||
|
||||
Status BinaryBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
std::shared_ptr<Array> result;
|
||||
RETURN_NOT_OK(ListBuilder::Finish(&result));
|
||||
|
||||
const auto list = std::dynamic_pointer_cast<ListArray>(result);
|
||||
auto values = std::dynamic_pointer_cast<UInt8Array>(list->values());
|
||||
|
||||
*out = std::make_shared<BinaryArray>(list->length(), list->offsets(), values->data(),
|
||||
list->null_count(), list->null_bitmap());
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status StringBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
std::shared_ptr<Array> result;
|
||||
RETURN_NOT_OK(ListBuilder::Finish(&result));
|
||||
|
||||
const auto list = std::dynamic_pointer_cast<ListArray>(result);
|
||||
auto values = std::dynamic_pointer_cast<UInt8Array>(list->values());
|
||||
|
||||
*out = std::make_shared<StringArray>(list->length(), list->offsets(), values->data(),
|
||||
list->null_count(), list->null_bitmap());
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
@@ -1,149 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#ifndef ARROW_TYPES_STRING_H
|
||||
#define ARROW_TYPES_STRING_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/util/status.h"
|
||||
#include "arrow/util/visibility.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
class Buffer;
|
||||
class MemoryPool;
|
||||
|
||||
class ARROW_EXPORT BinaryArray : public Array {
|
||||
public:
|
||||
using TypeClass = BinaryType;
|
||||
|
||||
BinaryArray(int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count = 0,
|
||||
const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
|
||||
// Constructor that allows sub-classes/builders to propagate there logical type up the
|
||||
// class hierarchy.
|
||||
BinaryArray(const TypePtr& type, int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count = 0,
|
||||
const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
|
||||
// Return the pointer to the given elements bytes
|
||||
// TODO(emkornfield) introduce a StringPiece or something similar to capture zero-copy
|
||||
// pointer + offset
|
||||
const uint8_t* GetValue(int i, int32_t* out_length) const {
|
||||
DCHECK(out_length);
|
||||
const int32_t pos = offsets_[i];
|
||||
*out_length = offsets_[i + 1] - pos;
|
||||
return data_ + pos;
|
||||
}
|
||||
|
||||
std::shared_ptr<Buffer> data() const { return data_buffer_; }
|
||||
std::shared_ptr<Buffer> offsets() const { return offset_buffer_; }
|
||||
|
||||
const int32_t* raw_offsets() const { return offsets_; }
|
||||
|
||||
int32_t offset(int i) const { return offsets_[i]; }
|
||||
|
||||
// Neither of these functions will perform boundschecking
|
||||
int32_t value_offset(int i) const { return offsets_[i]; }
|
||||
int32_t value_length(int i) const { return offsets_[i + 1] - offsets_[i]; }
|
||||
|
||||
bool EqualsExact(const BinaryArray& other) const;
|
||||
bool Equals(const std::shared_ptr<Array>& arr) const override;
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const ArrayPtr& arr) const override;
|
||||
|
||||
Status Validate() const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Buffer> offset_buffer_;
|
||||
const int32_t* offsets_;
|
||||
|
||||
std::shared_ptr<Buffer> data_buffer_;
|
||||
const uint8_t* data_;
|
||||
};
|
||||
|
||||
class ARROW_EXPORT StringArray : public BinaryArray {
|
||||
public:
|
||||
using TypeClass = StringType;
|
||||
|
||||
StringArray(int32_t length, const std::shared_ptr<Buffer>& offsets,
|
||||
const std::shared_ptr<Buffer>& data, int32_t null_count = 0,
|
||||
const std::shared_ptr<Buffer>& null_bitmap = nullptr);
|
||||
|
||||
// Construct a std::string
|
||||
// TODO: std::bad_alloc possibility
|
||||
std::string GetString(int i) const {
|
||||
int32_t nchars;
|
||||
const uint8_t* str = GetValue(i, &nchars);
|
||||
return std::string(reinterpret_cast<const char*>(str), nchars);
|
||||
}
|
||||
|
||||
Status Validate() const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
};
|
||||
|
||||
// BinaryBuilder : public ListBuilder
|
||||
class ARROW_EXPORT BinaryBuilder : public ListBuilder {
|
||||
public:
|
||||
explicit BinaryBuilder(MemoryPool* pool, const TypePtr& type);
|
||||
virtual ~BinaryBuilder() {}
|
||||
|
||||
Status Append(const uint8_t* value, int32_t length) {
|
||||
RETURN_NOT_OK(ListBuilder::Append());
|
||||
return byte_builder_->Append(value, length);
|
||||
}
|
||||
|
||||
Status Append(const char* value, int32_t length) {
|
||||
return Append(reinterpret_cast<const uint8_t*>(value), length);
|
||||
}
|
||||
|
||||
Status Append(const std::string& value) { return Append(value.c_str(), value.size()); }
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
|
||||
protected:
|
||||
UInt8Builder* byte_builder_;
|
||||
};
|
||||
|
||||
// String builder
|
||||
class ARROW_EXPORT StringBuilder : public BinaryBuilder {
|
||||
public:
|
||||
explicit StringBuilder(MemoryPool* pool, const TypePtr& type)
|
||||
: BinaryBuilder(pool, type) {}
|
||||
|
||||
using BinaryBuilder::Append;
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
|
||||
Status Append(const std::vector<std::string>& values, uint8_t* null_bytes);
|
||||
};
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_TYPES_STRING_H
|
||||
@@ -1,108 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#include "arrow/types/struct.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace arrow {
|
||||
|
||||
bool StructArray::Equals(const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (this->type_enum() != arr->type_enum()) { return false; }
|
||||
if (null_count_ != arr->null_count()) { return false; }
|
||||
return RangeEquals(0, length_, 0, arr);
|
||||
}
|
||||
|
||||
bool StructArray::RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const std::shared_ptr<Array>& arr) const {
|
||||
if (this == arr.get()) { return true; }
|
||||
if (!arr) { return false; }
|
||||
if (Type::STRUCT != arr->type_enum()) { return false; }
|
||||
const auto other = static_cast<StructArray*>(arr.get());
|
||||
|
||||
bool equal_fields = true;
|
||||
for (int32_t i = start_idx, o_i = other_start_idx; i < end_idx; ++i, ++o_i) {
|
||||
if (IsNull(i) != arr->IsNull(o_i)) { return false; }
|
||||
if (IsNull(i)) continue;
|
||||
for (size_t j = 0; j < field_arrays_.size(); ++j) {
|
||||
// TODO: really we should be comparing stretches of non-null data rather
|
||||
// than looking at one value at a time.
|
||||
equal_fields = field(j)->RangeEquals(i, i + 1, o_i, other->field(j));
|
||||
if (!equal_fields) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Status StructArray::Validate() const {
|
||||
if (length_ < 0) { return Status::Invalid("Length was negative"); }
|
||||
|
||||
if (null_count() > length_) {
|
||||
return Status::Invalid("Null count exceeds the length of this struct");
|
||||
}
|
||||
|
||||
if (field_arrays_.size() > 0) {
|
||||
// Validate fields
|
||||
int32_t array_length = field_arrays_[0]->length();
|
||||
size_t idx = 0;
|
||||
for (auto it : field_arrays_) {
|
||||
if (it->length() != array_length) {
|
||||
std::stringstream ss;
|
||||
ss << "Length is not equal from field " << it->type()->ToString()
|
||||
<< " at position {" << idx << "}";
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
|
||||
const Status child_valid = it->Validate();
|
||||
if (!child_valid.ok()) {
|
||||
std::stringstream ss;
|
||||
ss << "Child array invalid: " << child_valid.ToString() << " at position {" << idx
|
||||
<< "}";
|
||||
return Status::Invalid(ss.str());
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
|
||||
if (array_length > 0 && array_length != length_) {
|
||||
return Status::Invalid("Struct's length is not equal to its child arrays");
|
||||
}
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status StructArray::Accept(ArrayVisitor* visitor) const {
|
||||
return visitor->Visit(*this);
|
||||
}
|
||||
|
||||
Status StructBuilder::Finish(std::shared_ptr<Array>* out) {
|
||||
std::vector<std::shared_ptr<Array>> fields(field_builders_.size());
|
||||
for (size_t i = 0; i < field_builders_.size(); ++i) {
|
||||
RETURN_NOT_OK(field_builders_[i]->Finish(&fields[i]));
|
||||
}
|
||||
|
||||
*out = std::make_shared<StructArray>(type_, length_, fields, null_count_, null_bitmap_);
|
||||
|
||||
null_bitmap_ = nullptr;
|
||||
capacity_ = length_ = null_count_ = 0;
|
||||
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
@@ -1,116 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#ifndef ARROW_TYPES_STRUCT_H
|
||||
#define ARROW_TYPES_STRUCT_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/types/list.h"
|
||||
#include "arrow/types/primitive.h"
|
||||
#include "arrow/util/visibility.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
class ARROW_EXPORT StructArray : public Array {
|
||||
public:
|
||||
using TypeClass = StructType;
|
||||
|
||||
StructArray(const TypePtr& type, int32_t length, std::vector<ArrayPtr>& field_arrays,
|
||||
int32_t null_count = 0, std::shared_ptr<Buffer> null_bitmap = nullptr)
|
||||
: Array(type, length, null_count, null_bitmap) {
|
||||
type_ = type;
|
||||
field_arrays_ = field_arrays;
|
||||
}
|
||||
|
||||
Status Validate() const override;
|
||||
|
||||
virtual ~StructArray() {}
|
||||
|
||||
// Return a shared pointer in case the requestor desires to share ownership
|
||||
// with this array.
|
||||
std::shared_ptr<Array> field(int32_t pos) const {
|
||||
DCHECK_GT(field_arrays_.size(), 0);
|
||||
return field_arrays_[pos];
|
||||
}
|
||||
const std::vector<ArrayPtr>& fields() const { return field_arrays_; }
|
||||
|
||||
bool EqualsExact(const StructArray& other) const;
|
||||
bool Equals(const std::shared_ptr<Array>& arr) const override;
|
||||
bool RangeEquals(int32_t start_idx, int32_t end_idx, int32_t other_start_idx,
|
||||
const std::shared_ptr<Array>& arr) const override;
|
||||
|
||||
Status Accept(ArrayVisitor* visitor) const override;
|
||||
|
||||
protected:
|
||||
// The child arrays corresponding to each field of the struct data type.
|
||||
std::vector<ArrayPtr> field_arrays_;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// StructArray builder
|
||||
// Append, Resize and Reserve methods are acting on StructBuilder.
|
||||
// Please make sure all these methods of all child-builders' are consistently
|
||||
// called to maintain data-structure consistency.
|
||||
class ARROW_EXPORT StructBuilder : public ArrayBuilder {
|
||||
public:
|
||||
StructBuilder(MemoryPool* pool, const std::shared_ptr<DataType>& type,
|
||||
const std::vector<std::shared_ptr<ArrayBuilder>>& field_builders)
|
||||
: ArrayBuilder(pool, type) {
|
||||
field_builders_ = field_builders;
|
||||
}
|
||||
|
||||
Status Finish(std::shared_ptr<Array>* out) override;
|
||||
|
||||
// Null bitmap is of equal length to every child field, and any zero byte
|
||||
// will be considered as a null for that field, but users must using app-
|
||||
// end methods or advance methods of the child builders' independently to
|
||||
// insert data.
|
||||
Status Append(int32_t length, const uint8_t* valid_bytes) {
|
||||
RETURN_NOT_OK(Reserve(length));
|
||||
UnsafeAppendToBitmap(valid_bytes, length);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
// Append an element to the Struct. All child-builders' Append method must
|
||||
// be called independently to maintain data-structure consistency.
|
||||
Status Append(bool is_valid = true) {
|
||||
RETURN_NOT_OK(Reserve(1));
|
||||
UnsafeAppendToBitmap(is_valid);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status AppendNull() { return Append(false); }
|
||||
|
||||
std::shared_ptr<ArrayBuilder> field_builder(int pos) const {
|
||||
DCHECK_GT(field_builders_.size(), 0);
|
||||
return field_builders_[pos];
|
||||
}
|
||||
const std::vector<std::shared_ptr<ArrayBuilder>>& field_builders() const {
|
||||
return field_builders_;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<std::shared_ptr<ArrayBuilder>> field_builders_;
|
||||
};
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_TYPES_STRUCT_H
|
||||
@@ -1,70 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#ifndef ARROW_TYPES_TEST_COMMON_H
|
||||
#define ARROW_TYPES_TEST_COMMON_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/builder.h"
|
||||
#include "arrow/test-util.h"
|
||||
#include "arrow/type.h"
|
||||
#include "arrow/util/memory-pool.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
class TestBuilder : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() {
|
||||
pool_ = default_memory_pool();
|
||||
type_ = TypePtr(new UInt8Type());
|
||||
builder_.reset(new UInt8Builder(pool_, type_));
|
||||
builder_nn_.reset(new UInt8Builder(pool_, type_));
|
||||
}
|
||||
|
||||
protected:
|
||||
MemoryPool* pool_;
|
||||
|
||||
TypePtr type_;
|
||||
unique_ptr<ArrayBuilder> builder_;
|
||||
unique_ptr<ArrayBuilder> builder_nn_;
|
||||
};
|
||||
|
||||
template <class T, class Builder>
|
||||
Status MakeArray(const std::vector<uint8_t>& valid_bytes, const std::vector<T>& values,
|
||||
int size, Builder* builder, ArrayPtr* out) {
|
||||
// Append the first 1000
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (valid_bytes[i] > 0) {
|
||||
RETURN_NOT_OK(builder->Append(values[i]));
|
||||
} else {
|
||||
RETURN_NOT_OK(builder->AppendNull());
|
||||
}
|
||||
}
|
||||
return builder->Finish(out);
|
||||
}
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_TYPES_TEST_COMMON_H
|
||||
@@ -1,27 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#include "arrow/types/union.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "arrow/type.h"
|
||||
|
||||
namespace arrow {} // namespace arrow
|
||||
@@ -1,48 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
#ifndef ARROW_TYPES_UNION_H
|
||||
#define ARROW_TYPES_UNION_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "arrow/array.h"
|
||||
#include "arrow/type.h"
|
||||
|
||||
namespace arrow {
|
||||
|
||||
class Buffer;
|
||||
|
||||
class UnionArray : public Array {
|
||||
protected:
|
||||
// The data are types encoded as int16
|
||||
Buffer* types_;
|
||||
std::vector<std::shared_ptr<Array>> children_;
|
||||
};
|
||||
|
||||
class DenseUnionArray : public UnionArray {
|
||||
protected:
|
||||
Buffer* offset_buf_;
|
||||
};
|
||||
|
||||
class SparseUnionArray : public UnionArray {};
|
||||
|
||||
} // namespace arrow
|
||||
|
||||
#endif // ARROW_TYPES_UNION_H
|
||||
Reference in new issue
Block a user