Skip to content

Commit 62d3db6

Browse files
authored
GH-48364: [GLib][Ruby] Add CumulativeOptions (#48371)
### Rationale for this change The `CumulativeOptions` class is not available in GLib/Ruby, and it is used together with the `cumulative_sum`, `cumulative_prod`, etc compute functions. ### What changes are included in this PR? This adds the `CumulativeOptions` to GLib. ### Are these changes tested? Yes, with Ruby unit tests. ### Are there any user-facing changes? Yes, a new class. * GitHub Issue: #48364 Authored-by: Sten Larsson <[email protected]> Signed-off-by: Sutou Kouhei <[email protected]>
1 parent 19650fe commit 62d3db6

File tree

4 files changed

+288
-0
lines changed

4 files changed

+288
-0
lines changed

c_glib/arrow-glib/compute.cpp

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,10 @@ G_BEGIN_DECLS
254254
* #GArrowAssumeTimezoneOptions is a class to customize the `assume_timezone`
255255
* function.
256256
*
257+
* #GArrowCumulativeOptions is a class to customize the cumulative functions
258+
* such as `cumulative_sum`, `cumulative_prod`, `cumulative_max`, and
259+
* `cumulative_min`.
260+
*
257261
* There are many functions to compute data on an array.
258262
*/
259263

@@ -6491,6 +6495,173 @@ garrow_assume_timezone_options_new(void)
64916495
return GARROW_ASSUME_TIMEZONE_OPTIONS(options);
64926496
}
64936497

