diff --git a/arrow/scalar/scalar.go b/arrow/scalar/scalar.go index ccbe02193..f4fcbab70 100644 --- a/arrow/scalar/scalar.go +++ b/arrow/scalar/scalar.go @@ -421,10 +421,16 @@ func (e *Extension) Validate() (err error) { } if !e.Valid { - if e.Value != nil { - err = fmt.Errorf("null %s scalar has storage value", e.Type) + if e.Value == nil { + return nil } - return + if e.Value.IsValid() { + return fmt.Errorf("null %s scalar has non-null storage value", e.Type) + } + if err = e.Value.Validate(); err != nil { + return fmt.Errorf("%s scalar fails validation for storage value: %w", e.Type, err) + } + return nil } switch { diff --git a/arrow/scalar/scalar_test.go b/arrow/scalar/scalar_test.go index 749767c78..49ef342f2 100644 --- a/arrow/scalar/scalar_test.go +++ b/arrow/scalar/scalar_test.go @@ -33,6 +33,7 @@ import ( "github.com/apache/arrow-go/v18/arrow/decimal256" "github.com/apache/arrow-go/v18/arrow/memory" "github.com/apache/arrow-go/v18/arrow/scalar" + "github.com/apache/arrow-go/v18/internal/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" @@ -92,6 +93,23 @@ func checkMakeNullScalar(t *testing.T, dt arrow.DataType) scalar.Scalar { return s } +func TestMakeNullExtensionScalar(t *testing.T) { + dt := types.NewSmallintType() + sc := checkMakeNullScalar(t, dt) + ext := sc.(*scalar.Extension) + require.NotNil(t, ext.Value) + assert.False(t, ext.Value.IsValid()) + assert.True(t, arrow.TypeEqual(dt.StorageType(), ext.Value.DataType())) +} + +func TestNullExtensionScalarValidateRejectsNonNullStorage(t *testing.T) { + sc := scalar.NewExtensionScalar(scalar.NewInt16Scalar(1), types.NewSmallintType()) + sc.Valid = false + + assert.ErrorContains(t, sc.Validate(), "non-null storage value") + assert.ErrorContains(t, sc.ValidateFull(), "non-null storage value") +} + func TestMakeScalarUint(t *testing.T) { three := scalar.MakeScalar(uint(3)) assert.NoError(t, three.ValidateFull())