Skip to content

Commit b42561b

Browse files
committed
extract map[string]interface{} conversion for convertible named types and combine with change to bindAnyArgs test
1 parent ba0e7e7 commit b42561b

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

named.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,22 @@ func prepareNamed(p namedPreparer, query string) (*NamedStmt, error) {
146146
}, nil
147147
}
148148

149+
// convertMapStringInterface attempts to convert v to map[string]interface{}.
150+
// Unlike v.(map[string]interface{}), this function works on named types that
151+
// are convertible to map[string]interface{} as well.
152+
func convertMapStringInterface(v interface{}) (map[string]interface{}, bool) {
153+
var m map[string]interface{}
154+
mtype := reflect.TypeOf(m)
155+
t := reflect.TypeOf(v)
156+
if !t.ConvertibleTo(mtype) {
157+
return nil, false
158+
}
159+
return reflect.ValueOf(v).Convert(mtype).Interface().(map[string]interface{}), true
160+
161+
}
162+
149163
func bindAnyArgs(names []string, arg interface{}, m *reflectx.Mapper) ([]interface{}, error) {
150-
if maparg, ok := arg.(map[string]interface{}); ok {
164+
if maparg, ok := convertMapStringInterface(arg); ok {
151165
return bindMapArgs(names, maparg)
152166
}
153167
return bindArgs(names, arg, m)
@@ -383,12 +397,10 @@ func bindNamedMapper(bindType int, query string, arg interface{}, m *reflectx.Ma
383397
k := t.Kind()
384398
switch {
385399
case k == reflect.Map && t.Key().Kind() == reflect.String:
386-
var m map[string]interface{}
387-
if !t.ConvertibleTo(reflect.TypeOf(m)) {
400+
m, ok := convertMapStringInterface(arg)
401+
if !ok {
388402
return "", nil, fmt.Errorf("sqlx.bindNamedMapper: unsupported map type: %T", arg)
389403
}
390-
391-
m = reflect.ValueOf(arg).Convert(reflect.TypeOf(m)).Interface().(map[string]interface{})
392404
return bindMap(bindType, query, m)
393405
case k == reflect.Array || k == reflect.Slice:
394406
return bindArray(bindType, query, arg, m)

named_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,18 @@ func TestNamedQueries(t *testing.T) {
217217
VALUES (:first_name, :last_name, :email)`, slsMap)
218218
test.Error(err)
219219

220+
type A map[string]interface{}
221+
222+
typedMap := []A{
223+
{"first_name": "Ardie", "last_name": "Savea", "email": "[email protected]"},
224+
{"first_name": "Sonny Bill", "last_name": "Williams", "email": "[email protected]"},
225+
{"first_name": "Ngani", "last_name": "Laumape", "email": "[email protected]"},
226+
}
227+
228+
_, err = db.NamedExec(`INSERT INTO person (first_name, last_name, email)
229+
VALUES (:first_name, :last_name, :email)`, typedMap)
230+
test.Error(err)
231+
220232
for _, p := range sls {
221233
dest := Person{}
222234
err = db.Get(&dest, db.Rebind("SELECT * FROM person WHERE email=?"), p.Email)

0 commit comments

Comments
 (0)