Skip to content

Commit

Permalink
GH-44604: [GLib] Add Decimal32Array (#44617)
Browse files Browse the repository at this point in the history
### Rationale for this change

The `arrow::Decimal32Array` has been released.
The `GArrowDecimal32Array` class must be implemented in the GLib.

### What changes are included in this PR?

* Implement `GArrowDecimal32Array`
* Implement `GArrowDecimal32ArrayBuilder`

### Are these changes tested?

YES

### Are there any user-facing changes?

NO

* GitHub Issue: #44604

Authored-by: Hiroyuki Sato <[email protected]>
Signed-off-by: Sutou Kouhei <[email protected]>
  • Loading branch information
hiroyuki-sato authored Nov 2, 2024
1 parent 2312eff commit abda57c
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 0 deletions.
105 changes: 105 additions & 0 deletions c_glib/arrow-glib/array-builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,9 @@ G_BEGIN_DECLS
* #GArrowMapArrayBuilder is the class to create a new
* #GArrowMapArray.
*
* #GArrowDecimal32ArrayBuilder is the class to create a new
* #GArrowDecimal32Array.
*
* #GArrowDecimal64ArrayBuilder is the class to create a new
* #GArrowDecimal64Array.
*
Expand Down Expand Up @@ -6065,6 +6068,105 @@ garrow_map_array_builder_get_value_builder(GArrowMapArrayBuilder *builder)
return priv->value_builder;
}

G_DEFINE_TYPE(GArrowDecimal32ArrayBuilder,
garrow_decimal32_array_builder,
GARROW_TYPE_FIXED_SIZE_BINARY_ARRAY_BUILDER)

static void
garrow_decimal32_array_builder_init(GArrowDecimal32ArrayBuilder *builder)
{
}

static void
garrow_decimal32_array_builder_class_init(GArrowDecimal32ArrayBuilderClass *klass)
{
}

/**
* garrow_decimal32_array_builder_new:
* @data_type: #GArrowDecimal32DataType for the decimal.
*
* Returns: A newly created #GArrowDecimal32ArrayBuilder.
*
* Since: 19.0.0
*/
GArrowDecimal32ArrayBuilder *
garrow_decimal32_array_builder_new(GArrowDecimal32DataType *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, "[decimal32-array-builder][new]");
return GARROW_DECIMAL32_ARRAY_BUILDER(builder);
}

/**
* garrow_decimal32_array_builder_append_value:
* @builder: A #GArrowDecimal32ArrayBuilder.
* @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_decimal32_array_builder_append_value(GArrowDecimal32ArrayBuilder *builder,
GArrowDecimal32 *value,
GError **error)
{
if (value) {
auto arrow_decimal = garrow_decimal32_get_raw(value);
return garrow_array_builder_append_value<arrow::Decimal32Builder>(
GARROW_ARRAY_BUILDER(builder),
*arrow_decimal,
error,
"[decimal32-array-builder][append-value]");
} else {
return garrow_array_builder_append_null(GARROW_ARRAY_BUILDER(builder), error);
}
}

/**
* garrow_decimal32_array_builder_append_values:
* @builder: A #GArrowDecimal32ArrayBuilder.
* @values: (array length=values_length): The array of #GArrowDecimal32.
* @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_decimal32_array_builder_append_values(GArrowDecimal32ArrayBuilder *builder,
GArrowDecimal32 **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,
"[decimal32-array-builder][append-values]",
[](guint8 *output, GArrowDecimal32 *value, gsize size) {
auto arrow_decimal = garrow_decimal32_get_raw(value);
arrow_decimal->ToBytes(output);
});
}

G_DEFINE_TYPE(GArrowDecimal64ArrayBuilder,
garrow_decimal64_array_builder,
GARROW_TYPE_FIXED_SIZE_BINARY_ARRAY_BUILDER)
Expand Down Expand Up @@ -6683,6 +6785,9 @@ garrow_array_builder_new_raw(std::shared_ptr<arrow::ArrayBuilder> *arrow_builder
case arrow::Type::type::MAP:
type = GARROW_TYPE_MAP_ARRAY_BUILDER;
break;
case arrow::Type::type::DECIMAL32:
type = GARROW_TYPE_DECIMAL32_ARRAY_BUILDER;
break;
case arrow::Type::type::DECIMAL64:
type = GARROW_TYPE_DECIMAL64_ARRAY_BUILDER;
break;
Expand Down
30 changes: 30 additions & 0 deletions c_glib/arrow-glib/array-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1729,6 +1729,36 @@ GARROW_AVAILABLE_IN_0_17
GArrowArrayBuilder *
garrow_map_array_builder_get_value_builder(GArrowMapArrayBuilder *builder);

#define GARROW_TYPE_DECIMAL32_ARRAY_BUILDER (garrow_decimal32_array_builder_get_type())
GARROW_AVAILABLE_IN_19_0
G_DECLARE_DERIVABLE_TYPE(GArrowDecimal32ArrayBuilder,
garrow_decimal32_array_builder,
GARROW,
DECIMAL32_ARRAY_BUILDER,
GArrowFixedSizeBinaryArrayBuilder)
struct _GArrowDecimal32ArrayBuilderClass
{
GArrowFixedSizeBinaryArrayBuilderClass parent_class;
};

GARROW_AVAILABLE_IN_19_0
GArrowDecimal32ArrayBuilder *
garrow_decimal32_array_builder_new(GArrowDecimal32DataType *data_type);

GARROW_AVAILABLE_IN_19_0
gboolean
garrow_decimal32_array_builder_append_value(GArrowDecimal32ArrayBuilder *builder,
GArrowDecimal32 *value,
GError **error);
GARROW_AVAILABLE_IN_19_0
gboolean
garrow_decimal32_array_builder_append_values(GArrowDecimal32ArrayBuilder *builder,
GArrowDecimal32 **values,
gint64 values_length,
const gboolean *is_valids,
gint64 is_valids_length,
GError **error);

#define GARROW_TYPE_DECIMAL64_ARRAY_BUILDER (garrow_decimal64_array_builder_get_type())
GARROW_AVAILABLE_IN_19_0
G_DECLARE_DERIVABLE_TYPE(GArrowDecimal64ArrayBuilder,
Expand Down
62 changes: 62 additions & 0 deletions c_glib/arrow-glib/basic-array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,11 @@ G_BEGIN_DECLS
* have Arrow format data, you need to use #GArrowMonthDayNanoIntervalArray
* to create a new array.
*
* #GArrowDecimal32Array is a class for 32-bit decimal array. It can
* store zero or more 32-bit decimal data. If you don't have Arrow
* format data, you need to use #GArrowDecimal32ArrayBuilder 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
Expand Down Expand Up @@ -3095,6 +3100,60 @@ garrow_fixed_size_binary_array_get_values_bytes(GArrowFixedSizeBinaryArray *arra
arrow_binary_array->byte_width() * arrow_array->length());
}

G_DEFINE_TYPE(GArrowDecimal32Array,
garrow_decimal32_array,
GARROW_TYPE_FIXED_SIZE_BINARY_ARRAY)
static void
garrow_decimal32_array_init(GArrowDecimal32Array *object)
{
}

static void
garrow_decimal32_array_class_init(GArrowDecimal32ArrayClass *klass)
{
}

/**
* garrow_decimal32_array_format_value:
* @array: A #GArrowDecimal32Array.
* @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_decimal32_array_format_value(GArrowDecimal32Array *array, gint64 i)
{
auto arrow_array = garrow_array_get_raw(GARROW_ARRAY(array));
auto arrow_decimal32_array =
std::static_pointer_cast<arrow::Decimal32Array>(arrow_array);
auto value = arrow_decimal32_array->FormatValue(i);
return g_strndup(value.data(), value.size());
}

/**
* garrow_decimal32_array_get_value:
* @array: A #GArrowDecimal32Array.
* @i: The index of the target value.
*
* Returns: (transfer full): The @i-th value.
*
* Since: 19.0.0
*/
GArrowDecimal32 *
garrow_decimal32_array_get_value(GArrowDecimal32Array *array, gint64 i)
{
auto arrow_array = garrow_array_get_raw(GARROW_ARRAY(array));
auto arrow_decimal32_array =
std::static_pointer_cast<arrow::Decimal32Array>(arrow_array);
auto arrow_decimal32 =
std::make_shared<arrow::Decimal32>(arrow_decimal32_array->GetValue(i));
return garrow_decimal32_new_raw(&arrow_decimal32);
}

