Port fc020c24ac9590f6547f8ad1d291fc75b4873a84 from pgx v3

commit fc020c24ac9590f6547f8ad1d291fc75b4873a84
Author: Nicholas Wilson <nicholas.wilson@realvnc.com>
Date:   Wed Jul 24 12:32:18 2019 +0100

    Add support for pgtype.UUID to write into any [16]byte type
This commit is contained in:
Jack Christensen 2019-08-17 13:30:41 -05:00
parent 4e0ed911f5
commit bcc139a365
3 changed files with 51 additions and 1 deletions

View File

@ -163,6 +163,27 @@ func underlyingTimeType(val interface{}) (interface{}, bool) {
return time.Time{}, false
}
// underlyingUUIDType gets the underlying type that can be converted to [16]byte
func underlyingUUIDType(val interface{}) (interface{}, bool) {
refVal := reflect.ValueOf(val)
switch refVal.Kind() {
case reflect.Ptr:
if refVal.IsNil() {
return time.Time{}, false
}
convVal := refVal.Elem().Interface()
return convVal, true
}
uuidType := reflect.TypeOf([16]byte{})
if refVal.Type().ConvertibleTo(uuidType) {
return refVal.Convert(uuidType).Interface(), true
}
return nil, false
}
// underlyingSliceType gets the underlying slice type
func underlyingSliceType(val interface{}) (interface{}, bool) {
refVal := reflect.ValueOf(val)
@ -401,6 +422,14 @@ func GetAssignToDstType(dst interface{}) (interface{}, bool) {
}
}
if dstVal.Kind() == reflect.Array {
if baseElemType, ok := kindTypes[dstVal.Type().Elem().Kind()]; ok {
baseArrayType := reflect.PtrTo(reflect.ArrayOf(dstVal.Len(), baseElemType))
nextDst := dstPtr.Convert(baseArrayType)
return nextDst.Interface(), dstPtr.Type() != nextDst.Type()
}
}
return nil, false
}

View File

@ -39,7 +39,7 @@ func (dst *UUID) Set(src interface{}) error {
}
*dst = UUID{Bytes: uuid, Status: Present}
default:
if originalSrc, ok := underlyingPtrType(src); ok {
if originalSrc, ok := underlyingUUIDType(src); ok {
return dst.Set(originalSrc)
}
return errors.Errorf("cannot convert %v to UUID", value)

View File

@ -15,6 +15,8 @@ func TestUUIDTranscode(t *testing.T) {
})
}
type SomeUUIDType [16]byte
func TestUUIDSet(t *testing.T) {
successfulTests := []struct {
source interface{}
@ -32,6 +34,10 @@ func TestUUIDSet(t *testing.T) {
source: []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
result: pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Status: pgtype.Present},
},
{
source: SomeUUIDType{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
result: pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Status: pgtype.Present},
},
{
source: ([]byte)(nil),
result: pgtype.UUID{Status: pgtype.Null},
@ -86,6 +92,21 @@ func TestUUIDAssignTo(t *testing.T) {
}
}
{
src := pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Status: pgtype.Present}
var dst SomeUUIDType
expected := [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
err := src.AssignTo(&dst)
if err != nil {
t.Error(err)
}
if dst != expected {
t.Errorf("expected %v to assign %v, but result was %v", src, expected, dst)
}
}
{
src := pgtype.UUID{Bytes: [16]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, Status: pgtype.Present}
var dst string