Skip to content
Merged
87 changes: 87 additions & 0 deletions c_glib/arrow-glib/compute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <arrow-glib/error.hpp>
#include <arrow-glib/executor.hpp>
#include <arrow-glib/expression.hpp>
#include <arrow-glib/internal-hash-table.hpp>
#include <arrow-glib/reader.hpp>
#include <arrow-glib/record-batch.hpp>
#include <arrow-glib/scalar.hpp>
Expand Down Expand Up @@ -342,6 +343,9 @@ G_BEGIN_DECLS
* #GArrowSplitOptions is a class to customize the `ascii_split_whitespace` and
* `utf8_split_whitespace` functions.
*
* #GArrowMakeStructOptions is a class to customize the `make_struct`
* function.
*
* There are many functions to compute data on an array.
*/

Expand Down Expand Up @@ -10598,6 +10602,67 @@ garrow_split_options_new(void)
return GARROW_SPLIT_OPTIONS(g_object_new(GARROW_TYPE_SPLIT_OPTIONS, nullptr));
}

G_DEFINE_TYPE(GArrowMakeStructOptions,
garrow_make_struct_options,
GARROW_TYPE_FUNCTION_OPTIONS)

static void
garrow_make_struct_options_init(GArrowMakeStructOptions *object)
{
auto priv = GARROW_FUNCTION_OPTIONS_GET_PRIVATE(object);
priv->options = static_cast<arrow::compute::FunctionOptions *>(
new arrow::compute::MakeStructOptions());
}

static void
garrow_make_struct_options_class_init(GArrowMakeStructOptionsClass *klass)
{
}

/**
* garrow_make_struct_options_new:
*
* Returns: A newly created #GArrowMakeStructOptions.
*
* Since: 23.0.0
*/
GArrowMakeStructOptions *
garrow_make_struct_options_new(void)
{
auto options = g_object_new(GARROW_TYPE_MAKE_STRUCT_OPTIONS, nullptr);
return GARROW_MAKE_STRUCT_OPTIONS(options);
}

/**
* garrow_make_struct_options_add_field:
* @options: A #GArrowMakeStructOptions.
* @name: The name of the field to add.
* @nullability: Whether the field is nullable.
* @metadata: (nullable) (element-type utf8 utf8): A #GHashTable for the field's
* metadata, or %NULL.
*
* Adds a field to the struct options with the specified name, nullability,
* and optional metadata.
*
* Since: 23.0.0
*/
void
garrow_make_struct_options_add_field(GArrowMakeStructOptions *options,
const char *name,
gboolean nullability,
GHashTable *metadata)
{
auto arrow_options = garrow_make_struct_options_get_raw(options);
arrow_options->field_names.emplace_back(name);
arrow_options->field_nullability.push_back(nullability != FALSE);
if (metadata) {
arrow_options->field_metadata.push_back(
garrow_internal_hash_table_to_metadata(metadata));
} else {
arrow_options->field_metadata.push_back(nullptr);
}
}

G_END_DECLS

