diff --git a/arrow/array/arreflect/reflect_arrow_to_go.go b/arrow/array/arreflect/reflect_arrow_to_go.go index c5b1288b..086dbe6c 100644 --- a/arrow/array/arreflect/reflect_arrow_to_go.go +++ b/arrow/array/arreflect/reflect_arrow_to_go.go @@ -161,52 +161,89 @@ func setPrimitiveValue(v reflect.Value, arr arrow.Array, i int) error { if !isIntKind(v.Kind()) { return fmt.Errorf("cannot set int8 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetInt(int64(arr.(*array.Int8).Value(i))) + val := int64(arr.(*array.Int8).Value(i)) + if v.OverflowInt(val) { + return fmt.Errorf("cannot set int8 value %d into %s: %w", val, v.Type(), ErrTypeMismatch) + } + v.SetInt(val) case arrow.INT16: if !isIntKind(v.Kind()) { return fmt.Errorf("cannot set int16 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetInt(int64(arr.(*array.Int16).Value(i))) + val := int64(arr.(*array.Int16).Value(i)) + if v.OverflowInt(val) { + return fmt.Errorf("cannot set int16 value %d into %s: %w", val, v.Type(), ErrTypeMismatch) + } + v.SetInt(val) case arrow.INT32: if !isIntKind(v.Kind()) { return fmt.Errorf("cannot set int32 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetInt(int64(arr.(*array.Int32).Value(i))) + val := int64(arr.(*array.Int32).Value(i)) + if v.OverflowInt(val) { + return fmt.Errorf("cannot set int32 value %d into %s: %w", val, v.Type(), ErrTypeMismatch) + } + v.SetInt(val) case arrow.INT64: if !isIntKind(v.Kind()) { return fmt.Errorf("cannot set int64 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetInt(arr.(*array.Int64).Value(i)) + val := arr.(*array.Int64).Value(i) + if v.OverflowInt(val) { + return fmt.Errorf("cannot set int64 value %d into %s: %w", val, v.Type(), ErrTypeMismatch) + } + v.SetInt(val) case arrow.UINT8: if !isUintKind(v.Kind()) { return fmt.Errorf("cannot set uint8 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetUint(uint64(arr.(*array.Uint8).Value(i))) + val := uint64(arr.(*array.Uint8).Value(i)) + if v.OverflowUint(val) { + return fmt.Errorf("cannot set uint8 value %d into %s: %w", val, v.Type(), ErrTypeMismatch) + } + v.SetUint(val) case arrow.UINT16: if !isUintKind(v.Kind()) { return fmt.Errorf("cannot set uint16 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetUint(uint64(arr.(*array.Uint16).Value(i))) + val := uint64(arr.(*array.Uint16).Value(i)) + if v.OverflowUint(val) { + return fmt.Errorf("cannot set uint16 value %d into %s: %w", val, v.Type(), ErrTypeMismatch) + } + v.SetUint(val) case arrow.UINT32: if !isUintKind(v.Kind()) { return fmt.Errorf("cannot set uint32 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetUint(uint64(arr.(*array.Uint32).Value(i))) + val := uint64(arr.(*array.Uint32).Value(i)) + if v.OverflowUint(val) { + return fmt.Errorf("cannot set uint32 value %d into %s: %w", val, v.Type(), ErrTypeMismatch) + } + v.SetUint(val) case arrow.UINT64: if !isUintKind(v.Kind()) { return fmt.Errorf("cannot set uint64 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetUint(arr.(*array.Uint64).Value(i)) + val := arr.(*array.Uint64).Value(i) + if v.OverflowUint(val) { + return fmt.Errorf("cannot set uint64 value %d into %s: %w", val, v.Type(), ErrTypeMismatch) + } + v.SetUint(val) case arrow.FLOAT32: if !isFloatKind(v.Kind()) { return fmt.Errorf("cannot set float32 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetFloat(float64(arr.(*array.Float32).Value(i))) + val := float64(arr.(*array.Float32).Value(i)) + v.SetFloat(val) case arrow.FLOAT64: if !isFloatKind(v.Kind()) { return fmt.Errorf("cannot set float64 into %s: %w", v.Type(), ErrTypeMismatch) } - v.SetFloat(arr.(*array.Float64).Value(i)) + val := arr.(*array.Float64).Value(i) + if v.OverflowFloat(val) { + return fmt.Errorf("cannot set float64 value %f into %s: %w", val, v.Type(), ErrTypeMismatch) + } + v.SetFloat(val) default: return fmt.Errorf("unsupported primitive type %v: %w", arr.DataType(), ErrUnsupportedType) } diff --git a/arrow/array/arreflect/reflect_arrow_to_go_test.go b/arrow/array/arreflect/reflect_arrow_to_go_test.go index 1a17b33a..eceb5abf 100644 --- a/arrow/array/arreflect/reflect_arrow_to_go_test.go +++ b/arrow/array/arreflect/reflect_arrow_to_go_test.go @@ -17,6 +17,7 @@ package arreflect import ( + "math" "reflect" "testing" "time" @@ -217,6 +218,19 @@ func TestSetPrimitiveValue(t *testing.T) { assert.ErrorIs(t, setPrimitiveValue(reflect.ValueOf(&bad).Elem(), arr, 0), ErrTypeMismatch) }) + t.Run("int64 overflow into int8 returns error", func(t *testing.T) { + b := array.NewInt64Builder(mem) + defer b.Release() + b.Append(int64(300)) + arr := b.NewArray().(*array.Int64) + defer arr.Release() + + got := int8(7) + err := setPrimitiveValue(reflect.ValueOf(&got).Elem(), arr, 0) + assert.ErrorIs(t, err, ErrTypeMismatch) + assert.Equal(t, int8(7), got) + }) + t.Run("uint16", func(t *testing.T) { b := array.NewUint16Builder(mem) defer b.Release() @@ -232,6 +246,19 @@ func TestSetPrimitiveValue(t *testing.T) { assert.ErrorIs(t, setPrimitiveValue(reflect.ValueOf(&bad).Elem(), arr, 0), ErrTypeMismatch) }) + t.Run("uint64 overflow into uint8 returns error", func(t *testing.T) { + b := array.NewUint64Builder(mem) + defer b.Release() + b.Append(300) + arr := b.NewArray().(*array.Uint64) + defer arr.Release() + + got := uint8(7) + err := setPrimitiveValue(reflect.ValueOf(&got).Elem(), arr, 0) + assert.ErrorIs(t, err, ErrTypeMismatch) + assert.Equal(t, uint8(7), got) + }) + t.Run("uint32", func(t *testing.T) { b := array.NewUint32Builder(mem) defer b.Release() @@ -288,6 +315,19 @@ func TestSetPrimitiveValue(t *testing.T) { assert.ErrorIs(t, setPrimitiveValue(reflect.ValueOf(&bad).Elem(), arr, 0), ErrTypeMismatch) }) + t.Run("float64 overflow into float32 returns error", func(t *testing.T) { + b := array.NewFloat64Builder(mem) + defer b.Release() + b.Append(math.MaxFloat64) + arr := b.NewArray().(*array.Float64) + defer arr.Release() + + got := float32(1) + err := setPrimitiveValue(reflect.ValueOf(&got).Elem(), arr, 0) + assert.ErrorIs(t, err, ErrTypeMismatch) + assert.Equal(t, float32(1), got) + }) + t.Run("float64 mismatch", func(t *testing.T) { b := array.NewFloat64Builder(mem) defer b.Release()