diff --git a/cpp/src/arrow/ipc/writer.cc b/cpp/src/arrow/ipc/writer.cc index 8917410b27e..37927a47f33 100644 --- a/cpp/src/arrow/ipc/writer.cc +++ b/cpp/src/arrow/ipc/writer.cc @@ -346,6 +346,16 @@ class RecordBatchSerializer : public ArrayVisitor { Status Visit(const MapArray& array) override { return VisitList(array); } + Status Visit(const FixedSizeListArray& array) override { + --max_recursion_depth_; + auto size = array.list_type()->list_size(); + auto values = array.values()->Slice(array.offset() * size, array.length() * size); + + RETURN_NOT_OK(VisitArray(*values)); + ++max_recursion_depth_; + return Status::OK(); + } + Status Visit(const StructArray& array) override { --max_recursion_depth_; for (int i = 0; i < array.num_fields(); ++i) { diff --git a/integration/integration_test.py b/integration/integration_test.py index cb0501d843c..fad625ef208 100644 --- a/integration/integration_test.py +++ b/integration/integration_test.py @@ -765,6 +765,47 @@ def _get_children(self): return [self.pairs.get_json()] +class FixedSizeListType(DataType): + + def __init__(self, name, value_type, list_size, nullable=True): + super(FixedSizeListType, self).__init__(name, nullable=nullable) + self.value_type = value_type + self.list_size = list_size + + def _get_type(self): + return OrderedDict([ + ('name', 'fixedsizelist'), + ('listSize', self.list_size) + ]) + + def _get_children(self): + return [self.value_type.get_json()] + + def generate_column(self, size, name=None): + is_valid = self._make_is_valid(size) + values = self.value_type.generate_column(size * self.list_size) + + if name is None: + name = self.name + return FixedSizeListColumn(name, size, is_valid, values) + + +class FixedSizeListColumn(Column): + + def __init__(self, name, count, is_valid, values): + super(FixedSizeListColumn, self).__init__(name, count) + self.is_valid = is_valid + self.values = values + + def _get_buffers(self): + return [ + ('VALIDITY', [int(v) for v in self.is_valid]) + ] + + def _get_children(self): + return [self.values.get_json()] + + class StructType(DataType): def __init__(self, name, field_types, nullable=True): @@ -1032,6 +1073,8 @@ def generate_map_case(): def generate_nested_case(): fields = [ ListType('list_nullable', get_field('item', 'int32')), + FixedSizeListType('fixedsizelist_nullable', + get_field('item', 'int32'), 4), StructType('struct_nullable', [get_field('f1', 'int32'), get_field('f2', 'utf8')]), diff --git a/java/vector/src/main/java/org/apache/arrow/vector/ipc/ArrowFileReader.java b/java/vector/src/main/java/org/apache/arrow/vector/ipc/ArrowFileReader.java index aa25abd8267..e9ffaef78a0 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/ipc/ArrowFileReader.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/ipc/ArrowFileReader.java @@ -142,7 +142,7 @@ public boolean loadRecordBatch(ArrowBlock block) throws IOException { ensureInitialized(); int blockIndex = footer.getRecordBatches().indexOf(block); if (blockIndex == -1) { - throw new IllegalArgumentException("Arrow bock does not exist in record batches: " + block); + throw new IllegalArgumentException("Arrow block does not exist in record batches: " + block); } currentRecordBatch = blockIndex; return loadNextBatch();