95e67ba2 by slene

orm now support custom builtin types as model struct field or query args fix #489

1 parent 769f7c75
...@@ -51,9 +51,16 @@ outFor: ...@@ -51,9 +51,16 @@ outFor:
51 continue 51 continue
52 } 52 }
53 53
54 switch v := arg.(type) { 54 kind := val.Kind()
55 case []byte: 55 if kind == reflect.Ptr {
56 case string: 56 val = val.Elem()
57 kind = val.Kind()
58 arg = val.Interface()
59 }
60
61 switch kind {
62 case reflect.String:
63 v := val.String()
57 if fi != nil { 64 if fi != nil {
58 if fi.fieldType == TypeDateField || fi.fieldType == TypeDateTimeField { 65 if fi.fieldType == TypeDateField || fi.fieldType == TypeDateTimeField {
59 var t time.Time 66 var t time.Time
...@@ -78,61 +85,66 @@ outFor: ...@@ -78,61 +85,66 @@ outFor:
78 } 85 }
79 } 86 }
80 arg = v 87 arg = v
81 case time.Time: 88 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
82 if fi != nil && fi.fieldType == TypeDateField { 89 arg = val.Int()
83 arg = v.In(tz).Format(format_Date) 90 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
84 } else { 91 arg = val.Uint()
85 arg = v.In(tz).Format(format_DateTime) 92 case reflect.Float32:
93 arg, _ = StrTo(ToStr(arg)).Float64()
94 case reflect.Float64:
95 arg = val.Float()
96 case reflect.Bool:
97 arg = val.Bool()
98 case reflect.Slice, reflect.Array:
99 if _, ok := arg.([]byte); ok {
100 continue outFor
86 } 101 }
87 default:
88 kind := val.Kind()
89 switch kind {
90 case reflect.Slice, reflect.Array:
91
92 var args []interface{}
93 for i := 0; i < val.Len(); i++ {
94 v := val.Index(i)
95
96 var vu interface{}
97 if v.CanInterface() {
98 vu = v.Interface()
99 }
100 102
101 if vu == nil { 103 var args []interface{}
102 continue 104 for i := 0; i < val.Len(); i++ {
103 } 105 v := val.Index(i)
104 106
105 args = append(args, vu) 107 var vu interface{}
108 if v.CanInterface() {
109 vu = v.Interface()
106 } 110 }
107 111
108 if len(args) > 0 { 112 if vu == nil {
109 p := getFlatParams(fi, args, tz) 113 continue
110 params = append(params, p...)
111 } 114 }
112 continue outFor
113 115
114 case reflect.Ptr, reflect.Struct: 116 args = append(args, vu)
115 ind := reflect.Indirect(val) 117 }
116 118
117 if ind.Kind() == reflect.Struct { 119 if len(args) > 0 {
118 typ := ind.Type() 120 p := getFlatParams(fi, args, tz)
119 name := getFullName(typ) 121 params = append(params, p...)
120 var value interface{} 122 }
121 if mmi, ok := modelCache.getByFN(name); ok { 123 continue outFor
122 if _, vu, exist := getExistPk(mmi, ind); exist { 124 case reflect.Struct:
123 value = vu 125 if v, ok := arg.(time.Time); ok {
124 } 126 if fi != nil && fi.fieldType == TypeDateField {
127 arg = v.In(tz).Format(format_Date)
128 } else {
129 arg = v.In(tz).Format(format_DateTime)
130 }
131 } else {
132 typ := val.Type()
133 name := getFullName(typ)
134 var value interface{}
135 if mmi, ok := modelCache.getByFN(name); ok {
136 if _, vu, exist := getExistPk(mmi, val); exist {
137 value = vu
125 } 138 }
126 arg = value 139 }
140 arg = value
127 141
128 if arg == nil { 142 if arg == nil {
129 panic(fmt.Errorf("need a valid args value, unknown table or value `%s`", name)) 143 panic(fmt.Errorf("need a valid args value, unknown table or value `%s`", name))
130 }
131 } else {
132 arg = ind.Interface()
133 } 144 }
134 } 145 }
135 } 146 }
147
136 params = append(params, arg) 148 params = append(params, arg)
137 } 149 }
138 return 150 return
......
...@@ -144,6 +144,45 @@ type DataNull struct { ...@@ -144,6 +144,45 @@ type DataNull struct {
144 NullInt64 sql.NullInt64 `orm:"null"` 144 NullInt64 sql.NullInt64 `orm:"null"`
145 } 145 }
146 146
147 type String string
148 type Boolean bool
149 type Byte byte
150 type Rune rune
151 type Int int
152 type Int8 int8
153 type Int16 int16
154 type Int32 int32
155 type Int64 int64
156 type Uint uint
157 type Uint8 uint8
158 type Uint16 uint16
159 type Uint32 uint32
160 type Uint64 uint64
161 type Float32 float64
162 type Float64 float64
163
164 type DataCustom struct {
165 Id int
166 Boolean Boolean
167 Char string `orm:"size(50)"`
168 Text string `orm:"type(text)"`
169 Byte Byte
170 Rune Rune
171 Int Int
172 Int8 Int8
173 Int16 Int16
174 Int32 Int32
175 Int64 Int64
176 Uint Uint
177 Uint8 Uint8
178 Uint16 Uint16
179 Uint32 Uint32
180 Uint64 Uint64
181 Float32 Float32
182 Float64 Float64
183 Decimal Float64 `orm:"digits(8);decimals(4)"`
184 }
185
147 // only for mysql 186 // only for mysql
148 type UserBig struct { 187 type UserBig struct {
149 Id uint64 188 Id uint64
......
...@@ -99,34 +99,41 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col ...@@ -99,34 +99,41 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col
99 // return field type as type constant from reflect.Value 99 // return field type as type constant from reflect.Value
100 func getFieldType(val reflect.Value) (ft int, err error) { 100 func getFieldType(val reflect.Value) (ft int, err error) {
101 elm := reflect.Indirect(val) 101 elm := reflect.Indirect(val)
102 switch elm.Interface().(type) { 102 switch elm.Kind() {
103 case int8: 103 case reflect.Int8:
104 ft = TypeBitField 104 ft = TypeBitField
105 case int16: 105 case reflect.Int16:
106 ft = TypeSmallIntegerField 106 ft = TypeSmallIntegerField
107 case int32, int: 107 case reflect.Int32, reflect.Int:
108 ft = TypeIntegerField 108 ft = TypeIntegerField
109 case int64, sql.NullInt64: 109 case reflect.Int64:
110 ft = TypeBigIntegerField 110 ft = TypeBigIntegerField
111 case uint8: 111 case reflect.Uint8:
112 ft = TypePositiveBitField 112 ft = TypePositiveBitField
113 case uint16: 113 case reflect.Uint16:
114 ft = TypePositiveSmallIntegerField 114 ft = TypePositiveSmallIntegerField
115 case uint32, uint: 115 case reflect.Uint32, reflect.Uint:
116 ft = TypePositiveIntegerField 116 ft = TypePositiveIntegerField
117 case uint64: 117 case reflect.Uint64:
118 ft = TypePositiveBigIntegerField 118 ft = TypePositiveBigIntegerField
119 case float32, float64, sql.NullFloat64: 119 case reflect.Float32, reflect.Float64:
120 ft = TypeFloatField 120 ft = TypeFloatField
121 case bool, sql.NullBool: 121 case reflect.Bool:
122 ft = TypeBooleanField 122 ft = TypeBooleanField
123 case string, sql.NullString: 123 case reflect.String:
124 ft = TypeCharField 124 ft = TypeCharField
125 default: 125 default:
126 if elm.CanInterface() { 126 switch elm.Interface().(type) {
127 if _, ok := elm.Interface().(time.Time); ok { 127 case sql.NullInt64:
128 ft = TypeDateTimeField 128 ft = TypeBigIntegerField
129 } 129 case sql.NullFloat64:
130 ft = TypeFloatField
131 case sql.NullBool:
132 ft = TypeBooleanField
133 case sql.NullString:
134 ft = TypeCharField
135 case time.Time:
136 ft = TypeDateTimeField
130 } 137 }
131 } 138 }
132 if ft&IsFieldType == 0 { 139 if ft&IsFieldType == 0 {
......
...@@ -149,7 +149,7 @@ func TestGetDB(t *testing.T) { ...@@ -149,7 +149,7 @@ func TestGetDB(t *testing.T) {
149 } 149 }
150 150
151 func TestSyncDb(t *testing.T) { 151 func TestSyncDb(t *testing.T) {
152 RegisterModel(new(Data), new(DataNull)) 152 RegisterModel(new(Data), new(DataNull), new(DataCustom))
153 RegisterModel(new(User)) 153 RegisterModel(new(User))
154 RegisterModel(new(Profile)) 154 RegisterModel(new(Profile))
155 RegisterModel(new(Post)) 155 RegisterModel(new(Post))
...@@ -165,7 +165,7 @@ func TestSyncDb(t *testing.T) { ...@@ -165,7 +165,7 @@ func TestSyncDb(t *testing.T) {
165 } 165 }
166 166
167 func TestRegisterModels(t *testing.T) { 167 func TestRegisterModels(t *testing.T) {
168 RegisterModel(new(Data), new(DataNull)) 168 RegisterModel(new(Data), new(DataNull), new(DataCustom))
169 RegisterModel(new(User)) 169 RegisterModel(new(User))
170 RegisterModel(new(Profile)) 170 RegisterModel(new(Profile))
171 RegisterModel(new(Post)) 171 RegisterModel(new(Post))
...@@ -309,6 +309,39 @@ func TestNullDataTypes(t *testing.T) { ...@@ -309,6 +309,39 @@ func TestNullDataTypes(t *testing.T) {
309 throwFail(t, AssertIs(d.NullFloat64.Float64, 42.42)) 309 throwFail(t, AssertIs(d.NullFloat64.Float64, 42.42))
310 } 310 }
311 311
312 func TestDataCustomTypes(t *testing.T) {
313 d := DataCustom{}
314 ind := reflect.Indirect(reflect.ValueOf(&d))
315
316 for name, value := range Data_Values {
317 e := ind.FieldByName(name)
318 if !e.IsValid() {
319 continue
320 }
321 e.Set(reflect.ValueOf(value).Convert(e.Type()))
322 }
323
324 id, err := dORM.Insert(&d)
325 throwFail(t, err)
326 throwFail(t, AssertIs(id, 1))
327
328 d = DataCustom{Id: 1}
329 err = dORM.Read(&d)
330 throwFail(t, err)
331
332 ind = reflect.Indirect(reflect.ValueOf(&d))
333
334 for name, value := range Data_Values {
335 e := ind.FieldByName(name)
336 if !e.IsValid() {
337 continue
338 }
339 vu := e.Interface()
340 value = reflect.ValueOf(value).Convert(e.Type()).Interface()
341 throwFail(t, AssertIs(vu == value, true), value, vu)
342 }
343 }
344
312 func TestCRUD(t *testing.T) { 345 func TestCRUD(t *testing.T) {
313 profile := NewProfile() 346 profile := NewProfile()
314 profile.Age = 30 347 profile.Age = 30
...@@ -562,6 +595,10 @@ func TestOperators(t *testing.T) { ...@@ -562,6 +595,10 @@ func TestOperators(t *testing.T) {
562 throwFail(t, err) 595 throwFail(t, err)
563 throwFail(t, AssertIs(num, 1)) 596 throwFail(t, AssertIs(num, 1))
564 597
598 num, err = qs.Filter("user_name__exact", String("slene")).Count()
599 throwFail(t, err)
600 throwFail(t, AssertIs(num, 1))
601
565 num, err = qs.Filter("user_name__exact", "slene").Count() 602 num, err = qs.Filter("user_name__exact", "slene").Count()
566 throwFail(t, err) 603 throwFail(t, err)
567 throwFail(t, AssertIs(num, 1)) 604 throwFail(t, AssertIs(num, 1))
...@@ -602,11 +639,11 @@ func TestOperators(t *testing.T) { ...@@ -602,11 +639,11 @@ func TestOperators(t *testing.T) {
602 throwFail(t, err) 639 throwFail(t, err)
603 throwFail(t, AssertIs(num, 3)) 640 throwFail(t, AssertIs(num, 3))
604 641
605 num, err = qs.Filter("status__lt", 3).Count() 642 num, err = qs.Filter("status__lt", Uint(3)).Count()
606 throwFail(t, err) 643 throwFail(t, err)
607 throwFail(t, AssertIs(num, 2)) 644 throwFail(t, AssertIs(num, 2))
608 645
609 num, err = qs.Filter("status__lte", 3).Count() 646 num, err = qs.Filter("status__lte", Int(3)).Count()
610 throwFail(t, err) 647 throwFail(t, err)
611 throwFail(t, AssertIs(num, 3)) 648 throwFail(t, AssertIs(num, 3))
612 649
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!