From e721124b6c139859bf032a95a9173190fbb6f974 Mon Sep 17 00:00:00 2001 From: Wesley Wu Date: Mon, 20 Mar 2023 09:57:37 +0800 Subject: [PATCH] support microseconds resolution for created_at/updated_at/deleted_at (#2512) --- contrib/drivers/README.MD | 1 + contrib/drivers/dm/dm.go | 19 +- contrib/drivers/dm/dm_init_test.go | 4 +- contrib/drivers/dm/dm_z_basic_test.go | 14 +- contrib/drivers/mssql/mssql_init_test.go | 4 +- contrib/drivers/mssql/mssql_z_basic_test.go | 48 ++--- contrib/drivers/mssql/mssql_z_model_test.go | 8 +- contrib/drivers/mysql/mysql__test.go | 2 +- .../mysql/mysql_feature_time_maintain_test.go | 196 +++++++++++++++--- contrib/drivers/mysql/mysql_issue_test.go | 24 +-- contrib/drivers/mysql/mysql_model_test.go | 6 +- database/gdb/gdb_model_delete.go | 2 +- database/gdb/gdb_model_insert.go | 6 +- database/gdb/gdb_model_update.go | 5 +- 14 files changed, 231 insertions(+), 108 deletions(-) diff --git a/contrib/drivers/README.MD b/contrib/drivers/README.MD index 59897a066..698e54d7f 100644 --- a/contrib/drivers/README.MD +++ b/contrib/drivers/README.MD @@ -58,6 +58,7 @@ Note: - It does not support `Save/Replace` features. - It does not support `LastInsertId`. - It supports server version >= `SQL Server2005` +- It ONLY supports datetime2 and datetimeoffset types for auto handling created_at/updated_at/deleted_at columns, because datetime type does not support microseconds precision when column value is passed as string. ## Oracle ``` diff --git a/contrib/drivers/dm/dm.go b/contrib/drivers/dm/dm.go index 8e955e16d..cb1ad603e 100644 --- a/contrib/drivers/dm/dm.go +++ b/contrib/drivers/dm/dm.go @@ -23,6 +23,7 @@ import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gutil" ) @@ -283,23 +284,7 @@ func parseValue(listOne gdb.Map, char struct { ) } - va := reflect.ValueOf(listOne[column]) - ty := reflect.TypeOf(listOne[column]) - saveValue := "" - switch ty.Kind() { - case reflect.String: - saveValue = va.String() - - case reflect.Int: - saveValue = strconv.FormatInt(va.Int(), 10) - - case reflect.Int64: - saveValue = strconv.FormatInt(va.Int(), 10) - - default: - // The fish has no chance getting here. - // Nothing to do. - } + saveValue := gconv.String(listOne[column]) queryValues = append( queryValues, fmt.Sprintf( diff --git a/contrib/drivers/dm/dm_init_test.go b/contrib/drivers/dm/dm_init_test.go index ec5d3fe69..7f72bd693 100644 --- a/contrib/drivers/dm/dm_init_test.go +++ b/contrib/drivers/dm/dm_init_test.go @@ -125,9 +125,9 @@ func createTable(table ...string) (name string) { "ENABLED" INT DEFAULT 1 NOT NULL, "DELETED" INT DEFAULT 0 NOT NULL, "CREATED_BY" VARCHAR(32) DEFAULT '' NOT NULL, -"CREATED_TIME" TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP() NOT NULL, +"CREATED_TIME" TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP() NOT NULL, "UPDATED_BY" VARCHAR(32) DEFAULT '' NOT NULL, -"UPDATED_TIME" TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP() NOT NULL, +"UPDATED_TIME" TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP() NOT NULL, NOT CLUSTER PRIMARY KEY("ID")) STORAGE(ON "MAIN", CLUSTERBTR) ; `, name)); err != nil { gtest.Fatal(err) diff --git a/contrib/drivers/dm/dm_z_basic_test.go b/contrib/drivers/dm/dm_z_basic_test.go index 5f4bc0dd2..5f6eba833 100644 --- a/contrib/drivers/dm/dm_z_basic_test.go +++ b/contrib/drivers/dm/dm_z_basic_test.go @@ -233,7 +233,7 @@ func Test_DB_Insert(t *testing.T) { _, err := db.Insert(ctx, "A_tables", g.Map{ "ID": 1000, "ACCOUNT_NAME": "map1", - "CREATED_TIME": gtime.Now().String(), + "CREATED_TIME": gtime.Now(), }) t.AssertNil(err) @@ -249,7 +249,7 @@ func Test_DB_Insert(t *testing.T) { result, err = db.Insert(ctx, "A_tables", g.Map{ "ID": 3000, "ACCOUNT_NAME": "map3", - // "CREATED_TIME": gtime.Now().String(), + // "CREATED_TIME": gtime.Now(), }) t.AssertNil(err) n, _ = result.RowsAffected() @@ -320,12 +320,12 @@ func Test_DB_BatchInsert(t *testing.T) { { "ID": 400, "ACCOUNT_NAME": "list_400", - // "CREATE_TIME": gtime.Now().String(), + // "CREATE_TIME": gtime.Now(), }, { "ID": 401, "ACCOUNT_NAME": "list_401", - "CREATE_TIME": gtime.Now().String(), + "CREATE_TIME": gtime.Now(), }, }, 1) t.AssertNil(err) @@ -342,12 +342,12 @@ func Test_DB_BatchInsert(t *testing.T) { g.Map{ "ID": 500, "ACCOUNT_NAME": "500_batch_500", - "CREATE_TIME": gtime.Now().String(), + "CREATE_TIME": gtime.Now(), }, g.Map{ "ID": 501, "ACCOUNT_NAME": "501_batch_501", - // "CREATE_TIME": gtime.Now().String(), + // "CREATE_TIME": gtime.Now(), }, }, 1) t.AssertNil(err) @@ -363,7 +363,7 @@ func Test_DB_BatchInsert(t *testing.T) { result, err := db.Insert(ctx, table, g.Map{ "ID": 600, "ACCOUNT_NAME": "600_batch_600", - "CREATE_TIME": gtime.Now().String(), + "CREATE_TIME": gtime.Now(), }) t.AssertNil(err) n, _ := result.RowsAffected() diff --git a/contrib/drivers/mssql/mssql_init_test.go b/contrib/drivers/mssql/mssql_init_test.go index c9145c095..fdf383ae0 100644 --- a/contrib/drivers/mssql/mssql_init_test.go +++ b/contrib/drivers/mssql/mssql_init_test.go @@ -107,6 +107,8 @@ func createTable(table ...string) (name string) { PASSWORD VARCHAR(32) NULL, NICKNAME VARCHAR(45) NULL, CREATE_TIME datetime NULL, + CREATED_AT datetimeoffset NULL, + UPDATED_AT datetimeoffset NULL, PRIMARY KEY (ID)) `, name, name)); err != nil { gtest.Fatal(err) @@ -125,7 +127,7 @@ func createInitTable(table ...string) (name string) { "passport": fmt.Sprintf(`user_%d`, i), "password": fmt.Sprintf(`pass_%d`, i), "nickname": fmt.Sprintf(`name_%d`, i), - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), }) } result, err := db.Insert(context.Background(), name, array.Slice()) diff --git a/contrib/drivers/mssql/mssql_z_basic_test.go b/contrib/drivers/mssql/mssql_z_basic_test.go index 3f151c6a8..9b2e11df7 100644 --- a/contrib/drivers/mssql/mssql_z_basic_test.go +++ b/contrib/drivers/mssql/mssql_z_basic_test.go @@ -120,7 +120,7 @@ func TestDoInsert(t *testing.T) { "passport": fmt.Sprintf(`t%d`, i), "password": fmt.Sprintf(`p%d`, i), "nickname": fmt.Sprintf(`T%d`, i), - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), } _, err := db.Insert(context.Background(), "t_user", data) gtest.Assert(err, nil) @@ -137,7 +137,7 @@ func TestDoInsert(t *testing.T) { "passport": fmt.Sprintf(`t%d`, i), "password": fmt.Sprintf(`p%d`, i), "nickname": fmt.Sprintf(`T%d`, i), - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), } _, err := db.Save(context.Background(), "t_user", data, 10) gtest.AssertNE(err, nil) @@ -192,7 +192,7 @@ func Test_DB_Insert(t *testing.T) { "passport": "t1", "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "T1", - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), }) t.AssertNil(err) @@ -202,7 +202,7 @@ func Test_DB_Insert(t *testing.T) { "passport": "t2", "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "name_2", - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), }) t.AssertNil(err) n, _ := result.RowsAffected() @@ -210,19 +210,19 @@ func Test_DB_Insert(t *testing.T) { // struct type User struct { - Id int `gconv:"id"` - Passport string `json:"passport"` - Password string `gconv:"password"` - Nickname string `gconv:"nickname"` - CreateTime string `json:"create_time"` + Id int `gconv:"id"` + Passport string `json:"passport"` + Password string `gconv:"password"` + Nickname string `gconv:"nickname"` + CreateTime *gtime.Time `json:"create_time"` } - timeStr := gtime.Now().String() + timeNow := gtime.Now() result, err = db.Insert(ctx, table, User{ Id: 3, Passport: "user_3", Password: "25d55ad283aa400af464c76d713c07ad", Nickname: "name_3", - CreateTime: timeStr, + CreateTime: timeNow, }) t.AssertNil(err) n, _ = result.RowsAffected() @@ -235,16 +235,16 @@ func Test_DB_Insert(t *testing.T) { t.Assert(one["PASSPORT"].String(), "user_3") t.Assert(one["PASSWORD"].String(), "25d55ad283aa400af464c76d713c07ad") t.Assert(one["NICKNAME"].String(), "name_3") - t.Assert(one["CREATE_TIME"].GTime().String(), timeStr) + t.Assert(one["CREATE_TIME"].GTime(), timeNow) // *struct - timeStr = gtime.Now().String() + timeNow = gtime.Now() result, err = db.Insert(ctx, table, &User{ Id: 4, Passport: "t4", Password: "25d55ad283aa400af464c76d713c07ad", Nickname: "name_4", - CreateTime: timeStr, + CreateTime: timeNow, }) t.AssertNil(err) n, _ = result.RowsAffected() @@ -256,24 +256,24 @@ func Test_DB_Insert(t *testing.T) { t.Assert(one["PASSPORT"].String(), "t4") t.Assert(one["PASSWORD"].String(), "25d55ad283aa400af464c76d713c07ad") t.Assert(one["NICKNAME"].String(), "name_4") - t.Assert(one["CREATE_TIME"].GTime().String(), timeStr) + t.Assert(one["CREATE_TIME"].GTime(), timeNow) // batch with Insert - timeStr = gtime.Now().String() + timeNow = gtime.Now() r, err := db.Insert(ctx, table, g.Slice{ g.Map{ "id": 200, "passport": "t200", "password": "25d55ad283aa400af464c76d71qw07ad", "nickname": "T200", - "create_time": timeStr, + "create_time": timeNow, }, g.Map{ "id": 300, "passport": "t300", "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "T300", - "create_time": timeStr, + "create_time": timeNow, }, }) t.AssertNil(err) @@ -286,7 +286,7 @@ func Test_DB_Insert(t *testing.T) { t.Assert(one["PASSPORT"].String(), "t200") t.Assert(one["PASSWORD"].String(), "25d55ad283aa400af464c76d71qw07ad") t.Assert(one["NICKNAME"].String(), "T200") - t.Assert(one["CREATE_TIME"].GTime().String(), timeStr) + t.Assert(one["CREATE_TIME"].GTime(), timeNow) }) } @@ -360,14 +360,14 @@ func Test_DB_BatchInsert(t *testing.T) { "passport": "t2", "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "name_2", - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), }, { "id": 3, "passport": "user_3", "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "name_3", - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), }, }, 1) t.AssertNil(err) @@ -386,14 +386,14 @@ func Test_DB_BatchInsert(t *testing.T) { "passport": "t2", "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "name_2", - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), }, g.Map{ "id": 3, "passport": "user_3", "password": "25d55ad283aa400af464c76d713c07ad", "nickname": "name_3", - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), }, }, 1) t.AssertNil(err) @@ -410,7 +410,7 @@ func Test_DB_BatchInsert(t *testing.T) { "passport": "t1", "password": "p1", "nickname": "T1", - "create_time": gtime.Now().String(), + "create_time": gtime.Now(), }) t.AssertNil(err) n, _ := result.RowsAffected() diff --git a/contrib/drivers/mssql/mssql_z_model_test.go b/contrib/drivers/mssql/mssql_z_model_test.go index 3d5c45c6a..0b0ad2e43 100644 --- a/contrib/drivers/mssql/mssql_z_model_test.go +++ b/contrib/drivers/mssql/mssql_z_model_test.go @@ -1556,15 +1556,15 @@ func Test_Model_Option_Map(t *testing.T) { t.Assert(n, 1) _, err = db.Model(table).OmitEmptyData().Data(g.Map{"nickname": ""}).Where("id", 2).Update() - t.AssertNE(err, nil) + t.AssertNil(err) r, err = db.Model(table).OmitEmpty().Data(g.Map{"nickname": "", "password": "123"}).Where("id", 3).Update() t.AssertNil(err) n, _ = r.RowsAffected() t.Assert(n, 1) - _, err = db.Model(table).OmitEmpty().Fields("nickname").Data(g.Map{"nickname": "", "password": "123"}).Where("id", 4).Update() - t.AssertNE(err, nil) + _, err = db.Model(table).OmitEmpty().Fields("nickname", "password").Data(g.Map{"nickname": "", "password": "123", "passport": "123"}).Where("id", 4).Update() + t.AssertNil(err) r, err = db.Model(table).OmitEmpty(). Fields("password").Data(g.Map{ @@ -1639,7 +1639,7 @@ func Test_Model_FieldsEx(t *testing.T) { defer dropTable(table) // Select. gtest.C(t, func(t *gtest.T) { - r, err := db.Model(table).FieldsEx("create_time, id").Where("id in (?)", g.Slice{1, 2}).Order("id asc").All() + r, err := db.Model(table).FieldsEx("create_time, created_at, updated_at, id").Where("id in (?)", g.Slice{1, 2}).Order("id asc").All() t.AssertNil(err) t.Assert(len(r), 2) t.Assert(len(r[0]), 3) diff --git a/contrib/drivers/mysql/mysql__test.go b/contrib/drivers/mysql/mysql__test.go index be4a315f3..13bc81a05 100644 --- a/contrib/drivers/mysql/mysql__test.go +++ b/contrib/drivers/mysql/mysql__test.go @@ -117,7 +117,7 @@ func createTableWithDb(db gdb.DB, table ...string) (name string) { passport varchar(45) NULL, password char(32) NULL, nickname varchar(45) NULL, - create_time timestamp NULL, + create_time timestamp(6) NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `, name, diff --git a/contrib/drivers/mysql/mysql_feature_time_maintain_test.go b/contrib/drivers/mysql/mysql_feature_time_maintain_test.go index 110da78c2..13aac68b4 100644 --- a/contrib/drivers/mysql/mysql_feature_time_maintain_test.go +++ b/contrib/drivers/mysql/mysql_feature_time_maintain_test.go @@ -17,15 +17,149 @@ import ( ) // CreateAt/UpdateAt/DeleteAt. -func Test_SoftCreateUpdateDeleteTime(t *testing.T) { +func Test_SoftCreateUpdateDeleteTimeMicroSecond(t *testing.T) { table := "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 DEFAULT NULL, - update_at datetime DEFAULT NULL, - delete_at datetime 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_SoftCreateUpdateDeleteTimeSecond(t *testing.T) { + table := "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 { @@ -157,9 +291,9 @@ func Test_SoftCreatedUpdatedDeletedTime_Map(t *testing.T) { CREATE TABLE %s ( id int(11) NOT NULL, name varchar(45) DEFAULT NULL, - created_at datetime DEFAULT NULL, - updated_at datetime DEFAULT NULL, - deleted_at datetime 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 { @@ -291,9 +425,9 @@ func Test_SoftCreatedUpdatedDeletedTime_Struct(t *testing.T) { CREATE TABLE %s ( id int(11) NOT NULL, name varchar(45) DEFAULT NULL, - created_at datetime DEFAULT NULL, - updated_at datetime DEFAULT NULL, - deleted_at datetime 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 { @@ -431,9 +565,9 @@ func Test_SoftUpdateTime(t *testing.T) { CREATE TABLE %s ( id int(11) NOT NULL, num int(11) DEFAULT NULL, - create_at datetime DEFAULT NULL, - update_at datetime DEFAULT NULL, - delete_at datetime 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 { @@ -471,9 +605,9 @@ func Test_SoftUpdateTime_WithDO(t *testing.T) { CREATE TABLE %s ( id int(11) NOT NULL, num int(11) DEFAULT NULL, - created_at datetime DEFAULT NULL, - updated_at datetime DEFAULT NULL, - deleted_at datetime 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 { @@ -528,9 +662,9 @@ func Test_SoftDelete(t *testing.T) { CREATE TABLE %s ( id int(11) NOT NULL, name varchar(45) DEFAULT NULL, - create_at datetime DEFAULT NULL, - update_at datetime DEFAULT NULL, - delete_at datetime 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 { @@ -596,9 +730,9 @@ func Test_SoftDelete_Join(t *testing.T) { CREATE TABLE %s ( id int(11) NOT NULL, name varchar(45) DEFAULT NULL, - create_at datetime DEFAULT NULL, - update_at datetime DEFAULT NULL, - delete_at datetime 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 { @@ -611,9 +745,9 @@ CREATE TABLE %s ( CREATE TABLE %s ( id int(11) NOT NULL, name varchar(45) DEFAULT NULL, - createat datetime DEFAULT NULL, - updateat datetime DEFAULT NULL, - deleteat datetime 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 { @@ -667,9 +801,9 @@ func Test_SoftDelete_WhereAndOr(t *testing.T) { CREATE TABLE %s ( id int(11) NOT NULL, name varchar(45) DEFAULT NULL, - create_at datetime DEFAULT NULL, - update_at datetime DEFAULT NULL, - delete_at datetime 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 { @@ -709,9 +843,9 @@ func Test_CreateUpdateTime_Struct(t *testing.T) { CREATE TABLE %s ( id int(11) NOT NULL, name varchar(45) DEFAULT NULL, - create_at datetime DEFAULT NULL, - update_at datetime DEFAULT NULL, - delete_at datetime 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 { diff --git a/contrib/drivers/mysql/mysql_issue_test.go b/contrib/drivers/mysql/mysql_issue_test.go index 5e599cc10..380ab909f 100644 --- a/contrib/drivers/mysql/mysql_issue_test.go +++ b/contrib/drivers/mysql/mysql_issue_test.go @@ -532,8 +532,8 @@ func Test_Issue2338(t *testing.T) { CREATE TABLE %s ( id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID', nickname varchar(45) DEFAULT NULL COMMENT 'User Nickname', - create_at datetime DEFAULT NULL COMMENT 'Created Time', - update_at datetime DEFAULT NULL COMMENT 'Updated Time', + create_at datetime(6) DEFAULT NULL COMMENT 'Created Time', + update_at datetime(6) DEFAULT NULL COMMENT 'Updated Time', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `, table1, @@ -544,8 +544,8 @@ CREATE TABLE %s ( CREATE TABLE %s ( id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID', nickname varchar(45) DEFAULT NULL COMMENT 'User Nickname', - create_at datetime DEFAULT NULL COMMENT 'Created Time', - update_at datetime DEFAULT NULL COMMENT 'Updated Time', + create_at datetime(6) DEFAULT NULL COMMENT 'Created Time', + update_at datetime(6) DEFAULT NULL COMMENT 'Updated Time', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `, table2, @@ -585,9 +585,9 @@ CREATE TABLE %s ( CREATE TABLE %s ( id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID', nickname varchar(45) DEFAULT NULL COMMENT 'User Nickname', - create_at datetime DEFAULT NULL COMMENT 'Created Time', - update_at datetime DEFAULT NULL COMMENT 'Updated Time', - deleted_at datetime DEFAULT NULL COMMENT 'Deleted Time', + create_at datetime(6) DEFAULT NULL COMMENT 'Created Time', + update_at datetime(6) DEFAULT NULL COMMENT 'Updated Time', + deleted_at datetime(6) DEFAULT NULL COMMENT 'Deleted Time', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `, table1, @@ -598,9 +598,9 @@ CREATE TABLE %s ( CREATE TABLE %s ( id int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID', nickname varchar(45) DEFAULT NULL COMMENT 'User Nickname', - create_at datetime DEFAULT NULL COMMENT 'Created Time', - update_at datetime DEFAULT NULL COMMENT 'Updated Time', - deleted_at datetime DEFAULT NULL COMMENT 'Deleted Time', + create_at datetime(6) DEFAULT NULL COMMENT 'Created Time', + update_at datetime(6) DEFAULT NULL COMMENT 'Updated Time', + deleted_at datetime(6) DEFAULT NULL COMMENT 'Deleted Time', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `, table2, @@ -644,8 +644,8 @@ CREATE TABLE %s ( passport varchar(45) NOT NULL COMMENT 'User Passport', password varchar(45) NOT NULL COMMENT 'User Password', nickname varchar(45) NOT NULL COMMENT 'User Nickname', - create_at datetime DEFAULT NULL COMMENT 'Created Time', - update_at datetime DEFAULT NULL COMMENT 'Updated Time', + create_at datetime(6) DEFAULT NULL COMMENT 'Created Time', + update_at datetime(6) DEFAULT NULL COMMENT 'Updated Time', PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `, table, diff --git a/contrib/drivers/mysql/mysql_model_test.go b/contrib/drivers/mysql/mysql_model_test.go index ab005097b..371ea7094 100644 --- a/contrib/drivers/mysql/mysql_model_test.go +++ b/contrib/drivers/mysql/mysql_model_test.go @@ -3134,9 +3134,9 @@ func createTableForTimeZoneTest() string { passport varchar(45) NULL, password char(32) NULL, nickname varchar(45) NULL, - created_at timestamp NULL, - updated_at timestamp NULL, - deleted_at timestamp NULL, + created_at timestamp(6) NULL, + updated_at timestamp(6) NULL, + deleted_at timestamp(6) NULL, PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; `, tableName, diff --git a/database/gdb/gdb_model_delete.go b/database/gdb/gdb_model_delete.go index 4dd05ef98..26b23759c 100644 --- a/database/gdb/gdb_model_delete.go +++ b/database/gdb/gdb_model_delete.go @@ -63,7 +63,7 @@ func (m *Model) Delete(where ...interface{}) (result sql.Result, err error) { Table: m.tables, Data: fmt.Sprintf(`%s=?`, m.db.GetCore().QuoteString(fieldNameDelete)), Condition: conditionStr, - Args: append([]interface{}{gtime.Now().String()}, conditionArgs...), + Args: append([]interface{}{gtime.Now()}, conditionArgs...), } return in.Next(ctx) } diff --git a/database/gdb/gdb_model_insert.go b/database/gdb/gdb_model_insert.go index 09fb488b5..3cde85328 100644 --- a/database/gdb/gdb_model_insert.go +++ b/database/gdb/gdb_model_insert.go @@ -254,7 +254,7 @@ func (m *Model) doInsertWithOption(ctx context.Context, insertOption int) (resul } var ( list List - nowString = gtime.Now().String() + now = gtime.Now() fieldNameCreate = m.getSoftFieldNameCreated("", m.tablesInit) fieldNameUpdate = m.getSoftFieldNameUpdated("", m.tablesInit) ) @@ -338,10 +338,10 @@ func (m *Model) doInsertWithOption(ctx context.Context, insertOption int) (resul if !m.unscoped && (fieldNameCreate != "" || fieldNameUpdate != "") { for k, v := range list { if fieldNameCreate != "" { - v[fieldNameCreate] = nowString + v[fieldNameCreate] = now } if fieldNameUpdate != "" { - v[fieldNameUpdate] = nowString + v[fieldNameUpdate] = now } list[k] = v } diff --git a/database/gdb/gdb_model_update.go b/database/gdb/gdb_model_update.go index 5317bc73f..f819336b7 100644 --- a/database/gdb/gdb_model_update.go +++ b/database/gdb/gdb_model_update.go @@ -64,7 +64,7 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro } // Automatically update the record updating time. if fieldNameUpdate != "" { - dataMap[fieldNameUpdate] = gtime.Now().String() + dataMap[fieldNameUpdate] = gtime.Now() } updateData = dataMap @@ -73,7 +73,8 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro // Automatically update the record updating time. if fieldNameUpdate != "" { if fieldNameUpdate != "" && !gstr.Contains(updates, fieldNameUpdate) { - updates += fmt.Sprintf(`,%s='%s'`, fieldNameUpdate, gtime.Now().String()) + updates += fmt.Sprintf(`,%s=?`, fieldNameUpdate) + conditionArgs = append([]interface{}{gtime.Now()}, conditionArgs...) } } updateData = updates