Skip to content

Commit 7be3c13

Browse files
kouhiroyuki-sato
andauthored
GH-48602: [Ruby] Add support for reading interval arrays (#48603)
### Rationale for this change There are `YEAR_MONTH`, `DAY_TIME` and `MONTH_DAY_NANO` variants. ### What changes are included in this PR? * Add `ArrowFormat::YearMonthIntervalType` * Add `ArrowFormat::YearMonthIntervalArray` * Add `ArrowFormat::DayTimeIntervalType` * Add `ArrowFormat::DayTimeIntervalArray` * Add `ArrowFormat::MonthDayNanoIntervalType` * Add `ArrowFormat::MonthDayNanoIntervalArray` ### Are these changes tested? Yes. ### Are there any user-facing changes? Yes. * GitHub Issue: #48602 Lead-authored-by: Sutou Kouhei <[email protected]> Co-authored-by: Sutou Kouhei <[email protected]> Co-authored-by: Hiroyuki Sato <[email protected]> Signed-off-by: Sutou Kouhei <[email protected]>
1 parent c342ac5 commit 7be3c13

File tree

4 files changed

+145
-0
lines changed

4 files changed

+145
-0
lines changed

ruby/red-arrow-format/lib/arrow-format/array.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,39 @@ def to_a
189189
end
190190
end
191191

192+
class IntervalArray < TemporalArray
193+
end
194+
195+
class YearMonthIntervalArray < IntervalArray
196+
def to_a
197+
apply_validity(@values_buffer.values(:s32, 0, @size))
198+
end
199+
end
200+
201+
class DayTimeIntervalArray < IntervalArray
202+
def to_a
203+
values = @values_buffer.
204+
each(:s32, 0, @size * 2).
205+
each_slice(2).
206+
collect do |(_, day), (_, time)|
207+
[day, time]
208+
end
209+
apply_validity(values)
210+
end
211+
end
212+
213+
class MonthDayNanoIntervalArray < IntervalArray
214+
def to_a
215+
buffer_types = [:s32, :s32, :s64]
216+
value_size = IO::Buffer.size_of(buffer_types)
217+
values = @size.times.collect do |i|
218+
offset = value_size * i
219+
@values_buffer.get_values(buffer_types, offset)
220+
end
221+
apply_validity(values)
222+
end
223+
end
224+
192225
class DurationArray < TemporalArray
193226
def to_a
194227
apply_validity(@values_buffer.values(:s64, 0, @size))

ruby/red-arrow-format/lib/arrow-format/file-reader.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
require_relative "org/apache/arrow/flatbuf/floating_point"
3232
require_relative "org/apache/arrow/flatbuf/footer"
3333
require_relative "org/apache/arrow/flatbuf/int"
34+
require_relative "org/apache/arrow/flatbuf/interval"
35+
require_relative "org/apache/arrow/flatbuf/interval_unit"
3436
require_relative "org/apache/arrow/flatbuf/large_binary"
3537
require_relative "org/apache/arrow/flatbuf/large_list"
3638
require_relative "org/apache/arrow/flatbuf/large_utf8"
@@ -215,6 +217,15 @@ def read_field(fb_field)
215217
when Org::Apache::Arrow::Flatbuf::Timestamp
216218
unit = fb_type.unit.name.downcase.to_sym
217219
type = TimestampType.new(unit, fb_type.timezone)
220+
when Org::Apache::Arrow::Flatbuf::Interval
221+
case fb_type.unit
222+
when Org::Apache::Arrow::Flatbuf::IntervalUnit::YEAR_MONTH
223+
type = YearMonthIntervalType.new
224+
when Org::Apache::Arrow::Flatbuf::IntervalUnit::DAY_TIME
225+
type = DayTimeIntervalType.new
226+
when Org::Apache::Arrow::Flatbuf::IntervalUnit::MONTH_DAY_NANO
227+
type = MonthDayNanoIntervalType.new
228+
end
218229
when Org::Apache::Arrow::Flatbuf::Duration
219230
unit = fb_type.unit.name.downcase.to_sym
220231
type = DurationType.new(unit)

ruby/red-arrow-format/lib/arrow-format/type.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,42 @@ def build_array(size, validity_buffer, values_buffer)
315315
end
316316
end
317317

318+
class IntervalType < TemporalType
319+
end
320+
321+
class YearMonthIntervalType < IntervalType
322+
def initialize
323+
super("YearMonthInterval")
324+
end
325+
326+
def build_array(size, validity_buffer, values_buffer)
327+
YearMonthIntervalArray.new(self, size, validity_buffer, values_buffer)
328+
end
329+
end
330+
331+
class DayTimeIntervalType < IntervalType
332+
def initialize
333+
super("DayTimeInterval")
334+
end
335+
336+
def build_array(size, validity_buffer, values_buffer)
337+
DayTimeIntervalArray.new(self, size, validity_buffer, values_buffer)
338+
end
339+
end
340+
341+
class MonthDayNanoIntervalType < IntervalType
342+
def initialize
343+
super("MonthDayNanoInterval")
344+
end
345+
346+
def build_array(size, validity_buffer, values_buffer)
347+
MonthDayNanoIntervalArray.new(self,
348+
size,
349+
validity_buffer,
350+
values_buffer)
351+
end
352+
end
353+
318354
class DurationType < TemporalType
319355
attr_reader :unit
320356
def initialize(unit)

ruby/red-arrow-format/test/test-file-reader.rb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,71 @@ def test_type
489489
end
490490
end
491491

492+
sub_test_case("YearMonthInterval") do
493+
def build_array
494+
Arrow::MonthIntervalArray.new([0, nil, 100])
495+
end
496+
497+
def test_read
498+
assert_equal([{"value" => [0, nil, 100]}],
499+
read)
500+
end
501+
end
502+
503+
sub_test_case("DayTimeInterval") do
504+
def build_array
505+
Arrow::DayTimeIntervalArray.new([
506+
{day: 1, millisecond: 100},
507+
nil,
508+
{day: 3, millisecond: 300},
509+
])
510+
end
511+
512+
def test_read
513+
assert_equal([
514+
{
515+
"value" => [
516+
[1, 100],
517+
nil,
518+
[3, 300],
519+
],
520+
},
521+
],
522+
read)
523+
end
524+
end
525+
526+
sub_test_case("MonthDayNanoInterval") do
527+
def build_array
528+
Arrow::MonthDayNanoIntervalArray.new([
529+
{
530+
month: 1,
531+
day: 1,
532+
nanosecond: 100,
533+
},
534+
nil,
535+
{
536+
month: 3,
537+
day: 3,
538+
nanosecond: 300,
539+
},
540+
])
541+
end
542+
543+
def test_read
544+
assert_equal([
545+
{
546+
"value" => [
547+
[1, 1, 100],
548+
nil,
549+
[3, 3, 300],
550+
],
551+
},
552+
],
553+
read)
554+
end
555+
end
556+
492557
sub_test_case("Duration(:second)") do
493558
def build_array
494559
Arrow::DurationArray.new(:second, [0, nil, 100])

0 commit comments

Comments
 (0)