Skip to content

Commit d09233a

Browse files
authored
GH-48484: [GLib][Ruby] Add GArrowJoinOptions (#48485)
### Rationale for this change The `JoinOptions` class is not available in GLib/Ruby, and it is used together with the `binary_join_element_wise` compute function. ### What changes are included in this PR? This adds the `JoinOptions` class to GLib. ### Are these changes tested? Yes, with Ruby unit tests. ### Are there any user-facing changes? Yes, a new class. * GitHub Issue: #48484 Authored-by: Sten Larsson <[email protected]> Signed-off-by: Sutou Kouhei <[email protected]>
1 parent b3e2e08 commit d09233a

File tree

4 files changed

+246
-0
lines changed

4 files changed

+246
-0
lines changed

c_glib/arrow-glib/compute.cpp

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ G_BEGIN_DECLS
273273
* #GArrowExtractRegexSpanOptions is a class to customize the `extract_regex_span`
274274
* function.
275275
*
276+
* #GArrowJoinOptions is a class to customize the `binary_join_element_wise`
277+
* function.
278+
*
276279
* There are many functions to compute data on an array.
277280
*/
278281

@@ -7278,6 +7281,125 @@ garrow_extract_regex_span_options_new(void)
72787281
return GARROW_EXTRACT_REGEX_SPAN_OPTIONS(options);
72797282
}
72807283

7284+
enum {
7285+
PROP_JOIN_OPTIONS_NULL_HANDLING = 1,
7286+
PROP_JOIN_OPTIONS_NULL_REPLACEMENT,
7287+
};
7288+
7289+
G_DEFINE_TYPE(GArrowJoinOptions, garrow_join_options, GARROW_TYPE_FUNCTION_OPTIONS)
7290+
7291+
static void
7292+
garrow_join_options_set_property(GObject *object,
7293+
guint prop_id,
7294+
const GValue *value,
7295+
GParamSpec *pspec)
7296+
{
7297+
auto options = garrow_join_options_get_raw(GARROW_JOIN_OPTIONS(object));
7298+
7299+
switch (prop_id) {
7300+
case PROP_JOIN_OPTIONS_NULL_HANDLING:
7301+
options->null_handling =
7302+
static_cast<arrow::compute::JoinOptions::NullHandlingBehavior>(
7303+
g_value_get_enum(value));
7304+
break;
7305+
case PROP_JOIN_OPTIONS_NULL_REPLACEMENT:
7306+
options->null_replacement = g_value_get_string(value);
7307+
break;
7308+
default:
7309+
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
7310+
break;
7311+
}
7312+
}
7313+
7314+
static void
7315+
garrow_join_options_get_property(GObject *object,
7316+
guint prop_id,
7317+
GValue *value,
7318+
GParamSpec *pspec)
7319+
{
7320+
auto options = garrow_join_options_get_raw(GARROW_JOIN_OPTIONS(object));
7321+
7322+
switch (prop_id) {
7323+
case PROP_JOIN_OPTIONS_NULL_HANDLING:
7324+
g_value_set_enum(value,
7325+
static_cast<GArrowJoinNullHandlingBehavior>(options->null_handling));
7326+
break;
7327+
case PROP_JOIN_OPTIONS_NULL_REPLACEMENT:
7328+
g_value_set_string(value, options->null_replacement.c_str());
7329+
break;
7330+
default:
7331+
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
7332+
break;
7333+
}
7334+
}
7335+
7336+
static void
7337+
garrow_join_options_init(GArrowJoinOptions *object)
7338+
{
7339+
auto priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object);
7340+
priv->options =
7341+
static_cast<arrow::compute::FunctionOptions *>(new arrow::compute::JoinOptions());
7342+
}
7343+
7344+
static void
7345+
garrow_join_options_class_init(GArrowJoinOptionsClass *klass)
7346+
{
7347+
auto gobject_class = G_OBJECT_CLASS(klass);
7348+
7349+
gobject_class->set_property = garrow_join_options_set_property;
7350+
gobject_class->get_property = garrow_join_options_get_property;
7351+
7352+
arrow::compute::JoinOptions options;
7353+
7354+
GParamSpec *spec;
7355+
/**
7356+
* GArrowJoinOptions:null-handling:
7357+
*
7358+
* How to handle null values. (A null separator always results in a null output.)
7359+
*
7360+
* Since: 23.0.0
7361+
*/
7362+
spec =
7363+
g_param_spec_enum("null-handling",
7364+
"Null handling",
7365+
"How to handle null values",
7366+
GARROW_TYPE_JOIN_NULL_HANDLING_BEHAVIOR,
7367+
static_cast<GArrowJoinNullHandlingBehavior>(options.null_handling),
7368+
static_cast<GParamFlags>(G_PARAM_READWRITE));
7369+
g_object_class_install_property(gobject_class, PROP_JOIN_OPTIONS_NULL_HANDLING, spec);
7370+
7371+
/**
7372+
* GArrowJoinOptions:null-replacement:
7373+
*
7374+
* Replacement string for null values when null-handling is REPLACE.
7375+
*
7376+
* Since: 23.0.0
7377+
*/
7378+
spec = g_param_spec_string(
7379+
"null-replacement",
7380+
"Null replacement",
7381+
"Replacement string for null values when null-handling is REPLACE",
7382+
options.null_replacement.c_str(),
7383+
static_cast<GParamFlags>(G_PARAM_READWRITE));
7384+
g_object_class_install_property(gobject_class,
7385+
PROP_JOIN_OPTIONS_NULL_REPLACEMENT,
7386+
spec);
7387+
}
7388+
7389+
/**
7390+
* garrow_join_options_new:
7391+
*
7392+
* Returns: A newly created #GArrowJoinOptions.
7393+
*
7394+
* Since: 23.0.0
7395+
*/
7396+
GArrowJoinOptions *
7397+
garrow_join_options_new(void)
7398+
{
7399+
auto options = g_object_new(GARROW_TYPE_JOIN_OPTIONS, nullptr);
7400+
return GARROW_JOIN_OPTIONS(options);
7401+
}
7402+
72817403
G_END_DECLS
72827404

