Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 5 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions contrib/drivers/mysql/mysql_z_unit_feature_soft_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
})
}
2 changes: 1 addition & 1 deletion contrib/nosql/redis/redis_z_group_generic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
7 changes: 4 additions & 3 deletions database/gdb/gdb_model_insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
35 changes: 17 additions & 18 deletions database/gdb/gdb_model_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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(
Expand All @@ -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]) {
jswxstw marked this conversation as resolved.
Show resolved Hide resolved
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 ") {
Expand Down