From 5b68eca6cb7ec167cb55d7bdfd6be1850ece963c Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Thu, 31 Oct 2024 07:05:38 +0900 Subject: [PATCH] GH-44392: [GLib] Add GArrowDecimal32DataType (#44580) ### Rationale for this change `arrow::Decimal32Type` data type has been introduced. It is also necessary to support the same data type in GLib. ### What changes are included in this PR? This PR implements `GArrowDecimal32DataType`. ### Are these changes tested? YES ### Are there any user-facing changes? Before this change `garrow_decimal_data_type_new()` returns `GArrowDecimal64DataType` if the precision is less than `garrow_decimal64_data_type_max_precision()`. After this change, it returns `GArrowDecimal32DataType` if the precision is less than garrow_decimal32_data_type_max_precision(). * GitHub Issue: #44392 Authored-by: Hiroyuki Sato Signed-off-by: Sutou Kouhei --- c_glib/arrow-glib/basic-data-type.cpp | 68 +++++++++++++++++++++++-- c_glib/arrow-glib/basic-data-type.h | 20 ++++++++ c_glib/arrow-glib/type.cpp | 2 + c_glib/arrow-glib/type.h | 6 ++- c_glib/test/test-decimal32-data-type.rb | 54 ++++++++++++++++++++ 5 files changed, 144 insertions(+), 6 deletions(-) create mode 100644 c_glib/test/test-decimal32-data-type.rb diff --git a/c_glib/arrow-glib/basic-data-type.cpp b/c_glib/arrow-glib/basic-data-type.cpp index b2bd99e0f228d..ecb537aa1f905 100644 --- a/c_glib/arrow-glib/basic-data-type.cpp +++ b/c_glib/arrow-glib/basic-data-type.cpp @@ -114,6 +114,8 @@ G_BEGIN_DECLS * * #GArrowDecimalDataType is a base class for the decimal data types. * + * #GArrowDecimal32DataType is a class for the 32-bit decimal data type. + * * #GArrowDecimal64DataType is a class for the 64-bit decimal data type. * * #GArrowDecimal128DataType is a class for the 128-bit decimal data type. @@ -1493,16 +1495,20 @@ garrow_decimal_data_type_class_init(GArrowDecimalDataTypeClass *klass) * Returns: (nullable): * The newly created decimal data type on success, %NULL on error. * - * #GArrowDecimal256DataType is used if @precision is larger than - * garrow_decimal128_data_type_max_precision(), - * #GArrowDecimal128DataType is used otherwise. + * * #GArrowDecimal32DataType is used if @precision up to 9 + * * #GArrowDecimal64DataType is used if @precision up to 19 + * * #GArrowDecimal128DataType is used if @precision up to 38 + * * #GArrowDecimal256DataType is used otherwise * * Since: 0.10.0 */ GArrowDecimalDataType * garrow_decimal_data_type_new(gint32 precision, gint32 scale, GError **error) { - if (precision <= garrow_decimal64_data_type_max_precision()) { + if (precision <= garrow_decimal32_data_type_max_precision()) { + return GARROW_DECIMAL_DATA_TYPE( + garrow_decimal32_data_type_new(precision, scale, error)); + } else if (precision <= garrow_decimal64_data_type_max_precision()) { return GARROW_DECIMAL_DATA_TYPE( garrow_decimal64_data_type_new(precision, scale, error)); } else if (precision <= garrow_decimal128_data_type_max_precision()) { @@ -1550,6 +1556,57 @@ garrow_decimal_data_type_get_scale(GArrowDecimalDataType *decimal_data_type) return arrow_decimal_type->scale(); } +G_DEFINE_TYPE(GArrowDecimal32DataType, + garrow_decimal32_data_type, + GARROW_TYPE_DECIMAL_DATA_TYPE) + +static void +garrow_decimal32_data_type_init(GArrowDecimal32DataType *object) +{ +} + +static void +garrow_decimal32_data_type_class_init(GArrowDecimal32DataTypeClass *klass) +{ +} + +/** + * garrow_decimal32_data_type_max_precision: + * + * Returns: The max precision of 32-bit decimal data type. + * + * Since: 19.0.0 + */ +gint32 +garrow_decimal32_data_type_max_precision() +{ + return arrow::Decimal32Type::kMaxPrecision; +} + +/** + * garrow_decimal32_data_type_new: + * @precision: The precision of decimal data. + * @scale: The scale of decimal data. + * @error: (nullable): Return location for a #GError or %NULL. + * + * Returns: (nullable): + * The newly created 32-bit decimal data type on success, %NULL on error. + * + * Since: 19.0.0 + */ +GArrowDecimal32DataType * +garrow_decimal32_data_type_new(gint32 precision, gint32 scale, GError **error) +{ + auto arrow_data_type_result = arrow::Decimal32Type::Make(precision, scale); + if (garrow::check(error, arrow_data_type_result, "[decimal32-data-type][new]")) { + auto arrow_data_type = *arrow_data_type_result; + return GARROW_DECIMAL32_DATA_TYPE( + g_object_new(GARROW_TYPE_DECIMAL32_DATA_TYPE, "data-type", &arrow_data_type, NULL)); + } else { + return NULL; + } +} + G_DEFINE_TYPE(GArrowDecimal64DataType, garrow_decimal64_data_type, GARROW_TYPE_DECIMAL_DATA_TYPE) @@ -2249,6 +2306,9 @@ garrow_data_type_new_raw(std::shared_ptr *arrow_data_type) case arrow::Type::type::MAP: type = GARROW_TYPE_MAP_DATA_TYPE; break; + case arrow::Type::type::DECIMAL32: + type = GARROW_TYPE_DECIMAL32_DATA_TYPE; + break; case arrow::Type::type::DECIMAL64: type = GARROW_TYPE_DECIMAL64_DATA_TYPE; break; diff --git a/c_glib/arrow-glib/basic-data-type.h b/c_glib/arrow-glib/basic-data-type.h index 1a677a6e45ff4..edbe15e2df521 100644 --- a/c_glib/arrow-glib/basic-data-type.h +++ b/c_glib/arrow-glib/basic-data-type.h @@ -608,6 +608,26 @@ GARROW_AVAILABLE_IN_ALL gint32 garrow_decimal_data_type_get_scale(GArrowDecimalDataType *decimal_data_type); +#define GARROW_TYPE_DECIMAL32_DATA_TYPE (garrow_decimal32_data_type_get_type()) +GARROW_AVAILABLE_IN_19_0 +G_DECLARE_DERIVABLE_TYPE(GArrowDecimal32DataType, + garrow_decimal32_data_type, + GARROW, + DECIMAL32_DATA_TYPE, + GArrowDecimalDataType) +struct _GArrowDecimal32DataTypeClass +{ + GArrowDecimalDataTypeClass parent_class; +}; + +GARROW_AVAILABLE_IN_19_0 +gint32 +garrow_decimal32_data_type_max_precision(); + +GARROW_AVAILABLE_IN_19_0 +GArrowDecimal32DataType * +garrow_decimal32_data_type_new(gint32 precision, gint32 scale, GError **error); + #define GARROW_TYPE_DECIMAL64_DATA_TYPE (garrow_decimal64_data_type_get_type()) GARROW_AVAILABLE_IN_19_0 G_DECLARE_DERIVABLE_TYPE(GArrowDecimal64DataType, diff --git a/c_glib/arrow-glib/type.cpp b/c_glib/arrow-glib/type.cpp index c4c0748357673..26d21f6d82587 100644 --- a/c_glib/arrow-glib/type.cpp +++ b/c_glib/arrow-glib/type.cpp @@ -78,6 +78,8 @@ garrow_type_from_raw(arrow::Type::type type) return GARROW_TYPE_MONTH_INTERVAL; case arrow::Type::type::INTERVAL_DAY_TIME: return GARROW_TYPE_DAY_TIME_INTERVAL; + case arrow::Type::type::DECIMAL32: + return GARROW_TYPE_DECIMAL32; case arrow::Type::type::DECIMAL64: return GARROW_TYPE_DECIMAL64; case arrow::Type::type::DECIMAL128: diff --git a/c_glib/arrow-glib/type.h b/c_glib/arrow-glib/type.h index 3c7c2d5aa4c2b..a817da4b9413e 100644 --- a/c_glib/arrow-glib/type.h +++ b/c_glib/arrow-glib/type.h @@ -70,6 +70,7 @@ G_BEGIN_DECLS * @GARROW_TYPE_LARGE_LIST: A list of some logical data type with 64-bit offsets. * @GARROW_TYPE_MONTH_DAY_NANO_INTERVAL: MONTH_DAY_NANO interval in SQL style. * @GARROW_TYPE_RUN_END_ENCODED: Run-end encoded data. + * @GARROW_TYPE_DECIMAL32: Precision- and scale-based decimal * @GARROW_TYPE_DECIMAL64: Precision- and scale-based decimal * type with 64-bit. Storage type depends on the parameters. * @@ -115,8 +116,9 @@ typedef enum { GARROW_TYPE_LARGE_LIST, GARROW_TYPE_MONTH_DAY_NANO_INTERVAL, GARROW_TYPE_RUN_END_ENCODED, - /* TODO: Remove = 44 when we add STRING_VIEW..DECIMAL32. */ - GARROW_TYPE_DECIMAL64 = 44, + /* TODO: Remove = 43 when we add STRING_VIEW(39)..LARGE_LIST_VIEW(42). */ + GARROW_TYPE_DECIMAL32 = 43, + GARROW_TYPE_DECIMAL64, } GArrowType; /** diff --git a/c_glib/test/test-decimal32-data-type.rb b/c_glib/test/test-decimal32-data-type.rb new file mode 100644 index 0000000000000..f0f3778326b2b --- /dev/null +++ b/c_glib/test/test-decimal32-data-type.rb @@ -0,0 +1,54 @@ +# 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 TestDecimal32DataType < Test::Unit::TestCase + def test_type + data_type = Arrow::Decimal32DataType.new(2, 0) + assert_equal(Arrow::Type::DECIMAL32, data_type.id) + end + + def test_name + data_type = Arrow::Decimal32DataType.new(2, 0) + assert_equal("decimal32", data_type.name) + end + + def test_to_s + data_type = Arrow::Decimal32DataType.new(2, 0) + assert_equal("decimal32(2, 0)", data_type.to_s) + end + + def test_precision + data_type = Arrow::Decimal32DataType.new(8, 2) + assert_equal(8, data_type.precision) + end + + def test_scale + data_type = Arrow::Decimal32DataType.new(8, 2) + assert_equal(2, data_type.scale) + end + + def test_decimal_data_type_new + assert_equal(Arrow::Decimal32DataType.new(3, 2), + Arrow::DecimalDataType.new(3, 2)) + end + + def test_invalid_precision + assert_raise(Arrow::Error::Invalid) do + Arrow::Decimal32DataType.new(10, 1) + end + end +end