1
0
mirror of https://github.com/gogf/gf.git synced 2025-04-05 03:05:05 +08:00

fix: #3613 ignore automatic handling for creating/updating time if it has been specified (#3615)

This commit is contained in:
jswxstw 2024-06-12 21:41:44 +08:00 committed by GitHub
parent 01408f1a87
commit 2ccbb02c71
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 152 additions and 22 deletions

View File

@ -1267,3 +1267,133 @@ CREATE TABLE %s (
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")
})
}

View File

@ -434,7 +434,7 @@ func Test_GroupGeneric_ExpireAt(t *testing.T) {
result, err = redis.GroupGeneric().ExpireAt(ctx, TestKey, time.Now().Add(time.Millisecond*100))
t.AssertNil(err)
t.AssertEQ(result, int64(1))
time.Sleep(time.Millisecond * 100)
time.Sleep(time.Millisecond * 200)
result, err = redis.GroupGeneric().Exists(ctx, TestKey)
t.AssertNil(err)
t.AssertEQ(result, int64(0))

View File

@ -14,6 +14,7 @@ import (
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/reflection"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
@ -286,19 +287,19 @@ func (m *Model) doInsertWithOption(ctx context.Context, insertOption InsertOptio
// Automatic handling for creating/updating time.
if !m.unscoped && (fieldNameCreate != "" || fieldNameUpdate != "") {
for k, v := range list {
if fieldNameCreate != "" {
if fieldNameCreate != "" && empty.IsNil(v[fieldNameCreate]) {
fieldCreateValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeCreate, false)
if fieldCreateValue != nil {
v[fieldNameCreate] = fieldCreateValue
}
}
if fieldNameUpdate != "" {
if fieldNameUpdate != "" && empty.IsNil(v[fieldNameUpdate]) {
fieldUpdateValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeUpdate, false)
if fieldUpdateValue != nil {
v[fieldNameUpdate] = fieldUpdateValue
}
}
if fieldNameDelete != "" {
if fieldNameDelete != "" && empty.IsNil(v[fieldNameDelete]) {
fieldDeleteValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeDelete, true)
if fieldDeleteValue != nil {
v[fieldNameDelete] = fieldDeleteValue

View File

@ -11,10 +11,10 @@ import (
"fmt"
"reflect"
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/internal/empty"
"github.com/gogf/gf/v2/internal/intlog"
"github.com/gogf/gf/v2/internal/reflection"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
@ -45,9 +45,9 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro
return nil, gerror.NewCode(gcode.CodeMissingParameter, "updating table with empty data")
}
var (
newData interface{}
stm = m.softTimeMaintainer()
updateData = m.data
reflectInfo = reflection.OriginTypeAndKind(updateData)
reflectInfo = reflection.OriginTypeAndKind(m.data)
conditionWhere, conditionExtra, conditionArgs = m.formatCondition(ctx, false, false)
conditionStr = conditionWhere + conditionExtra
fieldNameUpdate, fieldTypeUpdate = stm.GetFieldNameAndTypeForUpdate(
@ -58,31 +58,30 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro
fieldNameUpdate = ""
}
newData, err = m.filterDataForInsertOrUpdate(m.data)
if err != nil {
return nil, err
}
switch reflectInfo.OriginKind {
case reflect.Map, reflect.Struct:
var dataMap = anyValueToMapBeforeToRecord(m.data)
var dataMap = anyValueToMapBeforeToRecord(newData)
// Automatically update the record updating time.
if fieldNameUpdate != "" {
if fieldNameUpdate != "" && empty.IsNil(dataMap[fieldNameUpdate]) {
dataValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeUpdate, false)
dataMap[fieldNameUpdate] = dataValue
}
updateData = dataMap
newData = dataMap
default:
updates := gconv.String(m.data)
var updateStr = gconv.String(newData)
// Automatically update the record updating time.
if fieldNameUpdate != "" {
if fieldNameUpdate != "" && !gstr.Contains(updateStr, fieldNameUpdate) {
dataValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeUpdate, false)
if fieldNameUpdate != "" && !gstr.Contains(updates, fieldNameUpdate) {
updates += fmt.Sprintf(`,%s=?`, fieldNameUpdate)
conditionArgs = append([]interface{}{dataValue}, conditionArgs...)
}
updateStr += fmt.Sprintf(`,%s=?`, fieldNameUpdate)
conditionArgs = append([]interface{}{dataValue}, conditionArgs...)
}
updateData = updates
}
newData, err := m.filterDataForInsertOrUpdate(updateData)
if err != nil {
return nil, err
newData = updateStr
}
if !gstr.ContainsI(conditionStr, " WHERE ") {