Skip to content

Commit

Permalink
Close jmoiron#238, support batch insert.
Browse files Browse the repository at this point in the history
usage:
places := []*Place{&place1, &place2}
db.NamedExec("INSERT INTO place (country, telcode) VALUES (:country, :telcode)", places)
  • Loading branch information
hmgle committed Feb 25, 2017
1 parent f407684 commit 018bd2d
Showing 1 changed file with 49 additions and 1 deletion.
50 changes: 49 additions & 1 deletion named.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ package sqlx
// * bindArgs, bindMapArgs, bindAnyArgs - given a list of names, return an arglist
//
import (
"bytes"
"database/sql"
"errors"
"fmt"
"reflect"
"regexp"
"strconv"
"unicode"

Expand Down Expand Up @@ -206,6 +208,47 @@ func bindStruct(bindType int, query string, arg interface{}, m *reflectx.Mapper)
return bound, arglist, nil
}

var (
EndBracketsReg = regexp.MustCompile(`\([^()]*\)\s*$`)
)

func fixBound(bound string, loop int) string {
endBrackets := EndBracketsReg.FindString(bound)
if endBrackets == "" {
return bound
}
var buffer bytes.Buffer
buffer.WriteString(bound)
for i := 0; i < loop-1; i++ {
buffer.WriteString(",")
buffer.WriteString(endBrackets)
}
return buffer.String()
}

// bindArray binds a named parameter query with fields from an array or slice of
// structs argument.
func bindArray(bindType int, query string, arg interface{}, m *reflectx.Mapper) (string, []interface{}, error) {
bound, names, err := compileNamedQuery([]byte(query), bindType)
if err != nil {
return "", []interface{}{}, err
}
arrayValue := reflect.ValueOf(arg)
arrayLen := arrayValue.Len()
var arglist []interface{}
for i := 0; i < arrayLen; i++ {
elemArglist, err := bindArgs(names, arrayValue.Index(i).Interface(), m)
if err != nil {
return "", []interface{}{}, err
}
arglist = append(arglist, elemArglist...)
}
if arrayLen > 1 {
bound = fixBound(bound, arrayLen)
}
return bound, arglist, nil
}

// bindMap binds a named parameter query with a map of arguments.
func bindMap(bindType int, query string, args map[string]interface{}) (string, []interface{}, error) {
bound, names, err := compileNamedQuery([]byte(query), bindType)
Expand Down Expand Up @@ -318,7 +361,12 @@ func bindNamedMapper(bindType int, query string, arg interface{}, m *reflectx.Ma
if maparg, ok := arg.(map[string]interface{}); ok {
return bindMap(bindType, query, maparg)
}
return bindStruct(bindType, query, arg, m)
switch reflect.TypeOf(arg).Kind() {
case reflect.Array, reflect.Slice:
return bindArray(bindType, query, arg, m)
default:
return bindStruct(bindType, query, arg, m)
}
}

// NamedQuery binds a named query and then runs Query on the result using the
Expand Down

0 comments on commit 018bd2d

Please sign in to comment.