Skip to content
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
36 changes: 29 additions & 7 deletions field/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ const (
AutoUpdateTime = "autoUpdateTime"
)

var (
timeType = reflect.TypeOf(time.Time{})
)

func ParseFields[T any](doc T) []*Filed {
docType := reflect.TypeOf(doc)
if docType == nil {
Expand Down Expand Up @@ -80,10 +84,14 @@ func ParseFields[T any](doc T) []*Filed {

fd.MongoField = getMongoField(bsonTag, structField.Name)

if structField.Name == CreatedAt && structField.Type == reflect.TypeOf(time.Time{}) {
fd.AutoCreateTime = UnixTime
} else if structField.Name == UpdatedAt && structField.Type == reflect.TypeOf(time.Time{}) {
fd.AutoUpdateTime = UnixTime
if structField.Name == CreatedAt {
parseDefaultTimeType(structField, fd, func(timeType TimeType) {
fd.AutoCreateTime = timeType
})
} else if structField.Name == UpdatedAt {
parseDefaultTimeType(structField, fd, func(timeType TimeType) {
fd.AutoUpdateTime = timeType
})
} else {
tag := structField.Tag.Get("mongox")
if tag != "" {
Expand All @@ -96,6 +104,18 @@ func ParseFields[T any](doc T) []*Filed {
return fields
}

func parseDefaultTimeType(structField reflect.StructField, fd *Filed, set func(timeType TimeType)) {
switch structField.Type.Kind() {
case reflect.Struct:
if structField.Type == timeType {
set(UnixTime)
}
case reflect.Int64, reflect.Int:
set(UnixSecond)
default:
}
}

func getMongoField(bsonTag string, defaultValue string) string {
if bsonTag == "" {
return defaultValue
Expand Down Expand Up @@ -125,13 +145,15 @@ func parseTimeType(tag string) TimeType {
if strings.Contains(tag, ":") {
timeType := strings.Split(tag, ":")[1]
switch timeType {
case "second":
return UnixSecond
case "milli":
return UnixMillisecond
case "nano":
return UnixNanosecond
case "second":
return UnixSecond
default:
return 0
}
}
return 0
return UnixSecond
}
46 changes: 44 additions & 2 deletions field/field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ func TestParseFields(t *testing.T) {
doc: struct {
model `bson:",inline"`
Name string `bson:"name"`
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime:second"`
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime:second"`
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime"`
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime"`
CreateMilliTime int64 `bson:"create_milli_time" mongox:"autoCreateTime:milli"`
UpdateMilliTime int64 `bson:"update_milli_time" mongox:"autoUpdateTime:milli"`
CreateNanoTime int64 `bson:"create_nano_time" mongox:"autoCreateTime:nano"`
Expand Down Expand Up @@ -239,6 +239,48 @@ func TestParseFields(t *testing.T) {
},
},
},
{
name: "Not time.Time type for default time field",
doc: struct {
CreatedAt int64 `bson:"created_at"`
UpdatedAt int `bson:"updated_at"`
}{},
want: []*Filed{
{
Name: "CreatedAt",
MongoField: "created_at",
FieldType: reflect.TypeOf(int64(0)),
AutoCreateTime: UnixSecond,
},
{
Name: "UpdatedAt",
MongoField: "updated_at",
FieldType: reflect.TypeOf(0),
AutoUpdateTime: UnixSecond,
},
},
},
{
name: "invalid type 4 default time field",
doc: struct {
CreatedAt string `bson:"created_at"`
UpdatedAt bool `bson:"updated_at"`
}{},
want: []*Filed{
{
Name: "CreatedAt",
MongoField: "created_at",
FieldType: reflect.TypeOf(""),
AutoCreateTime: 0,
},
{
Name: "UpdatedAt",
MongoField: "updated_at",
FieldType: reflect.TypeOf(false),
AutoUpdateTime: 0,
},
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
Expand Down
6 changes: 3 additions & 3 deletions internal/hook/field/field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type user struct {
UpdatedAt time.Time `bson:"updated_at"`
DeletedAt time.Time `bson:"deleted_at,omitempty"`
Name string `bson:"name"`
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime:second"`
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime"`
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime:second"`
CreateMilliTime int64 `bson:"create_milli_time" mongox:"autoCreateTime:milli"`
UpdateMilliTime int64 `bson:"update_milli_time" mongox:"autoUpdateTime:milli"`
Expand All @@ -64,7 +64,7 @@ type updatedUser struct {
UpdatedAt time.Time `bson:"updated_at"`
DeletedAt time.Time `bson:"deleted_at,omitempty"`
Name string `bson:"name"`
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime:second"`
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime"`
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime:second"`
CreateMilliTime int64 `bson:"create_milli_time" mongox:"autoCreateTime:milli"`
UpdateMilliTime int64 `bson:"update_milli_time" mongox:"autoUpdateTime:milli"`
Expand All @@ -76,7 +76,7 @@ type updatedUser struct {
type inlinedUpdatedUser struct {
updatedModel `bson:",inline"`
Name string `bson:"name"`
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime:second"`
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime"`
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime:second"`
CreateMilliTime int64 `bson:"create_milli_time" mongox:"autoCreateTime:milli"`
UpdateMilliTime int64 `bson:"update_milli_time" mongox:"autoUpdateTime:milli"`
Expand Down
46 changes: 30 additions & 16 deletions internal/hook/field/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,19 @@ func beforeInsert(dest any, currentTime time.Time, fields []*field.Filed, _ ...a

func processFields4Insert(dest reflect.Value, currentTime time.Time, fields []*field.Filed) error {
for idx, fd := range fields {
value := dest.Field(idx)
if fd.InlinedFields != nil {
err := processFields4Insert(dest.Field(idx), currentTime, fd.InlinedFields)
err := processFields4Insert(value, currentTime, fd.InlinedFields)
if err != nil {
return err
}
} else {
if fd.AutoID {
dest.Field(idx).Set(reflect.ValueOf(bson.NewObjectID()))
if value.IsZero() {
value.Set(reflect.ValueOf(bson.NewObjectID()))
}
} else {
handleTimeField(dest.Field(idx), fd, currentTime)
handleTimeField(value, fd, currentTime)
}
}
}
Expand All @@ -62,19 +65,27 @@ func processFields4Insert(dest reflect.Value, currentTime time.Time, fields []*f
func handleTimeField(dest reflect.Value, fd *field.Filed, currentTime time.Time) {
switch {
case fd.AutoCreateTime != 0:
setTimeField(dest, fd.AutoCreateTime, currentTime)
setTimeField(dest, fd.AutoCreateTime, currentTime, fd.FieldType)
case fd.AutoUpdateTime != 0:
setTimeField(dest, fd.AutoUpdateTime, currentTime)
setTimeField(dest, fd.AutoUpdateTime, currentTime, fd.FieldType)
}
}

// 设置具体的时间值
func setTimeField(dest reflect.Value, timeType field.TimeType, currentTime time.Time) {
func setTimeField(dest reflect.Value, timeType field.TimeType, currentTime time.Time, fieldType reflect.Type) {
if !dest.IsZero() {
return
}
switch timeType {
case field.UnixTime:
dest.Set(reflect.ValueOf(currentTime))
case field.UnixSecond:
dest.Set(reflect.ValueOf(currentTime.Unix()))
switch fieldType.Kind() {
case reflect.Int:
dest.Set(reflect.ValueOf(int(currentTime.Unix())))
default:
dest.Set(reflect.ValueOf(currentTime.Unix()))
}
case field.UnixMillisecond:
dest.Set(reflect.ValueOf(currentTime.UnixMilli()))
case field.UnixNanosecond:
Expand All @@ -96,7 +107,9 @@ func beforeUpdate(dest any, currentTime time.Time, fields []*field.Filed, _ ...a
updatedFields := findAdditionalFields(currentTime, fields, findUpdatedFields)

for k, v := range updatedFields {
setFields[k] = v
if _, exit := setFields[k]; !exit {
setFields[k] = v
}
}

return nil
Expand All @@ -115,7 +128,9 @@ func beforeUpsert(dest any, currentTime time.Time, fields []*field.Filed, _ ...a
updatedTimes := findAdditionalFields(currentTime, fields, findUpdatedFields)

for k, v := range updatedTimes {
setFields[k] = v
if _, exit := setFields[k]; !exit {
setFields[k] = v
}
}

idAndCreateFields := findAdditionalFields(currentTime, fields, findUpsertFields)
Expand All @@ -124,13 +139,12 @@ func beforeUpsert(dest any, currentTime time.Time, fields []*field.Filed, _ ...a
updates["$setOnInsert"] = bson.M{}
}

setOnInsertFields, ok := updates["$setOnInsert"].(bson.M)
if !ok {
return nil
}

for k, v := range idAndCreateFields {
setOnInsertFields[k] = v
if setOnInsertFields, ok := updates["$setOnInsert"].(bson.M); ok {
for k, v := range idAndCreateFields {
if _, exit := setOnInsertFields[k]; !exit {
setOnInsertFields[k] = v
}
}
}
}

Expand Down
Loading
Loading