Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion ruby/red-arrow/lib/arrow/struct-array-builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,20 @@ def append_value(*args)
value.each_with_index do |sub_value, i|
self[i].append_value(sub_value)
end
when Arrow::Struct
append_value_raw
value.values.each_with_index do |sub_value, i|
self[i].append_value(sub_value)
end
when Hash
append_value_raw
value.each do |name, sub_value|
self[name].append_value(sub_value)
end
else
message = "struct value must be nil, Array or Hash: #{value.inspect}"
message =
"struct value must be nil, Array, " +
"Arrow::Struct or Hash: #{value.inspect}"
raise ArgumentError, message
end
else
Expand Down
34 changes: 34 additions & 0 deletions ruby/red-arrow/lib/arrow/struct-array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,44 @@
# specific language governing permissions and limitations
# under the License.

require "arrow/struct"

module Arrow
class StructArray
def [](i)
warn("Use #{self.class}\#find_field instead. " +
"This will returns Arrow::Struct instead of Arrow::Array " +
"since 0.13.0.")
get_field(i)
end

def get_value(i)
Struct.new(self, i)
end

def find_field(index_or_name)
case index_or_name
when String, Symbol
name = index_or_name
(@name_to_field ||= build_name_to_field)[name.to_s]
else
index = index_or_name
cached_fields[index]
end
end

private
def cached_fields
@fields ||= fields
end

def build_name_to_field
name_to_field = {}
field_arrays = cached_fields
value_data_type.fields.each_with_index do |field, i|
name_to_field[field.name] = field_arrays[i]
end
name_to_field
end
end
end
68 changes: 68 additions & 0 deletions ruby/red-arrow/lib/arrow/struct.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# 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 Struct
attr_accessor :index
def initialize(array, index)
@array = array
@index = index
end

def [](field_name_or_field_index)
field = @array.find_field(field_name_or_field_index)
return nil if field.nil?
field[@index]
end

def fields
@array.value_data_type.fields
end

def values
@array.fields.collect do |field|
field[@index]
end
end

def to_a
values
end

def to_h
attributes = {}
field_arrays = @array.fields
fields.each_with_index do |field, i|
attributes[field.name] = field_arrays[i][@index]
end
attributes
end

def respond_to_missing?(name, include_private)
return true if @array.find_field(name)
super
end

def method_missing(name, *args, &block)
if args.empty?
field = @array.find_field(name)
return field[@index] if field
end
super
end
end
end
47 changes: 31 additions & 16 deletions ruby/red-arrow/test/test-struct-array-builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ def setup
[nil],
],
[
array[0].to_a,
array[1].to_a,
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end

Expand All @@ -44,8 +44,23 @@ def setup
[1],
],
[
array[0].to_a,
array[1].to_a,
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end

test("Arrow::Struct") do
source_array = Arrow::StructArray.new(@data_type, [[true, 1]])
struct = source_array.get_value(0)
@builder.append_value(struct)
array = @builder.finish
assert_equal([
[true],
[1],
],
[
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end

Expand All @@ -57,8 +72,8 @@ def setup
[1],
],
[
array[0].to_a,
array[1].to_a,
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end
end
Expand All @@ -72,8 +87,8 @@ def setup
[nil],
],
[
array[0].to_a,
array[1].to_a,
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end

Expand All @@ -85,8 +100,8 @@ def setup
[1],
],
[
array[0].to_a,
array[1].to_a,
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end

Expand All @@ -98,8 +113,8 @@ def setup
[1],
],
[
array[0].to_a,
array[1].to_a,
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end

Expand All @@ -115,8 +130,8 @@ def setup
[nil, 1, 2],
],
[
array[0].to_a,
array[1].to_a,
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end

Expand All @@ -137,8 +152,8 @@ def setup
[1, nil, 3],
],
[
array[0].to_a,
array[1].to_a,
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end
end
Expand Down
58 changes: 41 additions & 17 deletions ruby/red-arrow/test/test-struct-array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,51 @@ class StructArrayTest < Test::Unit::TestCase
[1, nil, 2],
],
[
array[0].to_a,
array[1].to_a,
array.find_field(0).to_a,
array.find_field(1).to_a,
])
end
end

test("#[]") do
type = Arrow::StructDataType.new([
Arrow::Field.new("field1", :boolean),
Arrow::Field.new("field2", :uint64),
])
builder = Arrow::StructArrayBuilder.new(type)
builder.append
builder.get_field_builder(0).append(true)
builder.get_field_builder(1).append(1)
builder.append
builder.get_field_builder(0).append(false)
builder.get_field_builder(1).append(2)
array = builder.finish
sub_test_case("instance methods") do
def setup
@data_type = Arrow::StructDataType.new(visible: {type: :boolean},
count: {type: :uint64})
@values = [
[true, 1],
[false, 2],
]
@array = Arrow::StructArray.new(@data_type, @values)
end

assert_equal([[true, false], [1, 2]],
[array[0].to_a, array[1].to_a])
test("#[]") do
notify("TODO: Returns Arrow::Struct instead.")
assert_equal([[true, false], [1, 2]],
[@array[0].to_a, @array[1].to_a])
end

sub_test_case("#find_field") do
test("Integer") do
assert_equal([
[true, false],
[1, 2],
],
[
@array.find_field(0).to_a,
@array.find_field(1).to_a,
])
end

test("String, Symbol") do
assert_equal([
[true, false],
[1, 2],
],
[
@array.find_field("visible").to_a,
@array.find_field(:count).to_a,
])
end
end
end
end
81 changes: 81 additions & 0 deletions ruby/red-arrow/test/test-struct.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# 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 StructTest < Test::Unit::TestCase
def setup
@data_type = Arrow::StructDataType.new(visible: {type: :boolean},
count: {type: :uint64})
@values = [
[true, 1],
[false, 2],
]
@array = Arrow::StructArray.new(@data_type, @values)
@struct = @array.get_value(0)
end

sub_test_case("#[]") do
test("Integer") do
assert_equal(true, @struct[0])
end

test("String") do
assert_equal(true, @struct["visible"])
end

test("Symbol") do
assert_equal(true, @struct[:visible])
end
end

test("#fields") do
assert_equal(@data_type.fields,
@struct.fields)
end

test("#values") do
assert_equal([true, 1],
@struct.values)
end

test("#to_a") do
assert_equal([true, 1],
@struct.to_a)
end

test("#to_h") do
assert_equal({
"visible" => true,
"count" => 1,
},
@struct.to_h)
end

test("#respond_to_missing?") do
assert_equal([
true,
false,
],
[
@struct.respond_to?(:visible),
@struct.respond_to?(:nonexistent),
])
end

test("#method_missing?") do
assert_equal(1, @struct.count)
end
end