G_DEFINE_TYPE(GArrowDecimal64Array,
garrow_decimal64_array,
GARROW_TYPE_FIXED_SIZE_BINARY_ARRAY)
Expand Down Expand Up @@ -3502,6 +3561,9 @@ garrow_array_new_raw_valist(std::shared_ptr<arrow::Array> *arrow_array,
case arrow::Type::type::DICTIONARY:
type = GARROW_TYPE_DICTIONARY_ARRAY;
break;
case arrow::Type::type::DECIMAL32:
type = GARROW_TYPE_DECIMAL32_ARRAY;
break;
case arrow::Type::type::DECIMAL64:
type = GARROW_TYPE_DECIMAL64_ARRAY;
break;
Expand Down
20 changes: 20 additions & 0 deletions c_glib/arrow-glib/basic-array.h
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,26 @@ GARROW_AVAILABLE_IN_3_0
GBytes *
garrow_fixed_size_binary_array_get_values_bytes(GArrowFixedSizeBinaryArray *array);

#define GARROW_TYPE_DECIMAL32_ARRAY (garrow_decimal32_array_get_type())
GARROW_AVAILABLE_IN_19_0
G_DECLARE_DERIVABLE_TYPE(GArrowDecimal32Array,
garrow_decimal32_array,
GARROW,
DECIMAL32_ARRAY,
GArrowFixedSizeBinaryArray)
struct _GArrowDecimal32ArrayClass
{
GArrowFixedSizeBinaryArrayClass parent_class;
};

GARROW_AVAILABLE_IN_19_0
gchar *
garrow_decimal32_array_format_value(GArrowDecimal32Array *array, gint64 i);

GARROW_AVAILABLE_IN_19_0
GArrowDecimal32 *
garrow_decimal32_array_get_value(GArrowDecimal32Array *array, gint64 i);

#define GARROW_TYPE_DECIMAL64_ARRAY (garrow_decimal64_array_get_type())
GARROW_AVAILABLE_IN_19_0
G_DECLARE_DERIVABLE_TYPE(GArrowDecimal64Array,
Expand Down
37 changes: 37 additions & 0 deletions c_glib/test/test-decimal32-array.rb
Original file line number Diff line number Diff line change
@@ -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 TestDecimal32Array < Test::Unit::TestCase
def test_format_value
data_type = Arrow::Decimal32DataType.new(8, 2)
builder = Arrow::Decimal32ArrayBuilder.new(data_type)
decimal = Arrow::Decimal32.new("23423445")
builder.append_value(decimal)
array = builder.finish
assert_equal("234234.45", array.format_value(0))
end

def test_value
data_type = Arrow::Decimal32DataType.new(8, 2)
builder = Arrow::Decimal32ArrayBuilder.new(data_type)
decimal = Arrow::Decimal32.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

0 comments on commit abda57c

Please sign in to comment.