72837405
arrow::Result<arrow::FieldRef>
@@ -7447,6 +7569,11 @@ garrow_function_options_new_raw(const arrow::compute::FunctionOptions *arrow_opt
74477569
auto options =
74487570
garrow_extract_regex_span_options_new_raw(arrow_extract_regex_span_options);
74497571
return GARROW_FUNCTION_OPTIONS(options);
7572+
} else if (arrow_type_name == "JoinOptions") {
7573+
const auto arrow_join_options =
7574+
static_cast<const arrow::compute::JoinOptions *>(arrow_options);
7575+
auto options = garrow_join_options_new_raw(arrow_join_options);
7576+
return GARROW_FUNCTION_OPTIONS(options);
74507577
} else {
74517578
auto options = g_object_new(GARROW_TYPE_FUNCTION_OPTIONS, NULL);
74527579
return GARROW_FUNCTION_OPTIONS(options);
@@ -8104,3 +8231,22 @@ garrow_extract_regex_span_options_get_raw(GArrowExtractRegexSpanOptions *options
81048231
return static_cast<arrow::compute::ExtractRegexSpanOptions *>(
81058232
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
81068233
}
8234+
8235+
GArrowJoinOptions *
8236+
garrow_join_options_new_raw(const arrow::compute::JoinOptions *arrow_options)
8237+
{
8238+
return GARROW_JOIN_OPTIONS(g_object_new(
8239+
GARROW_TYPE_JOIN_OPTIONS,
8240+
"null-handling",
8241+
static_cast<GArrowJoinNullHandlingBehavior>(arrow_options->null_handling),
8242+
"null-replacement",
8243+
arrow_options->null_replacement.c_str(),
8244+
nullptr));
8245+
}
8246+
8247+
arrow::compute::JoinOptions *
8248+
garrow_join_options_get_raw(GArrowJoinOptions *options)
8249+
{
8250+
return static_cast<arrow::compute::JoinOptions *>(
8251+
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
8252+
}

c_glib/arrow-glib/compute.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,4 +1290,36 @@ GARROW_AVAILABLE_IN_23_0
12901290
GArrowExtractRegexSpanOptions *
12911291
garrow_extract_regex_span_options_new(void);
12921292

1293+
/**
1294+
* GArrowJoinNullHandlingBehavior:
1295+
* @GARROW_JOIN_NULL_HANDLING_EMIT_NULL: A null in any input results in a null in the
1296+
* output.
1297+
* @GARROW_JOIN_NULL_HANDLING_SKIP: Nulls in inputs are skipped.
1298+
* @GARROW_JOIN_NULL_HANDLING_REPLACE: Nulls in inputs are replaced with the replacement
1299+
* string.
1300+
*
1301+
* They correspond to the values of
1302+
* `arrow::compute::JoinOptions::NullHandlingBehavior`.
1303+
*
1304+
* Since: 23.0.0
1305+
*/
1306+
typedef enum {
1307+
GARROW_JOIN_NULL_HANDLING_EMIT_NULL,
1308+
GARROW_JOIN_NULL_HANDLING_SKIP,
1309+
GARROW_JOIN_NULL_HANDLING_REPLACE,
1310+
} GArrowJoinNullHandlingBehavior;
1311+
1312+
#define GARROW_TYPE_JOIN_OPTIONS (garrow_join_options_get_type())
1313+
GARROW_AVAILABLE_IN_23_0
1314+
G_DECLARE_DERIVABLE_TYPE(
1315+
GArrowJoinOptions, garrow_join_options, GARROW, JOIN_OPTIONS, GArrowFunctionOptions)
1316+
struct _GArrowJoinOptionsClass
1317+
{
1318+
GArrowFunctionOptionsClass parent_class;
1319+
};
1320+
1321+
GARROW_AVAILABLE_IN_23_0
1322+
GArrowJoinOptions *
1323+
garrow_join_options_new(void);
1324+
12931325
G_END_DECLS

c_glib/arrow-glib/compute.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,3 +215,8 @@ garrow_extract_regex_span_options_new_raw(
215215
const arrow::compute::ExtractRegexSpanOptions *arrow_options);
216216
arrow::compute::ExtractRegexSpanOptions *
217217
garrow_extract_regex_span_options_get_raw(GArrowExtractRegexSpanOptions *options);
218+
219+
GArrowJoinOptions *
220+
garrow_join_options_new_raw(const arrow::compute::JoinOptions *arrow_options);
221+
arrow::compute::JoinOptions *
222+
garrow_join_options_get_raw(GArrowJoinOptions *options);

c_glib/test/test-join-options.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
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 TestJoinOptions < Test::Unit::TestCase
19+
include Helper::Buildable
20+
21+
def setup
22+
@options = Arrow::JoinOptions.new
23+
end
24+
25+
def test_null_handling_property
26+
assert_equal(Arrow::JoinNullHandlingBehavior::EMIT_NULL, @options.null_handling)
27+
@options.null_handling = :skip
28+
assert_equal(Arrow::JoinNullHandlingBehavior::SKIP, @options.null_handling)
29+
@options.null_handling = :replace
30+
assert_equal(Arrow::JoinNullHandlingBehavior::REPLACE, @options.null_handling)
31+
end
32+
33+
def test_null_replacement_property
34+
assert_equal("", @options.null_replacement)
35+
@options.null_replacement = "NULL"
36+
assert_equal("NULL", @options.null_replacement)
37+
end
38+
39+
def test_binary_join_element_wise_function
40+
args = [
41+
Arrow::ArrayDatum.new(build_string_array(["a", "b", nil])),
42+
Arrow::ArrayDatum.new(build_string_array(["x", "y", "z"])),
43+
Arrow::ScalarDatum.new(Arrow::StringScalar.new(Arrow::Buffer.new("-"))),
44+
]
45+
binary_join_element_wise_function = Arrow::Function.find("binary_join_element_wise")
46+
47+
@options.null_handling = :emit_null
48+
result = binary_join_element_wise_function.execute(args, @options).value
49+
assert_equal(build_string_array(["a-x", "b-y", nil]),
50+
result)
51+
52+
@options.null_handling = :skip
53+
result = binary_join_element_wise_function.execute(args, @options).value
54+
assert_equal(build_string_array(["a-x", "b-y", "z"]),
55+
result)
56+
57+
@options.null_handling = :replace
58+
@options.null_replacement = "NULL"
59+
result = binary_join_element_wise_function.execute(args, @options).value
60+
assert_equal(build_string_array(["a-x", "b-y", "NULL-z"]),
61+
result)
62+
end
63+
end

0 commit comments

Comments
 (0)