Skip to content

Commit 371b73d

Browse files
robert3005jbonofre
andauthored
MINOR: Reject non zero offset on array import (#1263)
## What's Changed Instead of silently accepting the array and pretending the import went fine reject arrays where offset is non 0. Add mention to the docs that this is not supported This is documentation and negative case for #251 --------- Signed-off-by: Robert Kruszewski <github@robertk.io> Co-authored-by: JB Onofré <jb.onofre@dremio.com>
1 parent df0627d commit 371b73d

4 files changed

Lines changed: 76 additions & 1 deletion

File tree

c/src/main/java/org/apache/arrow/c/ArrayImporter.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.arrow.vector.dictionary.Dictionary;
3131
import org.apache.arrow.vector.dictionary.DictionaryProvider;
3232
import org.apache.arrow.vector.ipc.message.ArrowFieldNode;
33+
import org.apache.arrow.vector.types.pojo.ArrowType;
3334
import org.apache.arrow.vector.types.pojo.DictionaryEncoding;
3435

3536
/** Importer for {@link ArrowArray}. */
@@ -83,6 +84,15 @@ private void importChild(ArrayImporter parent, ArrowArray src) {
8384
}
8485

8586
private void doImport(ArrowArray.Snapshot snapshot) {
87+
// A non-zero offset is only meaningful for arrays that have buffers to offset into.
88+
// Null arrays carry no buffers, so their offset is inert and safe to ignore.
89+
checkState(
90+
snapshot.offset == 0
91+
|| snapshot.length == 0
92+
|| vector.getField().getType().getTypeID() == ArrowType.ArrowTypeID.Null,
93+
"ArrowArray struct has non-zero offset (%s), which is not supported",
94+
snapshot.offset);
95+
8696
// First import children (required for reconstituting parent array data)
8797
long[] children =
8898
NativeUtil.toJavaArray(snapshot.children, checkedCastToInt(snapshot.n_children));

c/src/main/java/org/apache/arrow/c/Data.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
/**
3636
* Functions for working with the C data interface.
3737
*
38-
* <p>This API is EXPERIMENTAL. Note that currently only 64bit systems are supported.
38+
* <p>This API is EXPERIMENTAL. Note that currently only 64bit systems are supported. Importing
39+
* {@link ArrowArray ArrowArrays} with a non-zero offset is not supported.
3940
*/
4041
public final class Data {
4142

c/src/test/java/org/apache/arrow/c/RoundtripTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,65 @@ public void testImportReleasedArray() {
10511051
}
10521052
}
10531053

1054+
@Test
1055+
public void testImportArrayWithNonZeroOffset() {
1056+
try (IntVector source = new IntVector("source", allocator);
1057+
IntVector destination = new IntVector("destination", allocator);
1058+
ArrowArray array = ArrowArray.allocateNew(allocator)) {
1059+
setVector(source, 1, 2, 3);
1060+
Data.exportVector(allocator, source, null, array);
1061+
1062+
ArrowArray.Snapshot snapshot = array.snapshot();
1063+
snapshot.offset = 1;
1064+
array.save(snapshot);
1065+
1066+
Exception e =
1067+
assertThrows(
1068+
IllegalStateException.class,
1069+
() -> Data.importIntoVector(allocator, array, destination, null));
1070+
assertEquals(
1071+
"ArrowArray struct has non-zero offset (1), which is not supported", e.getMessage());
1072+
}
1073+
}
1074+
1075+
@Test
1076+
public void testImportEmptyArrayWithNonZeroOffset() {
1077+
try (IntVector source = new IntVector("source", allocator);
1078+
IntVector destination = new IntVector("destination", allocator);
1079+
ArrowArray array = ArrowArray.allocateNew(allocator)) {
1080+
setVector(source, 1, 2, 3);
1081+
Data.exportVector(allocator, source, null, array);
1082+
1083+
ArrowArray.Snapshot snapshot = array.snapshot();
1084+
snapshot.offset = source.getValueCount();
1085+
snapshot.length = 0;
1086+
array.save(snapshot);
1087+
1088+
Data.importIntoVector(allocator, array, destination, null);
1089+
assertEquals(0, destination.getValueCount());
1090+
}
1091+
}
1092+
1093+
@Test
1094+
public void testImportNullArrayWithNonZeroOffset() {
1095+
try (NullVector source = new NullVector("source", 10);
1096+
NullVector destination = new NullVector("destination");
1097+
ArrowArray array = ArrowArray.allocateNew(allocator)) {
1098+
Data.exportVector(allocator, source, null, array);
1099+
1100+
// Mimic a sliced null array. Arrow C++ propagates the slice offset onto the struct
1101+
// even for null arrays, which export no buffers at all (n_buffers == 0), so there is
1102+
// nothing for the offset to apply to and the import is safe.
1103+
ArrowArray.Snapshot snapshot = array.snapshot();
1104+
snapshot.offset = 2;
1105+
snapshot.length = 8;
1106+
array.save(snapshot);
1107+
1108+
Data.importIntoVector(allocator, array, destination, null);
1109+
assertEquals(8, destination.getValueCount());
1110+
}
1111+
}
1112+
10541113
@Test
10551114
public void testArrayStructReuse() {
10561115
// Consumer allocates empty structures

docs/source/cdata.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ C Data Interface
2222
Arrow supports exchanging data without copying or serialization within the same process
2323
through :external+arrow:ref:`c-data-interface`, even between different language runtimes.
2424

25+
.. note::
26+
27+
The Arrow Java C Data Interface implementation does not support importing arrays with
28+
a non-zero offset.
29+
2530
Java to Python
2631
--------------
2732

0 commit comments

Comments
 (0)