Skip to content

Commit ed67c9f

Browse files
committed
fix shouldWrapArray
1 parent 8d07a66 commit ed67c9f

File tree

5 files changed

+60
-11
lines changed

5 files changed

+60
-11
lines changed

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ module github.com/domonda/go-sqldb
33
go 1.19
44

55
require (
6-
github.com/domonda/go-errs v0.0.0-20221201115330-819262069697
7-
github.com/domonda/go-types v0.0.0-20230123091716-ceb113bdba48
6+
github.com/domonda/go-errs v0.0.0-20230207132857-bf0bda36a13a
7+
github.com/domonda/go-types v0.0.0-20230218120848-a48cfd6869c1
88
github.com/go-sql-driver/mysql v1.7.0
99
github.com/lib/pq v1.10.7
1010
github.com/stretchr/testify v1.8.1
11-
golang.org/x/exp v0.0.0-20230118134722-a68e582fa157
11+
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb
1212
)
1313

1414
require (

go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
22
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
33
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4-
github.com/domonda/go-errs v0.0.0-20221201115330-819262069697 h1:Z7QBf0irXHMZSuuex53IyyXHlGc48s/wDAoETz4FyBU=
5-
github.com/domonda/go-errs v0.0.0-20221201115330-819262069697/go.mod h1:WvIoE59Dfs0hhB2GYSlwowlBr2WWGXf/F74bg6HWUpQ=
4+
github.com/domonda/go-errs v0.0.0-20230207132857-bf0bda36a13a h1:5AcAgYGu1ayZP1+V8W8+CFxCh8Si5u82Xp9mKArFNss=
5+
github.com/domonda/go-errs v0.0.0-20230207132857-bf0bda36a13a/go.mod h1:r9rjz9Xo8n4hNV3M47CY5quNOLBlNYuzBVC4Qk2JDOY=
66
github.com/domonda/go-pretty v0.0.0-20220317123925-dd9e6bef129a h1:6/Is0KGl5Ot3E8ZLAgAFWYiSRdU+3t3jL38+5yIlCV4=
77
github.com/domonda/go-pretty v0.0.0-20220317123925-dd9e6bef129a/go.mod h1:3QkM8UJdyJMeKZiIo7hYzSkQBpRS3k0gOHw4ysyEIB4=
8-
github.com/domonda/go-types v0.0.0-20230123091716-ceb113bdba48 h1:vfjPQCCnspQRMdb31fKHBG+/2Qst2vVJGjUiBufecPE=
9-
github.com/domonda/go-types v0.0.0-20230123091716-ceb113bdba48/go.mod h1:OCpuKQfcYEWr4D7Z+1aBLO5NvGoRRZytOcvjFs/KJOg=
8+
github.com/domonda/go-types v0.0.0-20230218120848-a48cfd6869c1 h1:vtdhc3dr8UHodWjGha2pkyRFzfEqvZ+7LK2A3XSWit4=
9+
github.com/domonda/go-types v0.0.0-20230218120848-a48cfd6869c1/go.mod h1:oZMN5kztmvCTnoaBA2BWOkcMHhp3lggOwp8Xp3V7kRs=
1010
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
1111
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
1212
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
@@ -29,8 +29,8 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs
2929
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
3030
github.com/ungerik/go-reflection v0.0.0-20220113085621-6c5fc1f2694a h1:9vfYtqoyrPw08TbSLxkSXEflp6iXa3RL86Qjs+DrVas=
3131
github.com/ungerik/go-reflection v0.0.0-20220113085621-6c5fc1f2694a/go.mod h1:6Hnd2/4g3Tpt6TjvxHx8wXOZziwApVxRdIGkr7vNpXs=
32-
golang.org/x/exp v0.0.0-20230118134722-a68e582fa157 h1:fiNkyhJPUvxbRPbCqY/D9qdjmPzfHcpK3P4bM4gioSY=
33-
golang.org/x/exp v0.0.0-20230118134722-a68e582fa157/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
32+
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w=
33+
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
3434
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3535
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
3636
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

impl/foreachrow.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ var (
1515
typeOfContext = reflect.TypeOf((*context.Context)(nil)).Elem()
1616
typeOfSQLScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
1717
typeOfTime = reflect.TypeOf(time.Time{})
18-
typeOfByteSlice = reflect.TypeOf((*[]byte)(nil)).Elem()
18+
typeOfByte = reflect.TypeOf(byte(0))
1919
)
2020

2121
// ForEachRowCallFunc will call the passed callback with scanned values or a struct for every row.

impl/reflectstruct.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,30 @@ func reflectStructColumnPointers(structVal reflect.Value, namer sqldb.StructFiel
103103

104104
pointer := fieldValue.Addr().Interface()
105105
// If field is a slice or array that does not implement sql.Scanner
106+
// and it's not a string scannable []byte type underneath
106107
// then wrap it with pq.Array to make it scannable
107-
if k := field.Type.Kind(); (k == reflect.Slice || k == reflect.Array) && field.Type != typeOfByteSlice && !fieldValue.Addr().Type().Implements(typeOfSQLScanner) {
108+
if shouldWrapArray(fieldValue) {
108109
pointer = pq.Array(pointer)
109110
}
110111
pointers[colIndex] = pointer
111112
}
112113
return nil
113114
}
114115

116+
func shouldWrapArray(v reflect.Value) bool {
117+
t := v.Type()
118+
switch t.Kind() {
119+
case reflect.Slice:
120+
if t.Elem() == typeOfByte {
121+
return false // Byte slices are scanned as strings
122+
}
123+
return !v.Addr().Type().Implements(typeOfSQLScanner)
124+
case reflect.Array:
125+
return !v.Addr().Type().Implements(typeOfSQLScanner)
126+
}
127+
return false
128+
}
129+
115130
func ignoreColumn(filters []sqldb.ColumnFilter, name string, flags sqldb.FieldFlag, fieldType reflect.StructField, fieldValue reflect.Value) bool {
116131
for _, filter := range filters {
117132
if filter.IgnoreColumn(name, flags, fieldType, fieldValue) {

impl/reflectstruct_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package impl
2+
3+
import (
4+
"database/sql"
5+
"encoding/json"
6+
"reflect"
7+
"testing"
8+
9+
"github.com/domonda/go-types/nullable"
10+
)
11+
12+
func Test_shouldWrapArray(t *testing.T) {
13+
tests := []struct {
14+
v reflect.Value
15+
want bool
16+
}{
17+
{v: reflect.ValueOf([]byte(nil)), want: false},
18+
{v: reflect.ValueOf([]byte{}), want: false},
19+
{v: reflect.ValueOf(""), want: false},
20+
{v: reflect.ValueOf(0), want: false},
21+
{v: reflect.ValueOf(json.RawMessage([]byte("null"))), want: false},
22+
{v: reflect.ValueOf(nullable.JSON([]byte("null"))), want: false},
23+
{v: reflect.ValueOf(new(sql.NullInt64)).Elem(), want: false},
24+
25+
{v: reflect.ValueOf(new([3]string)).Elem(), want: true},
26+
{v: reflect.ValueOf(new([]string)).Elem(), want: true},
27+
{v: reflect.ValueOf(new([]sql.NullString)).Elem(), want: true},
28+
}
29+
for _, tt := range tests {
30+
if got := shouldWrapArray(tt.v); got != tt.want {
31+
t.Errorf("shouldWrapArray() = %v, want %v", got, tt.want)
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)