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 caec5052 fix(arrow/array): make dictionary suffix null indexes 
relative (#1064)
caec5052 is described below

commit caec50527ba7d3ad375635efde10dfe89a0e794f
Author: Minh Vu <[email protected]>
AuthorDate: Wed Aug 5 19:46:32 2026 +0200

    fix(arrow/array): make dictionary suffix null indexes relative (#1064)
    
    ## What changed
    
    Clear the validity bit using the null index relative to `startOffset`
    when exporting a dictionary suffix.
    
    ## Why
    
    `GetDictArrayData` builds a new dictionary whose bitmap starts at the
    requested offset, but it previously cleared the absolute memo-table
    index. For nonzero offsets this could mark the wrong dictionary entry
    valid while still reporting one null.
    
    The regression test exports a suffix containing a null and verifies that
    the corresponding relative entry is null.
    
    ## Testing
    
    - `go test ./arrow/array`
---
 arrow/array/util.go      |  2 +-
 arrow/array/util_test.go | 26 ++++++++++++++++++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/arrow/array/util.go b/arrow/array/util.go
index e369f788..1b303bf6 100644
--- a/arrow/array/util.go
+++ b/arrow/array/util.go
@@ -370,7 +370,7 @@ func GetDictArrayData(mem memory.Allocator, valueType 
arrow.DataType, memoTable
                nullcount = 1
                buffers[0].Resize(int(bitutil.BytesForBits(int64(dictLen))))
                memory.Set(buffers[0].Bytes(), 0xFF)
-               bitutil.ClearBit(buffers[0].Bytes(), idx)
+               bitutil.ClearBit(buffers[0].Bytes(), idx-startOffset)
        }
 
        return NewData(valueType, dictLen, buffers, nil, nullcount, 0), nil
diff --git a/arrow/array/util_test.go b/arrow/array/util_test.go
index 8fd36be8..6870cf8b 100644
--- a/arrow/array/util_test.go
+++ b/arrow/array/util_test.go
@@ -32,11 +32,37 @@ import (
        "github.com/apache/arrow-go/v18/arrow/decimal256"
        "github.com/apache/arrow-go/v18/arrow/internal/arrdata"
        "github.com/apache/arrow-go/v18/arrow/memory"
+       "github.com/apache/arrow-go/v18/internal/hashing"
        "github.com/apache/arrow-go/v18/internal/json"
        "github.com/stretchr/testify/assert"
        "github.com/stretchr/testify/require"
 )
 
+func TestGetDictArrayDataNullInSuffix(t *testing.T) {
+       mem := memory.NewCheckedAllocator(memory.DefaultAllocator)
+       defer mem.AssertSize(t, 0)
+
+       memo := hashing.NewMemoTable[int32](0)
+       for _, value := range []int32{10, 20, 30, 40} {
+               _, _, err := memo.GetOrInsert(value)
+               require.NoError(t, err)
+       }
+       nullIndex, found := memo.GetOrInsertNull()
+       require.False(t, found)
+       require.Equal(t, 4, nullIndex)
+
+       data, err := array.GetDictArrayData(mem, arrow.PrimitiveTypes.Int32, 
memo, 3)
+       require.NoError(t, err)
+       defer data.Release()
+
+       dict := array.MakeFromData(data)
+       defer dict.Release()
+       require.Equal(t, 2, dict.Len())
+       require.Equal(t, 1, dict.NullN())
+       assert.False(t, dict.IsNull(0))
+       assert.True(t, dict.IsNull(1))
+}
+
 var typemap = map[arrow.DataType]reflect.Type{
        arrow.PrimitiveTypes.Int8:   reflect.TypeOf(int8(0)),
        arrow.PrimitiveTypes.Uint8:  reflect.TypeOf(uint8(0)),

Reply via email to