Skip to content

Commit

Permalink
Fix: Scan and encode types with underlying types of arrays
Browse files Browse the repository at this point in the history
Rather than special case the reported issue with UUID and [16]byte, this
commit allows the system to find the underlying type of any type that is
an array.

fixes #2107
  • Loading branch information
jackc committed Aug 15, 2024
1 parent d6fc8b0 commit 5747f37
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 5 deletions.
26 changes: 21 additions & 5 deletions pgtype/pgtype.go
Original file line number Diff line number Diff line change
Expand Up @@ -573,17 +573,24 @@ func TryFindUnderlyingTypeScanPlan(dst any) (plan WrappedScanPlanNextSetter, nex
elemValue = dstValue.Elem()
}
nextDstType := elemKindToPointerTypes[elemValue.Kind()]
if nextDstType == nil && elemValue.Kind() == reflect.Slice {
if elemValue.Type().Elem().Kind() == reflect.Uint8 {
var v *[]byte
nextDstType = reflect.TypeOf(v)
if nextDstType == nil {
if elemValue.Kind() == reflect.Slice {
if elemValue.Type().Elem().Kind() == reflect.Uint8 {
var v *[]byte
nextDstType = reflect.TypeOf(v)
}
}

// Get underlying type of any array.
// https://github.com/jackc/pgx/issues/2107
if elemValue.Kind() == reflect.Array {
nextDstType = reflect.PointerTo(reflect.ArrayOf(elemValue.Len(), elemValue.Type().Elem()))
}
}

if nextDstType != nil && dstValue.Type() != nextDstType && dstValue.CanConvert(nextDstType) {
return &underlyingTypeScanPlan{dstType: dstValue.Type(), nextDstType: nextDstType}, dstValue.Convert(nextDstType).Interface(), true
}

}

return nil, nil, false
Expand Down Expand Up @@ -1423,6 +1430,15 @@ func TryWrapFindUnderlyingTypeEncodePlan(value any) (plan WrappedEncodePlanNextS
return &underlyingTypeEncodePlan{nextValueType: byteSliceType}, refValue.Convert(byteSliceType).Interface(), true
}

// Get underlying type of any array.
// https://github.com/jackc/pgx/issues/2107
if refValue.Kind() == reflect.Array {
underlyingArrayType := reflect.ArrayOf(refValue.Len(), refValue.Type().Elem())
if refValue.Type() != underlyingArrayType {
return &underlyingTypeEncodePlan{nextValueType: underlyingArrayType}, refValue.Convert(underlyingArrayType).Interface(), true
}
}

return nil, nil, false
}

Expand Down
12 changes: 12 additions & 0 deletions pgtype/uuid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"github.com/stretchr/testify/require"
)

type renamedUUIDByteArray [16]byte

func TestUUIDCodec(t *testing.T) {
pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "uuid", []pgxtest.ValueRoundTripTest{
{
Expand Down Expand Up @@ -43,6 +45,16 @@ func TestUUIDCodec(t *testing.T) {
new(pgtype.UUID),
isExpectedEq(pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}),
},
{
renamedUUIDByteArray{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
new(pgtype.UUID),
isExpectedEq(pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}),
},
{
[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
new(renamedUUIDByteArray),
isExpectedEq(renamedUUIDByteArray{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}),
},
{
[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
new(pgtype.UUID),
Expand Down

0 comments on commit 5747f37

Please sign in to comment.