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 48a8340e fix(arrow/ipc): return compression errors from record encoder 
(#1141)
48a8340e is described below

commit 48a8340efd5d1ca7038c5126ac9fdb4c709b444a
Author: Minh Vu <[email protected]>
AuthorDate: Fri Aug 14 19:30:29 2026 +0200

    fix(arrow/ipc): return compression errors from record encoder (#1141)
    
    ### Rationale for this change
    
    `recordEncoder.encode` ignored errors returned by body compression, so a
    failed compressor could still result in record metadata being built and
    returned as a successful encode.
    
    ### What changes are included in this PR?
    
    Return compression errors from `recordEncoder.encode`, release the
    temporary compressed buffer on failure, and add a regression test with a
    failing compressor.
    
    ### Are these changes tested?
    
    - `go test ./arrow/ipc`
    
    ### Are there any user-facing changes?
    
    IPC record encoding now reports compressor failures to the caller.
---
 arrow/ipc/ipc.go         |  7 +++++++
 arrow/ipc/writer.go      |  4 +++-
 arrow/ipc/writer_test.go | 33 ++++++++++++++++++++++++++++-----
 3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/arrow/ipc/ipc.go b/arrow/ipc/ipc.go
index da9cf333..9a043d9b 100644
--- a/arrow/ipc/ipc.go
+++ b/arrow/ipc/ipc.go
@@ -75,6 +75,7 @@ type config struct {
        minSpaceSavings    float64
        maxMetadataSize    int64
        maxBodySize        int64
+       compressors        []compressor
 }
 
 const (
@@ -86,6 +87,12 @@ const (
 // and streams.
 type Option func(*config)
 
+func withCompressors(compressors ...compressor) Option {
+       return func(cfg *config) {
+               cfg.compressors = compressors
+       }
+}
+
 func newConfig(opts ...Option) *config {
        cfg := &config{
                alloc:              memory.NewGoAllocator(),
diff --git a/arrow/ipc/writer.go b/arrow/ipc/writer.go
index 32edaf25..24340f44 100644
--- a/arrow/ipc/writer.go
+++ b/arrow/ipc/writer.go
@@ -1153,6 +1153,8 @@ func needTruncate(offset int64, buf *memory.Buffer, 
minLength int64) bool {
 // method after it is no longer needed.
 func GetRecordBatchPayload(batch arrow.RecordBatch, opts ...Option) (Payload, 
error) {
        cfg := newConfig(opts...)
+       compressors := make([]compressor, cfg.compressNP)
+       copy(compressors, cfg.compressors)
        var (
                data = Payload{msg: MessageRecordBatch}
                enc  = newRecordEncoder(
@@ -1163,7 +1165,7 @@ func GetRecordBatchPayload(batch arrow.RecordBatch, opts 
...Option) (Payload, er
                        cfg.codec,
                        cfg.compressNP,
                        cfg.minSpaceSavings,
-                       make([]compressor, cfg.compressNP),
+                       compressors,
                )
        )
 
diff --git a/arrow/ipc/writer_test.go b/arrow/ipc/writer_test.go
index 957d812c..6d18f5f0 100644
--- a/arrow/ipc/writer_test.go
+++ b/arrow/ipc/writer_test.go
@@ -48,13 +48,19 @@ type failingPayloadWriter struct {
 type shortWriteWriter struct{}
 
 type failingCompressor struct {
-       err error
+       err      error
+       closeErr error
 }
 
-func (failingCompressor) MaxCompressedLen(n int) int  { return n }
-func (failingCompressor) Reset(io.Writer)             {}
-func (f failingCompressor) Write([]byte) (int, error) { return 0, f.err }
-func (failingCompressor) Close() error                { return nil }
+func (failingCompressor) MaxCompressedLen(n int) int { return n }
+func (failingCompressor) Reset(io.Writer)            {}
+func (f failingCompressor) Write(p []byte) (int, error) {
+       if f.err != nil {
+               return 0, f.err
+       }
+       return len(p), nil
+}
+func (f failingCompressor) Close() error { return f.closeErr }
 func (failingCompressor) Type() flatbuf.CompressionType {
        return flatbuf.CompressionTypeZSTD
 }
@@ -412,6 +418,23 @@ func TestRecordEncoderReturnsCompressionError(t 
*testing.T) {
        require.ErrorIs(t, encoder.Encode(&payload, record), want)
 }
 
+func TestGetRecordBatchPayloadReturnsCompressionErrorOnClose(t *testing.T) {
+       want := errors.New("compression failed")
+       mem := memory.NewCheckedAllocator(memory.DefaultAllocator)
+       defer mem.AssertSize(t, 0)
+
+       schema := arrow.NewSchema([]arrow.Field{{Name: "col", Type: 
arrow.PrimitiveTypes.Int8}}, nil)
+       builder := array.NewRecordBuilder(mem, schema)
+       defer builder.Release()
+       builder.Field(0).(*array.Int8Builder).Append(1)
+       record := builder.NewRecordBatch()
+       defer record.Release()
+
+       _, err := GetRecordBatchPayload(record, WithAllocator(mem), WithZstd(),
+               withCompressors(failingCompressor{closeErr: want}))
+       require.ErrorIs(t, err, want)
+}
+
 func TestWriteWithCompressionAndMinSavings(t *testing.T) {
        mem := memory.NewCheckedAllocator(memory.DefaultAllocator)
        defer mem.AssertSize(t, 0)

Reply via email to