This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-java.git


The following commit(s) were added to refs/heads/main by this push:
     new 371b73d42 MINOR: Reject non zero offset on array import (#1263)
371b73d42 is described below

commit 371b73d4279fbca2b891f350a79dd9ec715efac6
Author: Robert Kruszewski <[email protected]>
AuthorDate: Mon Aug 31 14:40:46 2026 +0100

    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 <[email protected]>
    Co-authored-by: JB Onofré <[email protected]>
---
 .../java/org/apache/arrow/c/ArrayImporter.java     | 10 ++++
 c/src/main/java/org/apache/arrow/c/Data.java       |  3 +-
 .../java/org/apache/arrow/c/RoundtripTest.java     | 59 ++++++++++++++++++++++
 docs/source/cdata.rst                              |  5 ++
 4 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/c/src/main/java/org/apache/arrow/c/ArrayImporter.java 
b/c/src/main/java/org/apache/arrow/c/ArrayImporter.java
index f31a8a1fa..e92e83299 100644
--- a/c/src/main/java/org/apache/arrow/c/ArrayImporter.java
+++ b/c/src/main/java/org/apache/arrow/c/ArrayImporter.java
@@ -30,6 +30,7 @@ import org.apache.arrow.vector.FieldVector;
 import org.apache.arrow.vector.dictionary.Dictionary;
 import org.apache.arrow.vector.dictionary.DictionaryProvider;
 import org.apache.arrow.vector.ipc.message.ArrowFieldNode;
+import org.apache.arrow.vector.types.pojo.ArrowType;
 import org.apache.arrow.vector.types.pojo.DictionaryEncoding;
 
 /** Importer for {@link ArrowArray}. */
@@ -83,6 +84,15 @@ final class ArrayImporter {
   }
 
   private void doImport(ArrowArray.Snapshot snapshot) {
+    // A non-zero offset is only meaningful for arrays that have buffers to 
offset into.
+    // Null arrays carry no buffers, so their offset is inert and safe to 
ignore.
+    checkState(
+        snapshot.offset == 0
+            || snapshot.length == 0
+            || vector.getField().getType().getTypeID() == 
ArrowType.ArrowTypeID.Null,
+        "ArrowArray struct has non-zero offset (%s), which is not supported",
+        snapshot.offset);
+
     // First import children (required for reconstituting parent array data)
     long[] children =
         NativeUtil.toJavaArray(snapshot.children, 
checkedCastToInt(snapshot.n_children));
diff --git a/c/src/main/java/org/apache/arrow/c/Data.java 
b/c/src/main/java/org/apache/arrow/c/Data.java
index f9d2ee454..d870b5884 100644
--- a/c/src/main/java/org/apache/arrow/c/Data.java
+++ b/c/src/main/java/org/apache/arrow/c/Data.java
@@ -35,7 +35,8 @@ import org.apache.arrow.vector.types.pojo.Schema;
 /**
  * Functions for working with the C data interface.
  *
- * <p>This API is EXPERIMENTAL. Note that currently only 64bit systems are 
supported.
+ * <p>This API is EXPERIMENTAL. Note that currently only 64bit systems are 
supported. Importing
+ * {@link ArrowArray ArrowArrays} with a non-zero offset is not supported.
  */
 public final class Data {
 
diff --git a/c/src/test/java/org/apache/arrow/c/RoundtripTest.java 
b/c/src/test/java/org/apache/arrow/c/RoundtripTest.java
index f6ff88571..7a301cc3e 100644
--- a/c/src/test/java/org/apache/arrow/c/RoundtripTest.java
+++ b/c/src/test/java/org/apache/arrow/c/RoundtripTest.java
@@ -1051,6 +1051,65 @@ public class RoundtripTest {
     }
   }
 
+  @Test
+  public void testImportArrayWithNonZeroOffset() {
+    try (IntVector source = new IntVector("source", allocator);
+        IntVector destination = new IntVector("destination", allocator);
+        ArrowArray array = ArrowArray.allocateNew(allocator)) {
+      setVector(source, 1, 2, 3);
+      Data.exportVector(allocator, source, null, array);
+
+      ArrowArray.Snapshot snapshot = array.snapshot();
+      snapshot.offset = 1;
+      array.save(snapshot);
+
+      Exception e =
+          assertThrows(
+              IllegalStateException.class,
+              () -> Data.importIntoVector(allocator, array, destination, 
null));
+      assertEquals(
+          "ArrowArray struct has non-zero offset (1), which is not supported", 
e.getMessage());
+    }
+  }
+
+  @Test
+  public void testImportEmptyArrayWithNonZeroOffset() {
+    try (IntVector source = new IntVector("source", allocator);
+        IntVector destination = new IntVector("destination", allocator);
+        ArrowArray array = ArrowArray.allocateNew(allocator)) {
+      setVector(source, 1, 2, 3);
+      Data.exportVector(allocator, source, null, array);
+
+      ArrowArray.Snapshot snapshot = array.snapshot();
+      snapshot.offset = source.getValueCount();
+      snapshot.length = 0;
+      array.save(snapshot);
+
+      Data.importIntoVector(allocator, array, destination, null);
+      assertEquals(0, destination.getValueCount());
+    }
+  }
+
+  @Test
+  public void testImportNullArrayWithNonZeroOffset() {
+    try (NullVector source = new NullVector("source", 10);
+        NullVector destination = new NullVector("destination");
+        ArrowArray array = ArrowArray.allocateNew(allocator)) {
+      Data.exportVector(allocator, source, null, array);
+
+      // Mimic a sliced null array. Arrow C++ propagates the slice offset onto 
the struct
+      // even for null arrays, which export no buffers at all (n_buffers == 
0), so there is
+      // nothing for the offset to apply to and the import is safe.
+      ArrowArray.Snapshot snapshot = array.snapshot();
+      snapshot.offset = 2;
+      snapshot.length = 8;
+      array.save(snapshot);
+
+      Data.importIntoVector(allocator, array, destination, null);
+      assertEquals(8, destination.getValueCount());
+    }
+  }
+
   @Test
   public void testArrayStructReuse() {
     // Consumer allocates empty structures
diff --git a/docs/source/cdata.rst b/docs/source/cdata.rst
index 7b2924d25..d2b5ab0cc 100644
--- a/docs/source/cdata.rst
+++ b/docs/source/cdata.rst
@@ -22,6 +22,11 @@ C Data Interface
 Arrow supports exchanging data without copying or serialization within the 
same process
 through :external+arrow:ref:`c-data-interface`, even between different 
language runtimes.
 
+.. note::
+
+   The Arrow Java C Data Interface implementation does not support importing 
arrays with
+   a non-zero offset.
+
 Java to Python
 --------------
 

Reply via email to