From be649d68b452158d6cd92eefde2394500b4d65d0 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Fri, 1 Nov 2024 12:12:04 +0900 Subject: [PATCH] GH-44603: [GLib] Add Decimal64Array --- c_glib/arrow-glib/array-builder.cpp | 105 ++++++++++++++++++++++++++++ c_glib/arrow-glib/array-builder.h | 30 ++++++++ c_glib/arrow-glib/basic-array.cpp | 62 ++++++++++++++++ c_glib/arrow-glib/basic-array.h | 20 ++++++ c_glib/test/test-decimal64-array.rb | 37 ++++++++++ 5 files changed, 254 insertions(+) create mode 100644 c_glib/test/test-decimal64-array.rb diff --git a/c_glib/arrow-glib/array-builder.cpp b/c_glib/arrow-glib/array-builder.cpp index 1897562e13286..4f82ee2983b34 100644 --- a/c_glib/arrow-glib/array-builder.cpp +++ b/c_glib/arrow-glib/array-builder.cpp @@ -457,6 +457,9 @@ G_BEGIN_DECLS * #GArrowMapArrayBuilder is the class to create a new * #GArrowMapArray. * + * #GArrowDecimal64ArrayBuilder is the class to create a new + * #GArrowDecimal64Array. + * * #GArrowDecimal128ArrayBuilder is the class to create a new * #GArrowDecimal128Array. * @@ -6062,6 +6065,105 @@ garrow_map_array_builder_get_value_builder(GArrowMapArrayBuilder *builder) return priv->value_builder; } +G_DEFINE_TYPE(GArrowDecimal64ArrayBuilder, + garrow_decimal64_array_builder, + GARROW_TYPE_FIXED_SIZE_BINARY_ARRAY_BUILDER) + +static void +garrow_decimal64_array_builder_init(GArrowDecimal64ArrayBuilder *builder) +{ +} + +static void +garrow_decimal64_array_builder_class_init(GArrowDecimal64ArrayBuilderClass *klass) +{ +} + +/** + * garrow_decimal64_array_builder_new: + * @data_type: #GArrowDecimal64DataType for the decimal. + * + * Returns: A newly created #GArrowDecimal64ArrayBuilder. + * + * Since: 19.0.0 + */ +GArrowDecimal64ArrayBuilder * +garrow_decimal64_array_builder_new(GArrowDecimal64DataType *data_type) +{ + auto arrow_data_type = garrow_data_type_get_raw(GARROW_DATA_TYPE(data_type)); + auto builder = + garrow_array_builder_new(arrow_data_type, NULL, "[decimal64-array-builder][new]"); + return GARROW_DECIMAL64_ARRAY_BUILDER(builder); +} + +/** + * garrow_decimal64_array_builder_append_value: + * @builder: A #GArrowDecimal64ArrayBuilder. + * @value: (nullable): A decimal value. + * @error: (nullable): Return location for a #GError or %NULL. + * + * Returns: %TRUE on success, %FALSE if there was an error. + * + * Since: 19.0.0 + */ +gboolean +garrow_decimal64_array_builder_append_value(GArrowDecimal64ArrayBuilder *builder, + GArrowDecimal64 *value, + GError **error) +{ + if (value) { + auto arrow_decimal = garrow_decimal64_get_raw(value); + return garrow_array_builder_append_value( + GARROW_ARRAY_BUILDER(builder), + *arrow_decimal, + error, + "[decimal64-array-builder][append-value]"); + } else { + return garrow_array_builder_append_null(GARROW_ARRAY_BUILDER(builder), error); + } +} + +/** + * garrow_decimal64_array_builder_append_values: + * @builder: A #GArrowDecimal64ArrayBuilder. + * @values: (array length=values_length): The array of #GArrowDecimal64. + * @values_length: The length of @values. + * @is_valids: (nullable) (array length=is_valids_length): The array of + * boolean that shows whether the Nth value is valid or not. If the + * Nth @is_valids is %TRUE, the Nth @values is valid value. Otherwise + * the Nth value is null value. + * @is_valids_length: The length of @is_valids. + * @error: (nullable): Return location for a #GError or %NULL. + * + * Append multiple values at once. It's more efficient than multiple + * `append` and `append_null` calls. + * + * Returns: %TRUE on success, %FALSE if there was an error. + * + * Since: 19.0.0 + */ +gboolean +garrow_decimal64_array_builder_append_values(GArrowDecimal64ArrayBuilder *builder, + GArrowDecimal64 **values, + gint64 values_length, + const gboolean *is_valids, + gint64 is_valids_length, + GError **error) +{ + return garrow_array_builder_append_values( + GARROW_ARRAY_BUILDER(builder), + values, + values_length, + is_valids, + is_valids_length, + error, + "[decimal64-array-builder][append-values]", + [](guint8 *output, GArrowDecimal64 *value, gsize size) { + auto arrow_decimal = garrow_decimal64_get_raw(value); + arrow_decimal->ToBytes(output); + }); +} + G_DEFINE_TYPE(GArrowDecimal128ArrayBuilder, garrow_decimal128_array_builder, GARROW_TYPE_FIXED_SIZE_BINARY_ARRAY_BUILDER) @@ -6581,6 +6683,9 @@ garrow_array_builder_new_raw(std::shared_ptr *arrow_builder case arrow::Type::type::MAP: type = GARROW_TYPE_MAP_ARRAY_BUILDER; break; + case arrow::Type::type::DECIMAL64: + type = GARROW_TYPE_DECIMAL64_ARRAY_BUILDER; + break; case arrow::Type::type::DECIMAL128: type = GARROW_TYPE_DECIMAL128_ARRAY_BUILDER; break; diff --git a/c_glib/arrow-glib/array-builder.h b/c_glib/arrow-glib/array-builder.h index da9e8748ee387..f653ddb7781a3 100644 --- a/c_glib/arrow-glib/array-builder.h +++ b/c_glib/arrow-glib/array-builder.h @@ -1729,6 +1729,36 @@ GARROW_AVAILABLE_IN_0_17 GArrowArrayBuilder * garrow_map_array_builder_get_value_builder(GArrowMapArrayBuilder *builder); +#define GARROW_TYPE_DECIMAL64_ARRAY_BUILDER (garrow_decimal64_array_builder_get_type()) +GARROW_AVAILABLE_IN_19_0 +G_DECLARE_DERIVABLE_TYPE(GArrowDecimal64ArrayBuilder, + garrow_decimal64_array_builder, + GARROW, + DECIMAL64_ARRAY_BUILDER, + GArrowFixedSizeBinaryArrayBuilder) +struct _GArrowDecimal64ArrayBuilderClass +{ + GArrowFixedSizeBinaryArrayBuilderClass parent_class; +}; + +GARROW_AVAILABLE_IN_19_0 +GArrowDecimal64ArrayBuilder * +garrow_decimal64_array_builder_new(GArrowDecimal64DataType *data_type); + +GARROW_AVAILABLE_IN_19_0 +gboolean +garrow_decimal64_array_builder_append_value(GArrowDecimal64ArrayBuilder *builder, + GArrowDecimal64 *value, + GError **error); +GARROW_AVAILABLE_IN_19_0 +gboolean +garrow_decimal64_array_builder_append_values(GArrowDecimal64ArrayBuilder *builder, + GArrowDecimal64 **values, + gint64 values_length, + const gboolean *is_valids, + gint64 is_valids_length, + GError **error); + #define GARROW_TYPE_DECIMAL128_ARRAY_BUILDER (garrow_decimal128_array_builder_get_type()) GARROW_AVAILABLE_IN_ALL G_DECLARE_DERIVABLE_TYPE(GArrowDecimal128ArrayBuilder, diff --git a/c_glib/arrow-glib/basic-array.cpp b/c_glib/arrow-glib/basic-array.cpp index f102a252467a3..8c39715c384f0 100644 --- a/c_glib/arrow-glib/basic-array.cpp +++ b/c_glib/arrow-glib/basic-array.cpp @@ -171,6 +171,11 @@ G_BEGIN_DECLS * have Arrow format data, you need to use #GArrowMonthDayNanoIntervalArray * to create a new array. * + * #GArrowDecimal64Array is a class for 64-bit decimal array. It can + * store zero or more 64-bit decimal data. If you don't have Arrow + * format data, you need to use #GArrowDecimal64ArrayBuilder to + * create a new array. + * * #GArrowDecimal128Array is a class for 128-bit decimal array. It can * store zero or more 128-bit decimal data. If you don't have Arrow * format data, you need to use #GArrowDecimal128ArrayBuilder to @@ -3090,6 +3095,60 @@ garrow_fixed_size_binary_array_get_values_bytes(GArrowFixedSizeBinaryArray *arra arrow_binary_array->byte_width() * arrow_array->length()); } +G_DEFINE_TYPE(GArrowDecimal64Array, + garrow_decimal64_array, + GARROW_TYPE_FIXED_SIZE_BINARY_ARRAY) +static void +garrow_decimal64_array_init(GArrowDecimal64Array *object) +{ +} + +static void +garrow_decimal64_array_class_init(GArrowDecimal64ArrayClass *klass) +{ +} + +/** + * garrow_decimal64_array_format_value: + * @array: A #GArrowDecimal64Array. + * @i: The index of the target value. + * + * Returns: (transfer full): The formatted @i-th value. + * + * It should be freed with g_free() when no longer needed. + * + * Since: 19.0.0 + */ +gchar * +garrow_decimal64_array_format_value(GArrowDecimal64Array *array, gint64 i) +{ + auto arrow_array = garrow_array_get_raw(GARROW_ARRAY(array)); + auto arrow_decimal64_array = + std::static_pointer_cast(arrow_array); + auto value = arrow_decimal64_array->FormatValue(i); + return g_strndup(value.data(), value.size()); +} + +/** + * garrow_decimal64_array_get_value: + * @array: A #GArrowDecimal64Array. + * @i: The index of the target value. + * + * Returns: (transfer full): The @i-th value. + * + * Since: 19.0.0 + */ +GArrowDecimal64 * +garrow_decimal64_array_get_value(GArrowDecimal64Array *array, gint64 i) +{ + auto arrow_array = garrow_array_get_raw(GARROW_ARRAY(array)); + auto arrow_decimal64_array = + std::static_pointer_cast(arrow_array); + auto arrow_decimal64 = + std::make_shared(arrow_decimal64_array->GetValue(i)); + return garrow_decimal64_new_raw(&arrow_decimal64); +} + G_DEFINE_TYPE(GArrowDecimal128Array, garrow_decimal128_array, GARROW_TYPE_FIXED_SIZE_BINARY_ARRAY) @@ -3443,6 +3502,9 @@ garrow_array_new_raw_valist(std::shared_ptr *arrow_array, case arrow::Type::type::DICTIONARY: type = GARROW_TYPE_DICTIONARY_ARRAY; break; + case arrow::Type::type::DECIMAL64: + type = GARROW_TYPE_DECIMAL64_ARRAY; + break; case arrow::Type::type::DECIMAL128: type = GARROW_TYPE_DECIMAL128_ARRAY; break; diff --git a/c_glib/arrow-glib/basic-array.h b/c_glib/arrow-glib/basic-array.h index 95679aa37c57a..f70cf114a4a96 100644 --- a/c_glib/arrow-glib/basic-array.h +++ b/c_glib/arrow-glib/basic-array.h @@ -810,6 +810,26 @@ GARROW_AVAILABLE_IN_3_0 GBytes * garrow_fixed_size_binary_array_get_values_bytes(GArrowFixedSizeBinaryArray *array); +#define GARROW_TYPE_DECIMAL64_ARRAY (garrow_decimal64_array_get_type()) +GARROW_AVAILABLE_IN_19_0 +G_DECLARE_DERIVABLE_TYPE(GArrowDecimal64Array, + garrow_decimal64_array, + GARROW, + DECIMAL64_ARRAY, + GArrowFixedSizeBinaryArray) +struct _GArrowDecimal64ArrayClass +{ + GArrowFixedSizeBinaryArrayClass parent_class; +}; + +GARROW_AVAILABLE_IN_19_0 +gchar * +garrow_decimal64_array_format_value(GArrowDecimal64Array *array, gint64 i); + +GARROW_AVAILABLE_IN_19_0 +GArrowDecimal64 * +garrow_decimal64_array_get_value(GArrowDecimal64Array *array, gint64 i); + #define GARROW_TYPE_DECIMAL128_ARRAY (garrow_decimal128_array_get_type()) GARROW_AVAILABLE_IN_ALL G_DECLARE_DERIVABLE_TYPE(GArrowDecimal128Array, diff --git a/c_glib/test/test-decimal64-array.rb b/c_glib/test/test-decimal64-array.rb new file mode 100644 index 0000000000000..ab7b9e2523481 --- /dev/null +++ b/c_glib/test/test-decimal64-array.rb @@ -0,0 +1,37 @@ +# 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. + +class TestDecimal64Array < Test::Unit::TestCase + def test_format_value + data_type = Arrow::Decimal64DataType.new(8, 2) + builder = Arrow::Decimal64ArrayBuilder.new(data_type) + decimal = Arrow::Decimal64.new("23423445") + builder.append_value(decimal) + array = builder.finish + assert_equal("234234.45", array.format_value(0)) + end + + def test_value + data_type = Arrow::Decimal64DataType.new(8, 2) + builder = Arrow::Decimal64ArrayBuilder.new(data_type) + decimal = Arrow::Decimal64.new("23423445") + builder.append_value(decimal) + array = builder.finish + assert_equal("234234.45", + array.get_value(0).to_string_scale(array.value_data_type.scale)) + end +end