arrow::Result<arrow::FieldRef>
Expand Down Expand Up @@ -10883,6 +10948,11 @@ garrow_function_options_new_raw(const arrow::compute::FunctionOptions *arrow_opt
static_cast<const arrow::compute::SplitOptions *>(arrow_options);
auto options = garrow_split_options_new_raw(arrow_split_options);
return GARROW_FUNCTION_OPTIONS(options);
} else if (arrow_type_name == "MakeStructOptions") {
const auto arrow_make_struct_options =
static_cast<const arrow::compute::MakeStructOptions *>(arrow_options);
auto options = garrow_make_struct_options_new_raw(arrow_make_struct_options);
return GARROW_FUNCTION_OPTIONS(options);
} else {
auto options = g_object_new(GARROW_TYPE_FUNCTION_OPTIONS, NULL);
return GARROW_FUNCTION_OPTIONS(options);
Expand Down Expand Up @@ -12037,3 +12107,20 @@ garrow_split_options_get_raw(GArrowSplitOptions *options)
return static_cast<arrow::compute::SplitOptions *>(
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
}

GArrowMakeStructOptions *
garrow_make_struct_options_new_raw(const arrow::compute::MakeStructOptions *arrow_options)
{
auto options =
GARROW_MAKE_STRUCT_OPTIONS(g_object_new(GARROW_TYPE_MAKE_STRUCT_OPTIONS, nullptr));
auto arrow_new_options = garrow_make_struct_options_get_raw(options);
*arrow_new_options = *arrow_options;
return options;
}

arrow::compute::MakeStructOptions *
garrow_make_struct_options_get_raw(GArrowMakeStructOptions *options)
{
return static_cast<arrow::compute::MakeStructOptions *>(
garrow_function_options_get_raw(GARROW_FUNCTION_OPTIONS(options)));
}
23 changes: 23 additions & 0 deletions c_glib/arrow-glib/compute.h
Original file line number Diff line number Diff line change
Expand Up @@ -1800,4 +1800,27 @@ GARROW_AVAILABLE_IN_23_0
GArrowSplitOptions *
garrow_split_options_new(void);

#define GARROW_TYPE_MAKE_STRUCT_OPTIONS (garrow_make_struct_options_get_type())
GARROW_AVAILABLE_IN_23_0
G_DECLARE_DERIVABLE_TYPE(GArrowMakeStructOptions,
garrow_make_struct_options,
GARROW,
MAKE_STRUCT_OPTIONS,
GArrowFunctionOptions)
struct _GArrowMakeStructOptionsClass
{
GArrowFunctionOptionsClass parent_class;
};

GARROW_AVAILABLE_IN_23_0
GArrowMakeStructOptions *
garrow_make_struct_options_new(void);

GARROW_AVAILABLE_IN_23_0
void
garrow_make_struct_options_add_field(GArrowMakeStructOptions *options,
const char *name,
gboolean nullability,
GHashTable *metadata);

G_END_DECLS
6 changes: 6 additions & 0 deletions c_glib/arrow-glib/compute.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,3 +343,9 @@ GArrowSplitOptions *
garrow_split_options_new_raw(const arrow::compute::SplitOptions *arrow_options);
arrow::compute::SplitOptions *
garrow_split_options_get_raw(GArrowSplitOptions *options);

GArrowMakeStructOptions *
garrow_make_struct_options_new_raw(
const arrow::compute::MakeStructOptions *arrow_options);
arrow::compute::MakeStructOptions *
garrow_make_struct_options_get_raw(GArrowMakeStructOptions *options);
2 changes: 1 addition & 1 deletion c_glib/arrow-glib/internal-hash-table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ garrow_internal_hash_table_to_metadata(GHashTable *metadata)

static inline GHashTable *
garrow_internal_hash_table_from_metadata(
const std::shared_ptr<arrow::KeyValueMetadata> &arrow_metadata)
const std::shared_ptr<const arrow::KeyValueMetadata> &arrow_metadata)
{
auto metadata = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
const auto &keys = arrow_metadata->keys();
Expand Down
95 changes: 95 additions & 0 deletions c_glib/test/test-make-struct-options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# 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 TestMakeStructOptions < Test::Unit::TestCase
include Helper::Buildable

def setup
@options = Arrow::MakeStructOptions.new
end

def test_make_struct_function
a = build_int8_array([1, 2, 3])
b = build_boolean_array([true, false, nil])
args = [
Arrow::ArrayDatum.new(a),
Arrow::ArrayDatum.new(b),
]
@options.add_field("a", true, nil)
@options.add_field("b", true, nil)
make_struct_function = Arrow::Function.find("make_struct")
result = make_struct_function.execute(args, @options).value

expected = build_struct_array(
[
Arrow::Field.new("a", Arrow::Int8DataType.new),
Arrow::Field.new("b", Arrow::BooleanDataType.new),
],
[
{"a" => 1, "b" => true},
{"a" => 2, "b" => false},
{"a" => 3, "b" => nil},
]
)
assert_equal(expected, result)
end

def test_make_struct_function_with_nullability
a = build_int8_array([1, 2, 3])
b = build_boolean_array([true, false, nil])
args = [
Arrow::ArrayDatum.new(a),
Arrow::ArrayDatum.new(b),
]
@options.add_field("a", false, nil)
@options.add_field("b", true, nil)
make_struct_function = Arrow::Function.find("make_struct")
result = make_struct_function.execute(args, @options).value

expected = build_struct_array(
[
Arrow::Field.new("a", Arrow::Int8DataType.new, false),
Arrow::Field.new("b", Arrow::BooleanDataType.new, true),
],
[
{"a" => 1, "b" => true},
{"a" => 2, "b" => false},
{"a" => 3, "b" => nil},
]
)
assert_equal(expected, result)
end

def test_make_struct_function_with_metadata
a = build_int8_array([1, 2, 3])
b = build_boolean_array([true, false, nil])
args = [
Arrow::ArrayDatum.new(a),
Arrow::ArrayDatum.new(b),
]
metadata1 = {"key1" => "value1"}
metadata2 = {"key2" => "value2"}
@options.add_field("a", true, metadata1)
@options.add_field("b", true, metadata2)
make_struct_function = Arrow::Function.find("make_struct")
result = make_struct_function.execute(args, @options).value

fields = result.value_data_type.fields
assert_equal(metadata1, fields[0].metadata)
assert_equal(metadata2, fields[1].metadata)
end
end
1 change: 1 addition & 0 deletions ruby/red-arrow/lib/arrow/libraries.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
require_relative "list-array-builder"
require_relative "list-data-type"
require_relative "list-slice-options"
require_relative "make-struct-options"
require_relative "map-array"
require_relative "map-array-builder"
require_relative "map-data-type"
Expand Down
38 changes: 38 additions & 0 deletions ruby/red-arrow/lib/arrow/make-struct-options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 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.

module Arrow
class MakeStructOptions
class << self
def try_convert(value)
case value
when Hash
options = new
field_names = value[:field_names] || []
field_nullability = value[:field_nullability] || []
field_metadata = value[:field_metadata] || []
field_names.zip(field_nullability, field_metadata) do |name, nullability, metadata|
options.add_field(name, nullability, metadata)
end
options
else
nil
end
end
end
end
end
51 changes: 51 additions & 0 deletions ruby/red-arrow/test/test-make-struct-options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# 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 TestMakeStructOptions < Test::Unit::TestCase
def test_make_struct_function
a = Arrow::Int8Array.new([1, 2, 3])
b = Arrow::BooleanArray.new([true, false, nil])
metadata1 = {"a" => "b"}
metadata2 = {"c" => "d"}
options = {
field_names: ["a", "b"],
field_nullability: [false, true],
field_metadata: [metadata1, metadata2]
}
args = [a, b]
make_struct_function = Arrow::Function.find("make_struct")
result = make_struct_function.execute(args, options).value

expected = Arrow::StructArray.new(
Arrow::StructDataType.new(
[
Arrow::Field.new("a", Arrow::Int8DataType.new, false),
Arrow::Field.new("b", Arrow::BooleanDataType.new, true),
]
),
[
{"a" => 1, "b" => true},
{"a" => 2, "b" => false},
{"a" => 3, "b" => nil},
]
)
assert_equal(expected, result)
fields = result.value_data_type.fields
assert_equal(metadata1, fields[0].metadata)
assert_equal(metadata2, fields[1].metadata)
end
end
Loading