Support batch insert map #2019
|
@ -1065,3 +1065,82 @@ func TestInsertDeleted(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, has)
|
assert.True(t, has)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInsertMultipleMap(t *testing.T) {
|
||||||
|
type InsertMultipleMap struct {
|
||||||
|
Id int64
|
||||||
|
Width uint32
|
||||||
|
Height uint32
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, PrepareEngine())
|
||||||
|
assertSync(t, new(InsertMultipleMap))
|
||||||
|
|
||||||
|
cnt, err := testEngine.Table(new(InsertMultipleMap)).Insert([]map[string]interface{}{
|
||||||
|
{
|
||||||
|
"width": 20,
|
||||||
|
"height": 10,
|
||||||
|
"name": "lunny",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"width": 30,
|
||||||
|
"height": 20,
|
||||||
|
"name": "xiaolunwen",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 2, cnt)
|
||||||
|
|
||||||
|
var res []InsertMultipleMap
|
||||||
|
err = testEngine.Find(&res)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 2, len(res))
|
||||||
|
assert.EqualValues(t, InsertMultipleMap{
|
||||||
|
Id: 1,
|
||||||
|
Width: 20,
|
||||||
|
Height: 10,
|
||||||
|
Name: "lunny",
|
||||||
|
}, res[0])
|
||||||
|
assert.EqualValues(t, InsertMultipleMap{
|
||||||
|
Id: 2,
|
||||||
|
Width: 30,
|
||||||
|
Height: 20,
|
||||||
|
Name: "xiaolunwen",
|
||||||
|
}, res[1])
|
||||||
|
|
||||||
|
assert.NoError(t, PrepareEngine())
|
||||||
|
assertSync(t, new(InsertMultipleMap))
|
||||||
|
|
||||||
|
cnt, err = testEngine.Table(new(InsertMultipleMap)).Insert([]map[string]string{
|
||||||
|
{
|
||||||
|
"width": "20",
|
||||||
|
"height": "10",
|
||||||
|
"name": "lunny",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"width": "30",
|
||||||
|
"height": "20",
|
||||||
|
"name": "xiaolunwen",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 2, cnt)
|
||||||
|
|
||||||
|
res = make([]InsertMultipleMap, 0, 2)
|
||||||
|
err = testEngine.Find(&res)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 2, len(res))
|
||||||
|
assert.EqualValues(t, InsertMultipleMap{
|
||||||
|
Id: 1,
|
||||||
|
Width: 20,
|
||||||
|
Height: 10,
|
||||||
|
Name: "lunny",
|
||||||
|
}, res[0])
|
||||||
|
assert.EqualValues(t, InsertMultipleMap{
|
||||||
|
Id: 2,
|
||||||
|
Width: 30,
|
||||||
|
Height: 20,
|
||||||
|
Name: "xiaolunwen",
|
||||||
|
}, res[1])
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package statements
|
package statements
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -205,3 +206,55 @@ func (statement *Statement) GenInsertMapSQL(columns []string, args []interface{}
|
||||||
|
|
||||||
return buf.String(), buf.Args(), nil
|
return buf.String(), buf.Args(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (statement *Statement) GenInsertMultipleMapSQL(columns []string, argss [][]interface{}) (string, []interface{}, error) {
|
||||||
|
var (
|
||||||
|
buf = builder.NewWriter()
|
||||||
|
exprs = statement.ExprColumns
|
||||||
|
tableName = statement.TableName()
|
||||||
|
)
|
||||||
|
|
||||||
|
if _, err := buf.WriteString(fmt.Sprintf("INSERT INTO %s (", statement.quote(tableName))); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := statement.dialect.Quoter().JoinWrite(buf.Builder, append(columns, exprs.ColNames()...), ","); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// if insert where
|
||||||
|
if statement.Conds().IsValid() {
|
||||||
|
return "", nil, errors.New("batch insert don't support with where")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := buf.WriteString(") VALUES "); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
for i, args := range argss {
|
||||||
|
if _, err := buf.WriteString("("); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if err := statement.WriteArgs(buf, args); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(exprs) > 0 {
|
||||||
|
if _, err := buf.WriteString(","); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if err := exprs.WriteArgs(buf); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, err := buf.WriteString(")"); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
if i < len(argss)-1 {
|
||||||
|
if _, err := buf.WriteString(","); err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), buf.Args(), nil
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrNoElementsOnSlice represents an error there is no element when insert
|
// ErrNoElementsOnSlice represents an error there is no element when insert
|
||||||
var ErrNoElementsOnSlice = errors.New("No element on slice when insert")
|
var ErrNoElementsOnSlice = errors.New("no element on slice when insert")
|
||||||
|
|
||||||
// Insert insert one or more beans
|
// Insert insert one or more beans
|
||||||
func (session *Session) Insert(beans ...interface{}) (int64, error) {
|
func (session *Session) Insert(beans ...interface{}) (int64, error) {
|
||||||
|
@ -36,71 +36,42 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
for _, bean := range beans {
|
for _, bean := range beans {
|
||||||
switch bean.(type) {
|
var cnt int64
|
||||||
|
var err error
|
||||||
|
switch v := bean.(type) {
|
||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
cnt, err := session.insertMapInterface(bean.(map[string]interface{}))
|
cnt, err = session.insertMapInterface(v)
|
||||||
if err != nil {
|
|
||||||
return affected, err
|
|
||||||
}
|
|
||||||
affected += cnt
|
|
||||||
case []map[string]interface{}:
|
case []map[string]interface{}:
|
||||||
s := bean.([]map[string]interface{})
|
cnt, err = session.insertMultipleMapInterface(v)
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
cnt, err := session.insertMapInterface(s[i])
|
|
||||||
if err != nil {
|
|
||||||
return affected, err
|
|
||||||
}
|
|
||||||
affected += cnt
|
|
||||||
}
|
|
||||||
case map[string]string:
|
case map[string]string:
|
||||||
cnt, err := session.insertMapString(bean.(map[string]string))
|
cnt, err = session.insertMapString(v)
|
||||||
if err != nil {
|
|
||||||
return affected, err
|
|
||||||
}
|
|
||||||
affected += cnt
|
|
||||||
case []map[string]string:
|
case []map[string]string:
|
||||||
s := bean.([]map[string]string)
|
cnt, err = session.insertMultipleMapString(v)
|
||||||
for i := 0; i < len(s); i++ {
|
|
||||||
cnt, err := session.insertMapString(s[i])
|
|
||||||
if err != nil {
|
|
||||||
return affected, err
|
|
||||||
}
|
|
||||||
affected += cnt
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
sliceValue := reflect.Indirect(reflect.ValueOf(bean))
|
sliceValue := reflect.Indirect(reflect.ValueOf(bean))
|
||||||
if sliceValue.Kind() == reflect.Slice {
|
if sliceValue.Kind() == reflect.Slice {
|
||||||
size := sliceValue.Len()
|
cnt, err = session.insertMultipleStruct(bean)
|
||||||
if size <= 0 {
|
|
||||||
return 0, ErrNoElementsOnSlice
|
|
||||||
}
|
|
||||||
|
|
||||||
cnt, err := session.innerInsertMulti(bean)
|
|
||||||
if err != nil {
|
|
||||||
return affected, err
|
|
||||||
}
|
|
||||||
affected += cnt
|
|
||||||
} else {
|
} else {
|
||||||
cnt, err := session.innerInsert(bean)
|
cnt, err = session.insertStruct(bean)
|
||||||
if err != nil {
|
|
||||||
return affected, err
|
|
||||||
}
|
|
||||||
affected += cnt
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return affected, err
|
||||||
|
}
|
||||||
|
affected += cnt
|
||||||
}
|
}
|
||||||
|
|
||||||
return affected, err
|
return affected, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error) {
|
func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, error) {
|
||||||
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
|
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
|
||||||
if sliceValue.Kind() != reflect.Slice {
|
if sliceValue.Kind() != reflect.Slice {
|
||||||
return 0, errors.New("needs a pointer to a slice")
|
return 0, errors.New("needs a pointer to a slice")
|
||||||
}
|
}
|
||||||
|
|
||||||
if sliceValue.Len() <= 0 {
|
if sliceValue.Len() <= 0 {
|
||||||
return 0, errors.New("could not insert a empty slice")
|
return 0, ErrNoElementsOnSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := session.statement.SetRefBean(sliceValue.Index(0).Interface()); err != nil {
|
if err := session.statement.SetRefBean(sliceValue.Index(0).Interface()); err != nil {
|
||||||
|
@ -269,14 +240,10 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
|
||||||
return 0, ErrPtrSliceType
|
return 0, ErrPtrSliceType
|
||||||
}
|
}
|
||||||
|
|
||||||
if sliceValue.Len() <= 0 {
|
return session.insertMultipleStruct(rowsSlicePtr)
|
||||||
return 0, ErrNoElementsOnSlice
|
|
||||||
}
|
|
||||||
|
|
||||||
return session.innerInsertMulti(rowsSlicePtr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) innerInsert(bean interface{}) (int64, error) {
|
func (session *Session) insertStruct(bean interface{}) (int64, error) {
|
||||||
if err := session.statement.SetRefBean(bean); err != nil {
|
if err := session.statement.SetRefBean(bean); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -434,7 +401,7 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
return session.innerInsert(bean)
|
return session.insertStruct(bean)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) cacheInsert(table string) error {
|
func (session *Session) cacheInsert(table string) error {
|
||||||
|
@ -561,6 +528,37 @@ func (session *Session) insertMapInterface(m map[string]interface{}) (int64, err
|
||||||
return session.insertMap(columns, args)
|
return session.insertMap(columns, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *Session) insertMultipleMapInterface(maps []map[string]interface{}) (int64, error) {
|
||||||
|
if len(maps) <= 0 {
|
||||||
|
return 0, ErrNoElementsOnSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
tableName := session.statement.TableName()
|
||||||
|
if len(tableName) <= 0 {
|
||||||
|
return 0, ErrTableNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
var columns = make([]string, 0, len(maps[0]))
|
||||||
|
exprs := session.statement.ExprColumns
|
||||||
|
for k := range maps[0] {
|
||||||
|
if !exprs.IsColExist(k) {
|
||||||
|
columns = append(columns, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(columns)
|
||||||
|
|
||||||
|
var argss = make([][]interface{}, 0, len(maps))
|
||||||
|
for _, m := range maps {
|
||||||
|
var args = make([]interface{}, 0, len(m))
|
||||||
|
for _, colName := range columns {
|
||||||
|
args = append(args, m[colName])
|
||||||
|
}
|
||||||
|
argss = append(argss, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
return session.insertMultipleMap(columns, argss)
|
||||||
|
}
|
||||||
|
|
||||||
func (session *Session) insertMapString(m map[string]string) (int64, error) {
|
func (session *Session) insertMapString(m map[string]string) (int64, error) {
|
||||||
if len(m) == 0 {
|
if len(m) == 0 {
|
||||||
return 0, ErrParamsType
|
return 0, ErrParamsType
|
||||||
|
@ -589,6 +587,37 @@ func (session *Session) insertMapString(m map[string]string) (int64, error) {
|
||||||
return session.insertMap(columns, args)
|
return session.insertMap(columns, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *Session) insertMultipleMapString(maps []map[string]string) (int64, error) {
|
||||||
|
if len(maps) <= 0 {
|
||||||
|
return 0, ErrNoElementsOnSlice
|
||||||
|
}
|
||||||
|
|
||||||
|
tableName := session.statement.TableName()
|
||||||
|
if len(tableName) <= 0 {
|
||||||
|
return 0, ErrTableNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
var columns = make([]string, 0, len(maps[0]))
|
||||||
|
exprs := session.statement.ExprColumns
|
||||||
|
for k := range maps[0] {
|
||||||
|
if !exprs.IsColExist(k) {
|
||||||
|
columns = append(columns, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sort.Strings(columns)
|
||||||
|
|
||||||
|
var argss = make([][]interface{}, 0, len(maps))
|
||||||
|
for _, m := range maps {
|
||||||
|
var args = make([]interface{}, 0, len(m))
|
||||||
|
for _, colName := range columns {
|
||||||
|
args = append(args, m[colName])
|
||||||
|
}
|
||||||
|
argss = append(argss, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
return session.insertMultipleMap(columns, argss)
|
||||||
|
}
|
||||||
|
|
||||||
func (session *Session) insertMap(columns []string, args []interface{}) (int64, error) {
|
func (session *Session) insertMap(columns []string, args []interface{}) (int64, error) {
|
||||||
tableName := session.statement.TableName()
|
tableName := session.statement.TableName()
|
||||||
if len(tableName) <= 0 {
|
if len(tableName) <= 0 {
|
||||||
|
@ -614,3 +643,29 @@ func (session *Session) insertMap(columns []string, args []interface{}) (int64,
|
||||||
}
|
}
|
||||||
return affected, nil
|
return affected, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *Session) insertMultipleMap(columns []string, argss [][]interface{}) (int64, error) {
|
||||||
|
tableName := session.statement.TableName()
|
||||||
|
if len(tableName) <= 0 {
|
||||||
|
return 0, ErrTableNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
sql, args, err := session.statement.GenInsertMultipleMapSQL(columns, argss)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := session.cacheInsert(tableName); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := session.exec(sql, args...)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
affected, err := res.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return affected, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user