This is an automated email from the ASF dual-hosted git repository.
kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git
The following commit(s) were added to refs/heads/main by this push:
new 93c4e002c6 GH-49093: [Ruby] Add support for writing duration array
(#49094)
93c4e002c6 is described below
commit 93c4e002c652d41ac262ed5eab377214a038b2b4
Author: Sutou Kouhei <[email protected]>
AuthorDate: Mon Feb 2 20:36:17 2026 +0900
GH-49093: [Ruby] Add support for writing duration array (#49094)
### Rationale for this change
It has unit parameter.
### What changes are included in this PR?
* Add `ArrowFormat::DurationType#to_flatbuffers`
* Add duration support to `#values` and `raw_records`
### Are these changes tested?
Yes.
### Are there any user-facing changes?
Yes.
* GitHub Issue: #49093
Authored-by: Sutou Kouhei <[email protected]>
Signed-off-by: Sutou Kouhei <[email protected]>
---
ruby/red-arrow-format/lib/arrow-format/type.rb | 6 +++
ruby/red-arrow-format/test/test-writer.rb | 62 ++++++++++++++++++++++
ruby/red-arrow/ext/arrow/converters.hpp | 16 ++++--
ruby/red-arrow/ext/arrow/raw-records.cpp | 2 +
ruby/red-arrow/ext/arrow/values.cpp | 1 +
.../test/raw-records/test-basic-arrays.rb | 40 ++++++++++++++
ruby/red-arrow/test/values/test-basic-arrays.rb | 40 ++++++++++++++
7 files changed, 162 insertions(+), 5 deletions(-)
diff --git a/ruby/red-arrow-format/lib/arrow-format/type.rb
b/ruby/red-arrow-format/lib/arrow-format/type.rb
index 5be6a506d7..c12d2d6e08 100644
--- a/ruby/red-arrow-format/lib/arrow-format/type.rb
+++ b/ruby/red-arrow-format/lib/arrow-format/type.rb
@@ -536,6 +536,12 @@ module ArrowFormat
def build_array(size, validity_buffer, values_buffer)
DurationArray.new(self, size, validity_buffer, values_buffer)
end
+
+ def to_flatbuffers
+ fb_type = FB::Duration::Data.new
+ fb_type.unit = FB::TimeUnit.try_convert(@unit.to_s.upcase)
+ fb_type
+ end
end
class VariableSizeBinaryType < Type
diff --git a/ruby/red-arrow-format/test/test-writer.rb
b/ruby/red-arrow-format/test/test-writer.rb
index 17c0b9ede1..c0e4dd4607 100644
--- a/ruby/red-arrow-format/test/test-writer.rb
+++ b/ruby/red-arrow-format/test/test-writer.rb
@@ -67,6 +67,8 @@ module WriterTests
ArrowFormat::DayTimeIntervalType.singleton
when Arrow::MonthDayNanoIntervalDataType
ArrowFormat::MonthDayNanoIntervalType.singleton
+ when Arrow::DurationDataType
+ ArrowFormat::DurationType.new(convert_time_unit(red_arrow_type.unit))
when Arrow::BinaryDataType
ArrowFormat::BinaryType.singleton
when Arrow::LargeBinaryDataType
@@ -622,6 +624,66 @@ module WriterTests
end
end
+ sub_test_case("Duration(:second)") do
+ def build_array
+ Arrow::DurationArray.new(:second, [0, nil, 100])
+ end
+
+ def test_write
+ assert_equal([0, nil, 100],
+ @values)
+ end
+
+ def test_type
+ assert_equal(Arrow::TimeUnit::SECOND, @type.unit)
+ end
+ end
+
+ sub_test_case("Duration(:millisecond)") do
+ def build_array
+ Arrow::DurationArray.new(:milli, [0, nil, 100])
+ end
+
+ def test_write
+ assert_equal([0, nil, 100],
+ @values)
+ end
+
+ def test_type
+ assert_equal(Arrow::TimeUnit::MILLI, @type.unit)
+ end
+ end
+
+ sub_test_case("Duration(:microsecond)") do
+ def build_array
+ Arrow::DurationArray.new(:micro, [0, nil, 100])
+ end
+
+ def test_write
+ assert_equal([0, nil, 100],
+ @values)
+ end
+
+ def test_type
+ assert_equal(Arrow::TimeUnit::MICRO, @type.unit)
+ end
+ end
+
+ sub_test_case("Duration(:nanosecond)") do
+ def build_array
+ Arrow::DurationArray.new(:nano, [0, nil, 100])
+ end
+
+ def test_write
+ assert_equal([0, nil, 100],
+ @values)
+ end
+
+ def test_type
+ assert_equal(Arrow::TimeUnit::NANO, @type.unit)
+ end
+ end
+
sub_test_case("Binary") do
def build_array
Arrow::BinaryArray.new(["Hello".b, nil, "World".b])
diff --git a/ruby/red-arrow/ext/arrow/converters.hpp
b/ruby/red-arrow/ext/arrow/converters.hpp
index 6a1ceb20b8..b4838c8f79 100644
--- a/ruby/red-arrow/ext/arrow/converters.hpp
+++ b/ruby/red-arrow/ext/arrow/converters.hpp
@@ -241,11 +241,6 @@ namespace red_arrow {
return rb_time_num_new(sec, Qnil);
}
- // TODO
- // inline VALUE convert(const arrow::IntervalArray& array,
- // const int64_t i) {
- // };
-
inline VALUE convert(const arrow::MonthIntervalArray& array,
const int64_t i) {
return INT2NUM(array.Value(i));
@@ -280,6 +275,11 @@ namespace red_arrow {
return value;
}
+ inline VALUE convert(const arrow::DurationArray& array,
+ const int64_t i) {
+ return LL2NUM(array.Value(i));
+ }
+
VALUE convert(const arrow::ListArray& array,
const int64_t i);
@@ -382,6 +382,7 @@ namespace red_arrow {
VISIT(MonthInterval)
VISIT(DayTimeInterval)
VISIT(MonthDayNanoInterval)
+ VISIT(Duration)
VISIT(List)
VISIT(LargeList)
VISIT(Struct)
@@ -481,6 +482,7 @@ namespace red_arrow {
VISIT(MonthInterval)
VISIT(DayTimeInterval)
VISIT(MonthDayNanoInterval)
+ VISIT(Duration)
VISIT(List)
VISIT(LargeList)
VISIT(Struct)
@@ -588,6 +590,7 @@ namespace red_arrow {
VISIT(MonthInterval)
VISIT(DayTimeInterval)
VISIT(MonthDayNanoInterval)
+ VISIT(Duration)
VISIT(List)
VISIT(LargeList)
VISIT(Struct)
@@ -691,6 +694,7 @@ namespace red_arrow {
VISIT(MonthInterval)
VISIT(DayTimeInterval)
VISIT(MonthDayNanoInterval)
+ VISIT(Duration)
VISIT(List)
VISIT(LargeList)
VISIT(Struct)
@@ -795,6 +799,7 @@ namespace red_arrow {
VISIT(MonthInterval)
VISIT(DayTimeInterval)
VISIT(MonthDayNanoInterval)
+ VISIT(Duration)
VISIT(List)
VISIT(LargeList)
VISIT(Struct)
@@ -907,6 +912,7 @@ namespace red_arrow {
VISIT(MonthInterval)
VISIT(DayTimeInterval)
VISIT(MonthDayNanoInterval)
+ VISIT(Duration)
VISIT(List)
VISIT(LargeList)
VISIT(Struct)
diff --git a/ruby/red-arrow/ext/arrow/raw-records.cpp
b/ruby/red-arrow/ext/arrow/raw-records.cpp
index 67f1dab13e..7f643bad41 100644
--- a/ruby/red-arrow/ext/arrow/raw-records.cpp
+++ b/ruby/red-arrow/ext/arrow/raw-records.cpp
@@ -100,6 +100,7 @@ namespace red_arrow {
VISIT(MonthInterval)
VISIT(DayTimeInterval)
VISIT(MonthDayNanoInterval)
+ VISIT(Duration)
VISIT(List)
VISIT(Struct)
VISIT(Map)
@@ -238,6 +239,7 @@ namespace red_arrow {
VISIT(MonthInterval)
VISIT(DayTimeInterval)
VISIT(MonthDayNanoInterval)
+ VISIT(Duration)
VISIT(List)
VISIT(Struct)
VISIT(Map)
diff --git a/ruby/red-arrow/ext/arrow/values.cpp
b/ruby/red-arrow/ext/arrow/values.cpp
index 9a26baf1d5..0296f27398 100644
--- a/ruby/red-arrow/ext/arrow/values.cpp
+++ b/ruby/red-arrow/ext/arrow/values.cpp
@@ -81,6 +81,7 @@ namespace red_arrow {
VISIT(MonthInterval)
VISIT(DayTimeInterval)
VISIT(MonthDayNanoInterval)
+ VISIT(Duration)
VISIT(List)
VISIT(LargeList)
VISIT(Struct)
diff --git a/ruby/red-arrow/test/raw-records/test-basic-arrays.rb
b/ruby/red-arrow/test/raw-records/test-basic-arrays.rb
index 1c21a493c5..7a6e6115d6 100644
--- a/ruby/red-arrow/test/raw-records/test-basic-arrays.rb
+++ b/ruby/red-arrow/test/raw-records/test-basic-arrays.rb
@@ -406,6 +406,46 @@ module RawRecordsBasicArraysTests
target = build({column: :month_day_nano_interval}, records)
assert_equal(records, actual_records(target))
end
+
+ def test_duration_second
+ records = [
+ [0],
+ [nil],
+ [100],
+ ]
+ target = build({column: {type: :duration, unit: :second}}, records)
+ assert_equal(records, actual_records(target))
+ end
+
+ def test_duration_milli
+ records = [
+ [0],
+ [nil],
+ [100],
+ ]
+ target = build({column: {type: :duration, unit: :milli}}, records)
+ assert_equal(records, actual_records(target))
+ end
+
+ def test_duration_micro
+ records = [
+ [0],
+ [nil],
+ [100],
+ ]
+ target = build({column: {type: :duration, unit: :micro}}, records)
+ assert_equal(records, actual_records(target))
+ end
+
+ def test_duration_nano
+ records = [
+ [0],
+ [nil],
+ [100],
+ ]
+ target = build({column: {type: :duration, unit: :nano}}, records)
+ assert_equal(records, actual_records(target))
+ end
end
class EachRawRecordRecordBatchBasicArraysTest < Test::Unit::TestCase
diff --git a/ruby/red-arrow/test/values/test-basic-arrays.rb
b/ruby/red-arrow/test/values/test-basic-arrays.rb
index ddaaa3db64..b3c8e18172 100644
--- a/ruby/red-arrow/test/values/test-basic-arrays.rb
+++ b/ruby/red-arrow/test/values/test-basic-arrays.rb
@@ -336,6 +336,46 @@ module ValuesBasicArraysTests
target = build(Arrow::MonthDayNanoIntervalArray.new(values))
assert_equal(values, target.values)
end
+
+ def test_duration_second
+ values = [
+ 0,
+ nil,
+ 100,
+ ]
+ target = build(Arrow::DurationArray.new(:second, values))
+ assert_equal(values, target.values)
+ end
+
+ def test_duration_milli
+ values = [
+ 0,
+ nil,
+ 100,
+ ]
+ target = build(Arrow::DurationArray.new(:milli, values))
+ assert_equal(values, target.values)
+ end
+
+ def test_duration_micro
+ values = [
+ 0,
+ nil,
+ 100,
+ ]
+ target = build(Arrow::DurationArray.new(:micro, values))
+ assert_equal(values, target.values)
+ end
+
+ def test_duration_nano
+ values = [
+ 0,
+ nil,
+ 100,
+ ]
+ target = build(Arrow::DurationArray.new(:nano, values))
+ assert_equal(values, target.values)
+ end
end
class ValuesArrayBasicArraysTest < Test::Unit::TestCase