Skip to content

Commit 5747f37

Browse files
committed
Fix: Scan and encode types with underlying types of arrays
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
1 parent d6fc8b0 commit 5747f37

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

pgtype/pgtype.go

+21-5
Original file line numberDiff line numberDiff line change
@@ -573,17 +573,24 @@ func TryFindUnderlyingTypeScanPlan(dst any) (plan WrappedScanPlanNextSetter, nex
573573
elemValue = dstValue.Elem()
574574
}
575575
nextDstType := elemKindToPointerTypes[elemValue.Kind()]
576-
if nextDstType == nil && elemValue.Kind() == reflect.Slice {
577-
if elemValue.Type().Elem().Kind() == reflect.Uint8 {
578-
var v *[]byte
579-
nextDstType = reflect.TypeOf(v)
576+
if nextDstType == nil {
577+
if elemValue.Kind() == reflect.Slice {
578+
if elemValue.Type().Elem().Kind() == reflect.Uint8 {
579+
var v *[]byte
580+
nextDstType = reflect.TypeOf(v)
581+
}
582+
}
583+
584+
// Get underlying type of any array.
585+
// https://github.com/jackc/pgx/issues/2107
586+
if elemValue.Kind() == reflect.Array {
587+
nextDstType = reflect.PointerTo(reflect.ArrayOf(elemValue.Len(), elemValue.Type().Elem()))
580588
}
581589
}
582590

583591
if nextDstType != nil && dstValue.Type() != nextDstType && dstValue.CanConvert(nextDstType) {
584592
return &underlyingTypeScanPlan{dstType: dstValue.Type(), nextDstType: nextDstType}, dstValue.Convert(nextDstType).Interface(), true
585593
}
586-
587594
}
588595

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

1433+
// Get underlying type of any array.
1434+
// https://github.com/jackc/pgx/issues/2107
1435+
if refValue.Kind() == reflect.Array {
1436+
underlyingArrayType := reflect.ArrayOf(refValue.Len(), refValue.Type().Elem())
1437+
if refValue.Type() != underlyingArrayType {
1438+
return &underlyingTypeEncodePlan{nextValueType: underlyingArrayType}, refValue.Convert(underlyingArrayType).Interface(), true
1439+
}
1440+
}
1441+
14261442
return nil, nil, false
14271443
}
14281444

pgtype/uuid_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"github.com/stretchr/testify/require"
1111
)
1212

13+
type renamedUUIDByteArray [16]byte
14+
1315
func TestUUIDCodec(t *testing.T) {
1416
pgxtest.RunValueRoundTripTests(context.Background(), t, defaultConnTestRunner, nil, "uuid", []pgxtest.ValueRoundTripTest{
1517
{
@@ -43,6 +45,16 @@ func TestUUIDCodec(t *testing.T) {
4345
new(pgtype.UUID),
4446
isExpectedEq(pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}),
4547
},
48+
{
49+
renamedUUIDByteArray{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
50+
new(pgtype.UUID),
51+
isExpectedEq(pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Valid: true}),
52+
},
53+
{
54+
[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
55+
new(renamedUUIDByteArray),
56+
isExpectedEq(renamedUUIDByteArray{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}),
57+
},
4658
{
4759
[]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
4860
new(pgtype.UUID),

0 commit comments

Comments
 (0)