improve Model.Data for shallow value copy for value type of map/slice

This commit is contained in:
John Guo
2020-12-27 00:11:26 +08:00
parent ac827d3154
commit 65785db659
3 changed files with 83 additions and 6 deletions

View File

@ -25,6 +25,8 @@ func (m *Model) Batch(batch int) *Model {
// Data sets the operation data for the model.
// The parameter <data> can be type of string/map/gmap/slice/struct/*struct, etc.
// Note that, it uses shallow value copying for `data` if `data` is type of map/slice
// to avoid changing it inside function.
// Eg:
// Data("uid=10000")
// Data("uid", 10000)
@ -34,8 +36,7 @@ func (m *Model) Batch(batch int) *Model {
func (m *Model) Data(data ...interface{}) *Model {
model := m.getModel()
if len(data) > 1 {
s := gconv.String(data[0])
if gstr.Contains(s, "?") {
if s := gconv.String(data[0]); gstr.Contains(s, "?") {
model.data = s
model.extraArgs = data[1:]
} else {
@ -52,9 +53,13 @@ func (m *Model) Data(data ...interface{}) *Model {
case Record:
model.data = params.Map()
case List:
model.data = params
list := make(List, len(params))
for k, v := range params {
list[k] = gutil.MapCopy(v)
}
model.data = list
case Map:
model.data = params
model.data = gutil.MapCopy(params)
default:
var (
rv = reflect.ValueOf(params)

View File

@ -114,7 +114,7 @@ func createTableWithDb(db gdb.DB, table ...string) (name string) {
case "sqlite":
if _, err := db.Exec(fmt.Sprintf(`
CREATE TABLE %s (
id bigint NOT NULL,
id bigint unsigned NOT NULL AUTO_INCREMENT,
passport varchar(45),
password char(32) NOT NULL,
nickname varchar(45) NOT NULL,

View File

@ -99,6 +99,60 @@ func Test_Model_Insert(t *testing.T) {
})
}
// Using filter dose not affect the outside value inside function.
func Test_Model_Insert_Filter(t *testing.T) {
// map
gtest.C(t, func(t *gtest.T) {
table := createTable()
defer dropTable(table)
data := g.Map{
"id": 1,
"uid": 1,
"passport": "t1",
"password": "25d55ad283aa400af464c76d713c07ad",
"nickname": "name_1",
"create_time": gtime.Now().String(),
}
result, err := db.Table(table).Filter().Data(data).Insert()
t.Assert(err, nil)
n, _ := result.LastInsertId()
t.Assert(n, 1)
t.Assert(data["uid"], 1)
})
// slice
gtest.C(t, func(t *gtest.T) {
table := createTable()
defer dropTable(table)
data := g.List{
g.Map{
"id": 1,
"uid": 1,
"passport": "t1",
"password": "25d55ad283aa400af464c76d713c07ad",
"nickname": "name_1",
"create_time": gtime.Now().String(),
},
g.Map{
"id": 2,
"uid": 2,
"passport": "t1",
"password": "25d55ad283aa400af464c76d713c07ad",
"nickname": "name_1",
"create_time": gtime.Now().String(),
},
}
result, err := db.Table(table).Filter().Data(data).Insert()
t.Assert(err, nil)
n, _ := result.LastInsertId()
t.Assert(n, 2)
t.Assert(data[0]["uid"], 1)
t.Assert(data[1]["uid"], 2)
})
}
// Fix issue: https://github.com/gogf/gf/issues/819
func Test_Model_Insert_WithStructAndSliceAttribute(t *testing.T) {
table := createTable()
@ -285,7 +339,7 @@ func Test_Model_InsertIgnore(t *testing.T) {
}
func Test_Model_Batch(t *testing.T) {
// bacth insert
// batch insert
gtest.C(t, func(t *gtest.T) {
table := createTable()
defer dropTable(table)
@ -314,6 +368,24 @@ func Test_Model_Batch(t *testing.T) {
t.Assert(n, 2)
})
// batch insert, retrieving last insert auto-increment id.
gtest.C(t, func(t *gtest.T) {
table := createTable()
defer dropTable(table)
result, err := db.Table(table).Data(g.List{
{"passport": "t1"},
{"passport": "t2"},
{"passport": "t3"},
{"passport": "t4"},
{"passport": "t5"},
}).Batch(2).Insert()
if err != nil {
gtest.Error(err)
}
n, _ := result.RowsAffected()
t.Assert(n, 5)
})
// batch save
gtest.C(t, func(t *gtest.T) {
table := createInitTable()