From 030cd848364e8d00026b6b3e34879ce737bf7823 Mon Sep 17 00:00:00 2001 From: Jack Ling <34231795+lingcoder@users.noreply.github.com> Date: Thu, 12 Mar 2026 11:15:42 +0800 Subject: [PATCH] test(contrib/drivers/mariadb): add softtime, with, scanlist, union and do tests (#4721) ## Summary - Port 48 soft-time tests: soft create/update/delete with timestamp/datetime/date types, SoftTime switches (SoftTimeTypeOff/Delete/Timestamp), Unscoped, ForceDelete, joined queries with soft-delete - Port 19 With/ScanList tests: With/WithAll for eager loading of hasOne/hasMany/belongsTo relations, ScanList for manual relation mapping, nested With - Port 12 union tests: Union/UnionAll with various parameter forms (string/Model/subquery), combined with OrderBy, Limit, Where conditions - Port 12 gdb.Do tests: DoSelect/DoInsert/DoUpdate/DoDelete raw operation hooks, batch insert, InsertIgnore/InsertGetId/Replace via DoInsert option Includes testdata SQL files for With relation table schemas (with_tpl). Soft-time tests create tables inline via SQL, no separate testdata files needed. All tests are structurally identical to the MySQL driver baseline. SQL syntax is standard and shared. Package and import references are adapted for MariaDB. ref #4689 --- .../mariadb_z_unit_feature_model_do_test.go | 390 +++ .../mariadb_z_unit_feature_scanlist_test.go | 2105 +++++++++++++++++ .../mariadb_z_unit_feature_soft_time_test.go | 1399 +++++++++++ .../mariadb_z_unit_feature_union_test.go | 146 ++ .../mariadb_z_unit_feature_with_test.go | 1998 ++++++++++++++++ .../mariadb/testdata/table_with_prefix.sql | 7 + .../testdata/with_multiple_depends.sql | 33 + .../mariadb/testdata/with_tpl_user.sql | 5 + .../mariadb/testdata/with_tpl_user_detail.sql | 5 + .../mariadb/testdata/with_tpl_user_scores.sql | 6 + 10 files changed, 6094 insertions(+) create mode 100644 contrib/drivers/mariadb/mariadb_z_unit_feature_model_do_test.go create mode 100644 contrib/drivers/mariadb/mariadb_z_unit_feature_scanlist_test.go create mode 100644 contrib/drivers/mariadb/mariadb_z_unit_feature_soft_time_test.go create mode 100644 contrib/drivers/mariadb/mariadb_z_unit_feature_union_test.go create mode 100644 contrib/drivers/mariadb/mariadb_z_unit_feature_with_test.go create mode 100644 contrib/drivers/mariadb/testdata/table_with_prefix.sql create mode 100644 contrib/drivers/mariadb/testdata/with_multiple_depends.sql create mode 100644 contrib/drivers/mariadb/testdata/with_tpl_user.sql create mode 100644 contrib/drivers/mariadb/testdata/with_tpl_user_detail.sql create mode 100644 contrib/drivers/mariadb/testdata/with_tpl_user_scores.sql diff --git a/contrib/drivers/mariadb/mariadb_z_unit_feature_model_do_test.go b/contrib/drivers/mariadb/mariadb_z_unit_feature_model_do_test.go new file mode 100644 index 000000000..ba52ead54 --- /dev/null +++ b/contrib/drivers/mariadb/mariadb_z_unit_feature_model_do_test.go @@ -0,0 +1,390 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mariadb_test + +import ( + "testing" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" +) + +func Test_Model_Insert_Data_DO(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := User{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + } + result, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := result.LastInsertId() + t.Assert(n, 1) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], `1`) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], ``) + t.Assert(one[`create_time`], ``) + }) +} + +func Test_Model_Insert_Data_List_DO(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := g.Slice{ + User{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + }, + User{ + Id: 2, + Passport: "user_2", + Password: "pass_2", + }, + } + result, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := result.LastInsertId() + t.Assert(n, 2) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], `1`) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], ``) + t.Assert(one[`create_time`], ``) + + one, err = db.Model(table).WherePri(2).One() + t.AssertNil(err) + t.Assert(one[`id`], `2`) + t.Assert(one[`passport`], `user_2`) + t.Assert(one[`password`], `pass_2`) + t.Assert(one[`nickname`], ``) + t.Assert(one[`create_time`], ``) + }) +} + +func Test_Model_Update_Data_DO(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := User{ + Id: 1, + Passport: "user_100", + Password: "pass_100", + } + _, err := db.Model(table).Data(data).WherePri(1).Update() + t.AssertNil(err) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], `1`) + t.Assert(one[`passport`], `user_100`) + t.Assert(one[`password`], `pass_100`) + t.Assert(one[`nickname`], `name_1`) + }) +} + +func Test_Model_Update_Pointer_Data_DO(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type NN string + type Req struct { + Id int + Passport *string + Password *string + Nickname *NN + } + type UserDo struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + var ( + nickname = NN("nickname_111") + req = Req{ + Password: gconv.PtrString("12345678"), + Nickname: &nickname, + } + data = UserDo{ + Passport: req.Passport, + Password: req.Password, + Nickname: req.Nickname, + } + ) + + _, err := db.Model(table).Data(data).WherePri(1).Update() + t.AssertNil(err) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], `1`) + t.Assert(one[`password`], `12345678`) + t.Assert(one[`nickname`], `nickname_111`) + }) +} + +func Test_Model_Where_DO(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type User struct { + g.Meta `orm:"do:true"` + Id any + Passport any + Password any + Nickname any + CreateTime any + } + where := User{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + } + one, err := db.Model(table).Where(where).One() + t.AssertNil(err) + t.Assert(one[`id`], `1`) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], `name_1`) + }) +} + +func Test_Model_Insert_Data_ForDao(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type UserForDao struct { + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := UserForDao{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + } + result, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := result.LastInsertId() + t.Assert(n, 1) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], `1`) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], ``) + t.Assert(one[`create_time`], ``) + }) +} + +func Test_Model_Insert_Data_List_ForDao(t *testing.T) { + table := createTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type UserForDao struct { + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := g.Slice{ + UserForDao{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + }, + UserForDao{ + Id: 2, + Passport: "user_2", + Password: "pass_2", + }, + } + result, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := result.LastInsertId() + t.Assert(n, 2) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], `1`) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], ``) + t.Assert(one[`create_time`], ``) + + one, err = db.Model(table).WherePri(2).One() + t.AssertNil(err) + t.Assert(one[`id`], `2`) + t.Assert(one[`passport`], `user_2`) + t.Assert(one[`password`], `pass_2`) + t.Assert(one[`nickname`], ``) + t.Assert(one[`create_time`], ``) + }) +} + +func Test_Model_Update_Data_ForDao(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type UserForDao struct { + Id any + Passport any + Password any + Nickname any + CreateTime any + } + data := UserForDao{ + Id: 1, + Passport: "user_100", + Password: "pass_100", + } + _, err := db.Model(table).Data(data).WherePri(1).Update() + t.AssertNil(err) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one[`id`], `1`) + t.Assert(one[`passport`], `user_100`) + t.Assert(one[`password`], `pass_100`) + t.Assert(one[`nickname`], `name_1`) + }) +} + +func Test_Model_Where_ForDao(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + type UserForDao struct { + Id any + Passport any + Password any + Nickname any + CreateTime any + } + where := UserForDao{ + Id: 1, + Passport: "user_1", + Password: "pass_1", + } + one, err := db.Model(table).Where(where).One() + t.AssertNil(err) + t.Assert(one[`id`], `1`) + t.Assert(one[`passport`], `user_1`) + t.Assert(one[`password`], `pass_1`) + t.Assert(one[`nickname`], `name_1`) + }) +} + +func Test_Model_Where_FieldPrefix(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + array := gstr.SplitAndTrim(gtest.DataContent(`table_with_prefix.sql`), ";") + for _, v := range array { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + defer dropTable("instance") + + type Instance struct { + ID int `orm:"f_id"` + Name string + } + + type InstanceDo struct { + g.Meta `orm:"table:instance, do:true"` + ID any `orm:"f_id"` + } + var instance *Instance + err := db.Model("instance").Where(InstanceDo{ + ID: 1, + }).Scan(&instance) + t.AssertNil(err) + t.AssertNE(instance, nil) + t.Assert(instance.ID, 1) + t.Assert(instance.Name, "john") + }) + // With omitempty. + gtest.C(t, func(t *gtest.T) { + array := gstr.SplitAndTrim(gtest.DataContent(`table_with_prefix.sql`), ";") + for _, v := range array { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + defer dropTable("instance") + + type Instance struct { + ID int `orm:"f_id,omitempty"` + Name string + } + + type InstanceDo struct { + g.Meta `orm:"table:instance, do:true"` + ID any `orm:"f_id,omitempty"` + } + var instance *Instance + err := db.Model("instance").Where(InstanceDo{ + ID: 1, + }).Scan(&instance) + t.AssertNil(err) + t.AssertNE(instance, nil) + t.Assert(instance.ID, 1) + t.Assert(instance.Name, "john") + }) +} diff --git a/contrib/drivers/mariadb/mariadb_z_unit_feature_scanlist_test.go b/contrib/drivers/mariadb/mariadb_z_unit_feature_scanlist_test.go new file mode 100644 index 000000000..0d8beeac4 --- /dev/null +++ b/contrib/drivers/mariadb/mariadb_z_unit_feature_scanlist_test.go @@ -0,0 +1,2105 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mariadb_test + +import ( + "context" + "fmt" + "testing" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/gconv" +) + +func Test_Table_Relation_One(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + course varchar(45) NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `orm:"uid"` + Name string `orm:"name"` + } + + type EntityUserDetail struct { + Uid int `orm:"uid"` + Address string `orm:"address"` + } + + type EntityUserScores struct { + Id int `orm:"id"` + Uid int `orm:"uid"` + Score int `orm:"score"` + Course string `orm:"course"` + } + + type Entity struct { + User *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + // Initialize the data. + var err error + gtest.C(t, func(t *gtest.T) { + err = db.Transaction(context.TODO(), func(ctx context.Context, tx gdb.TX) error { + r, err := tx.Model(tableUser).Save(EntityUser{ + Name: "john", + }) + if err != nil { + return err + } + uid, err := r.LastInsertId() + if err != nil { + return err + } + _, err = tx.Model(tableUserDetail).Save(EntityUserDetail{ + Uid: int(uid), + Address: "Beijing DongZhiMen #66", + }) + if err != nil { + return err + } + _, err = tx.Model(tableUserScores).Save(g.Slice{ + EntityUserScores{Uid: int(uid), Score: 100, Course: "math"}, + EntityUserScores{Uid: int(uid), Score: 99, Course: "physics"}, + }) + return err + }) + t.AssertNil(err) + }) + // Data check. + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(tableUser).All() + t.AssertNil(err) + t.Assert(r.Len(), 1) + t.Assert(r[0]["uid"].Int(), 1) + t.Assert(r[0]["name"].String(), "john") + + r, err = db.Model(tableUserDetail).Where("uid", r[0]["uid"].Int()).All() + t.AssertNil(err) + t.Assert(r.Len(), 1) + t.Assert(r[0]["uid"].Int(), 1) + t.Assert(r[0]["address"].String(), `Beijing DongZhiMen #66`) + + r, err = db.Model(tableUserScores).Where("uid", r[0]["uid"].Int()).All() + t.AssertNil(err) + t.Assert(r.Len(), 2) + t.Assert(r[0]["uid"].Int(), 1) + t.Assert(r[1]["uid"].Int(), 1) + t.Assert(r[0]["course"].String(), `math`) + t.Assert(r[1]["course"].String(), `physics`) + }) + // Entity query. + gtest.C(t, func(t *gtest.T) { + var user Entity + // SELECT * FROM `user` WHERE `name`='john' + err := db.Model(tableUser).Scan(&user.User, "name", "john") + t.AssertNil(err) + + // SELECT * FROM `user_detail` WHERE `uid`=1 + err = db.Model(tableUserDetail).Scan(&user.UserDetail, "uid", user.User.Uid) + t.AssertNil(err) + + // SELECT * FROM `user_scores` WHERE `uid`=1 + err = db.Model(tableUserScores).Scan(&user.UserScores, "uid", user.User.Uid) + t.AssertNil(err) + + t.Assert(user.User, EntityUser{ + Uid: 1, + Name: "john", + }) + t.Assert(user.UserDetail, EntityUserDetail{ + Uid: 1, + Address: "Beijing DongZhiMen #66", + }) + t.Assert(user.UserScores, []EntityUserScores{ + {Id: 1, Uid: 1, Course: "math", Score: 100}, + {Id: 2, Uid: 1, Course: "physics", Score: 99}, + }) + }) +} + +func Test_Table_Relation_Many(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + // Initialize the data. + gtest.C(t, func(t *gtest.T) { + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "uid": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + t.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + t.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + t.AssertNil(err) + } + } + }) + + // MapKeyValue. + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + t.Assert(all.Len(), 2) + t.Assert(len(all.MapKeyValue("uid")), 2) + t.Assert(all.MapKeyValue("uid")["3"].Map()["uid"], 3) + t.Assert(all.MapKeyValue("uid")["4"].Map()["uid"], 4) + all, err = db.Model(tableUserScores).Where("uid", g.Slice{3, 4}).Order("id asc").All() + t.AssertNil(err) + t.Assert(all.Len(), 10) + t.Assert(len(all.MapKeyValue("uid")), 2) + t.Assert(len(all.MapKeyValue("uid")["3"].Slice()), 5) + t.Assert(len(all.MapKeyValue("uid")["4"].Slice()), 5) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[0])["uid"], 3) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[0])["score"], 1) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[4])["uid"], 3) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[4])["score"], 5) + }) + // Result ScanList with struct elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with struct elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []*Entity + + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Model ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + err := db.Model(tableUser). + Where("uid", g.Slice{3, 4}). + Order("uid asc"). + ScanList(&users, "User") + t.AssertNil(err) + // Detail + err = db.Model(tableUserDetail). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("uid asc"). + ScanList(&users, "UserDetail", "User", "uid:Uid") + t.AssertNil(err) + // Scores + err = db.Model(tableUserScores). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("id asc"). + ScanList(&users, "UserScores", "User", "uid:Uid") + t.AssertNil(err) + + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_Many_ModelScanList(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + // Initialize the data. + gtest.C(t, func(t *gtest.T) { + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "uid": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + t.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + t.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + t.AssertNil(err) + } + } + }) + + //db.SetDebug(true) + // Result ScanList with struct elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []Entity + // User + err := db.Model(tableUser). + Where("uid", g.Slice{3, 4}). + Order("uid asc"). + ScanList(&users, "User") + t.AssertNil(err) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + + // Detail + err = db.Model(tableUserDetail). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("uid asc"). + ScanList(&users, "UserDetail", "User", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + + // Scores + err = db.Model(tableUserScores). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("id asc"). + ScanList(&users, "UserScores", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_Many_RelationKeyCaseInsensitive(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + // Initialize the data. + gtest.C(t, func(t *gtest.T) { + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "uid": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + t.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + t.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + t.AssertNil(err) + } + } + }) + + // MapKeyValue. + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + t.Assert(all.Len(), 2) + t.Assert(len(all.MapKeyValue("uid")), 2) + t.Assert(all.MapKeyValue("uid")["3"].Map()["uid"], 3) + t.Assert(all.MapKeyValue("uid")["4"].Map()["uid"], 4) + all, err = db.Model(tableUserScores).Where("uid", g.Slice{3, 4}).Order("id asc").All() + t.AssertNil(err) + t.Assert(all.Len(), 10) + t.Assert(len(all.MapKeyValue("uid")), 2) + t.Assert(len(all.MapKeyValue("uid")["3"].Slice()), 5) + t.Assert(len(all.MapKeyValue("uid")["4"].Slice()), 5) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[0])["uid"], 3) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[0])["score"], 1) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[4])["uid"], 3) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[4])["score"], 5) + }) + // Result ScanList with struct elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "uid:uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "Uid:UID") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "Uid:UID") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with struct elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:UId") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "UId:Uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []*Entity + + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:Uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "UID:Uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Model ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + err := db.Model(tableUser). + Where("uid", g.Slice{3, 4}). + Order("uid asc"). + ScanList(&users, "User") + t.AssertNil(err) + // Detail + err = db.Model(tableUserDetail). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("uid asc"). + ScanList(&users, "UserDetail", "User", "uid:Uid") + t.AssertNil(err) + // Scores + err = db.Model(tableUserScores). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("id asc"). + ScanList(&users, "UserScores", "User", "uid:Uid") + t.AssertNil(err) + + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_Many_TheSameRelationNames(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + // Initialize the data. + gtest.C(t, func(t *gtest.T) { + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "uid": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + t.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + t.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + t.AssertNil(err) + } + } + }) + + // Result ScanList with struct elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "Uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "UID") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with struct elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "UId") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "Uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []*Entity + + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "UID") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Model ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + err := db.Model(tableUser). + Where("uid", g.Slice{3, 4}). + Order("uid asc"). + ScanList(&users, "User") + t.AssertNil(err) + // Detail + err = db.Model(tableUserDetail). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("uid asc"). + ScanList(&users, "UserDetail", "User", "uid") + t.AssertNil(err) + // Scores + err = db.Model(tableUserScores). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("id asc"). + ScanList(&users, "UserScores", "User", "uid") + t.AssertNil(err) + + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_EmptyData(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + // Result ScanList with struct elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 0) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:uid") + t.AssertNil(err) + + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "uid:uid") + t.AssertNil(err) + }) + return + // Result ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 0) + + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "Uid:UID") + t.AssertNil(err) + + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "Uid:UID") + t.AssertNil(err) + }) + + // Result ScanList with struct elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:UId") + t.AssertNil(err) + + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "UId:Uid") + t.AssertNil(err) + }) + + // Result ScanList with pointer elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []*Entity + + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 0) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid:Uid") + t.AssertNil(err) + + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "UID:Uid") + t.AssertNil(err) + }) + + // Model ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + err := db.Model(tableUser). + Where("uid", g.Slice{3, 4}). + Order("uid asc"). + ScanList(&users, "User") + t.AssertNil(err) + // Detail + err = db.Model(tableUserDetail). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("uid asc"). + ScanList(&users, "UserDetail", "User", "uid:Uid") + t.AssertNil(err) + // Scores + err = db.Model(tableUserScores). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("id asc"). + ScanList(&users, "UserScores", "User", "uid:Uid") + t.AssertNil(err) + + t.Assert(len(users), 0) + }) +} + +func Test_Table_Relation_NoneEqualDataSize(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + // Initialize the data. + gtest.C(t, func(t *gtest.T) { + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "uid": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + t.AssertNil(err) + // Detail. + // _, err = db.Insert(ctx, tableUserDetail, g.Map{ + // "uid": i, + // "address": fmt.Sprintf(`address_%d`, i), + // }) + // t.AssertNil(err) + // Scores. + // for j := 1; j <= 5; j++ { + // _, err = db.Insert(ctx, tableUserScores, g.Map{ + // "uid": i, + // "score": j, + // }) + // t.AssertNil(err) + // } + } + }) + + // Result ScanList with struct elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, nil) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 0) + }) + + // Result ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "Uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, nil) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "UID") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 0) + }) + + // Result ScanList with struct elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []Entity + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "UId") + t.AssertNil(err) + t.Assert(users[0].UserDetail, EntityUserDetail{}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "Uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 0) + }) + + // Result ScanList with pointer elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + User EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []*Entity + + // User + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "User") + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + // Detail + all, err = db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "User", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, EntityUserDetail{}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "User", "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "User", "UID") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 0) + }) + + // Model ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + err := db.Model(tableUser). + Where("uid", g.Slice{3, 4}). + Order("uid asc"). + ScanList(&users, "User") + t.AssertNil(err) + // Detail + err = db.Model(tableUserDetail). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("uid asc"). + ScanList(&users, "UserDetail", "User", "uid") + t.AssertNil(err) + // Scores + err = db.Model(tableUserScores). + Where("uid", gdb.ListItemValues(users, "User", "Uid")). + Order("id asc"). + ScanList(&users, "UserScores", "User", "uid") + t.AssertNil(err) + + t.Assert(len(users), 2) + t.Assert(users[0].User, &EntityUser{3, "name_3"}) + t.Assert(users[1].User, &EntityUser{4, "name_4"}) + + t.Assert(users[0].UserDetail, nil) + + t.Assert(len(users[0].UserScores), 0) + }) +} + +func Test_Table_Relation_EmbeddedStruct1(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + *EntityUser + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + *EntityUser + *EntityUserDetail + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + // Initialize the data. + gtest.C(t, func(t *gtest.T) { + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "uid": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + t.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + t.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + t.AssertNil(err) + } + } + }) + + gtest.C(t, func(t *gtest.T) { + var ( + err error + scores []*EntityUserScores + ) + // SELECT * FROM `user_scores` + err = db.Model(tableUserScores).Scan(&scores) + t.AssertNil(err) + + // SELECT * FROM `user_scores` WHERE `uid` IN(1,2,3,4,5) + err = db.Model(tableUser). + Where("uid", gdb.ListItemValuesUnique(&scores, "Uid")). + ScanList(&scores, "EntityUser", "uid:Uid") + t.AssertNil(err) + + // SELECT * FROM `user_detail` WHERE `uid` IN(1,2,3,4,5) + err = db.Model(tableUserDetail). + Where("uid", gdb.ListItemValuesUnique(&scores, "Uid")). + ScanList(&scores, "EntityUserDetail", "uid:Uid") + t.AssertNil(err) + + // Assertions. + t.Assert(len(scores), 25) + t.Assert(scores[0].Id, 1) + t.Assert(scores[0].Uid, 1) + t.Assert(scores[0].Name, "name_1") + t.Assert(scores[0].Address, "address_1") + t.Assert(scores[24].Id, 25) + t.Assert(scores[24].Uid, 5) + t.Assert(scores[24].Name, "name_5") + t.Assert(scores[24].Address, "address_5") + }) +} + +func Test_Table_Relation_EmbeddedStruct2(t *testing.T) { + var ( + tableUser = "user_" + gtime.TimestampMicroStr() + tableUserDetail = "user_detail_" + gtime.TimestampMicroStr() + tableUserScores = "user_scores_" + gtime.TimestampMicroStr() + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + *EntityUser + UserDetail *EntityUserDetail + UserScores []*EntityUserScores + } + + // Initialize the data. + gtest.C(t, func(t *gtest.T) { + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "uid": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + t.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + t.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + t.AssertNil(err) + } + } + }) + + // MapKeyValue. + gtest.C(t, func(t *gtest.T) { + all, err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").All() + t.AssertNil(err) + t.Assert(all.Len(), 2) + t.Assert(len(all.MapKeyValue("uid")), 2) + t.Assert(all.MapKeyValue("uid")["3"].Map()["uid"], 3) + t.Assert(all.MapKeyValue("uid")["4"].Map()["uid"], 4) + all, err = db.Model(tableUserScores).Where("uid", g.Slice{3, 4}).Order("id asc").All() + t.AssertNil(err) + t.Assert(all.Len(), 10) + t.Assert(len(all.MapKeyValue("uid")), 2) + t.Assert(len(all.MapKeyValue("uid")["3"].Slice()), 5) + t.Assert(len(all.MapKeyValue("uid")["4"].Slice()), 5) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[0])["uid"], 3) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[0])["score"], 1) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[4])["uid"], 3) + t.Assert(gconv.Map(all.MapKeyValue("uid")["3"].Slice()[4])["score"], 5) + }) + + // Result ScanList with struct elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []Entity + // User + err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + // Detail + all, err := db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + // Detail + all, err := db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with struct elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []Entity + // User + err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + // Detail + all, err := db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Result ScanList with pointer elements and struct attributes. + gtest.C(t, func(t *gtest.T) { + type EntityUser struct { + Uid int `json:"uid"` + Name string `json:"name"` + } + type EntityUserDetail struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + type EntityUserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + type Entity struct { + EntityUser + UserDetail EntityUserDetail + UserScores []EntityUserScores + } + var users []*Entity + + // User + err := db.Model(tableUser).Where("uid", g.Slice{3, 4}).Order("uid asc").Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + // Detail + all, err := db.Model(tableUserDetail).Where("uid", gdb.ListItemValues(users, "Uid")).Order("uid asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserDetail", "uid") + t.AssertNil(err) + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + // Scores + all, err = db.Model(tableUserScores).Where("uid", gdb.ListItemValues(users, "Uid")).Order("id asc").All() + t.AssertNil(err) + err = all.ScanList(&users, "UserScores", "uid") + t.AssertNil(err) + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) + + // Model ScanList with pointer elements and pointer attributes. + gtest.C(t, func(t *gtest.T) { + var users []*Entity + // User + err := db.Model(tableUser). + Where("uid", g.Slice{3, 4}). + Order("uid asc"). + Scan(&users) + t.AssertNil(err) + // Detail + err = db.Model(tableUserDetail). + Where("uid", gdb.ListItemValues(users, "Uid")). + Order("uid asc"). + ScanList(&users, "UserDetail", "uid:Uid") + t.AssertNil(err) + // Scores + err = db.Model(tableUserScores). + Where("uid", gdb.ListItemValues(users, "Uid")). + Order("id asc"). + ScanList(&users, "UserScores", "uid:Uid") + t.AssertNil(err) + + t.Assert(len(users), 2) + t.Assert(users[0].EntityUser, &EntityUser{3, "name_3"}) + t.Assert(users[1].EntityUser, &EntityUser{4, "name_4"}) + + t.Assert(users[0].UserDetail, &EntityUserDetail{3, "address_3"}) + t.Assert(users[1].UserDetail, &EntityUserDetail{4, "address_4"}) + + t.Assert(len(users[0].UserScores), 5) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Score, 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Score, 5) + }) +} diff --git a/contrib/drivers/mariadb/mariadb_z_unit_feature_soft_time_test.go b/contrib/drivers/mariadb/mariadb_z_unit_feature_soft_time_test.go new file mode 100644 index 000000000..41658a5c3 --- /dev/null +++ b/contrib/drivers/mariadb/mariadb_z_unit_feature_soft_time_test.go @@ -0,0 +1,1399 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mariadb_test + +import ( + "fmt" + "testing" + "time" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/test/gtest" +) + +// CreateAt/UpdateAt/DeleteAt. +func Test_SoftTime_CreateUpdateDelete1(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at datetime(6) DEFAULT NULL, + update_at datetime(6) DEFAULT NULL, + delete_at datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + // Insert + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInsert, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInsert["id"].Int(), 1) + t.Assert(oneInsert["name"].String(), "name_1") + t.Assert(oneInsert["delete_at"].String(), "") + t.AssertGE(oneInsert["create_at"].GTime().Timestamp(), gtime.Timestamp()-2) + t.AssertGE(oneInsert["update_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Save + dataSave := g.Map{ + "id": 1, + "name": "name_10", + } + r, err = db.Model(table).Data(dataSave).Save() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneSave, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneSave["id"].Int(), 1) + t.Assert(oneSave["name"].String(), "name_10") + t.Assert(oneSave["delete_at"].String(), "") + t.Assert(oneSave["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp()) + t.AssertNE(oneSave["update_at"].GTime().Timestamp(), oneInsert["update_at"].GTime().Timestamp()) + t.AssertGE(oneSave["update_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Update + dataUpdate := g.Map{ + "name": "name_1000", + } + r, err = db.Model(table).Data(dataUpdate).WherePri(1).Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + oneUpdate, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneUpdate["id"].Int(), 1) + t.Assert(oneUpdate["name"].String(), "name_1000") + t.Assert(oneUpdate["delete_at"].String(), "") + t.Assert(oneUpdate["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp()) + t.AssertGE(oneUpdate["update_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // Replace + dataReplace := g.Map{ + "id": 1, + "name": "name_100", + } + r, err = db.Model(table).Data(dataReplace).Replace() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneReplace, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneReplace["id"].Int(), 1) + t.Assert(oneReplace["name"].String(), "name_100") + t.Assert(oneReplace["delete_at"].String(), "") + t.AssertGE(oneReplace["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp()) + t.AssertGE(oneReplace["update_at"].GTime().Timestamp(), oneInsert["update_at"].GTime().Timestamp()) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Delete + r, err = db.Model(table).Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + // Delete Select + one4, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one4), 0) + one5, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(one5["id"].Int(), 1) + t.AssertGE(one5["delete_at"].GTime().Timestamp(), gtime.Timestamp()-2) + // Delete Count + i, err := db.Model(table).Count() + t.AssertNil(err) + t.Assert(i, 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 1) + + // Delete Unscoped + r, err = db.Model(table).Unscoped().Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + one6, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one6), 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 0) + }) +} + +// CreateAt/UpdateAt/DeleteAt. +func Test_SoftTime_CreateUpdateDelete2(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at datetime(0) DEFAULT NULL, + update_at datetime(0) DEFAULT NULL, + delete_at datetime(0) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + // Insert + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInsert, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInsert["id"].Int(), 1) + t.Assert(oneInsert["name"].String(), "name_1") + t.Assert(oneInsert["delete_at"].String(), "") + t.AssertGE(oneInsert["create_at"].GTime().Timestamp(), gtime.Timestamp()-2) + t.AssertGE(oneInsert["update_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Save + dataSave := g.Map{ + "id": 1, + "name": "name_10", + } + r, err = db.Model(table).Data(dataSave).Save() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneSave, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneSave["id"].Int(), 1) + t.Assert(oneSave["name"].String(), "name_10") + t.Assert(oneSave["delete_at"].String(), "") + t.Assert(oneSave["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp()) + t.AssertNE(oneSave["update_at"].GTime().Timestamp(), oneInsert["update_at"].GTime().Timestamp()) + t.AssertGE(oneSave["update_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Update + dataUpdate := g.Map{ + "name": "name_1000", + } + r, err = db.Model(table).Data(dataUpdate).WherePri(1).Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + oneUpdate, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneUpdate["id"].Int(), 1) + t.Assert(oneUpdate["name"].String(), "name_1000") + t.Assert(oneUpdate["delete_at"].String(), "") + t.Assert(oneUpdate["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp()) + t.AssertGE(oneUpdate["update_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // Replace + dataReplace := g.Map{ + "id": 1, + "name": "name_100", + } + r, err = db.Model(table).Data(dataReplace).Replace() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneReplace, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneReplace["id"].Int(), 1) + t.Assert(oneReplace["name"].String(), "name_100") + t.Assert(oneReplace["delete_at"].String(), "") + t.AssertGE(oneReplace["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp()) + t.AssertGE(oneReplace["update_at"].GTime().Timestamp(), oneInsert["update_at"].GTime().Timestamp()) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Delete + r, err = db.Model(table).Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + // Delete Select + one4, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one4), 0) + one5, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(one5["id"].Int(), 1) + t.AssertGE(one5["delete_at"].GTime().Timestamp(), gtime.Timestamp()-2) + // Delete Count + i, err := db.Model(table).Count() + t.AssertNil(err) + t.Assert(i, 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 1) + + // Delete Unscoped + r, err = db.Model(table).Unscoped().Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + one6, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one6), 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 0) + }) +} + +// CreatedAt/UpdatedAt/DeletedAt. +func Test_SoftTime_CreatedUpdatedDeleted_Map(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + created_at datetime(6) DEFAULT NULL, + updated_at datetime(6) DEFAULT NULL, + deleted_at datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + // Insert + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInsert, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInsert["id"].Int(), 1) + t.Assert(oneInsert["name"].String(), "name_1") + t.Assert(oneInsert["deleted_at"].String(), "") + t.AssertGE(oneInsert["created_at"].GTime().Timestamp(), gtime.Timestamp()-2) + t.AssertGE(oneInsert["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Save + dataSave := g.Map{ + "id": 1, + "name": "name_10", + } + r, err = db.Model(table).Data(dataSave).Save() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneSave, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneSave["id"].Int(), 1) + t.Assert(oneSave["name"].String(), "name_10") + t.Assert(oneSave["deleted_at"].String(), "") + t.Assert(oneSave["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp()) + t.AssertNE(oneSave["updated_at"].GTime().Timestamp(), oneInsert["updated_at"].GTime().Timestamp()) + t.AssertGE(oneSave["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Update + dataUpdate := g.Map{ + "name": "name_1000", + } + r, err = db.Model(table).Data(dataUpdate).WherePri(1).Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + oneUpdate, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneUpdate["id"].Int(), 1) + t.Assert(oneUpdate["name"].String(), "name_1000") + t.Assert(oneUpdate["deleted_at"].String(), "") + t.Assert(oneUpdate["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp()) + t.AssertGE(oneUpdate["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // Replace + dataReplace := g.Map{ + "id": 1, + "name": "name_100", + } + r, err = db.Model(table).Data(dataReplace).Replace() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneReplace, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneReplace["id"].Int(), 1) + t.Assert(oneReplace["name"].String(), "name_100") + t.Assert(oneReplace["deleted_at"].String(), "") + t.AssertGE(oneReplace["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp()) + t.AssertGE(oneReplace["updated_at"].GTime().Timestamp(), oneInsert["updated_at"].GTime().Timestamp()) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Delete + r, err = db.Model(table).Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + // Delete Select + one4, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one4), 0) + one5, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(one5["id"].Int(), 1) + t.AssertGE(one5["deleted_at"].GTime().Timestamp(), gtime.Timestamp()-2) + // Delete Count + i, err := db.Model(table).Count() + t.AssertNil(err) + t.Assert(i, 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 1) + + // Delete Unscoped + r, err = db.Model(table).Unscoped().Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + one6, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one6), 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 0) + }) +} + +// CreatedAt/UpdatedAt/DeletedAt. +func Test_SoftTime_CreatedUpdatedDeleted_Struct(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + created_at datetime(6) DEFAULT NULL, + updated_at datetime(6) DEFAULT NULL, + deleted_at datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + type User struct { + Id int + Name string + CreatedAT *gtime.Time + UpdatedAT *gtime.Time + DeletedAT *gtime.Time + } + gtest.C(t, func(t *gtest.T) { + // Insert + dataInsert := User{ + Id: 1, + Name: "name_1", + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInsert, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInsert["id"].Int(), 1) + t.Assert(oneInsert["name"].String(), "name_1") + t.Assert(oneInsert["deleted_at"].String(), "") + t.AssertGE(oneInsert["created_at"].GTime().Timestamp(), gtime.Timestamp()-2) + t.AssertGE(oneInsert["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Save + dataSave := User{ + Id: 1, + Name: "name_10", + } + r, err = db.Model(table).Data(dataSave).OmitEmpty().Save() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneSave, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneSave["id"].Int(), 1) + t.Assert(oneSave["name"].String(), "name_10") + t.Assert(oneSave["deleted_at"].String(), "") + t.Assert(oneSave["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp()) + t.AssertNE(oneSave["updated_at"].GTime().Timestamp(), oneInsert["updated_at"].GTime().Timestamp()) + t.AssertGE(oneSave["updated_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Update + dataUpdate := User{ + Name: "name_1000", + } + r, err = db.Model(table).Data(dataUpdate).OmitEmpty().WherePri(1).Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + oneUpdate, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneUpdate["id"].Int(), 1) + t.Assert(oneUpdate["name"].String(), "name_1000") + t.Assert(oneUpdate["deleted_at"].String(), "") + t.Assert(oneUpdate["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp()) + t.AssertGE(oneUpdate["updated_at"].GTime().Timestamp(), gtime.Timestamp()-4) + + // Replace + dataReplace := User{ + Id: 1, + Name: "name_100", + } + r, err = db.Model(table).Data(dataReplace).OmitEmpty().Replace() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneReplace, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneReplace["id"].Int(), 1) + t.Assert(oneReplace["name"].String(), "name_100") + t.Assert(oneReplace["deleted_at"].String(), "") + t.AssertGE(oneReplace["created_at"].GTime().Timestamp(), oneInsert["created_at"].GTime().Timestamp()) + t.AssertGE(oneReplace["updated_at"].GTime().Timestamp(), oneInsert["updated_at"].GTime().Timestamp()) + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Delete + r, err = db.Model(table).Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + // Delete Select + one4, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one4), 0) + one5, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(one5["id"].Int(), 1) + t.AssertGE(one5["deleted_at"].GTime().Timestamp(), gtime.Timestamp()-2) + // Delete Count + i, err := db.Model(table).Count() + t.AssertNil(err) + t.Assert(i, 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 1) + + // Delete Unscoped + r, err = db.Model(table).Unscoped().Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + one6, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one6), 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 0) + }) +} + +func Test_SoftUpdateTime(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + num int(11) DEFAULT NULL, + create_at datetime(6) DEFAULT NULL, + update_at datetime(6) DEFAULT NULL, + delete_at datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + // Insert + dataInsert := g.Map{ + "id": 1, + "num": 10, + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInsert, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInsert["id"].Int(), 1) + t.Assert(oneInsert["num"].Int(), 10) + + // Update. + r, err = db.Model(table).Data("num=num+1").Where("id=?", 1).Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + }) +} + +func Test_SoftUpdateTime_WithDO(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + num int(11) DEFAULT NULL, + created_at datetime(6) DEFAULT NULL, + updated_at datetime(6) DEFAULT NULL, + deleted_at datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + // Insert + dataInsert := g.Map{ + "id": 1, + "num": 10, + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInserted, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInserted["id"].Int(), 1) + t.Assert(oneInserted["num"].Int(), 10) + + // Update. + time.Sleep(2 * time.Second) + type User struct { + g.Meta `orm:"do:true"` + Id any + Num any + CreatedAt any + UpdatedAt any + DeletedAt any + } + r, err = db.Model(table).Data(User{ + Num: 100, + }).Where("id=?", 1).Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + oneUpdated, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneUpdated["num"].Int(), 100) + t.Assert(oneUpdated["created_at"].String(), oneInserted["created_at"].String()) + t.AssertNE(oneUpdated["updated_at"].String(), oneInserted["updated_at"].String()) + }) +} + +func Test_SoftDelete(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at datetime(6) DEFAULT NULL, + update_at datetime(6) DEFAULT NULL, + delete_at datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + // db.SetDebug(true) + gtest.C(t, func(t *gtest.T) { + for i := 1; i <= 10; i++ { + data := g.Map{ + "id": i, + "name": fmt.Sprintf("name_%d", i), + } + r, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + } + }) + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.AssertNE(one["create_at"].String(), "") + t.AssertNE(one["update_at"].String(), "") + t.Assert(one["delete_at"].String(), "") + }) + gtest.C(t, func(t *gtest.T) { + one, err := db.Model(table).WherePri(10).One() + t.AssertNil(err) + t.AssertNE(one["create_at"].String(), "") + t.AssertNE(one["update_at"].String(), "") + t.Assert(one["delete_at"].String(), "") + }) + gtest.C(t, func(t *gtest.T) { + ids := g.SliceInt{1, 3, 5} + r, err := db.Model(table).Where("id", ids).Delete() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 3) + + count, err := db.Model(table).Where("id", ids).Count() + t.AssertNil(err) + t.Assert(count, 0) + + all, err := db.Model(table).Unscoped().Where("id", ids).All() + t.AssertNil(err) + t.Assert(len(all), 3) + t.AssertNE(all[0]["create_at"].String(), "") + t.AssertNE(all[0]["update_at"].String(), "") + t.AssertNE(all[0]["delete_at"].String(), "") + t.AssertNE(all[1]["create_at"].String(), "") + t.AssertNE(all[1]["update_at"].String(), "") + t.AssertNE(all[1]["delete_at"].String(), "") + t.AssertNE(all[2]["create_at"].String(), "") + t.AssertNE(all[2]["update_at"].String(), "") + t.AssertNE(all[2]["delete_at"].String(), "") + }) +} + +func Test_SoftDelete_Join(t *testing.T) { + table1 := "time_test_table1" + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at datetime(6) DEFAULT NULL, + update_at datetime(6) DEFAULT NULL, + delete_at datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table1)); err != nil { + gtest.Error(err) + } + defer dropTable(table1) + + table2 := "time_test_table2" + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + createat datetime(6) DEFAULT NULL, + updateat datetime(6) DEFAULT NULL, + deleteat datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table2)); err != nil { + gtest.Error(err) + } + defer dropTable(table2) + + gtest.C(t, func(t *gtest.T) { + // db.SetDebug(true) + dataInsert1 := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table1).Data(dataInsert1).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + dataInsert2 := g.Map{ + "id": 1, + "name": "name_2", + } + r, err = db.Model(table2).Data(dataInsert2).Insert() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table1, "t1").LeftJoin(table2, "t2", "t2.id=t1.id").Fields("t1.name").One() + t.AssertNil(err) + t.Assert(one["name"], "name_1") + + // Soft deleting. + r, err = db.Model(table1).Where(1).Delete() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + one, err = db.Model(table1, "t1").LeftJoin(table2, "t2", "t2.id=t1.id").Fields("t1.name").One() + t.AssertNil(err) + t.Assert(one.IsEmpty(), true) + + one, err = db.Model(table2, "t2").LeftJoin(table1, "t1", "t2.id=t1.id").Fields("t2.name").One() + t.AssertNil(err) + t.Assert(one.IsEmpty(), true) + }) +} + +func Test_SoftDelete_WhereAndOr(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at datetime(6) DEFAULT NULL, + update_at datetime(6) DEFAULT NULL, + delete_at datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + // db.SetDebug(true) + // Add datas. + gtest.C(t, func(t *gtest.T) { + for i := 1; i <= 10; i++ { + data := g.Map{ + "id": i, + "name": fmt.Sprintf("name_%d", i), + } + r, err := db.Model(table).Data(data).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + } + }) + gtest.C(t, func(t *gtest.T) { + ids := g.SliceInt{1, 3, 5} + r, err := db.Model(table).Where("id", ids).Delete() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 3) + + count, err := db.Model(table).Where("id", 1).WhereOr("id", 3).Count() + t.AssertNil(err) + t.Assert(count, 0) + }) +} + +func Test_CreateUpdateTime_Struct(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at datetime(6) DEFAULT NULL, + update_at datetime(6) DEFAULT NULL, + delete_at datetime(6) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + // db.SetDebug(true) + // defer db.SetDebug(false) + + type Entity struct { + Id uint64 `orm:"id,primary" json:"id"` + Name string `orm:"name" json:"name"` + CreateAt *gtime.Time `orm:"create_at" json:"create_at"` + UpdateAt *gtime.Time `orm:"update_at" json:"update_at"` + DeleteAt *gtime.Time `orm:"delete_at" json:"delete_at"` + } + gtest.C(t, func(t *gtest.T) { + // Insert + dataInsert := &Entity{ + Id: 1, + Name: "name_1", + CreateAt: nil, + UpdateAt: nil, + DeleteAt: nil, + } + r, err := db.Model(table).Data(dataInsert).OmitEmpty().Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInsert, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInsert["id"].Int(), 1) + t.Assert(oneInsert["name"].String(), "name_1") + t.Assert(oneInsert["delete_at"].String(), "") + t.AssertGE(oneInsert["create_at"].GTime().Timestamp(), gtime.Timestamp()-2) + t.AssertGE(oneInsert["update_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + time.Sleep(2 * time.Second) + + // Save + dataSave := &Entity{ + Id: 1, + Name: "name_10", + CreateAt: nil, + UpdateAt: nil, + DeleteAt: nil, + } + r, err = db.Model(table).Data(dataSave).OmitEmpty().Save() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneSave, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneSave["id"].Int(), 1) + t.Assert(oneSave["name"].String(), "name_10") + t.Assert(oneSave["delete_at"].String(), "") + t.Assert(oneSave["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp()) + t.AssertNE(oneSave["update_at"].GTime().Timestamp(), oneInsert["update_at"].GTime().Timestamp()) + t.AssertGE(oneSave["update_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + time.Sleep(2 * time.Second) + + // Update + dataUpdate := &Entity{ + Id: 1, + Name: "name_1000", + CreateAt: nil, + UpdateAt: nil, + DeleteAt: nil, + } + r, err = db.Model(table).Data(dataUpdate).WherePri(1).OmitEmpty().Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + oneUpdate, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneUpdate["id"].Int(), 1) + t.Assert(oneUpdate["name"].String(), "name_1000") + t.Assert(oneUpdate["delete_at"].String(), "") + t.Assert(oneUpdate["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp()) + t.AssertGE(oneUpdate["update_at"].GTime().Timestamp(), gtime.Timestamp()-2) + + // Replace + dataReplace := &Entity{ + Id: 1, + Name: "name_100", + CreateAt: nil, + UpdateAt: nil, + DeleteAt: nil, + } + r, err = db.Model(table).Data(dataReplace).OmitEmpty().Replace() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneReplace, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneReplace["id"].Int(), 1) + t.Assert(oneReplace["name"].String(), "name_100") + t.Assert(oneReplace["delete_at"].String(), "") + t.AssertGE(oneReplace["create_at"].GTime().Timestamp(), oneInsert["create_at"].GTime().Timestamp()) + t.AssertGE(oneReplace["update_at"].GTime().Timestamp(), oneInsert["update_at"].GTime().Timestamp()) + + time.Sleep(2 * time.Second) + + // Delete + r, err = db.Model(table).Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + // Delete Select + one4, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one4), 0) + one5, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(one5["id"].Int(), 1) + t.AssertGE(one5["delete_at"].GTime().Timestamp(), gtime.Timestamp()-2) + // Delete Count + i, err := db.Model(table).Count() + t.AssertNil(err) + t.Assert(i, 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 1) + + // Delete Unscoped + r, err = db.Model(table).Unscoped().Delete("id", 1) + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + one6, err := db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one6), 0) + i, err = db.Model(table).Unscoped().Count() + t.AssertNil(err) + t.Assert(i, 0) + }) +} + +func Test_SoftTime_CreateUpdateDelete_UnixTimestamp(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at int(11) DEFAULT NULL, + update_at int(11) DEFAULT NULL, + delete_at int(11) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + // insert + gtest.C(t, func(t *gtest.T) { + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_1") + t.AssertGT(one["create_at"].Int64(), 0) + t.AssertGT(one["update_at"].Int64(), 0) + t.Assert(one["delete_at"].Int64(), 0) + t.Assert(len(one["create_at"].String()), 10) + t.Assert(len(one["update_at"].String()), 10) + }) + + // sleep some seconds to make update time greater than create time. + time.Sleep(2 * time.Second) + + // update + gtest.C(t, func(t *gtest.T) { + // update: map + dataInsert := g.Map{ + "name": "name_11", + } + r, err := db.Model(table).Data(dataInsert).WherePri(1).Update() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_11") + t.AssertGT(one["create_at"].Int64(), 0) + t.AssertGT(one["update_at"].Int64(), 0) + t.Assert(one["delete_at"].Int64(), 0) + t.Assert(len(one["create_at"].String()), 10) + t.Assert(len(one["update_at"].String()), 10) + + var ( + lastCreateTime = one["create_at"].Int64() + lastUpdateTime = one["update_at"].Int64() + ) + + time.Sleep(2 * time.Second) + + // update: string + r, err = db.Model(table).Data("name='name_111'").WherePri(1).Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + one, err = db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_111") + t.Assert(one["create_at"].Int64(), lastCreateTime) + t.AssertGT(one["update_at"].Int64(), lastUpdateTime) + t.Assert(one["delete_at"].Int64(), 0) + }) + + // delete + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).WherePri(1).Delete() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one), 0) + + one, err = db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_111") + t.AssertGT(one["create_at"].Int64(), 0) + t.AssertGT(one["update_at"].Int64(), 0) + t.AssertGT(one["delete_at"].Int64(), 0) + }) +} + +func Test_SoftTime_CreateUpdateDelete_Bool_Deleted(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at int(11) DEFAULT NULL, + update_at int(11) DEFAULT NULL, + delete_at bit(1) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + //db.SetDebug(true) + // insert + gtest.C(t, func(t *gtest.T) { + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_1") + t.AssertGT(one["create_at"].Int64(), 0) + t.AssertGT(one["update_at"].Int64(), 0) + t.Assert(one["delete_at"].Int64(), 0) + t.Assert(len(one["create_at"].String()), 10) + t.Assert(len(one["update_at"].String()), 10) + }) + + // delete + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).WherePri(1).Delete() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one), 0) + + one, err = db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_1") + t.AssertGT(one["create_at"].Int64(), 0) + t.AssertGT(one["update_at"].Int64(), 0) + t.Assert(one["delete_at"].Int64(), 1) + }) +} + +func Test_SoftTime_CreateUpdateDelete_Option_SoftTimeTypeTimestampMilli(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at bigint(19) unsigned DEFAULT NULL, + update_at bigint(19) unsigned DEFAULT NULL, + delete_at bit(1) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + var softTimeOption = gdb.SoftTimeOption{ + SoftTimeType: gdb.SoftTimeTypeTimestampMilli, + } + + // insert + gtest.C(t, func(t *gtest.T) { + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table).SoftTime(softTimeOption).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).SoftTime(softTimeOption).WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_1") + t.Assert(len(one["create_at"].String()), 13) + t.Assert(len(one["update_at"].String()), 13) + t.Assert(one["delete_at"].Int64(), 0) + }) + + // delete + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).SoftTime(softTimeOption).WherePri(1).Delete() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).SoftTime(softTimeOption).WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one), 0) + + one, err = db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_1") + t.AssertGT(one["create_at"].Int64(), 0) + t.AssertGT(one["update_at"].Int64(), 0) + t.Assert(one["delete_at"].Int64(), 1) + }) +} + +func Test_SoftTime_CreateUpdateDelete_Option_SoftTimeTypeTimestampNano(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at bigint(19) unsigned DEFAULT NULL, + update_at bigint(19) unsigned DEFAULT NULL, + delete_at bit(1) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + var softTimeOption = gdb.SoftTimeOption{ + SoftTimeType: gdb.SoftTimeTypeTimestampNano, + } + + // insert + gtest.C(t, func(t *gtest.T) { + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + } + r, err := db.Model(table).SoftTime(softTimeOption).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).SoftTime(softTimeOption).WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_1") + t.Assert(len(one["create_at"].String()), 19) + t.Assert(len(one["update_at"].String()), 19) + t.Assert(one["delete_at"].Int64(), 0) + }) + + // delete + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).SoftTime(softTimeOption).WherePri(1).Delete() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + one, err := db.Model(table).SoftTime(softTimeOption).WherePri(1).One() + t.AssertNil(err) + t.Assert(len(one), 0) + + one, err = db.Model(table).Unscoped().WherePri(1).One() + t.AssertNil(err) + t.Assert(one["name"].String(), "name_1") + t.AssertGT(one["create_at"].Int64(), 0) + t.AssertGT(one["update_at"].Int64(), 0) + t.Assert(one["delete_at"].Int64(), 1) + }) +} + +func Test_SoftTime_CreateUpdateDelete_Specified(t *testing.T) { + table := "soft_time_test_table_" + gtime.TimestampNanoStr() + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE %s ( + id int(11) NOT NULL, + name varchar(45) DEFAULT NULL, + create_at datetime(0) DEFAULT NULL, + update_at datetime(0) DEFAULT NULL, + delete_at datetime(0) DEFAULT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, table)); err != nil { + gtest.Error(err) + } + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + // Insert + dataInsert := g.Map{ + "id": 1, + "name": "name_1", + "create_at": gtime.NewFromStr("2024-05-30 20:00:00"), + "update_at": gtime.NewFromStr("2024-05-30 20:00:00"), + } + r, err := db.Model(table).Data(dataInsert).Insert() + t.AssertNil(err) + n, _ := r.RowsAffected() + t.Assert(n, 1) + + oneInsert, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneInsert["id"].Int(), 1) + t.Assert(oneInsert["name"].String(), "name_1") + t.Assert(oneInsert["delete_at"].String(), "") + t.Assert(oneInsert["create_at"].String(), "2024-05-30 20:00:00") + t.Assert(oneInsert["update_at"].String(), "2024-05-30 20:00:00") + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Save + dataSave := g.Map{ + "id": 1, + "name": "name_10", + "update_at": gtime.NewFromStr("2024-05-30 20:15:00"), + } + r, err = db.Model(table).Data(dataSave).Save() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneSave, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneSave["id"].Int(), 1) + t.Assert(oneSave["name"].String(), "name_10") + t.Assert(oneSave["delete_at"].String(), "") + t.Assert(oneSave["create_at"].String(), "2024-05-30 20:00:00") + t.Assert(oneSave["update_at"].String(), "2024-05-30 20:15:00") + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Update + dataUpdate := g.Map{ + "name": "name_1000", + "update_at": gtime.NewFromStr("2024-05-30 20:30:00"), + } + r, err = db.Model(table).Data(dataUpdate).WherePri(1).Update() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + oneUpdate, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneUpdate["id"].Int(), 1) + t.Assert(oneUpdate["name"].String(), "name_1000") + t.Assert(oneUpdate["delete_at"].String(), "") + t.Assert(oneUpdate["create_at"].String(), "2024-05-30 20:00:00") + t.Assert(oneUpdate["update_at"].String(), "2024-05-30 20:30:00") + + // Replace + dataReplace := g.Map{ + "id": 1, + "name": "name_100", + "create_at": gtime.NewFromStr("2024-05-30 21:00:00"), + "update_at": gtime.NewFromStr("2024-05-30 21:00:00"), + } + r, err = db.Model(table).Data(dataReplace).Replace() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 2) + + oneReplace, err := db.Model(table).WherePri(1).One() + t.AssertNil(err) + t.Assert(oneReplace["id"].Int(), 1) + t.Assert(oneReplace["name"].String(), "name_100") + t.Assert(oneReplace["delete_at"].String(), "") + t.Assert(oneReplace["create_at"].String(), "2024-05-30 21:00:00") + t.Assert(oneReplace["update_at"].String(), "2024-05-30 21:00:00") + + // For time asserting purpose. + time.Sleep(2 * time.Second) + + // Insert with delete_at + dataInsertDelete := g.Map{ + "id": 2, + "name": "name_2", + "create_at": gtime.NewFromStr("2024-05-30 20:00:00"), + "update_at": gtime.NewFromStr("2024-05-30 20:00:00"), + "delete_at": gtime.NewFromStr("2024-05-30 20:00:00"), + } + r, err = db.Model(table).Data(dataInsertDelete).Insert() + t.AssertNil(err) + n, _ = r.RowsAffected() + t.Assert(n, 1) + + // Delete Select + oneDelete, err := db.Model(table).WherePri(2).One() + t.AssertNil(err) + t.Assert(len(oneDelete), 0) + oneDeleteUnscoped, err := db.Model(table).Unscoped().WherePri(2).One() + t.AssertNil(err) + t.Assert(oneDeleteUnscoped["id"].Int(), 2) + t.Assert(oneDeleteUnscoped["name"].String(), "name_2") + t.Assert(oneDeleteUnscoped["delete_at"].String(), "2024-05-30 20:00:00") + t.Assert(oneDeleteUnscoped["create_at"].String(), "2024-05-30 20:00:00") + t.Assert(oneDeleteUnscoped["update_at"].String(), "2024-05-30 20:00:00") + }) +} diff --git a/contrib/drivers/mariadb/mariadb_z_unit_feature_union_test.go b/contrib/drivers/mariadb/mariadb_z_unit_feature_union_test.go new file mode 100644 index 000000000..328f03e05 --- /dev/null +++ b/contrib/drivers/mariadb/mariadb_z_unit_feature_union_test.go @@ -0,0 +1,146 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mariadb_test + +import ( + "testing" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/test/gtest" +) + +func Test_Union(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Union( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").All() + + t.AssertNil(err) + + t.Assert(len(r), 3) + t.Assert(r[0]["id"], 3) + t.Assert(r[1]["id"], 2) + t.Assert(r[2]["id"], 1) + }) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Union( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").One() + + t.AssertNil(err) + + t.Assert(r["id"], 3) + }) +} + +func Test_UnionAll(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + r, err := db.UnionAll( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").All() + + t.AssertNil(err) + + t.Assert(len(r), 5) + t.Assert(r[0]["id"], 3) + t.Assert(r[1]["id"], 2) + t.Assert(r[2]["id"], 2) + t.Assert(r[3]["id"], 1) + t.Assert(r[4]["id"], 1) + }) + + gtest.C(t, func(t *gtest.T) { + r, err := db.UnionAll( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").One() + + t.AssertNil(err) + + t.Assert(r["id"], 3) + }) +} + +func Test_Model_Union(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).Union( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").All() + + t.AssertNil(err) + + t.Assert(len(r), 3) + t.Assert(r[0]["id"], 3) + t.Assert(r[1]["id"], 2) + t.Assert(r[2]["id"], 1) + }) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).Union( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").One() + + t.AssertNil(err) + + t.Assert(r["id"], 3) + }) +} + +func Test_Model_UnionAll(t *testing.T) { + table := createInitTable() + defer dropTable(table) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).UnionAll( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").All() + + t.AssertNil(err) + + t.Assert(len(r), 5) + t.Assert(r[0]["id"], 3) + t.Assert(r[1]["id"], 2) + t.Assert(r[2]["id"], 2) + t.Assert(r[3]["id"], 1) + t.Assert(r[4]["id"], 1) + }) + + gtest.C(t, func(t *gtest.T) { + r, err := db.Model(table).UnionAll( + db.Model(table).Where("id", 1), + db.Model(table).Where("id", 2), + db.Model(table).WhereIn("id", g.Slice{1, 2, 3}).OrderDesc("id"), + ).OrderDesc("id").One() + + t.AssertNil(err) + + t.Assert(r["id"], 3) + }) +} diff --git a/contrib/drivers/mariadb/mariadb_z_unit_feature_with_test.go b/contrib/drivers/mariadb/mariadb_z_unit_feature_with_test.go new file mode 100644 index 000000000..7da4122c5 --- /dev/null +++ b/contrib/drivers/mariadb/mariadb_z_unit_feature_with_test.go @@ -0,0 +1,1998 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package mariadb_test + +import ( + "fmt" + "testing" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gmeta" +) + +/* +mysql> show tables; ++----------------+ +| Tables_in_test | ++----------------+ +| user | +| user_detail | +| user_score | ++----------------+ +3 rows in set (0.01 sec) + +mysql> select * from `user`; ++----+--------+ +| id | name | ++----+--------+ +| 1 | name_1 | +| 2 | name_2 | +| 3 | name_3 | +| 4 | name_4 | +| 5 | name_5 | ++----+--------+ +5 rows in set (0.01 sec) + +mysql> select * from `user_detail`; ++-----+-----------+ +| uid | address | ++-----+-----------+ +| 1 | address_1 | +| 2 | address_2 | +| 3 | address_3 | +| 4 | address_4 | +| 5 | address_5 | ++-----+-----------+ +5 rows in set (0.00 sec) + +mysql> select * from `user_score`; ++----+-----+-------+ +| id | uid | score | ++----+-----+-------+ +| 1 | 1 | 1 | +| 2 | 1 | 2 | +| 3 | 1 | 3 | +| 4 | 1 | 4 | +| 5 | 1 | 5 | +| 6 | 2 | 1 | +| 7 | 2 | 2 | +| 8 | 2 | 3 | +| 9 | 2 | 4 | +| 10 | 2 | 5 | +| 11 | 3 | 1 | +| 12 | 3 | 2 | +| 13 | 3 | 3 | +| 14 | 3 | 4 | +| 15 | 3 | 5 | +| 16 | 4 | 1 | +| 17 | 4 | 2 | +| 18 | 4 | 3 | +| 19 | 4 | 4 | +| 20 | 4 | 5 | +| 21 | 5 | 1 | +| 22 | 5 | 2 | +| 23 | 5 | 3 | +| 24 | 5 | 4 | +| 25 | 5 | 5 | ++----+-----+-------+ +25 rows in set (0.00 sec) +*/ + +func Test_Table_Relation_With_Scan(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_score" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + } + + type UserScore struct { + gmeta.Meta `orm:"table:user_score"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + Id int `json:"id"` + Name string `json:"name"` + UserDetail *UserDetail `orm:"with:uid=id"` + UserScores []*UserScore `orm:"with:uid=id"` + } + + // Initialize the data. + gtest.C(t, func(t *gtest.T) { + for i := 1; i <= 5; i++ { + // User. + user := User{ + Name: fmt.Sprintf(`name_%d`, i), + } + lastInsertId, err := db.Model(user).Data(user).OmitEmpty().InsertAndGetId() + t.AssertNil(err) + // Detail. + userDetail := UserDetail{ + Uid: int(lastInsertId), + Address: fmt.Sprintf(`address_%d`, lastInsertId), + } + _, err = db.Model(userDetail).Data(userDetail).OmitEmpty().Insert() + t.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + userScore := UserScore{ + Uid: int(lastInsertId), + Score: j, + } + _, err = db.Model(userScore).Data(userScore).OmitEmpty().Insert() + t.AssertNil(err) + } + } + }) + for i := 1; i <= 5; i++ { + // User. + user := User{ + Name: fmt.Sprintf(`name_%d`, i), + } + lastInsertId, err := db.Model(user).Data(user).OmitEmpty().InsertAndGetId() + gtest.AssertNil(err) + // Detail. + userDetail := UserDetail{ + Uid: int(lastInsertId), + Address: fmt.Sprintf(`address_%d`, lastInsertId), + } + _, err = db.Model(userDetail).Data(userDetail).Insert() + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + userScore := UserScore{ + Uid: int(lastInsertId), + Score: j, + } + _, err = db.Model(userScore).Data(userScore).Insert() + gtest.AssertNil(err) + } + } + gtest.C(t, func(t *gtest.T) { + var user *User + err := db.With(User{}). + With(User{}.UserDetail). + With(User{}.UserScores). + Where("id", 3). + Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 3) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 3) + t.Assert(user.UserDetail.Address, `address_3`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 3) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 3) + t.Assert(user.UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var user User + err := db.With(user). + With(user.UserDetail). + With(user.UserScores). + Where("id", 4). + Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 4) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 4) + t.Assert(user.UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var user *User + err := db.With(User{}). + With(UserDetail{}). + With(UserScore{}). + Where("id", 4). + Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 4) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 4) + t.Assert(user.UserScores[4].Score, 5) + }) + // With part attribute: UserDetail. + gtest.C(t, func(t *gtest.T) { + var user User + err := db.With(user). + With(user.UserDetail). + Where("id", 4). + Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserScores), 0) + }) + // With part attribute: UserScores. + gtest.C(t, func(t *gtest.T) { + var user User + err := db.With(user). + With(user.UserScores). + Where("id", 4). + Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.Assert(user.UserDetail, nil) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 4) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 4) + t.Assert(user.UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_With(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + } + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + Id int `json:"id"` + Name string `json:"name"` + UserDetail *UserDetail `orm:"with:uid=id"` + UserScores []*UserScores `orm:"with:uid=id"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + + gtest.C(t, func(t *gtest.T) { + var users []*User + err := db.With(User{}). + With(User{}.UserDetail). + With(User{}.UserScores). + Where("id", []int{3, 4}). + Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].Id, 3) + t.Assert(users[0].Name, "name_3") + t.AssertNE(users[0].UserDetail, nil) + t.Assert(users[0].UserDetail.Uid, 3) + t.Assert(users[0].UserDetail.Address, "address_3") + t.Assert(len(users[0].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Uid, 3) + t.Assert(users[0].UserScores[4].Score, 5) + + t.Assert(users[1].Id, 4) + t.Assert(users[1].Name, "name_4") + t.AssertNE(users[1].UserDetail, nil) + t.Assert(users[1].UserDetail.Uid, 4) + t.Assert(users[1].UserDetail.Address, "address_4") + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Uid, 4) + t.Assert(users[1].UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var users []User + err := db.With(User{}). + With(User{}.UserDetail). + With(User{}.UserScores). + Where("id", []int{3, 4}). + Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].Id, 3) + t.Assert(users[0].Name, "name_3") + t.AssertNE(users[0].UserDetail, nil) + t.Assert(users[0].UserDetail.Uid, 3) + t.Assert(users[0].UserDetail.Address, "address_3") + t.Assert(len(users[0].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Uid, 3) + t.Assert(users[0].UserScores[4].Score, 5) + + t.Assert(users[1].Id, 4) + t.Assert(users[1].Name, "name_4") + t.AssertNE(users[1].UserDetail, nil) + t.Assert(users[1].UserDetail.Uid, 4) + t.Assert(users[1].UserDetail.Address, "address_4") + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Uid, 4) + t.Assert(users[1].UserScores[4].Score, 5) + }) + // With part attribute: UserDetail. + gtest.C(t, func(t *gtest.T) { + var users []*User + err := db.With(User{}). + With(User{}.UserDetail). + Where("id", []int{3, 4}). + Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].Id, 3) + t.Assert(users[0].Name, "name_3") + t.AssertNE(users[0].UserDetail, nil) + t.Assert(users[0].UserDetail.Uid, 3) + t.Assert(users[0].UserDetail.Address, "address_3") + t.Assert(len(users[0].UserScores), 0) + + t.Assert(users[1].Id, 4) + t.Assert(users[1].Name, "name_4") + t.AssertNE(users[1].UserDetail, nil) + t.Assert(users[1].UserDetail.Uid, 4) + t.Assert(users[1].UserDetail.Address, "address_4") + t.Assert(len(users[1].UserScores), 0) + }) + // With part attribute: UserScores. + gtest.C(t, func(t *gtest.T) { + var users []*User + err := db.With(User{}). + With(User{}.UserScores). + Where("id", []int{3, 4}). + Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].Id, 3) + t.Assert(users[0].Name, "name_3") + t.Assert(users[0].UserDetail, nil) + t.Assert(len(users[0].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Uid, 3) + t.Assert(users[0].UserScores[4].Score, 5) + + t.Assert(users[1].Id, 4) + t.Assert(users[1].Name, "name_4") + t.Assert(users[1].UserDetail, nil) + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Uid, 4) + t.Assert(users[1].UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_WithAll(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + } + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + Id int `json:"id"` + Name string `json:"name"` + UserDetail *UserDetail `orm:"with:uid=id"` + UserScores []*UserScores `orm:"with:uid=id"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + gtest.C(t, func(t *gtest.T) { + var user *User + err := db.Model(tableUser).WithAll().Where("id", 3).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 3) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 3) + t.Assert(user.UserDetail.Address, `address_3`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 3) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 3) + t.Assert(user.UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var user User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 4) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 4) + t.Assert(user.UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_WithAll_List(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + } + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + Id int `json:"id"` + Name string `json:"name"` + UserDetail *UserDetail `orm:"with:uid=id"` + UserScores []*UserScores `orm:"with:uid=id"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + gtest.C(t, func(t *gtest.T) { + var users []*User + err := db.Model(tableUser).WithAll().Where("id", []int{3, 4}).Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].Id, 3) + t.Assert(users[0].Name, "name_3") + t.AssertNE(users[0].UserDetail, nil) + t.Assert(users[0].UserDetail.Uid, 3) + t.Assert(users[0].UserDetail.Address, "address_3") + t.Assert(len(users[0].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Uid, 3) + t.Assert(users[0].UserScores[4].Score, 5) + + t.Assert(users[1].Id, 4) + t.Assert(users[1].Name, "name_4") + t.AssertNE(users[1].UserDetail, nil) + t.Assert(users[1].UserDetail.Uid, 4) + t.Assert(users[1].UserDetail.Address, "address_4") + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Uid, 4) + t.Assert(users[1].UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var users []User + err := db.Model(tableUser).WithAll().Where("id", []int{3, 4}).Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].Id, 3) + t.Assert(users[0].Name, "name_3") + t.AssertNE(users[0].UserDetail, nil) + t.Assert(users[0].UserDetail.Uid, 3) + t.Assert(users[0].UserDetail.Address, "address_3") + t.Assert(len(users[0].UserScores), 5) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 1) + t.Assert(users[0].UserScores[4].Uid, 3) + t.Assert(users[0].UserScores[4].Score, 5) + + t.Assert(users[1].Id, 4) + t.Assert(users[1].Name, "name_4") + t.AssertNE(users[1].UserDetail, nil) + t.Assert(users[1].UserDetail.Uid, 4) + t.Assert(users[1].UserDetail.Address, "address_4") + t.Assert(len(users[1].UserScores), 5) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 1) + t.Assert(users[1].UserScores[4].Uid, 4) + t.Assert(users[1].UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_WithAllCondition_List(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + } + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + Id int `json:"id"` + Name string `json:"name"` + UserDetail *UserDetail `orm:"with:uid=id, where:uid > 3"` + UserScores []*UserScores `orm:"with:uid=id, where:score>1 and score<5, order:score desc"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + + db.SetDebug(true) + defer db.SetDebug(false) + + gtest.C(t, func(t *gtest.T) { + var users []*User + err := db.Model(tableUser).WithAll().Where("id", []int{3, 4}).Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].Id, 3) + t.Assert(users[0].Name, "name_3") + t.Assert(users[0].UserDetail, nil) + t.Assert(users[1].Id, 4) + t.Assert(users[1].Name, "name_4") + t.AssertNE(users[1].UserDetail, nil) + t.Assert(users[1].UserDetail.Uid, 4) + t.Assert(users[1].UserDetail.Address, "address_4") + t.Assert(len(users[1].UserScores), 3) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 4) + t.Assert(users[1].UserScores[2].Uid, 4) + t.Assert(users[1].UserScores[2].Score, 2) + }) + gtest.C(t, func(t *gtest.T) { + var users []User + err := db.Model(tableUser).WithAll().Where("id", []int{3, 4}).Scan(&users) + t.AssertNil(err) + t.Assert(len(users), 2) + t.Assert(users[0].Id, 3) + t.Assert(users[0].Name, "name_3") + t.Assert(users[0].UserDetail, nil) + + t.Assert(len(users[0].UserScores), 3) + t.Assert(users[0].UserScores[0].Uid, 3) + t.Assert(users[0].UserScores[0].Score, 4) + t.Assert(users[0].UserScores[2].Uid, 3) + t.Assert(users[0].UserScores[2].Score, 2) + + t.Assert(users[1].Id, 4) + t.Assert(users[1].Name, "name_4") + t.AssertNE(users[1].UserDetail, nil) + t.Assert(users[1].UserDetail.Uid, 4) + t.Assert(users[1].UserDetail.Address, "address_4") + t.Assert(len(users[1].UserScores), 3) + t.Assert(users[1].UserScores[0].Uid, 4) + t.Assert(users[1].UserScores[0].Score, 4) + t.Assert(users[1].UserScores[2].Uid, 4) + t.Assert(users[1].UserScores[2].Score, 2) + }) +} + +func Test_Table_Relation_WithAll_Embedded_With_SelfMaintained_Attributes(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + } + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + *UserDetail `orm:"with:uid=id"` + Id int `json:"id"` + Name string `json:"name"` + UserScores []*UserScores `orm:"with:uid=id"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + gtest.C(t, func(t *gtest.T) { + var user *User + err := db.Model(tableUser).WithAll().Where("id", 3).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 3) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 3) + t.Assert(user.UserDetail.Address, `address_3`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 3) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 3) + t.Assert(user.UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var user User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 4) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 4) + t.Assert(user.UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_WithAll_Embedded_Without_SelfMaintained_Attributes(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + } + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + // For Test Only + type UserEmbedded struct { + Id int `json:"id"` + Name string `json:"name"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + *UserDetail `orm:"with:uid=id"` + UserEmbedded + UserScores []*UserScores `orm:"with:uid=id"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + db.SetDebug(true) + defer db.SetDebug(false) + + gtest.C(t, func(t *gtest.T) { + var user *User + err := db.Model(tableUser).WithAll().Where("id", 3).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 3) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 3) + t.Assert(user.UserDetail.Address, `address_3`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 3) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 3) + t.Assert(user.UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var user User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 4) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 4) + t.Assert(user.UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_WithAll_Embedded_WithoutMeta(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserDetailBase struct { + Uid int `json:"uid"` + Address string `json:"address"` + } + + type UserDetail struct { + UserDetailBase + } + + type UserScores struct { + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type User struct { + *UserDetail `orm:"with:uid=id"` + Id int `json:"id"` + Name string `json:"name"` + UserScores []*UserScores `orm:"with:uid=id"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + gtest.C(t, func(t *gtest.T) { + var user *User + err := db.Model(tableUser).WithAll().Where("id", 3).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 3) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 3) + t.Assert(user.UserDetail.Address, `address_3`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 3) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 3) + t.Assert(user.UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var user User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].Uid, 4) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].Uid, 4) + t.Assert(user.UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_WithAll_AttributeStructAlsoHasWithTag(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + UserScores []*UserScores `orm:"with:uid"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + *UserDetail `orm:"with:uid=id"` + Id int `json:"id"` + Name string `json:"name"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + + gtest.C(t, func(t *gtest.T) { + var user *User + err := db.Model(tableUser).WithAll().Where("id", 3).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 3) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 3) + t.Assert(user.UserDetail.Address, `address_3`) + t.Assert(len(user.UserDetail.UserScores), 5) + t.Assert(user.UserDetail.UserScores[0].Uid, 3) + t.Assert(user.UserDetail.UserScores[0].Score, 1) + t.Assert(user.UserDetail.UserScores[4].Uid, 3) + t.Assert(user.UserDetail.UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var user User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserDetail.UserScores), 5) + t.Assert(user.UserDetail.UserScores[0].Uid, 4) + t.Assert(user.UserDetail.UserScores[0].Score, 1) + t.Assert(user.UserDetail.UserScores[4].Uid, 4) + t.Assert(user.UserDetail.UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_WithAll_AttributeStructAlsoHasWithTag_MoreDeep(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type UserDetail1 struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + UserScores []*UserScores `orm:"with:uid"` + } + + type UserDetail2 struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + UserDetail1 *UserDetail1 `orm:"with:uid"` + UserScores []*UserScores `orm:"with:uid"` + } + + type UserDetail3 struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + UserDetail2 *UserDetail2 `orm:"with:uid"` + UserScores []*UserScores `orm:"with:uid"` + } + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + UserDetail3 *UserDetail3 `orm:"with:uid"` + UserScores []*UserScores `orm:"with:uid"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + *UserDetail `orm:"with:uid=id"` + Id int `json:"id"` + Name string `json:"name"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + + gtest.C(t, func(t *gtest.T) { + var user *User + err := db.Model(tableUser).WithAll().Where("id", 3).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 3) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 3) + t.Assert(user.UserDetail.UserDetail3.Uid, 3) + t.Assert(user.UserDetail.UserDetail3.UserDetail2.Uid, 3) + t.Assert(user.UserDetail.UserDetail3.UserDetail2.UserDetail1.Uid, 3) + t.Assert(user.UserDetail.Address, `address_3`) + t.Assert(len(user.UserDetail.UserScores), 5) + t.Assert(user.UserDetail.UserScores[0].Uid, 3) + t.Assert(user.UserDetail.UserScores[0].Score, 1) + t.Assert(user.UserDetail.UserScores[4].Uid, 3) + t.Assert(user.UserDetail.UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var user User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.UserDetail3.Uid, 4) + t.Assert(user.UserDetail.UserDetail3.UserDetail2.Uid, 4) + t.Assert(user.UserDetail.UserDetail3.UserDetail2.UserDetail1.Uid, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserDetail.UserScores), 5) + t.Assert(user.UserDetail.UserScores[0].Uid, 4) + t.Assert(user.UserDetail.UserScores[0].Score, 1) + t.Assert(user.UserDetail.UserScores[4].Uid, 4) + t.Assert(user.UserDetail.UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_With_AttributeStructAlsoHasWithTag_MoreDeep(t *testing.T) { + var ( + tableUser = "user" + tableUserDetail = "user_detail" + tableUserScores = "user_scores" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user.sql"), tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_detail.sql"), tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(gtest.DataContent("with_tpl_user_scores.sql"), tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores"` + Id int `json:"id"` + Uid int `json:"uid"` + Score int `json:"score"` + } + + type UserDetail1 struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + UserScores []*UserScores `orm:"with:uid"` + } + + type UserDetail2 struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + UserDetail1 *UserDetail1 `orm:"with:uid"` + UserScores []*UserScores `orm:"with:uid"` + } + + type UserDetail3 struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + UserDetail2 *UserDetail2 `orm:"with:uid"` + UserScores []*UserScores `orm:"with:uid"` + } + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail"` + Uid int `json:"uid"` + Address string `json:"address"` + UserDetail3 *UserDetail3 `orm:"with:uid"` + UserScores []*UserScores `orm:"with:uid"` + } + + type User struct { + gmeta.Meta `orm:"table:user"` + *UserDetail `orm:"with:uid=id"` + Id int `json:"id"` + Name string `json:"name"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "uid": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "uid": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + + gtest.C(t, func(t *gtest.T) { + var user *User + err := db.Model(tableUser).With(UserDetail{}, UserDetail2{}, UserDetail3{}, UserScores{}).Where("id", 3).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 3) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 3) + t.Assert(user.UserDetail.UserDetail3.Uid, 3) + t.Assert(user.UserDetail.UserDetail3.UserDetail2.Uid, 3) + t.Assert(user.UserDetail.UserDetail3.UserDetail2.UserDetail1, nil) + t.Assert(user.UserDetail.Address, `address_3`) + t.Assert(len(user.UserDetail.UserScores), 5) + t.Assert(user.UserDetail.UserScores[0].Uid, 3) + t.Assert(user.UserDetail.UserScores[0].Score, 1) + t.Assert(user.UserDetail.UserScores[4].Uid, 3) + t.Assert(user.UserDetail.UserScores[4].Score, 5) + }) + gtest.C(t, func(t *gtest.T) { + var user User + err := db.Model(tableUser).With(UserDetail{}, UserDetail2{}, UserDetail3{}, UserScores{}).Where("id", 4).Scan(&user) + t.AssertNil(err) + t.Assert(user.Id, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.Uid, 4) + t.Assert(user.UserDetail.UserDetail3.Uid, 4) + t.Assert(user.UserDetail.UserDetail3.UserDetail2.Uid, 4) + t.Assert(user.UserDetail.UserDetail3.UserDetail2.UserDetail1, nil) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserDetail.UserScores), 5) + t.Assert(user.UserDetail.UserScores[0].Uid, 4) + t.Assert(user.UserDetail.UserScores[0].Score, 1) + t.Assert(user.UserDetail.UserScores[4].Uid, 4) + t.Assert(user.UserDetail.UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_With_MultipleDepends1(t *testing.T) { + defer func() { + dropTable("table_a") + dropTable("table_b") + dropTable("table_c") + }() + for _, v := range gstr.SplitAndTrim(gfile.GetContents(gtest.DataPath("with_multiple_depends.sql")), ";") { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + + type TableC struct { + gmeta.Meta `orm:"table_c"` + Id int `orm:"id,primary" json:"id"` + TableBId int `orm:"table_b_id" json:"table_b_id"` + } + + type TableB struct { + gmeta.Meta `orm:"table_b"` + Id int `orm:"id,primary" json:"id"` + TableAId int `orm:"table_a_id" json:"table_a_id"` + TableC *TableC `orm:"with:table_b_id=id" json:"table_c"` + } + + type TableA struct { + gmeta.Meta `orm:"table_a"` + Id int `orm:"id,primary" json:"id"` + TableB *TableB `orm:"with:table_a_id=id" json:"table_b"` + } + + db.SetDebug(true) + defer db.SetDebug(false) + + // Struct. + gtest.C(t, func(t *gtest.T) { + var tableA *TableA + err := db.Model("table_a").WithAll().Scan(&tableA) + // g.Dump(tableA) + t.AssertNil(err) + t.AssertNE(tableA, nil) + t.Assert(tableA.Id, 1) + + t.AssertNE(tableA.TableB, nil) + t.AssertNE(tableA.TableB.TableC, nil) + t.Assert(tableA.TableB.TableAId, 1) + t.Assert(tableA.TableB.TableC.Id, 100) + t.Assert(tableA.TableB.TableC.TableBId, 10) + }) + + // Structs + gtest.C(t, func(t *gtest.T) { + var tableA []*TableA + err := db.Model("table_a").WithAll().OrderAsc("id").Scan(&tableA) + // g.Dump(tableA) + t.AssertNil(err) + t.Assert(len(tableA), 2) + t.AssertNE(tableA[0].TableB, nil) + t.AssertNE(tableA[1].TableB, nil) + t.AssertNE(tableA[0].TableB.TableC, nil) + t.AssertNE(tableA[1].TableB.TableC, nil) + + t.Assert(tableA[0].Id, 1) + t.Assert(tableA[0].TableB.Id, 10) + t.Assert(tableA[0].TableB.TableC.Id, 100) + + t.Assert(tableA[1].Id, 2) + t.Assert(tableA[1].TableB.Id, 20) + t.Assert(tableA[1].TableB.TableC.Id, 300) + }) +} + +func Test_Table_Relation_With_MultipleDepends2(t *testing.T) { + defer func() { + dropTable("table_a") + dropTable("table_b") + dropTable("table_c") + }() + for _, v := range gstr.SplitAndTrim(gfile.GetContents(gtest.DataPath("with_multiple_depends.sql")), ";") { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + + type TableC struct { + gmeta.Meta `orm:"table_c"` + Id int `orm:"id,primary" json:"id"` + TableBId int `orm:"table_b_id" json:"table_b_id"` + } + + type TableB struct { + gmeta.Meta `orm:"table_b"` + Id int `orm:"id,primary" json:"id"` + TableAId int `orm:"table_a_id" json:"table_a_id"` + TableC []*TableC `orm:"with:table_b_id=id" json:"table_c"` + } + + type TableA struct { + gmeta.Meta `orm:"table_a"` + Id int `orm:"id,primary" json:"id"` + TableB []*TableB `orm:"with:table_a_id=id" json:"table_b"` + } + + db.SetDebug(true) + defer db.SetDebug(false) + + // Struct. + gtest.C(t, func(t *gtest.T) { + var tableA *TableA + err := db.Model("table_a").WithAll().Scan(&tableA) + // g.Dump(tableA) + t.AssertNil(err) + t.AssertNE(tableA, nil) + t.Assert(tableA.Id, 1) + + t.Assert(len(tableA.TableB), 2) + t.Assert(tableA.TableB[0].Id, 10) + t.Assert(tableA.TableB[1].Id, 30) + + t.Assert(len(tableA.TableB[0].TableC), 2) + t.Assert(len(tableA.TableB[1].TableC), 1) + t.Assert(tableA.TableB[0].TableC[0].Id, 100) + t.Assert(tableA.TableB[0].TableC[0].TableBId, 10) + t.Assert(tableA.TableB[0].TableC[1].Id, 200) + t.Assert(tableA.TableB[0].TableC[1].TableBId, 10) + t.Assert(tableA.TableB[1].TableC[0].Id, 400) + t.Assert(tableA.TableB[1].TableC[0].TableBId, 30) + }) + + // Structs + gtest.C(t, func(t *gtest.T) { + var tableA []*TableA + err := db.Model("table_a").WithAll().OrderAsc("id").Scan(&tableA) + // g.Dump(tableA) + t.AssertNil(err) + t.Assert(len(tableA), 2) + + t.Assert(len(tableA[0].TableB), 2) + t.Assert(tableA[0].TableB[0].Id, 10) + t.Assert(tableA[0].TableB[1].Id, 30) + + t.Assert(len(tableA[0].TableB[0].TableC), 2) + t.Assert(len(tableA[0].TableB[1].TableC), 1) + t.Assert(tableA[0].TableB[0].TableC[0].Id, 100) + t.Assert(tableA[0].TableB[0].TableC[0].TableBId, 10) + t.Assert(tableA[0].TableB[0].TableC[1].Id, 200) + t.Assert(tableA[0].TableB[0].TableC[1].TableBId, 10) + t.Assert(tableA[0].TableB[1].TableC[0].Id, 400) + t.Assert(tableA[0].TableB[1].TableC[0].TableBId, 30) + + t.Assert(tableA[1].TableB[0].TableC[0].Id, 300) + t.Assert(tableA[1].TableB[0].TableC[0].TableBId, 20) + + t.Assert(tableA[1].TableB[1].Id, 40) + t.Assert(tableA[1].TableB[1].TableAId, 2) + t.Assert(tableA[1].TableB[1].TableC, nil) + }) +} + +func Test_Table_Relation_With_MultipleDepends_Embedded(t *testing.T) { + defer func() { + dropTable("table_a") + dropTable("table_b") + dropTable("table_c") + }() + for _, v := range gstr.SplitAndTrim(gfile.GetContents(gtest.DataPath("with_multiple_depends.sql")), ";") { + if _, err := db.Exec(ctx, v); err != nil { + gtest.Error(err) + } + } + + type TableC struct { + gmeta.Meta `orm:"table_c"` + Id int `orm:"id,primary" json:"id"` + TableBId int `orm:"table_b_id" json:"table_b_id"` + } + + type TableB struct { + gmeta.Meta `orm:"table_b"` + Id int `orm:"id,primary" json:"id"` + TableAId int `orm:"table_a_id" json:"table_a_id"` + *TableC `orm:"with:table_b_id=id" json:"table_c"` + } + + type TableA struct { + gmeta.Meta `orm:"table_a"` + Id int `orm:"id,primary" json:"id"` + *TableB `orm:"with:table_a_id=id" json:"table_b"` + } + + db.SetDebug(true) + defer db.SetDebug(false) + + // Struct. + gtest.C(t, func(t *gtest.T) { + var tableA *TableA + err := db.Model("table_a").WithAll().Scan(&tableA) + // g.Dump(tableA) + t.AssertNil(err) + t.AssertNE(tableA, nil) + t.Assert(tableA.Id, 1) + + t.AssertNE(tableA.TableB, nil) + t.AssertNE(tableA.TableB.TableC, nil) + t.Assert(tableA.TableB.TableAId, 1) + t.Assert(tableA.TableB.TableC.Id, 100) + t.Assert(tableA.TableB.TableC.TableBId, 10) + }) + + // Structs + gtest.C(t, func(t *gtest.T) { + var tableA []*TableA + err := db.Model("table_a").WithAll().OrderAsc("id").Scan(&tableA) + // g.Dump(tableA) + t.AssertNil(err) + t.Assert(len(tableA), 2) + t.AssertNE(tableA[0].TableB, nil) + t.AssertNE(tableA[1].TableB, nil) + t.AssertNE(tableA[0].TableB.TableC, nil) + t.AssertNE(tableA[1].TableB.TableC, nil) + + t.Assert(tableA[0].Id, 1) + t.Assert(tableA[0].TableB.Id, 10) + t.Assert(tableA[0].TableB.TableC.Id, 100) + + t.Assert(tableA[1].Id, 2) + t.Assert(tableA[1].TableB.Id, 20) + t.Assert(tableA[1].TableB.TableC.Id, 300) + }) +} + +func Test_Table_Relation_WithAll_Embedded_Meta_NameMatchingRule(t *testing.T) { + var ( + tableUser = "user100" + tableUserDetail = "user_detail100" + tableUserScores = "user_scores100" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE IF NOT EXISTS %s ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +name varchar(45) NOT NULL, +PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE IF NOT EXISTS %s ( +user_id int(10) unsigned NOT NULL, +address varchar(45) NOT NULL, +PRIMARY KEY (user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE IF NOT EXISTS %s ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +user_id int(10) unsigned NOT NULL, +score int(10) unsigned NOT NULL, +PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserScores)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserScores) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail100"` + UserID int `json:"user_id"` + Address string `json:"address"` + } + + type UserScores struct { + gmeta.Meta `orm:"table:user_scores100"` + ID int `json:"id"` + UserID int `json:"user_id"` + Score int `json:"score"` + } + + // For Test Only + type UserEmbedded struct { + ID int `json:"id"` + Name string `json:"name"` + } + + type User struct { + gmeta.Meta `orm:"table:user100"` + UserEmbedded + UserDetail UserDetail `orm:"with:user_id=id"` + UserScores []*UserScores `orm:"with:user_id=id"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "user_id": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + gtest.AssertNil(err) + // Scores. + for j := 1; j <= 5; j++ { + _, err = db.Insert(ctx, tableUserScores, g.Map{ + "user_id": i, + "score": j, + }) + gtest.AssertNil(err) + } + } + + // gtest.C(t, func(t *gtest.T) { + // var user *User + // err := db.Model(tableUser).WithAll().Where("id", 3).Scan(&user) + // t.AssertNil(err) + // t.Assert(user.ID, 3) + // t.AssertNE(user.UserDetail, nil) + // t.Assert(user.UserDetail.UserID, 3) + // t.Assert(user.UserDetail.Address, `address_3`) + // t.Assert(len(user.UserScores), 5) + // t.Assert(user.UserScores[0].UserID, 3) + // t.Assert(user.UserScores[0].Score, 1) + // t.Assert(user.UserScores[4].UserID, 3) + // t.Assert(user.UserScores[4].Score, 5) + // }) + gtest.C(t, func(t *gtest.T) { + var user User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user) + t.AssertNil(err) + t.Assert(user.ID, 4) + t.AssertNE(user.UserDetail, nil) + t.Assert(user.UserDetail.UserID, 4) + t.Assert(user.UserDetail.Address, `address_4`) + t.Assert(len(user.UserScores), 5) + t.Assert(user.UserScores[0].UserID, 4) + t.Assert(user.UserScores[0].Score, 1) + t.Assert(user.UserScores[4].UserID, 4) + t.Assert(user.UserScores[4].Score, 5) + }) +} + +func Test_Table_Relation_WithAll_Unscoped(t *testing.T) { + var ( + tableUser = "user101" + tableUserDetail = "user_detail101" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE IF NOT EXISTS %s ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +name varchar(45) NOT NULL, +PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE IF NOT EXISTS %s ( +user_id int(10) unsigned NOT NULL, +address varchar(45) NOT NULL, +deleted_at datetime default NULL , +PRIMARY KEY (user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail101"` + UserID int `json:"user_id"` + Address string `json:"address"` + DeletedAt *gtime.Time `json:"deleted_at"` + } + + // For Test Only + type UserEmbedded struct { + ID int `json:"id"` + Name string `json:"name"` + } + + type User struct { + gmeta.Meta `orm:"table:user101"` + UserEmbedded + UserDetail *UserDetail `orm:"with:user_id=id"` + } + type UserWithDeletedDetail struct { + gmeta.Meta `orm:"table:user101"` + UserEmbedded + UserDetail *UserDetail `orm:"with:user_id=id, unscoped:true"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "user_id": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + // Delete detail where i = 3 + if i == 3 { + _, err = db.Delete(ctx, tableUserDetail, g.Map{ + "user_id": i, + }) + } + gtest.AssertNil(err) + } + gtest.C(t, func(t *gtest.T) { + var user0 User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user0) + t.AssertNil(err) + t.Assert(user0.ID, 4) + t.AssertNE(user0.UserDetail, nil) + t.AssertNil(user0.UserDetail.DeletedAt) + t.Assert(user0.UserDetail.UserID, 4) + t.Assert(user0.UserDetail.Address, `address_4`) + + var user1 User + err = db.Model(tableUser).WithAll().Where("id", 3).Scan(&user1) + t.AssertNil(err) + t.Assert(user1.ID, 3) + t.AssertNil(user1.UserDetail) + + var user2 UserWithDeletedDetail + err = db.Model(tableUser).WithAll().Where("id", 3).Scan(&user2) + t.AssertNil(err) + t.Assert(user2.ID, 3) + t.AssertNE(user2.UserDetail, nil) + t.AssertNE(user2.UserDetail.DeletedAt, nil) + t.Assert(user2.UserDetail.UserID, 3) + t.Assert(user2.UserDetail.Address, `address_3`) + + // Unscoped outside test + var user3 User + err = db.Model(tableUser).Unscoped().WithAll().Where("id", 3).Scan(&user3) + t.AssertNil(err) + t.Assert(user3.ID, 3) + t.AssertNil(user3.UserDetail) + }) +} + +func Test_Table_Relation_WithAll_Order(t *testing.T) { + var ( + tableUser = "user101" + tableUserDetail = "user_detail101" + ) + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE IF NOT EXISTS %s ( +id int(10) unsigned NOT NULL AUTO_INCREMENT, +name varchar(45) NOT NULL, +PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUser)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUser) + + if _, err := db.Exec(ctx, fmt.Sprintf(` +CREATE TABLE IF NOT EXISTS %s ( +user_id int(10) unsigned NOT NULL, +address varchar(45) NOT NULL, +deleted_at datetime default NULL , +PRIMARY KEY (user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + `, tableUserDetail)); err != nil { + gtest.Error(err) + } + defer dropTable(tableUserDetail) + + type UserDetail struct { + gmeta.Meta `orm:"table:user_detail101"` + UserID int `json:"user_id"` + Address string `json:"address"` + DeletedAt *gtime.Time `json:"deleted_at"` + } + + // For Test Only + type UserEmbedded struct { + ID int `json:"id"` + Name string `json:"name"` + } + + type User struct { + gmeta.Meta `orm:"table:user101"` + UserEmbedded + UserDetail *UserDetail `orm:"with:user_id=id"` + } + type UserWithDeletedDetail struct { + gmeta.Meta `orm:"table:user101"` + UserEmbedded + UserDetail *UserDetail `orm:"with:user_id=id, order:user_id asc,address desc, unscoped:true"` + } + + // Initialize the data. + var err error + for i := 1; i <= 5; i++ { + // User. + _, err = db.Insert(ctx, tableUser, g.Map{ + "id": i, + "name": fmt.Sprintf(`name_%d`, i), + }) + gtest.AssertNil(err) + // Detail. + _, err = db.Insert(ctx, tableUserDetail, g.Map{ + "user_id": i, + "address": fmt.Sprintf(`address_%d`, i), + }) + // Delete detail where i = 3 + if i == 3 { + _, err = db.Delete(ctx, tableUserDetail, g.Map{ + "user_id": i, + }) + } + gtest.AssertNil(err) + } + gtest.C(t, func(t *gtest.T) { + var user0 User + err := db.Model(tableUser).WithAll().Where("id", 4).Scan(&user0) + t.AssertNil(err) + t.Assert(user0.ID, 4) + t.AssertNE(user0.UserDetail, nil) + t.AssertNil(user0.UserDetail.DeletedAt) + t.Assert(user0.UserDetail.UserID, 4) + t.Assert(user0.UserDetail.Address, `address_4`) + + var user1 User + err = db.Model(tableUser).WithAll().Where("id", 3).Scan(&user1) + t.AssertNil(err) + t.Assert(user1.ID, 3) + t.AssertNil(user1.UserDetail) + + var user2 UserWithDeletedDetail + err = db.Model(tableUser).WithAll().Where("id", 3).Scan(&user2) + t.AssertNil(err) + t.Assert(user2.ID, 3) + t.AssertNE(user2.UserDetail, nil) + t.AssertNE(user2.UserDetail.DeletedAt, nil) + t.Assert(user2.UserDetail.UserID, 3) + t.Assert(user2.UserDetail.Address, `address_3`) + + // Unscoped outside test + var user3 User + err = db.Model(tableUser).Unscoped().WithAll().Where("id", 3).Scan(&user3) + t.AssertNil(err) + t.Assert(user3.ID, 3) + t.AssertNil(user3.UserDetail) + }) +} diff --git a/contrib/drivers/mariadb/testdata/table_with_prefix.sql b/contrib/drivers/mariadb/testdata/table_with_prefix.sql new file mode 100644 index 000000000..8c4188d49 --- /dev/null +++ b/contrib/drivers/mariadb/testdata/table_with_prefix.sql @@ -0,0 +1,7 @@ +CREATE TABLE `instance` ( + `f_id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NULL DEFAULT '', + PRIMARY KEY (`f_id`) USING BTREE +) ENGINE = InnoDB; + +INSERT INTO `instance` VALUES (1, 'john'); \ No newline at end of file diff --git a/contrib/drivers/mariadb/testdata/with_multiple_depends.sql b/contrib/drivers/mariadb/testdata/with_multiple_depends.sql new file mode 100644 index 000000000..f4327b947 --- /dev/null +++ b/contrib/drivers/mariadb/testdata/with_multiple_depends.sql @@ -0,0 +1,33 @@ + +CREATE TABLE `table_a` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `alias` varchar(255) NULL DEFAULT '', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB; + +INSERT INTO `table_a` VALUES (1, 'table_a_test1'); +INSERT INTO `table_a` VALUES (2, 'table_a_test2'); + +CREATE TABLE `table_b` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `table_a_id` int(11) NOT NULL, + `alias` varchar(255) NULL DEFAULT '', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB; + +INSERT INTO `table_b` VALUES (10, 1, 'table_b_test1'); +INSERT INTO `table_b` VALUES (20, 2, 'table_b_test2'); +INSERT INTO `table_b` VALUES (30, 1, 'table_b_test3'); +INSERT INTO `table_b` VALUES (40, 2, 'table_b_test4'); + +CREATE TABLE `table_c` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `table_b_id` int(11) NOT NULL, + `alias` varchar(255) NULL DEFAULT '', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB; + +INSERT INTO `table_c` VALUES (100, 10, 'table_c_test1'); +INSERT INTO `table_c` VALUES (200, 10, 'table_c_test2'); +INSERT INTO `table_c` VALUES (300, 20, 'table_c_test3'); +INSERT INTO `table_c` VALUES (400, 30, 'table_c_test4'); \ No newline at end of file diff --git a/contrib/drivers/mariadb/testdata/with_tpl_user.sql b/contrib/drivers/mariadb/testdata/with_tpl_user.sql new file mode 100644 index 000000000..032e9c55d --- /dev/null +++ b/contrib/drivers/mariadb/testdata/with_tpl_user.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + name varchar(45) NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/contrib/drivers/mariadb/testdata/with_tpl_user_detail.sql b/contrib/drivers/mariadb/testdata/with_tpl_user_detail.sql new file mode 100644 index 000000000..54bbccd09 --- /dev/null +++ b/contrib/drivers/mariadb/testdata/with_tpl_user_detail.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS %s ( + uid int(10) unsigned NOT NULL AUTO_INCREMENT, + address varchar(45) NOT NULL, + PRIMARY KEY (uid) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/contrib/drivers/mariadb/testdata/with_tpl_user_scores.sql b/contrib/drivers/mariadb/testdata/with_tpl_user_scores.sql new file mode 100644 index 000000000..d1640ee0a --- /dev/null +++ b/contrib/drivers/mariadb/testdata/with_tpl_user_scores.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS %s ( + id int(10) unsigned NOT NULL AUTO_INCREMENT, + uid int(10) unsigned NOT NULL, + score int(10) unsigned NOT NULL, + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file