Skip to content

Commit

Permalink
fix/3764 (#4)
Browse files Browse the repository at this point in the history
* feat(database/gdb): add `time` field type for value converting for/from field (gogf#3712)

* fix(net/goai): fix openapi miss `required` tag of `BizRequest` when set `CommonRequest` (gogf#3724)

* perf(database/gdb): performance improvement for struct scanning when with feature disabled (gogf#3677)

* up

---------

Co-authored-by: CyJaySong <29367599+cyjaysong@users.noreply.github.com>
Co-authored-by: Zwei <zwei.elen@outlook.com>
Co-authored-by: wln32 <49137144+wln32@users.noreply.github.com>
  • Loading branch information
4 people authored Sep 12, 2024
1 parent 0596dd1 commit 247243c
Show file tree
Hide file tree
Showing 15 changed files with 198 additions and 62 deletions.
2 changes: 1 addition & 1 deletion cmd/gf/internal/cmd/gendao/gendao_structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func generateStructFieldDefinition(
}
localTypeNameStr = string(localTypeName)
switch localTypeName {
case gdb.LocalTypeDate, gdb.LocalTypeDatetime:
case gdb.LocalTypeDate, gdb.LocalTypeTime, gdb.LocalTypeDatetime:
if in.StdTime {
localTypeNameStr = "time.Time"
} else {
Expand Down
33 changes: 23 additions & 10 deletions contrib/drivers/mysql/mysql_z_unit_core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func Test_DB_Insert(t *testing.T) {
"password": "25d55ad283aa400af464c76d713c07ad",
"nickname": "T1",
"create_time": gtime.Now().String(),
"create_date": gtime.Date(),
})
t.AssertNil(err)

Expand All @@ -114,26 +115,30 @@ func Test_DB_Insert(t *testing.T) {
"password": "25d55ad283aa400af464c76d713c07ad",
"nickname": "name_2",
"create_time": gtime.Now().String(),
"create_date": gtime.Date(),
})
t.AssertNil(err)
n, _ := result.RowsAffected()
t.Assert(n, 1)

// 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"`
}
timeStr := gtime.New("2024-10-01 12:01:01").String()
Id int `gconv:"id"`
Passport string `json:"passport"`
Password string `gconv:"password"`
Nickname string `gconv:"nickname"`
CreateTime string `json:"create_time"`
CreateDate *gtime.Time `json:"create_date"`
}
gTime := gtime.New("2024-10-01 12:01:01")
timeStr, dateStr := gTime.String(), "2024-10-01 00:00:00"
result, err = db.Insert(ctx, table, User{
Id: 3,
Passport: "user_3",
Password: "25d55ad283aa400af464c76d713c07ad",
Nickname: "name_3",
CreateTime: timeStr,
CreateDate: gTime,
})
t.AssertNil(err)
n, _ = result.RowsAffected()
Expand All @@ -147,15 +152,18 @@ func Test_DB_Insert(t *testing.T) {
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_date"].GTime().String(), dateStr)

// *struct
timeStr = gtime.New("2024-10-01 12:01:01").String()
gTime = gtime.New("2024-10-01 12:01:01")
timeStr, dateStr = gTime.String(), "2024-10-01 00:00:00"
result, err = db.Insert(ctx, table, &User{
Id: 4,
Passport: "t4",
Password: "25d55ad283aa400af464c76d713c07ad",
Nickname: "name_4",
CreateTime: timeStr,
CreateDate: gTime,
})
t.AssertNil(err)
n, _ = result.RowsAffected()
Expand All @@ -168,23 +176,27 @@ func Test_DB_Insert(t *testing.T) {
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_date"].GTime().String(), dateStr)

// batch with Insert
timeStr = gtime.New("2024-10-01 12:01:01").String()
gTime = gtime.New("2024-10-01 12:01:01")
timeStr, dateStr = gTime.String(), "2024-10-01 00:00:00"
r, err := db.Insert(ctx, table, g.Slice{
g.Map{
"id": 200,
"passport": "t200",
"password": "25d55ad283aa400af464c76d71qw07ad",
"nickname": "T200",
"create_time": timeStr,
"create_date": gTime,
},
g.Map{
"id": 300,
"passport": "t300",
"password": "25d55ad283aa400af464c76d713c07ad",
"nickname": "T300",
"create_time": timeStr,
"create_date": gTime,
},
})
t.AssertNil(err)
Expand All @@ -198,6 +210,7 @@ func Test_DB_Insert(t *testing.T) {
t.Assert(one["password"].String(), "25d55ad283aa400af464c76d71qw07ad")
t.Assert(one["nickname"].String(), "T200")
t.Assert(one["create_time"].GTime().String(), timeStr)
t.Assert(one["create_date"].GTime().String(), dateStr)
})
}

Expand Down Expand Up @@ -1644,7 +1657,7 @@ func Test_Core_ClearTableFields(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
fields, err := db.TableFields(ctx, table)
t.AssertNil(err)
t.Assert(len(fields), 5)
t.Assert(len(fields), 6)
})
gtest.C(t, func(t *gtest.T) {
err := db.GetCore().ClearTableFields(ctx, table)
Expand Down
1 change: 1 addition & 0 deletions contrib/drivers/mysql/mysql_z_unit_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ func createTableWithDb(db gdb.DB, table ...string) (name string) {
password char(32) NULL,
nickname varchar(45) NULL,
create_time timestamp(6) NULL,
create_date date NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
`, name,
Expand Down
8 changes: 4 additions & 4 deletions contrib/drivers/mysql/mysql_z_unit_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1063,7 +1063,7 @@ func Test_Issue2552_ClearTableFieldsAll(t *testing.T) {
ctx = context.Background()
sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error {
one, err := db.Model(table).Ctx(ctx).One()
t.Assert(len(one), 5)
t.Assert(len(one), 6)
return err
})
t.AssertNil(err)
Expand All @@ -1078,7 +1078,7 @@ func Test_Issue2552_ClearTableFieldsAll(t *testing.T) {
ctx = context.Background()
sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error {
one, err := db.Model(table).Ctx(ctx).One()
t.Assert(len(one), 4)
t.Assert(len(one), 5)
return err
})
t.AssertNil(err)
Expand Down Expand Up @@ -1109,7 +1109,7 @@ func Test_Issue2552_ClearTableFields(t *testing.T) {
ctx = context.Background()
sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error {
one, err := db.Model(table).Ctx(ctx).One()
t.Assert(len(one), 5)
t.Assert(len(one), 6)
return err
})
t.AssertNil(err)
Expand All @@ -1124,7 +1124,7 @@ func Test_Issue2552_ClearTableFields(t *testing.T) {
ctx = context.Background()
sqlArray, err = gdb.CatchSQL(ctx, func(ctx context.Context) error {
one, err := db.Model(table).Ctx(ctx).One()
t.Assert(len(one), 4)
t.Assert(len(one), 5)
return err
})
t.AssertNil(err)
Expand Down
19 changes: 10 additions & 9 deletions contrib/drivers/mysql/mysql_z_unit_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2335,7 +2335,7 @@ func Test_Model_FieldsEx(t *testing.T) {
r, err := db.Model(table).FieldsEx("create_time, 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)
t.Assert(len(r[0]), 4)
t.Assert(r[0]["id"], "")
t.Assert(r[0]["passport"], "user_1")
t.Assert(r[0]["password"], "pass_1")
Expand Down Expand Up @@ -2982,7 +2982,7 @@ func Test_Model_FieldsEx_AutoMapping(t *testing.T) {
"CreateTime": 1,
}).Where("id", 2).One()
t.AssertNil(err)
t.Assert(len(one), 2)
t.Assert(len(one), 3)
t.Assert(one["id"], 2)
t.Assert(one["nickname"], "name_2")
})
Expand All @@ -2999,7 +2999,7 @@ func Test_Model_FieldsEx_AutoMapping(t *testing.T) {
CreateTime: 0,
}).Where("id", 2).One()
t.AssertNil(err)
t.Assert(len(one), 2)
t.Assert(len(one), 3)
t.Assert(one["id"], 2)
t.Assert(one["nickname"], "name_2")
})
Expand Down Expand Up @@ -3157,8 +3157,8 @@ func Test_TimeZoneInsert(t *testing.T) {
gtest.AssertNil(err)

CreateTime := "2020-11-22 12:23:45"
UpdateTime := "2020-11-22 13:23:45"
DeleteTime := "2020-11-22 14:23:45"
UpdateTime := "2020-11-22 13:23:46"
DeleteTime := "2020-11-22 14:23:47"
type User struct {
Id int `json:"id"`
CreatedAt *gtime.Time `json:"created_at"`
Expand All @@ -3176,13 +3176,14 @@ func Test_TimeZoneInsert(t *testing.T) {
}

gtest.C(t, func(t *gtest.T) {
_, _ = db.Model(tableName).Unscoped().Insert(u)
_, err = db.Model(tableName).Unscoped().Insert(u)
t.AssertNil(err)
userEntity := &User{}
err := db.Model(tableName).Where("id", 1).Unscoped().Scan(&userEntity)
err = db.Model(tableName).Where("id", 1).Unscoped().Scan(&userEntity)
t.AssertNil(err)
t.Assert(userEntity.CreatedAt.String(), "2020-11-22 11:23:45")
t.Assert(userEntity.UpdatedAt.String(), "2020-11-22 12:23:45")
t.Assert(gtime.NewFromTime(userEntity.DeletedAt).String(), "2020-11-22 13:23:45")
t.Assert(userEntity.UpdatedAt.String(), "2020-11-22 12:23:46")
t.Assert(gtime.NewFromTime(userEntity.DeletedAt).String(), "2020-11-22 13:23:47")
})
}

Expand Down
2 changes: 2 additions & 0 deletions database/gdb/gdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ type LocalType string
const (
LocalTypeUndefined LocalType = ""
LocalTypeString LocalType = "string"
LocalTypeTime LocalType = "time"
LocalTypeDate LocalType = "date"
LocalTypeDatetime LocalType = "datetime"
LocalTypeInt LocalType = "int"
Expand Down Expand Up @@ -492,6 +493,7 @@ const (
fieldTypeBool = "bool"
fieldTypeBit = "bit"
fieldTypeDate = "date"
fieldTypeTime = "time"
fieldTypeDatetime = "datetime"
fieldTypeTimestamp = "timestamp"
fieldTypeTimestampz = "timestamptz"
Expand Down
46 changes: 41 additions & 5 deletions database/gdb/gdb_core_structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,18 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field
err error
convertedValue = fieldValue
)
switch fieldValue.(type) {
case time.Time, *time.Time, gtime.Time, *gtime.Time:
goto Default
}
// If `value` implements interface `driver.Valuer`, it then uses the interface for value converting.
if valuer, ok := fieldValue.(driver.Valuer); ok {
if convertedValue, err = valuer.Value(); err != nil {
return nil, err
}
return convertedValue, nil
}
Default:
// Default value converting.
var (
rvValue = reflect.ValueOf(fieldValue)
Expand All @@ -100,6 +105,9 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field
rvKind = rvValue.Kind()
}
switch rvKind {
case reflect.Invalid:
convertedValue = nil

case reflect.Slice, reflect.Array, reflect.Map:
// It should ignore the bytes type.
if _, ok := fieldValue.([]byte); !ok {
Expand All @@ -109,33 +117,50 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field
return nil, err
}
}

case reflect.Struct:
switch r := fieldValue.(type) {
// If the time is zero, it then updates it to nil,
// which will insert/update the value to database as "null".
case time.Time:
if r.IsZero() {
convertedValue = nil
} else if fieldType == fieldTypeDate {
convertedValue = r.Format("2006-01-02")
} else if fieldType == fieldTypeTime {
convertedValue = r.Format("15:04:05")
}

case *time.Time:
if r == nil {
// Nothing to do.
} else if fieldType == fieldTypeDate {
convertedValue = r.Format("2006-01-02")
} else if fieldType == fieldTypeTime {
convertedValue = r.Format("15:04:05")
}

case gtime.Time:
if r.IsZero() {
convertedValue = nil
} else if fieldType == fieldTypeDate {
convertedValue = r.Layout("2006-01-02")
} else if fieldType == fieldTypeTime {
convertedValue = r.Layout("15:04:05")
} else {
convertedValue = r.Time
}

case *gtime.Time:
if r.IsZero() {
convertedValue = nil
} else if fieldType == fieldTypeDate {
convertedValue = r.Layout("2006-01-02")
} else if fieldType == fieldTypeTime {
convertedValue = r.Layout("15:04:05")
} else {
convertedValue = r.Time
}

case *time.Time:
// Nothing to do.

case Counter, *Counter:
// Nothing to do.

Expand All @@ -157,6 +182,7 @@ func (c *Core) ConvertValueForField(ctx context.Context, fieldType string, field
}
}
}

return convertedValue, nil
}

Expand Down Expand Up @@ -247,6 +273,10 @@ func (c *Core) CheckLocalTypeForField(ctx context.Context, fieldType string, fie
fieldTypeDate:
return LocalTypeDate, nil

case
fieldTypeTime:
return LocalTypeTime, nil

case
fieldTypeDatetime,
fieldTypeTimestamp,
Expand Down Expand Up @@ -353,13 +383,19 @@ func (c *Core) ConvertValueForLocal(
return gconv.Bool(fieldValue), nil

case LocalTypeDate:
// Date without time.
if t, ok := fieldValue.(time.Time); ok {
return gtime.NewFromTime(t).Format("Y-m-d"), nil
}
t, _ := gtime.StrToTime(gconv.String(fieldValue))
return t.Format("Y-m-d"), nil

case LocalTypeTime:
if t, ok := fieldValue.(time.Time); ok {
return gtime.NewFromTime(t).Format("H:i:s"), nil
}
t, _ := gtime.StrToTime(gconv.String(fieldValue))
return t.Format("H:i:s"), nil

case LocalTypeDatetime:
if t, ok := fieldValue.(time.Time); ok {
return gtime.NewFromTime(t), nil
Expand Down
Loading

0 comments on commit 247243c

Please sign in to comment.