Fix simple protocol empty array and original recursive empty array issue

Original issue https://github.com/jackc/pgtype/issues/68

This crash occurred in the recursive assignment system used to support
multidimensional arrays.

This was fixed in 9639a69d45. However,
that fix incorrectly used nil instead of an empty slice.

In hindsight, it appears the fundamental error is that an assignment to
a slice of a type that is not specified is handled with the recursive /
reflection path. Or another way of looking at it is as an unexpected
feature where []T can now be scanned if individual elements are
assignable to T even if []T is not specifically handled.

But this new reflection / recursive path did not handle empty arrays.

This fix handles the reflection path for an empty slice by allocating an
empty slice.
non-blocking
Jack Christensen 2020-10-31 17:12:16 -05:00
parent 9d7fc8e63a
commit af0ca3a39b
44 changed files with 191 additions and 119 deletions

View File

@ -190,10 +190,6 @@ func (dst ACLItemArray) Get() interface{} {
func (src *ACLItemArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -232,6 +228,13 @@ func (src *ACLItemArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -192,7 +192,7 @@ func TestACLItemArrayAssignTo(t *testing.T) {
{
src: pgtype.ACLItemArray{Status: pgtype.Present},
dst: &stringSlice,
expected: (([]string)(nil)),
expected: []string{},
},
{
src: pgtype.ACLItemArray{

View File

@ -192,10 +192,6 @@ func (dst BoolArray) Get() interface{} {
func (src *BoolArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -234,6 +230,13 @@ func (src *BoolArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -171,7 +171,7 @@ func TestBoolArrayAssignTo(t *testing.T) {
{
src: pgtype.BoolArray{Status: pgtype.Present},
dst: &boolSlice,
expected: (([]bool)(nil)),
expected: []bool{},
},
{
src: pgtype.BoolArray{

View File

@ -192,10 +192,6 @@ func (dst BPCharArray) Get() interface{} {
func (src *BPCharArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -234,6 +230,13 @@ func (src *BPCharArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -173,10 +173,6 @@ func (dst ByteaArray) Get() interface{} {
func (src *ByteaArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -206,6 +202,13 @@ func (src *ByteaArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -160,7 +160,7 @@ func TestByteaArrayAssignTo(t *testing.T) {
{
src: pgtype.ByteaArray{Status: pgtype.Present},
dst: &byteByteSlice,
expected: (([][]byte)(nil)),
expected: [][]byte{},
},
{
src: pgtype.ByteaArray{

View File

@ -212,10 +212,6 @@ func (dst CIDRArray) Get() interface{} {
func (src *CIDRArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -263,6 +259,13 @@ func (src *CIDRArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -220,7 +220,7 @@ func TestCIDRArrayAssignTo(t *testing.T) {
{
src: pgtype.CIDRArray{Status: pgtype.Present},
dst: &ipnetSlice,
expected: (([]*net.IPNet)(nil)),
expected: []*net.IPNet{},
},
{
src: pgtype.CIDRArray{Status: pgtype.Null},
@ -230,7 +230,7 @@ func TestCIDRArrayAssignTo(t *testing.T) {
{
src: pgtype.CIDRArray{Status: pgtype.Present},
dst: &ipSlice,
expected: (([]net.IP)(nil)),
expected: []net.IP{},
},
{
src: pgtype.CIDRArray{

View File

@ -193,10 +193,6 @@ func (dst DateArray) Get() interface{} {
func (src *DateArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -235,6 +231,13 @@ func (src *DateArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -185,7 +185,7 @@ func TestDateArrayAssignTo(t *testing.T) {
{
src: pgtype.DateArray{Status: pgtype.Present},
dst: &timeSlice,
expected: (([]time.Time)(nil)),
expected: []time.Time{},
},
{
src: pgtype.DateArray{

View File

@ -190,10 +190,6 @@ func (dst EnumArray) Get() interface{} {
func (src *EnumArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -232,6 +228,13 @@ func (src *EnumArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -170,7 +170,7 @@ func TestEnumArrayArrayAssignTo(t *testing.T) {
{
src: pgtype.EnumArray{Status: pgtype.Present},
dst: &stringSlice,
expected: (([]string)(nil)),
expected: []string{},
},
{
src: pgtype.EnumArray{

View File

@ -192,10 +192,6 @@ func (dst Float4Array) Get() interface{} {
func (src *Float4Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -234,6 +230,13 @@ func (src *Float4Array) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -170,7 +170,7 @@ func TestFloat4ArrayAssignTo(t *testing.T) {
{
src: pgtype.Float4Array{Status: pgtype.Present},
dst: &float32Slice,
expected: (([]float32)(nil)),
expected: []float32{},
},
{
src: pgtype.Float4Array{

View File

@ -192,10 +192,6 @@ func (dst Float8Array) Get() interface{} {
func (src *Float8Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -234,6 +230,13 @@ func (src *Float8Array) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -146,7 +146,7 @@ func TestFloat8ArrayAssignTo(t *testing.T) {
{
src: pgtype.Float8Array{Status: pgtype.Present},
dst: &float64Slice,
expected: (([]float64)(nil)),
expected: []float64{},
},
{
src: pgtype.Float8Array{

View File

@ -173,10 +173,6 @@ func (dst HstoreArray) Get() interface{} {
func (src *HstoreArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -206,6 +202,13 @@ func (src *HstoreArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -303,7 +303,7 @@ func TestHstoreArrayAssignTo(t *testing.T) {
src: pgtype.HstoreArray{Status: pgtype.Null}, dst: &hstoreSlice, expected: (([]map[string]string)(nil)),
},
{
src: pgtype.HstoreArray{Status: pgtype.Present}, dst: &hstoreSlice, expected: (([]map[string]string)(nil)),
src: pgtype.HstoreArray{Status: pgtype.Present}, dst: &hstoreSlice, expected: []map[string]string{},
},
{
src: pgtype.HstoreArray{

View File

@ -212,10 +212,6 @@ func (dst InetArray) Get() interface{} {
func (src *InetArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -263,6 +259,13 @@ func (src *InetArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -220,7 +220,7 @@ func TestInetArrayAssignTo(t *testing.T) {
{
src: pgtype.InetArray{Status: pgtype.Present},
dst: &ipnetSlice,
expected: (([]*net.IPNet)(nil)),
expected: []*net.IPNet{},
},
{
src: pgtype.InetArray{Status: pgtype.Null},
@ -230,7 +230,7 @@ func TestInetArrayAssignTo(t *testing.T) {
{
src: pgtype.InetArray{Status: pgtype.Present},
dst: &ipSlice,
expected: (([]net.IP)(nil)),
expected: []net.IP{},
},
{
src: pgtype.InetArray{

View File

@ -458,10 +458,6 @@ func (dst Int2Array) Get() interface{} {
func (src *Int2Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -626,6 +622,13 @@ func (src *Int2Array) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -222,7 +222,7 @@ func TestInt2ArrayAssignTo(t *testing.T) {
{
src: pgtype.Int2Array{Status: pgtype.Present},
dst: &int16Slice,
expected: (([]int16)(nil)),
expected: []int16{},
},
{
src: pgtype.Int2Array{

View File

@ -458,10 +458,6 @@ func (dst Int4Array) Get() interface{} {
func (src *Int4Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -626,6 +622,13 @@ func (src *Int4Array) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -236,7 +236,7 @@ func TestInt4ArrayAssignTo(t *testing.T) {
{
src: pgtype.Int4Array{Status: pgtype.Present},
dst: &int32Slice,
expected: (([]int32)(nil)),
expected: []int32{},
},
{
src: pgtype.Int4Array{

View File

@ -458,10 +458,6 @@ func (dst Int8Array) Get() interface{} {
func (src *Int8Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -626,6 +622,13 @@ func (src *Int8Array) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -229,7 +229,7 @@ func TestInt8ArrayAssignTo(t *testing.T) {
{
src: pgtype.Int8Array{Status: pgtype.Present},
dst: &int64Slice,
expected: (([]int64)(nil)),
expected: []int64{},
},
{
src: pgtype.Int8Array{

View File

@ -192,10 +192,6 @@ func (dst JSONBArray) Get() interface{} {
func (src *JSONBArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -234,6 +230,13 @@ func (src *JSONBArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -193,10 +193,6 @@ func (dst MacaddrArray) Get() interface{} {
func (src *MacaddrArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -235,6 +231,13 @@ func (src *MacaddrArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -169,7 +169,7 @@ func TestMacaddrArrayAssignTo(t *testing.T) {
{
src: pgtype.MacaddrArray{Status: pgtype.Present},
dst: &macaddrSlice,
expected: (([]net.HardwareAddr)(nil)),
expected: []net.HardwareAddr{},
},
{
src: pgtype.MacaddrArray{

View File

@ -306,10 +306,6 @@ func (dst NumericArray) Get() interface{} {
func (src *NumericArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -402,6 +398,13 @@ func (src *NumericArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -193,7 +193,7 @@ func TestNumericArrayAssignTo(t *testing.T) {
{
src: pgtype.NumericArray{Status: pgtype.Present},
dst: &float32Slice,
expected: (([]float32)(nil)),
expected: []float32{},
},
{
src: pgtype.NumericArray{

View File

@ -192,10 +192,6 @@ func (dst TextArray) Get() interface{} {
func (src *TextArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -234,6 +230,13 @@ func (src *TextArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -171,7 +171,7 @@ func TestTextArrayAssignTo(t *testing.T) {
{
src: pgtype.TextArray{Status: pgtype.Present},
dst: &stringSlice,
expected: (([]string)(nil)),
expected: []string{},
},
{
src: pgtype.TextArray{

View File

@ -193,10 +193,6 @@ func (dst TimestampArray) Get() interface{} {
func (src *TimestampArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -235,6 +231,13 @@ func (src *TimestampArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -165,7 +165,7 @@ func TestTimestampArrayAssignTo(t *testing.T) {
{
src: pgtype.TimestampArray{Status: pgtype.Present},
dst: &timeSlice,
expected: (([]time.Time)(nil)),
expected: []time.Time{},
},
{
src: pgtype.TimestampArray{

View File

@ -193,10 +193,6 @@ func (dst TimestamptzArray) Get() interface{} {
func (src *TimestamptzArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -235,6 +231,13 @@ func (src *TimestamptzArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -201,7 +201,7 @@ func TestTimestamptzArrayAssignTo(t *testing.T) {
{
src: pgtype.TimestamptzArray{Status: pgtype.Present},
dst: &timeSlice,
expected: (([]time.Time)(nil)),
expected: []time.Time{},
},
{
src: pgtype.TimestamptzArray{

View File

@ -154,10 +154,6 @@ func (dst TstzrangeArray) Get() interface{} {
func (src *TstzrangeArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -187,6 +183,13 @@ func (src *TstzrangeArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -174,10 +174,6 @@ func (dst <%= pgtype_array_type %>) Get() interface{} {
func (src *<%= pgtype_array_type %>) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1{
// Attempt to match to select common types:
switch v := dst.(type) {
@ -207,6 +203,13 @@ func (src *<%= pgtype_array_type %>) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -230,10 +230,6 @@ func (dst UUIDArray) Get() interface{} {
func (src *UUIDArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -290,6 +286,13 @@ func (src *UUIDArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -256,12 +256,12 @@ func TestUUIDArrayAssignTo(t *testing.T) {
{
src: pgtype.UUIDArray{Status: pgtype.Present},
dst: &byteSlice,
expected: ([]byte)(nil),
expected: []byte{},
},
{
src: pgtype.UUIDArray{Status: pgtype.Present},
dst: &stringSlice,
expected: (([]string)(nil)),
expected: []string{},
},
{
src: pgtype.UUIDArray{

View File

@ -192,10 +192,6 @@ func (dst VarcharArray) Get() interface{} {
func (src *VarcharArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Elements) == 0 || len(src.Dimensions) == 0 {
// No values to assign
return nil
}
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
@ -234,6 +230,13 @@ func (src *VarcharArray) AssignTo(dst interface{}) error {
value = value.Elem()
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err

View File

@ -171,7 +171,7 @@ func TestVarcharArrayAssignTo(t *testing.T) {
{
src: pgtype.VarcharArray{Status: pgtype.Present},
dst: &stringSlice,
expected: (([]string)(nil)),
expected: []string{},
},
{
src: pgtype.VarcharArray{