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 601311b  Fix: Handle null values in PlainFixedLenByteArrayEncoder 
gracefully (#320)
601311b is described below

commit 601311bdb15c4c2612779a361acf0f66f9f5b754
Author: Saurabh Singh <[email protected]>
AuthorDate: Mon Mar 24 18:37:47 2025 +0530

    Fix: Handle null values in PlainFixedLenByteArrayEncoder gracefully (#320)
    
    Fixes: #71
    
    ### Rationale for this change
    Ensures `PlainFixedLenByteArrayEncoder` handles null values gracefully
    in non-nullable fields by writing zero-filled bytes instead of
    panicking, maintaining consistency with `DictFixedLenByteArrayEncoder`.
    
    ### What changes are included in this PR?
    
    - Replaces panics on null values with writing zero-filled bytes to
    maintain byte alignment.
    - Ensures encoding consistency between dictionary and plain encoding.
    - Prevents unexpected failures when handling schema inconsistencies.
    
    
    ### Are these changes tested?
    Yes:
    
    - Passed existing test suite.
    - Verified with local Arrow-Go modifications.
    
    ### Are there any user-facing changes?
    Not Sure (Need possible guidance if required)
    
    ---------
    
    Signed-off-by: Saurabh Kumar Singh <[email protected]>
---
 .../encoding/fixed_len_byte_array_encoder.go       |  8 ++-
 .../encoding/fixed_len_byte_array_encoder_test.go  | 80 ++++++++++++++++++++++
 2 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/parquet/internal/encoding/fixed_len_byte_array_encoder.go 
b/parquet/internal/encoding/fixed_len_byte_array_encoder.go
index 3f2a097..56cf242 100644
--- a/parquet/internal/encoding/fixed_len_byte_array_encoder.go
+++ b/parquet/internal/encoding/fixed_len_byte_array_encoder.go
@@ -41,11 +41,15 @@ func (enc *PlainFixedLenByteArrayEncoder) Put(in 
[]parquet.FixedLenByteArray) {
 
        bytesNeeded := len(in) * typeLen
        enc.sink.Reserve(bytesNeeded)
+
+       emptyValue := make([]byte, typeLen)
+
        for _, val := range in {
                if val == nil {
-                       panic("value cannot be nil")
+                       enc.sink.UnsafeWrite(emptyValue)
+               } else {
+                       enc.sink.UnsafeWrite(val[:typeLen])
                }
-               enc.sink.UnsafeWrite(val[:typeLen])
        }
 }
 
diff --git a/parquet/internal/encoding/fixed_len_byte_array_encoder_test.go 
b/parquet/internal/encoding/fixed_len_byte_array_encoder_test.go
new file mode 100644
index 0000000..67e83b0
--- /dev/null
+++ b/parquet/internal/encoding/fixed_len_byte_array_encoder_test.go
@@ -0,0 +1,80 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package encoding
+
+import (
+       "testing"
+
+       "github.com/apache/arrow-go/v18/parquet"
+       "github.com/apache/arrow-go/v18/parquet/schema"
+       "github.com/stretchr/testify/require"
+)
+
+func TestPlainFixedLenByteArrayEncoder_Put(t *testing.T) {
+       sink := NewPooledBufferWriter(0)
+       elem := schema.NewFixedLenByteArrayNode("test", 
parquet.Repetitions.Required, 4, 0)
+       descr := schema.NewColumn(elem, 0, 0)
+       encoder := &PlainFixedLenByteArrayEncoder{
+               encoder: encoder{
+                       descr: descr,
+                       sink:  sink,
+               },
+       }
+
+       tests := []struct {
+               name     string
+               input    []parquet.FixedLenByteArray
+               expected []byte
+       }{
+               {
+                       name: "Normal input",
+                       input: []parquet.FixedLenByteArray{
+                               []byte("abcd"),
+                               []byte("efgh"),
+                               []byte("ijkl"),
+                       },
+                       expected: []byte("abcdefghijkl"),
+               },
+               {
+                       name: "Input with nil values",
+                       input: []parquet.FixedLenByteArray{
+                               []byte("abcd"),
+                               nil,
+                               []byte("ijkl"),
+                       },
+                       expected: []byte("abcd\x00\x00\x00\x00ijkl"), // Nil 
replaced with zero bytes
+               },
+               {
+                       name:     "Empty input",
+                       input:    []parquet.FixedLenByteArray{},
+                       expected: []byte{},
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       // Reset the sink before each test
+                       sink.Reset(0)
+
+                       // Perform the encoding
+                       encoder.Put(tt.input)
+
+                       // Assert the result
+                       require.Equal(t, tt.expected, sink.Bytes(), "Encoded 
bytes should match expected output")
+               })
+       }
+}

Reply via email to