6498+
typedef struct GArrowCumulativeOptionsPrivate_
6499+
{
6500+
GArrowScalar *start;
6501+
} GArrowCumulativeOptionsPrivate;
6502+
6503+
enum {
6504+
PROP_CUMULATIVE_OPTIONS_START = 1,
6505+
PROP_CUMULATIVE_OPTIONS_SKIP_NULLS,
6506+
};
6507+
6508+
G_DEFINE_TYPE_WITH_PRIVATE(GArrowCumulativeOptions,
6509+
garrow_cumulative_options,
6510+
GARROW_TYPE_FUNCTION_OPTIONS)
6511+
6512+
#define GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object) \
6513+
static_cast<GArrowCumulativeOptionsPrivate *>( \
6514+
garrow_cumulative_options_get_instance_private(GARROW_CUMULATIVE_OPTIONS(object)))
6515+
6516+
static void
6517+
garrow_cumulative_options_dispose(GObject *object)
6518+
{
6519+
auto priv = GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object);
6520+
6521+
if (priv->start) {
6522+
g_object_unref(priv->start);
6523+
priv->start = nullptr;
6524+
}
6525+
6526+
G_OBJECT_CLASS(garrow_cumulative_options_parent_class)->dispose(object);
6527+
}
6528+
6529+
static void
6530+
garrow_cumulative_options_set_property(GObject *object,
6531+
guint prop_id,
6532+
const GValue *value,
6533+
GParamSpec *pspec)
6534+
{
6535+
auto priv = GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object);
6536+
auto options = garrow_cumulative_options_get_raw(GARROW_CUMULATIVE_OPTIONS(object));
6537+
6538+
switch (prop_id) {
6539+
case PROP_CUMULATIVE_OPTIONS_START:
6540+
{
6541+
auto scalar = GARROW_SCALAR(g_value_get_object(value));
6542+
if (priv->start == scalar) {
6543+
return;
6544+
}
6545+
if (priv->start) {
6546+
g_object_unref(priv->start);
6547+
}
6548+
priv->start = scalar;
6549+
if (priv->start) {
6550+
g_object_ref(priv->start);
6551+
options->start = garrow_scalar_get_raw(scalar);
6552+
} else {
6553+
options->start = std::nullopt;
6554+
}
6555+
break;
6556+
}
6557+
case PROP_CUMULATIVE_OPTIONS_SKIP_NULLS:
6558+
options->skip_nulls = g_value_get_boolean(value);
6559+
break;
6560+
default:
6561+
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
6562+
break;
6563+
}
6564+
}
6565+
6566+
static void
6567+
garrow_cumulative_options_get_property(GObject *object,
6568+
guint prop_id,
6569+
GValue *value,
6570+
GParamSpec *pspec)
6571+
{
6572+
auto priv = GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object);
6573+
auto options = garrow_cumulative_options_get_raw(GARROW_CUMULATIVE_OPTIONS(object));
6574+
6575+
switch (prop_id) {
6576+
case PROP_CUMULATIVE_OPTIONS_START:
6577+
{
6578+
if (priv->start) {
6579+
g_value_set_object(value, G_OBJECT(priv->start));
6580+
} else {
6581+
g_value_set_object(value, NULL);
6582+
}
6583+
break;
6584+
}
6585+
case PROP_CUMULATIVE_OPTIONS_SKIP_NULLS:
6586+
g_value_set_boolean(value, options->skip_nulls);
6587+
break;
6588+
default:
6589+
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
6590+
break;
6591+
}
6592+
}
6593+
6594+
static void
6595+
garrow_cumulative_options_init(GArrowCumulativeOptions *object)
6596+
{
6597+
auto priv = GARROW_CUMULATIVE_OPTIONS_GET_PRIVATE(object);
6598+
priv->start = nullptr;
6599+
auto function_options_priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object);
6600+
function_options_priv->options = static_cast<arrow::compute::FunctionOptions *>(
6601+
new arrow::compute::CumulativeOptions());
6602+
}
6603+
6604+
static void
6605+
garrow_cumulative_options_class_init(GArrowCumulativeOptionsClass *klass)
6606+
{
6607+
auto gobject_class = G_OBJECT_CLASS(klass);
6608+
6609+
gobject_class->dispose = garrow_cumulative_options_dispose;
6610+
gobject_class->set_property = garrow_cumulative_options_set_property;
6611+
gobject_class->get_property = garrow_cumulative_options_get_property;
6612+
6613+
arrow::compute::CumulativeOptions options;
6614+
6615+
GParamSpec *spec;
6616+
/**
6617+
* GArrowCumulativeOptions:start:
6618+
*
6619+
* Optional starting value for cumulative operation computation.
6620+
*
6621+
* Since: 23.0.0
6622+
*/
6623+
spec =
6624+
g_param_spec_object("start",
6625+
"Start",
6626+
"Optional starting value for cumulative operation computation",
6627+
GARROW_TYPE_SCALAR,
6628+
static_cast<GParamFlags>(G_PARAM_READWRITE));
6629+
g_object_class_install_property(gobject_class, PROP_CUMULATIVE_OPTIONS_START, spec);
6630+
6631+
/**
6632+
* GArrowCumulativeOptions:skip-nulls:
6633+
*
6634+
* If true, nulls in the input are ignored and produce a corresponding null output.
6635+
* When false, the first null encountered is propagated through the remaining output.
6636+
*
6637+
* Since: 23.0.0
6638+
*/
6639+
spec = g_param_spec_boolean(
6640+
"skip-nulls",
6641+
"Skip nulls",
6642+
"If true, nulls in the input are ignored and produce a corresponding null output. "
6643+
"When false, the first null encountered is propagated through the remaining output",
6644+
options.skip_nulls,
6645+
static_cast<GParamFlags>(G_PARAM_READWRITE));
6646+
g_object_class_install_property(gobject_class,
6647+
PROP_CUMULATIVE_OPTIONS_SKIP_NULLS,
6648+
spec);
6649+
}
6650+
6651+
/**
6652+
* garrow_cumulative_options_new:
6653+
*
6654+
* Returns: A newly created #GArrowCumulativeOptions.
6655+
*
6656+
* Since: 23.0.0
6657+
*/
6658+
GArrowCumulativeOptions *
6659+
garrow_cumulative_options_new(void)
6660+
{
6661+
auto options = g_object_new(GARROW_TYPE_CUMULATIVE_OPTIONS, NULL);
6662+
return GARROW_CUMULATIVE_OPTIONS(options);
6663+
}
6664+
64946665
G_END_DECLS
64956666

