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

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


The following commit(s) were added to refs/heads/main by this push:
     new 2b2e5c70 fix(arrow/array): skip empty table chunks (#1023)
2b2e5c70 is described below

commit 2b2e5c7040e5c65b85fadb90284acad8508eed94
Author: Minh Vu <[email protected]>
AuthorDate: Mon Jul 27 22:30:48 2026 +0200

    fix(arrow/array): skip empty table chunks (#1023)
    
    ### Rationale for this change
    
    TableReader treats an empty column chunk as the next batch boundary. A
    valid table with an empty chunk therefore emits a zero-row record batch
    before returning its actual rows.
    
    ### What changes are included in this PR?
    
    * Advance each column past empty chunks before calculating the next
    batch size.
    * Keep chunk slots synchronized without exposing zero-row batches.
    
    ### Are these changes tested?
    
    Yes. The regression test builds a valid chunked column with empty chunks
    and verifies that only the non-empty batch is returned. The full
    arrow/array package, assertion build, compute packages, and IPC package
    also pass.
---
 arrow/array/table.go      |  5 +++++
 arrow/array/table_test.go | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/arrow/array/table.go b/arrow/array/table.go
index 6bd44045..92d265e0 100644
--- a/arrow/array/table.go
+++ b/arrow/array/table.go
@@ -353,6 +353,11 @@ func (tr *TableReader) Next() bool {
        for i := range chunks {
                j := tr.slots[i]
                chunk := tr.chunks[i].Chunk(j)
+               for chunk.Len() == 0 && j+1 < len(tr.chunks[i].Chunks()) {
+                       j++
+                       tr.slots[i] = j
+                       chunk = tr.chunks[i].Chunk(j)
+               }
                remain := int64(chunk.Len()) - tr.offsets[i]
                if remain < chunksz {
                        chunksz = remain
diff --git a/arrow/array/table_test.go b/arrow/array/table_test.go
index 110b1c7c..08fea1a8 100644
--- a/arrow/array/table_test.go
+++ b/arrow/array/table_test.go
@@ -845,6 +845,39 @@ func TestTableReader(t *testing.T) {
        }
 }
 
+func TestTableReaderSkipsEmptyChunks(t *testing.T) {
+       mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
+       defer mem.AssertSize(t, 0)
+
+       builder := array.NewInt32Builder(mem)
+       empty := builder.NewInt32Array()
+       defer empty.Release()
+       builder.AppendValues([]int32{1, 2}, nil)
+       values := builder.NewInt32Array()
+       defer values.Release()
+       builder.Release()
+
+       chunked := arrow.NewChunked(arrow.PrimitiveTypes.Int32, 
[]arrow.Array{empty, values, empty})
+       defer chunked.Release()
+       field := arrow.Field{Name: "values", Type: arrow.PrimitiveTypes.Int32}
+       column := arrow.NewColumn(field, chunked)
+       defer column.Release()
+       table := array.NewTable(arrow.NewSchema([]arrow.Field{field}, nil), 
[]arrow.Column{*column}, -1)
+       defer table.Release()
+
+       reader := array.NewTableReader(table, 10)
+       defer reader.Release()
+       if !reader.Next() {
+               t.Fatal("expected a record batch")
+       }
+       if got, want := reader.RecordBatch().NumRows(), int64(2); got != want {
+               t.Fatalf("invalid number of rows: got=%d, want=%d", got, want)
+       }
+       if reader.Next() {
+               t.Fatal("unexpected additional record batch")
+       }
+}
+
 func TestTableToString(t *testing.T) {
        mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
        defer mem.AssertSize(t, 0)

Reply via email to