diff --git a/named.go b/named.go index 1f416121..5ffe44c1 100644 --- a/named.go +++ b/named.go @@ -224,13 +224,13 @@ func bindStruct(bindType int, query string, arg interface{}, m *reflectx.Mapper) return bound, arglist, nil } -var valueBracketReg = regexp.MustCompile(`(?i)VALUES\s*(\([^(]*.[^(]\))`) +var valueBracketReg = regexp.MustCompile(`(?i)VALUES\s*(\((?:[^(]|\([^(]*\))*\))`) func fixBound(bound string, loop int) string { loc := valueBracketReg.FindAllStringSubmatchIndex(bound, -1) - // Either no VALUES () found or more than one found?? - if len(loc) != 1 { + // defensive guard when "VALUES (...)" not found + if len(loc) < 1 { return bound } // defensive guard. loc should be len 4 representing the starting and diff --git a/named_test.go b/named_test.go index 70bc4484..0c1f0f80 100644 --- a/named_test.go +++ b/named_test.go @@ -105,6 +105,7 @@ type Test struct { } func (t Test) Error(err error, msg ...interface{}) { + t.t.Helper() if err != nil { if len(msg) == 0 { t.t.Error(err) @@ -115,6 +116,7 @@ func (t Test) Error(err error, msg ...interface{}) { } func (t Test) Errorf(err error, format string, args ...interface{}) { + t.t.Helper() if err != nil { t.t.Errorf(format, args...) } @@ -339,7 +341,7 @@ func TestFixBounds(t *testing.T) { { name: `found twice test`, query: `INSERT INTO foo (a,b,c,d) VALUES (:name, :age, :first, :last) VALUES (:name, :age, :first, :last)`, - expect: `INSERT INTO foo (a,b,c,d) VALUES (:name, :age, :first, :last) VALUES (:name, :age, :first, :last)`, + expect: `INSERT INTO foo (a,b,c,d) VALUES (:name, :age, :first, :last),(:name, :age, :first, :last) VALUES (:name, :age, :first, :last)`, loop: 2, }, { @@ -354,6 +356,24 @@ func TestFixBounds(t *testing.T) { expect: `INSERT INTO foo (a,b) values(:a, :b),(:a, :b)`, loop: 2, }, + { + name: `on duplicate key using VALUES`, + query: `INSERT INTO foo (a,b) VALUES(:a, :b) ON DUPLICATE KEY UPDATE a=VALUES(a)`, + expect: `INSERT INTO foo (a,b) VALUES(:a, :b),(:a, :b) ON DUPLICATE KEY UPDATE a=VALUES(a)`, + loop: 2, + }, + { + name: `single column`, + query: `INSERT INTO foo (a) VALUES(:a)`, + expect: `INSERT INTO foo (a) VALUES(:a),(:a)`, + loop: 2, + }, + { + name: `call now`, + query: `INSERT INTO foo (a, b) VALUES(:a, NOW())`, + expect: `INSERT INTO foo (a, b) VALUES(:a, NOW()),(:a, NOW())`, + loop: 2, + }, } for _, tc := range table {