64966667
arrow::Result<arrow::FieldRef>
@@ -6627,6 +6798,11 @@ garrow_function_options_new_raw(const arrow::compute::FunctionOptions *arrow_opt
66276798
static_cast<const arrow::compute::AssumeTimezoneOptions *>(arrow_options);
66286799
auto options = garrow_assume_timezone_options_new_raw(arrow_assume_timezone_options);
66296800
return GARROW_FUNCTION_OPTIONS(options);
6801+
} else if (arrow_type_name == "CumulativeOptions") {
6802+
const auto arrow_cumulative_options =
6803+
static_cast<const arrow::compute::CumulativeOptions *>(arrow_options);
6804+
auto options = garrow_cumulative_options_new_raw(arrow_cumulative_options);
6805+
return GARROW_FUNCTION_OPTIONS(options);
66306806
} else {
66316807
auto options = g_object_new(GARROW_TYPE_FUNCTION_OPTIONS, NULL);
66326808
return GARROW_FUNCTION_OPTIONS(options);
@@ -7167,3 +7343,30 @@ garrow_assume_timezone_options_get_raw(GArrowAssumeTimezoneOptions *options)
71677343
return static_cast<arrow::compute::AssumeTimezoneOptions *>(
71687344
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
71697345
}
7346+
7347+
GArrowCumulativeOptions *
7348+
garrow_cumulative_options_new_raw(const arrow::compute::CumulativeOptions *arrow_options)
7349+
{
7350+
GArrowScalar *start = nullptr;
7351+
if (arrow_options->start.has_value()) {
7352+
std::shared_ptr<arrow::Scalar> arrow_start = arrow_options->start.value();
7353+
start = garrow_scalar_new_raw(&arrow_start);
7354+
}
7355+
auto options = GARROW_CUMULATIVE_OPTIONS(g_object_new(GARROW_TYPE_CUMULATIVE_OPTIONS,
7356+
"start",
7357+
start,
7358+
"skip-nulls",
7359+
arrow_options->skip_nulls,
7360+
NULL));
7361+
if (start) {
7362+
g_object_unref(start);
7363+
}
7364+
return options;
7365+
}
7366+
7367+
arrow::compute::CumulativeOptions *
7368+
garrow_cumulative_options_get_raw(GArrowCumulativeOptions *options)
7369+
{
7370+
return static_cast<arrow::compute::CumulativeOptions *>(
7371+
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
7372+
}

c_glib/arrow-glib/compute.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,4 +1173,20 @@ GARROW_AVAILABLE_IN_23_0
11731173
GArrowAssumeTimezoneOptions *
11741174
garrow_assume_timezone_options_new(void);
11751175

1176+
#define GARROW_TYPE_CUMULATIVE_OPTIONS (garrow_cumulative_options_get_type())
1177+
GARROW_AVAILABLE_IN_23_0
1178+
G_DECLARE_DERIVABLE_TYPE(GArrowCumulativeOptions,
1179+
garrow_cumulative_options,
1180+
GARROW,
1181+
CUMULATIVE_OPTIONS,
1182+
GArrowFunctionOptions)
1183+
struct _GArrowCumulativeOptionsClass
1184+
{
1185+
GArrowFunctionOptionsClass parent_class;
1186+
};
1187+
1188+
GARROW_AVAILABLE_IN_23_0
1189+
GArrowCumulativeOptions *
1190+
garrow_cumulative_options_new(void);
1191+
11761192
G_END_DECLS

c_glib/arrow-glib/compute.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,8 @@ garrow_assume_timezone_options_new_raw(
181181
const arrow::compute::AssumeTimezoneOptions *arrow_options);
182182
arrow::compute::AssumeTimezoneOptions *
183183
garrow_assume_timezone_options_get_raw(GArrowAssumeTimezoneOptions *options);
184+
185+
GArrowCumulativeOptions *
186+
garrow_cumulative_options_new_raw(const arrow::compute::CumulativeOptions *arrow_options);
187+
arrow::compute::CumulativeOptions *
188+
garrow_cumulative_options_get_raw(GArrowCumulativeOptions *options);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
class TestCumulativeOptions < Test::Unit::TestCase
19+
include Helper::Buildable
20+
21+
def setup
22+
@options = Arrow::CumulativeOptions.new
23+
end
24+
25+
def test_start_property
26+
assert_nil(@options.start)
27+
start_scalar = Arrow::Int64Scalar.new(10)
28+
@options.start = start_scalar
29+
assert_equal(start_scalar, @options.start)
30+
@options.start = nil
31+
assert_nil(@options.start)
32+
end
33+
34+
def test_skip_nulls_property
35+
assert do
36+
!@options.skip_nulls?
37+
end
38+
@options.skip_nulls = true
39+
assert do
40+
@options.skip_nulls?
41+
end
42+
end
43+
44+
def test_cumulative_sum_with_skip_nulls
45+
args = [
46+
Arrow::ArrayDatum.new(build_int64_array([1, 2, 3, nil, 4, 5])),
47+
]
48+
@options.skip_nulls = true
49+
cumulative_sum_function = Arrow::Function.find("cumulative_sum")
50+
assert_equal(build_int64_array([1, 3, 6, nil, 10, 15]),
51+
cumulative_sum_function.execute(args, @options).value)
52+
end
53+
54+
def test_cumulative_sum_with_start
55+
args = [
56+
Arrow::ArrayDatum.new(build_int64_array([1, 2, 3])),
57+
]
58+
@options.start = Arrow::Int64Scalar.new(10)
59+
cumulative_sum_function = Arrow::Function.find("cumulative_sum")
60+
assert_equal(build_int64_array([11, 13, 16]),
61+
cumulative_sum_function.execute(args, @options).value)
62+
end
63+
end
64+

0 commit comments

Comments
 (0)