From 056f9e506f935e81beca857cd1702031e46aa8da Mon Sep 17 00:00:00 2001 From: fifsky Date: Thu, 8 Apr 2021 11:12:26 +0800 Subject: [PATCH 1/2] fix: bulk insert regular expression is too strict --- named.go | 2 +- named_test.go | 22 ++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/named.go b/named.go index 11a68e0c..32b0059a 100644 --- a/named.go +++ b/named.go @@ -224,7 +224,7 @@ func bindStruct(bindType int, query string, arg interface{}, m *reflectx.Mapper) return bound, arglist, nil } -var valueBracketReg = regexp.MustCompile(`VALUES\s+(\([^(]*.[^(]\))`) +var valueBracketReg = regexp.MustCompile(`(?i:VALUES)\s*(\([^(]*.[^(]\))`) func fixBound(bound string, loop int) string { loc := valueBracketReg.FindAllStringSubmatchIndex(bound, -1) diff --git a/named_test.go b/named_test.go index f5545d51..e0a6a68d 100644 --- a/named_test.go +++ b/named_test.go @@ -342,6 +342,24 @@ func TestFixBounds(t *testing.T) { expect: `INSERT INTO foo (a,b,c,d) VALUES (:name, :age, :first, :last) VALUES (:name, :age, :first, :last)`, loop: 2, }, + { + name: `lowercase`, + query: `INSERT INTO foo (a,b,c,d) values (:name, :age, :first, :last)`, + expect: `INSERT INTO foo (a,b,c,d) values (:name, :age, :first, :last),(:name, :age, :first, :last)`, + loop: 2, + }, + { + name: `not blank space`, + query: `INSERT INTO foo (a,b,c,d) VALUES(:name, :age, :first, :last)`, + expect: `INSERT INTO foo (a,b,c,d) VALUES(:name, :age, :first, :last),(:name, :age, :first, :last)`, + loop: 2, + }, + { + name: `capital letter`, + query: `INSERT INTO foo (a,b,c,d) Values(:name, :age, :first, :last)`, + expect: `INSERT INTO foo (a,b,c,d) Values(:name, :age, :first, :last),(:name, :age, :first, :last)`, + loop: 2, + }, } for _, tc := range table { @@ -354,7 +372,7 @@ func TestFixBounds(t *testing.T) { } t.Run("regex changed", func(t *testing.T) { - var valueBracketRegChanged = regexp.MustCompile(`(VALUES)\s+(\([^(]*.[^(]\))`) + var valueBracketRegChanged = regexp.MustCompile(`(?i:VALUES)\s*(\([^(]*.[^(]\))`) saveRegexp := valueBracketReg defer func() { valueBracketReg = saveRegexp @@ -362,7 +380,7 @@ func TestFixBounds(t *testing.T) { valueBracketReg = valueBracketRegChanged res := fixBound("VALUES (:a, :b)", 2) - if res != "VALUES (:a, :b)" { + if res != "VALUES (:a, :b),(:a, :b)" { t.Errorf("changed regex should return string") } }) From ac30690b72518ffd1de807b542b62e8ea2a1ca70 Mon Sep 17 00:00:00 2001 From: fifsky Date: Sun, 17 Apr 2022 11:37:30 +0800 Subject: [PATCH 2/2] fix: batch insert bind for ptr slice --- named.go | 7 ++++++- named_test.go | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/named.go b/named.go index 728aa04d..9bcd7800 100644 --- a/named.go +++ b/named.go @@ -277,7 +277,7 @@ func bindArray(bindType int, query string, arg interface{}, m *reflectx.Mapper) if err != nil { return "", []interface{}{}, err } - arrayValue := reflect.ValueOf(arg) + arrayValue := reflect.Indirect(reflect.ValueOf(arg)) arrayLen := arrayValue.Len() if arrayLen == 0 { return "", []interface{}{}, fmt.Errorf("length of array is 0: %#v", arg) @@ -421,6 +421,11 @@ func Named(query string, arg interface{}) (string, []interface{}, error) { func bindNamedMapper(bindType int, query string, arg interface{}, m *reflectx.Mapper) (string, []interface{}, error) { t := reflect.TypeOf(arg) k := t.Kind() + + if k == reflect.Ptr { + k = t.Elem().Kind() + } + switch { case k == reflect.Map && t.Key().Kind() == reflect.String: m, ok := convertMapStringInterface(arg) diff --git a/named_test.go b/named_test.go index 8481b35b..26031389 100644 --- a/named_test.go +++ b/named_test.go @@ -211,6 +211,10 @@ func TestNamedQueries(t *testing.T) { _, err = db.NamedExec(insert, sls) test.Error(err) + // and test ptr batch inserts + _, err = db.NamedExec(insert, &sls) + test.Error(err) + // test map batch inserts slsMap := []map[string]interface{}{ {"first_name": "Ardie", "last_name": "Savea", "email": "asavea@ab.co.nz"},