Skip to content

Commit e681e67

Browse files
refactor the internal field hook and restore model hook (#81)
1 parent 228af5b commit e681e67

File tree

8 files changed

+959
-33
lines changed

8 files changed

+959
-33
lines changed

field/field.go

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ const (
5252
AutoUpdateTime = "autoUpdateTime"
5353
)
5454

55+
var (
56+
timeType = reflect.TypeOf(time.Time{})
57+
)
58+
5559
func ParseFields[T any](doc T) []*Filed {
5660
docType := reflect.TypeOf(doc)
5761
if docType == nil {
@@ -80,10 +84,14 @@ func ParseFields[T any](doc T) []*Filed {
8084

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

83-
if structField.Name == CreatedAt && structField.Type == reflect.TypeOf(time.Time{}) {
84-
fd.AutoCreateTime = UnixTime
85-
} else if structField.Name == UpdatedAt && structField.Type == reflect.TypeOf(time.Time{}) {
86-
fd.AutoUpdateTime = UnixTime
87+
if structField.Name == CreatedAt {
88+
parseDefaultTimeType(structField, fd, func(timeType TimeType) {
89+
fd.AutoCreateTime = timeType
90+
})
91+
} else if structField.Name == UpdatedAt {
92+
parseDefaultTimeType(structField, fd, func(timeType TimeType) {
93+
fd.AutoUpdateTime = timeType
94+
})
8795
} else {
8896
tag := structField.Tag.Get("mongox")
8997
if tag != "" {
@@ -96,6 +104,18 @@ func ParseFields[T any](doc T) []*Filed {
96104
return fields
97105
}
98106

107+
func parseDefaultTimeType(structField reflect.StructField, fd *Filed, set func(timeType TimeType)) {
108+
switch structField.Type.Kind() {
109+
case reflect.Struct:
110+
if structField.Type == timeType {
111+
set(UnixTime)
112+
}
113+
case reflect.Int64, reflect.Int:
114+
set(UnixSecond)
115+
default:
116+
}
117+
}
118+
99119
func getMongoField(bsonTag string, defaultValue string) string {
100120
if bsonTag == "" {
101121
return defaultValue
@@ -125,13 +145,15 @@ func parseTimeType(tag string) TimeType {
125145
if strings.Contains(tag, ":") {
126146
timeType := strings.Split(tag, ":")[1]
127147
switch timeType {
128-
case "second":
129-
return UnixSecond
130148
case "milli":
131149
return UnixMillisecond
132150
case "nano":
133151
return UnixNanosecond
152+
case "second":
153+
return UnixSecond
154+
default:
155+
return 0
134156
}
135157
}
136-
return 0
158+
return UnixSecond
137159
}

field/field_test.go

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ func TestParseFields(t *testing.T) {
159159
doc: struct {
160160
model `bson:",inline"`
161161
Name string `bson:"name"`
162-
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime:second"`
163-
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime:second"`
162+
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime"`
163+
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime"`
164164
CreateMilliTime int64 `bson:"create_milli_time" mongox:"autoCreateTime:milli"`
165165
UpdateMilliTime int64 `bson:"update_milli_time" mongox:"autoUpdateTime:milli"`
166166
CreateNanoTime int64 `bson:"create_nano_time" mongox:"autoCreateTime:nano"`
@@ -239,6 +239,48 @@ func TestParseFields(t *testing.T) {
239239
},
240240
},
241241
},
242+
{
243+
name: "Not time.Time type for default time field",
244+
doc: struct {
245+
CreatedAt int64 `bson:"created_at"`
246+
UpdatedAt int `bson:"updated_at"`
247+
}{},
248+
want: []*Filed{
249+
{
250+
Name: "CreatedAt",
251+
MongoField: "created_at",
252+
FieldType: reflect.TypeOf(int64(0)),
253+
AutoCreateTime: UnixSecond,
254+
},
255+
{
256+
Name: "UpdatedAt",
257+
MongoField: "updated_at",
258+
FieldType: reflect.TypeOf(0),
259+
AutoUpdateTime: UnixSecond,
260+
},
261+
},
262+
},
263+
{
264+
name: "invalid type 4 default time field",
265+
doc: struct {
266+
CreatedAt string `bson:"created_at"`
267+
UpdatedAt bool `bson:"updated_at"`
268+
}{},
269+
want: []*Filed{
270+
{
271+
Name: "CreatedAt",
272+
MongoField: "created_at",
273+
FieldType: reflect.TypeOf(""),
274+
AutoCreateTime: 0,
275+
},
276+
{
277+
Name: "UpdatedAt",
278+
MongoField: "updated_at",
279+
FieldType: reflect.TypeOf(false),
280+
AutoUpdateTime: 0,
281+
},
282+
},
283+
},
242284
}
243285
for _, tc := range testCases {
244286
t.Run(tc.name, func(t *testing.T) {

internal/hook/field/field_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ type user struct {
5050
UpdatedAt time.Time `bson:"updated_at"`
5151
DeletedAt time.Time `bson:"deleted_at,omitempty"`
5252
Name string `bson:"name"`
53-
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime:second"`
53+
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime"`
5454
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime:second"`
5555
CreateMilliTime int64 `bson:"create_milli_time" mongox:"autoCreateTime:milli"`
5656
UpdateMilliTime int64 `bson:"update_milli_time" mongox:"autoUpdateTime:milli"`
@@ -64,7 +64,7 @@ type updatedUser struct {
6464
UpdatedAt time.Time `bson:"updated_at"`
6565
DeletedAt time.Time `bson:"deleted_at,omitempty"`
6666
Name string `bson:"name"`
67-
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime:second"`
67+
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime"`
6868
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime:second"`
6969
CreateMilliTime int64 `bson:"create_milli_time" mongox:"autoCreateTime:milli"`
7070
UpdateMilliTime int64 `bson:"update_milli_time" mongox:"autoUpdateTime:milli"`
@@ -76,7 +76,7 @@ type updatedUser struct {
7676
type inlinedUpdatedUser struct {
7777
updatedModel `bson:",inline"`
7878
Name string `bson:"name"`
79-
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime:second"`
79+
CreateSecondTime int64 `bson:"create_second_time" mongox:"autoCreateTime"`
8080
UpdateSecondTime int64 `bson:"update_second_time" mongox:"autoUpdateTime:second"`
8181
CreateMilliTime int64 `bson:"create_milli_time" mongox:"autoCreateTime:milli"`
8282
UpdateMilliTime int64 `bson:"update_milli_time" mongox:"autoUpdateTime:milli"`

internal/hook/field/strategy.go

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,19 @@ func beforeInsert(dest any, currentTime time.Time, fields []*field.Filed, _ ...a
4242

4343
func processFields4Insert(dest reflect.Value, currentTime time.Time, fields []*field.Filed) error {
4444
for idx, fd := range fields {
45+
value := dest.Field(idx)
4546
if fd.InlinedFields != nil {
46-
err := processFields4Insert(dest.Field(idx), currentTime, fd.InlinedFields)
47+
err := processFields4Insert(value, currentTime, fd.InlinedFields)
4748
if err != nil {
4849
return err
4950
}
5051
} else {
5152
if fd.AutoID {
52-
dest.Field(idx).Set(reflect.ValueOf(bson.NewObjectID()))
53+
if value.IsZero() {
54+
value.Set(reflect.ValueOf(bson.NewObjectID()))
55+
}
5356
} else {
54-
handleTimeField(dest.Field(idx), fd, currentTime)
57+
handleTimeField(value, fd, currentTime)
5558
}
5659
}
5760
}
@@ -62,19 +65,27 @@ func processFields4Insert(dest reflect.Value, currentTime time.Time, fields []*f
6265
func handleTimeField(dest reflect.Value, fd *field.Filed, currentTime time.Time) {
6366
switch {
6467
case fd.AutoCreateTime != 0:
65-
setTimeField(dest, fd.AutoCreateTime, currentTime)
68+
setTimeField(dest, fd.AutoCreateTime, currentTime, fd.FieldType)
6669
case fd.AutoUpdateTime != 0:
67-
setTimeField(dest, fd.AutoUpdateTime, currentTime)
70+
setTimeField(dest, fd.AutoUpdateTime, currentTime, fd.FieldType)
6871
}
6972
}
7073

7174
// 设置具体的时间值
72-
func setTimeField(dest reflect.Value, timeType field.TimeType, currentTime time.Time) {
75+
func setTimeField(dest reflect.Value, timeType field.TimeType, currentTime time.Time, fieldType reflect.Type) {
76+
if !dest.IsZero() {
77+
return
78+
}
7379
switch timeType {
7480
case field.UnixTime:
7581
dest.Set(reflect.ValueOf(currentTime))
7682
case field.UnixSecond:
77-
dest.Set(reflect.ValueOf(currentTime.Unix()))
83+
switch fieldType.Kind() {
84+
case reflect.Int:
85+
dest.Set(reflect.ValueOf(int(currentTime.Unix())))
86+
default:
87+
dest.Set(reflect.ValueOf(currentTime.Unix()))
88+
}
7889
case field.UnixMillisecond:
7990
dest.Set(reflect.ValueOf(currentTime.UnixMilli()))
8091
case field.UnixNanosecond:
@@ -96,7 +107,9 @@ func beforeUpdate(dest any, currentTime time.Time, fields []*field.Filed, _ ...a
96107
updatedFields := findAdditionalFields(currentTime, fields, findUpdatedFields)
97108

98109
for k, v := range updatedFields {
99-
setFields[k] = v
110+
if _, exit := setFields[k]; !exit {
111+
setFields[k] = v
112+
}
100113
}
101114

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

117130
for k, v := range updatedTimes {
118-
setFields[k] = v
131+
if _, exit := setFields[k]; !exit {
132+
setFields[k] = v
133+
}
119134
}
120135

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

127-
setOnInsertFields, ok := updates["$setOnInsert"].(bson.M)
128-
if !ok {
129-
return nil
130-
}
131-
132-
for k, v := range idAndCreateFields {
133-
setOnInsertFields[k] = v
142+
if setOnInsertFields, ok := updates["$setOnInsert"].(bson.M); ok {
143+
for k, v := range idAndCreateFields {
144+
if _, exit := setOnInsertFields[k]; !exit {
145+
setOnInsertFields[k] = v
146+
}
147+
}
134148
}
135149
}
136150

0 commit comments

Comments
 (0)