@@ -69,6 +69,12 @@ using arrow::Decimal128Type;
6969using arrow::Decimal256;
7070using arrow::Decimal256Array;
7171using arrow::Decimal256Type;
72+ using arrow::Decimal32;
73+ using arrow::Decimal32Array;
74+ using arrow::Decimal32Type;
75+ using arrow::Decimal64;
76+ using arrow::Decimal64Array;
77+ using arrow::Decimal64Type;
7278using arrow::Field;
7379using arrow::Int32Array;
7480using arrow::ListArray;
@@ -153,7 +159,8 @@ static Status FromInt32Statistics(const Int32Statistics& statistics,
153159 const LogicalType& logical_type,
154160 std::shared_ptr<::arrow::Scalar>* min,
155161 std::shared_ptr<::arrow::Scalar>* max) {
156- ARROW_ASSIGN_OR_RAISE (auto type, FromInt32 (logical_type));
162+ ARROW_ASSIGN_OR_RAISE (auto type,
163+ FromInt32 (logical_type, default_arrow_reader_properties ()));
157164
158165 switch (logical_type.type ()) {
159166 case LogicalType::Type::INT:
@@ -175,7 +182,8 @@ static Status FromInt64Statistics(const Int64Statistics& statistics,
175182 const LogicalType& logical_type,
176183 std::shared_ptr<::arrow::Scalar>* min,
177184 std::shared_ptr<::arrow::Scalar>* max) {
178- ARROW_ASSIGN_OR_RAISE (auto type, FromInt64 (logical_type));
185+ ARROW_ASSIGN_OR_RAISE (auto type,
186+ FromInt64 (logical_type, default_arrow_reader_properties ()));
179187
180188 switch (logical_type.type ()) {
181189 case LogicalType::Type::INT:
@@ -600,17 +608,10 @@ Status RawBytesToDecimalBytes(const uint8_t* value, int32_t byte_width,
600608 return ::arrow::Status::OK ();
601609}
602610
603- template <typename DecimalArrayType>
604- struct DecimalTypeTrait ;
605-
606- template <>
607- struct DecimalTypeTrait <::arrow::Decimal128Array> {
608- using value = ::arrow::Decimal128;
609- };
610-
611- template <>
612- struct DecimalTypeTrait <::arrow::Decimal256Array> {
613- using value = ::arrow::Decimal256;
611+ template <typename DecimalArrayType,
612+ typename = ::arrow::enable_if_decimal<typename DecimalArrayType::TypeClass>>
613+ struct DecimalTypeTrait {
614+ using value = typename ::arrow::TypeTraits<typename DecimalArrayType::TypeClass>::CType;
614615};
615616
616617template <typename DecimalArrayType, typename ParquetType>
@@ -725,16 +726,17 @@ struct DecimalConverter<DecimalArrayType, ByteArrayType> {
725726// / The parquet spec allows systems to write decimals in int32, int64 if the values are
726727// / small enough to fit in less 4 bytes or less than 8 bytes, respectively.
727728// / This function implements the conversion from int32 and int64 arrays to decimal arrays.
728- template <
729- typename DecimalArrayType, typename ParquetIntegerType,
730- typename = ::arrow::enable_if_t <std::is_same<ParquetIntegerType, Int32Type>::value ||
731- std::is_same<ParquetIntegerType, Int64Type>::value>>
729+ template <typename DecimalArrayType, typename ParquetIntegerType,
730+ typename = ::arrow::enable_if_t <::arrow::internal::IsOneOf<
731+ ParquetIntegerType, Int32Type, Int64Type>::value>>
732732static Status DecimalIntegerTransfer (RecordReader* reader, MemoryPool* pool,
733733 const std::shared_ptr<Field>& field, Datum* out) {
734- // Decimal128 and Decimal256 are only Arrow constructs. Parquet does not
735- // specifically distinguish between decimal byte widths.
736- DCHECK (field->type ()->id () == ::arrow::Type::DECIMAL128 ||
737- field->type ()->id () == ::arrow::Type::DECIMAL256);
734+ using ArrayTypeClass = typename DecimalArrayType::TypeClass;
735+ using DecimalValue = typename DecimalTypeTrait<DecimalArrayType>::value;
736+
737+ // Decimal32, Decimal64, Decimal128 and Decimal256 are only Arrow constructs. Parquet
738+ // does not specifically distinguish between decimal byte widths.
739+ DCHECK (field->type ()->id () == ArrayTypeClass::type_id);
738740
739741 const int64_t length = reader->values_written ();
740742
@@ -745,25 +747,17 @@ static Status DecimalIntegerTransfer(RecordReader* reader, MemoryPool* pool,
745747
746748 const auto values = reinterpret_cast <const ElementType*>(reader->values ());
747749
748- const auto & decimal_type = checked_cast<const ::arrow::DecimalType &>(*field->type ());
750+ const auto & decimal_type = checked_cast<const ArrayTypeClass &>(*field->type ());
749751 const int64_t type_length = decimal_type.byte_width ();
750752
751753 ARROW_ASSIGN_OR_RAISE (auto data, ::arrow::AllocateBuffer (length * type_length, pool));
752754 uint8_t * out_ptr = data->mutable_data ();
753755
754- using ::arrow::bit_util::FromLittleEndian;
755-
756756 for (int64_t i = 0 ; i < length; ++i, out_ptr += type_length) {
757757 // sign/zero extend int32_t values, otherwise a no-op
758758 const auto value = static_cast <int64_t >(values[i]);
759-
760- if constexpr (std::is_same_v<DecimalArrayType, Decimal128Array>) {
761- ::arrow::Decimal128 decimal (value);
762- decimal.ToBytes (out_ptr);
763- } else {
764- ::arrow::Decimal256 decimal (value);
765- decimal.ToBytes (out_ptr);
766- }
759+ DecimalValue decimal (value);
760+ decimal.ToBytes (out_ptr);
767761 }
768762
769763 if (reader->nullable_values () && field->nullable ()) {
@@ -802,6 +796,33 @@ Status TransferDecimal(RecordReader* reader, MemoryPool* pool,
802796 return Status::OK ();
803797}
804798
799+ template <typename DecimalArrayType, typename ... Args>
800+ Status TransferDecimalTo (Type::type physical_type, Args&&... args) {
801+ switch (physical_type) {
802+ case ::parquet::Type::INT32: {
803+ auto fn = DecimalIntegerTransfer<DecimalArrayType, Int32Type>;
804+ RETURN_NOT_OK (fn (std::forward<Args>(args)...));
805+ } break ;
806+ case ::parquet::Type::INT64: {
807+ auto fn = DecimalIntegerTransfer<DecimalArrayType, Int64Type>;
808+ RETURN_NOT_OK (fn (std::forward<Args>(args)...));
809+ } break ;
810+ case ::parquet::Type::BYTE_ARRAY: {
811+ auto fn = TransferDecimal<DecimalArrayType, ByteArrayType>;
812+ RETURN_NOT_OK (fn (std::forward<Args>(args)...));
813+ } break ;
814+ case ::parquet::Type::FIXED_LEN_BYTE_ARRAY: {
815+ auto fn = TransferDecimal<DecimalArrayType, FLBAType>;
816+ RETURN_NOT_OK (fn (std::forward<Args>(args)...));
817+ } break ;
818+ default :
819+ return Status::Invalid (
820+ " Physical type for decimal must be int32, int64, byte array, or fixed length "
821+ " binary" );
822+ }
823+ return Status::OK ();
824+ }
825+
805826Status TransferHalfFloat (RecordReader* reader, MemoryPool* pool,
806827 const std::shared_ptr<Field>& field, Datum* out) {
807828 static const auto binary_type = ::arrow::fixed_size_binary (2 );
@@ -902,55 +923,22 @@ Status TransferColumnData(RecordReader* reader,
902923 }
903924 RETURN_NOT_OK (TransferHalfFloat (reader, pool, value_field, &result));
904925 } break ;
926+ case ::arrow::Type::DECIMAL32: {
927+ RETURN_NOT_OK (TransferDecimalTo<Decimal32Array>(descr->physical_type (), reader,
928+ pool, value_field, &result));
929+ } break ;
930+ case ::arrow::Type::DECIMAL64: {
931+ RETURN_NOT_OK (TransferDecimalTo<Decimal64Array>(descr->physical_type (), reader,
932+ pool, value_field, &result));
933+ } break ;
905934 case ::arrow::Type::DECIMAL128: {
906- switch (descr->physical_type ()) {
907- case ::parquet::Type::INT32: {
908- auto fn = DecimalIntegerTransfer<Decimal128Array, Int32Type>;
909- RETURN_NOT_OK (fn (reader, pool, value_field, &result));
910- } break ;
911- case ::parquet::Type::INT64: {
912- auto fn = &DecimalIntegerTransfer<Decimal128Array, Int64Type>;
913- RETURN_NOT_OK (fn (reader, pool, value_field, &result));
914- } break ;
915- case ::parquet::Type::BYTE_ARRAY: {
916- auto fn = &TransferDecimal<Decimal128Array, ByteArrayType>;
917- RETURN_NOT_OK (fn (reader, pool, value_field, &result));
918- } break ;
919- case ::parquet::Type::FIXED_LEN_BYTE_ARRAY: {
920- auto fn = &TransferDecimal<Decimal128Array, FLBAType>;
921- RETURN_NOT_OK (fn (reader, pool, value_field, &result));
922- } break ;
923- default :
924- return Status::Invalid (
925- " Physical type for decimal128 must be int32, int64, byte array, or fixed "
926- " length binary" );
927- }
935+ RETURN_NOT_OK (TransferDecimalTo<Decimal128Array>(descr->physical_type (), reader,
936+ pool, value_field, &result));
937+ } break ;
938+ case ::arrow::Type::DECIMAL256: {
939+ RETURN_NOT_OK (TransferDecimalTo<Decimal256Array>(descr->physical_type (), reader,
940+ pool, value_field, &result));
928941 } break ;
929- case ::arrow::Type::DECIMAL256:
930- switch (descr->physical_type ()) {
931- case ::parquet::Type::INT32: {
932- auto fn = DecimalIntegerTransfer<Decimal256Array, Int32Type>;
933- RETURN_NOT_OK (fn (reader, pool, value_field, &result));
934- } break ;
935- case ::parquet::Type::INT64: {
936- auto fn = &DecimalIntegerTransfer<Decimal256Array, Int64Type>;
937- RETURN_NOT_OK (fn (reader, pool, value_field, &result));
938- } break ;
939- case ::parquet::Type::BYTE_ARRAY: {
940- auto fn = &TransferDecimal<Decimal256Array, ByteArrayType>;
941- RETURN_NOT_OK (fn (reader, pool, value_field, &result));
942- } break ;
943- case ::parquet::Type::FIXED_LEN_BYTE_ARRAY: {
944- auto fn = &TransferDecimal<Decimal256Array, FLBAType>;
945- RETURN_NOT_OK (fn (reader, pool, value_field, &result));
946- } break ;
947- default :
948- return Status::Invalid (
949- " Physical type for decimal256 must be int32, int64, byte array, or fixed "
950- " length binary" );
951- }
952- break ;
953-
954942 case ::arrow::Type::TIMESTAMP: {
955943 const ::arrow::TimestampType& timestamp_type =
956944 checked_cast<::arrow::TimestampType&>(*value_field->type ());
0 commit comments