f2b359d8 by slene

orm full remove orm.Manager for simple use, add struct tag `-` for skip struct field

1 parent 402932aa
...@@ -33,7 +33,6 @@ import ( ...@@ -33,7 +33,6 @@ import (
33 type User struct { 33 type User struct {
34 Id int `orm:"auto"` 34 Id int `orm:"auto"`
35 Name string `orm:"size(100)"` 35 Name string `orm:"size(100)"`
36 orm.Manager
37 } 36 }
38 37
39 func init() { 38 func init() {
...@@ -72,7 +71,6 @@ type Post struct { ...@@ -72,7 +71,6 @@ type Post struct {
72 Id int `orm:"auto"` 71 Id int `orm:"auto"`
73 Title string `orm:"size(100)"` 72 Title string `orm:"size(100)"`
74 User *User `orm:"rel(fk)"` 73 User *User `orm:"rel(fk)"`
75 orm.Manager
76 } 74 }
77 75
78 var posts []*Post 76 var posts []*Post
......
...@@ -582,8 +582,6 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value) error { ...@@ -582,8 +582,6 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value) error {
582 return err 582 return err
583 } else { 583 } else {
584 elm := reflect.New(mi.addrField.Elem().Type()) 584 elm := reflect.New(mi.addrField.Elem().Type())
585 md := elm.Interface().(Modeler)
586 md.Init(md)
587 mind := reflect.Indirect(elm) 585 mind := reflect.Indirect(elm)
588 586
589 d.setColsValues(mi, &mind, mi.fields.dbcols, refs) 587 d.setColsValues(mi, &mind, mi.fields.dbcols, refs)
...@@ -803,25 +801,27 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi ...@@ -803,25 +801,27 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
803 801
804 val := reflect.ValueOf(container) 802 val := reflect.ValueOf(container)
805 ind := reflect.Indirect(val) 803 ind := reflect.Indirect(val)
806 typ := ind.Type()
807 804
808 errTyp := true 805 errTyp := true
809 806
810 one := true 807 one := true
811 808
812 if val.Kind() == reflect.Ptr { 809 if val.Kind() == reflect.Ptr {
813 tp := typ 810 fn := ""
814 if ind.Kind() == reflect.Slice { 811 if ind.Kind() == reflect.Slice {
815 one = false 812 one = false
816 if ind.Type().Elem().Kind() == reflect.Ptr { 813 if ind.Type().Elem().Kind() == reflect.Ptr {
817 tp = ind.Type().Elem().Elem() 814 typ := ind.Type().Elem().Elem()
815 fn = getFullName(typ)
818 } 816 }
817 } else {
818 fn = getFullName(ind.Type())
819 } 819 }
820 errTyp = tp.PkgPath()+"."+tp.Name() != mi.fullName 820 errTyp = fn != mi.fullName
821 } 821 }
822 822
823 if errTyp { 823 if errTyp {
824 panic(fmt.Sprintf("wrong object type `%s` for rows scan, need *[]*%s or *%s", val.Type(), mi.fullName, mi.fullName)) 824 panic(fmt.Sprintf("wrong object type `%s` for rows scan, need *[]*%s or *%s", ind.Type(), mi.fullName, mi.fullName))
825 } 825 }
826 826
827 rlimit := qs.limit 827 rlimit := qs.limit
...@@ -873,8 +873,6 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi ...@@ -873,8 +873,6 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
873 } 873 }
874 874
875 elm := reflect.New(mi.addrField.Elem().Type()) 875 elm := reflect.New(mi.addrField.Elem().Type())
876 md := elm.Interface().(Modeler)
877 md.Init(md)
878 mind := reflect.Indirect(elm) 876 mind := reflect.Indirect(elm)
879 877
880 cacheV := make(map[string]*reflect.Value) 878 cacheV := make(map[string]*reflect.Value)
...@@ -989,9 +987,9 @@ func (d *dbBase) getOperatorParams(operator string, args []interface{}) (params ...@@ -989,9 +987,9 @@ func (d *dbBase) getOperatorParams(operator string, args []interface{}) (params
989 987
990 if ind.Kind() == reflect.Struct { 988 if ind.Kind() == reflect.Struct {
991 typ := ind.Type() 989 typ := ind.Type()
992 fullName := typ.PkgPath() + "." + typ.Name() 990 name := getFullName(typ)
993 var value interface{} 991 var value interface{}
994 if mmi, ok := modelCache.get(fullName); ok { 992 if mmi, ok := modelCache.getByFN(name); ok {
995 if _, vu, exist := d.existPk(mmi, ind); exist { 993 if _, vu, exist := d.existPk(mmi, ind); exist {
996 value = vu 994 value = vu
997 } 995 }
...@@ -999,7 +997,7 @@ func (d *dbBase) getOperatorParams(operator string, args []interface{}) (params ...@@ -999,7 +997,7 @@ func (d *dbBase) getOperatorParams(operator string, args []interface{}) (params
999 arg = value 997 arg = value
1000 998
1001 if arg == nil { 999 if arg == nil {
1002 panic(fmt.Sprintf("`%s` operator need a valid args value, unknown table or value `%v`", operator, val.Type())) 1000 panic(fmt.Sprintf("`%s` operator need a valid args value, unknown table or value `%s`", operator, name))
1003 } 1001 }
1004 } else { 1002 } else {
1005 arg = ind.Interface() 1003 arg = ind.Interface()
...@@ -1266,8 +1264,6 @@ setValue: ...@@ -1266,8 +1264,6 @@ setValue:
1266 if value != nil { 1264 if value != nil {
1267 fieldType = fi.relModelInfo.fields.pk.fieldType 1265 fieldType = fi.relModelInfo.fields.pk.fieldType
1268 mf := reflect.New(fi.relModelInfo.addrField.Elem().Type()) 1266 mf := reflect.New(fi.relModelInfo.addrField.Elem().Type())
1269 md := mf.Interface().(Modeler)
1270 md.Init(md)
1271 field.Set(mf) 1267 field.Set(mf)
1272 f := mf.Elem().Field(fi.relModelInfo.fields.pk.fieldIndex) 1268 f := mf.Elem().Field(fi.relModelInfo.fields.pk.fieldIndex)
1273 field = &f 1269 field = &f
......
...@@ -11,6 +11,17 @@ orm:"null;rel(fk)" ...@@ -11,6 +11,17 @@ orm:"null;rel(fk)"
11 11
12 多个设置间使用 `;` 分隔,设置的值如果是多个,使用 `,` 分隔。 12 多个设置间使用 `;` 分隔,设置的值如果是多个,使用 `,` 分隔。
13 13
14 #### 忽略字段
15
16 设置 `-` 即可忽略 struct 中的字段
17
18 ```go
19 type User struct {
20 ...
21 AnyField string `orm:"-"`
22 ...
23 ```
24
14 #### auto 25 #### auto
15 26
16 设置为 Autoincrement Primary Key 27 设置为 Autoincrement Primary Key
...@@ -49,23 +60,6 @@ type User struct { ...@@ -49,23 +60,6 @@ type User struct {
49 ... 60 ...
50 Status int `orm:"default(1)"` 61 Status int `orm:"default(1)"`
51 ``` 62 ```
52 仅当进行 orm.Manager 初始化时才会赋值
53 ```go
54 func NewUser() *User {
55 obj := new(User)
56 obj.Manager.Init(obj)
57 return obj
58 }
59
60 u := NewUser()
61 fmt.Println(u.Status) // 1
62 ```
63 #### choices
64
65 为字段设置一组可选的值,类型必须符合。其他值 clean 会返回错误
66 ```go
67 Status int `orm:"choices(1,2,3,4)"`
68 ```
69 #### size (string) 63 #### size (string)
70 64
71 string 类型字段设置 size 以后,db type 将使用 varchar 65 string 类型字段设置 size 以后,db type 将使用 varchar
......
...@@ -17,14 +17,12 @@ type User struct { ...@@ -17,14 +17,12 @@ type User struct {
17 Id int `orm:"auto"` // 设置为auto主键 17 Id int `orm:"auto"` // 设置为auto主键
18 Name string 18 Name string
19 Profile *Profile `orm:"rel(one)"` // OneToOne relation 19 Profile *Profile `orm:"rel(one)"` // OneToOne relation
20 orm.Manager // 每个model都需要定义orm.Manager
21 } 20 }
22 21
23 type Profile struct { 22 type Profile struct {
24 Id int `orm:"auto"` 23 Id int `orm:"auto"`
25 Age int16 24 Age int16
26 User *User `orm:"reverse(one)"` // 设置反向关系(可选) 25 User *User `orm:"reverse(one)"` // 设置反向关系(可选)
27 orm.Manager
28 } 26 }
29 27
30 func init() { 28 func init() {
......
...@@ -18,6 +18,7 @@ var ( ...@@ -18,6 +18,7 @@ var (
18 cacheByFN: make(map[string]*modelInfo), 18 cacheByFN: make(map[string]*modelInfo),
19 } 19 }
20 supportTag = map[string]int{ 20 supportTag = map[string]int{
21 "-": 1,
21 "null": 1, 22 "null": 1,
22 "blank": 1, 23 "blank": 1,
23 "index": 1, 24 "index": 1,
...@@ -27,7 +28,6 @@ var ( ...@@ -27,7 +28,6 @@ var (
27 "auto_now": 1, 28 "auto_now": 1,
28 "auto_now_add": 1, 29 "auto_now_add": 1,
29 "size": 2, 30 "size": 2,
30 "choices": 2,
31 "column": 2, 31 "column": 2,
32 "default": 2, 32 "default": 2,
33 "rel": 2, 33 "rel": 2,
...@@ -67,9 +67,11 @@ func (mc *_modelCache) allOrdered() []*modelInfo { ...@@ -67,9 +67,11 @@ func (mc *_modelCache) allOrdered() []*modelInfo {
67 67
68 func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) { 68 func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) {
69 mi, ok = mc.cache[table] 69 mi, ok = mc.cache[table]
70 if ok == false { 70 return
71 mi, ok = mc.cacheByFN[table] 71 }
72 } 72
73 func (mc *_modelCache) getByFN(name string) (mi *modelInfo, ok bool) {
74 mi, ok = mc.cacheByFN[name]
73 return 75 return
74 } 76 }
75 77
......
...@@ -8,20 +8,36 @@ import ( ...@@ -8,20 +8,36 @@ import (
8 "strings" 8 "strings"
9 ) 9 )
10 10
11 func registerModel(model Modeler) { 11 func registerModel(model interface{}) {
12 info := newModelInfo(model) 12 val := reflect.ValueOf(model)
13 model.Init(model) 13 ind := reflect.Indirect(val)
14 table := model.GetTableName() 14 typ := ind.Type()
15
16 if val.Kind() != reflect.Ptr {
17 panic(fmt.Sprintf("<orm.RegisterModel> cannot use non-ptr model struct `%s`", getFullName(typ)))
18 }
19
20 info := newModelInfo(val)
21
22 name := getFullName(typ)
23 if _, ok := modelCache.getByFN(name); ok {
24 fmt.Printf("<orm.RegisterModel> model `%s` redeclared, must be unique\n", name)
25 os.Exit(2)
26 }
27
28 table := getTableName(val)
15 if _, ok := modelCache.get(table); ok { 29 if _, ok := modelCache.get(table); ok {
16 fmt.Printf("model <%T> redeclared, must be unique\n", model) 30 fmt.Printf("<orm.RegisterModel> table name `%s` redeclared, must be unique\n", table)
17 os.Exit(2) 31 os.Exit(2)
18 } 32 }
33
19 if info.fields.pk == nil { 34 if info.fields.pk == nil {
20 fmt.Printf("model <%T> need a primary key field\n", model) 35 fmt.Printf("<orm.RegisterModel> `%s` need a primary key field\n", name)
21 os.Exit(2) 36 os.Exit(2)
22 } 37 }
38
23 info.table = table 39 info.table = table
24 info.pkg = getPkgPath(model) 40 info.pkg = typ.PkgPath()
25 info.model = model 41 info.model = model
26 info.manual = true 42 info.manual = true
27 modelCache.set(table, info) 43 modelCache.set(table, info)
...@@ -52,8 +68,8 @@ func bootStrap() { ...@@ -52,8 +68,8 @@ func bootStrap() {
52 elm = elm.Elem() 68 elm = elm.Elem()
53 } 69 }
54 70
55 tn := getTableName(reflect.New(elm).Interface().(Modeler)) 71 name := getFullName(elm)
56 mii, ok := modelCache.get(tn) 72 mii, ok := modelCache.getByFN(name)
57 if ok == false || mii.pkg != elm.PkgPath() { 73 if ok == false || mii.pkg != elm.PkgPath() {
58 err = fmt.Errorf("can not found rel in field `%s`, `%s` may be miss register", fi.fullName, elm.String()) 74 err = fmt.Errorf("can not found rel in field `%s`, `%s` may be miss register", fi.fullName, elm.String())
59 goto end 75 goto end
...@@ -202,7 +218,7 @@ end: ...@@ -202,7 +218,7 @@ end:
202 } 218 }
203 } 219 }
204 220
205 func RegisterModel(models ...Modeler) { 221 func RegisterModel(models ...interface{}) {
206 if modelCache.done { 222 if modelCache.done {
207 panic(fmt.Errorf("RegisterModel must be run begore BootStrap")) 223 panic(fmt.Errorf("RegisterModel must be run begore BootStrap"))
208 } 224 }
......
...@@ -7,30 +7,7 @@ import ( ...@@ -7,30 +7,7 @@ import (
7 "strings" 7 "strings"
8 ) 8 )
9 9
10 type fieldChoices []StrTo 10 var errSkipField = errors.New("skip field")
11
12 func (f *fieldChoices) Add(s StrTo) {
13 if f.Have(s) == false {
14 *f = append(*f, s)
15 }
16 }
17
18 func (f *fieldChoices) Clear() {
19 *f = fieldChoices([]StrTo{})
20 }
21
22 func (f *fieldChoices) Have(s StrTo) bool {
23 for _, v := range *f {
24 if v == s {
25 return true
26 }
27 }
28 return false
29 }
30
31 func (f *fieldChoices) Clone() fieldChoices {
32 return *f
33 }
34 11
35 type fields struct { 12 type fields struct {
36 pk *fieldInfo 13 pk *fieldInfo
...@@ -111,7 +88,7 @@ type fieldInfo struct { ...@@ -111,7 +88,7 @@ type fieldInfo struct {
111 name string 88 name string
112 fullName string 89 fullName string
113 column string 90 column string
114 addrValue *reflect.Value 91 addrValue reflect.Value
115 sf *reflect.StructField 92 sf *reflect.StructField
116 auto bool 93 auto bool
117 pk bool 94 pk bool
...@@ -120,7 +97,6 @@ type fieldInfo struct { ...@@ -120,7 +97,6 @@ type fieldInfo struct {
120 index bool 97 index bool
121 unique bool 98 unique bool
122 initial StrTo 99 initial StrTo
123 choices fieldChoices
124 size int 100 size int
125 auto_now bool 101 auto_now bool
126 auto_now_add bool 102 auto_now_add bool
...@@ -142,13 +118,10 @@ func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField) (f ...@@ -142,13 +118,10 @@ func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField) (f
142 var ( 118 var (
143 tag string 119 tag string
144 tagValue string 120 tagValue string
145 choices fieldChoices
146 values fieldChoices
147 initial StrTo 121 initial StrTo
148 fieldType int 122 fieldType int
149 attrs map[string]bool 123 attrs map[string]bool
150 tags map[string]string 124 tags map[string]string
151 parts []string
152 addrField reflect.Value 125 addrField reflect.Value
153 ) 126 )
154 127
...@@ -162,11 +135,20 @@ func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField) (f ...@@ -162,11 +135,20 @@ func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField) (f
162 135
163 parseStructTag(sf.Tag.Get(defaultStructTagName), &attrs, &tags) 136 parseStructTag(sf.Tag.Get(defaultStructTagName), &attrs, &tags)
164 137
138 if _, ok := attrs["-"]; ok {
139 return nil, errSkipField
140 }
141
165 digits := tags["digits"] 142 digits := tags["digits"]
166 decimals := tags["decimals"] 143 decimals := tags["decimals"]
167 size := tags["size"] 144 size := tags["size"]
168 onDelete := tags["on_delete"] 145 onDelete := tags["on_delete"]
169 146
147 initial.Clear()
148 if v, ok := tags["default"]; ok {
149 initial.Set(v)
150 }
151
170 checkType: 152 checkType:
171 switch f := addrField.Interface().(type) { 153 switch f := addrField.Interface().(type) {
172 case Fielder: 154 case Fielder:
...@@ -237,10 +219,6 @@ checkType: ...@@ -237,10 +219,6 @@ checkType:
237 219
238 switch fieldType { 220 switch fieldType {
239 case RelForeignKey, RelOneToOne, RelReverseOne: 221 case RelForeignKey, RelOneToOne, RelReverseOne:
240 if _, ok := addrField.Interface().(Modeler); ok == false {
241 err = fmt.Errorf("rel/reverse:one field must be implements Modeler")
242 goto end
243 }
244 if field.Kind() != reflect.Ptr { 222 if field.Kind() != reflect.Ptr {
245 err = fmt.Errorf("rel/reverse:one field must be *%s", field.Type().Name()) 223 err = fmt.Errorf("rel/reverse:one field must be *%s", field.Type().Name())
246 goto end 224 goto end
...@@ -254,10 +232,6 @@ checkType: ...@@ -254,10 +232,6 @@ checkType:
254 err = fmt.Errorf("rel/reverse:many slice must be []*%s", field.Type().Elem().Name()) 232 err = fmt.Errorf("rel/reverse:many slice must be []*%s", field.Type().Elem().Name())
255 goto end 233 goto end
256 } 234 }
257 if _, ok := reflect.New(field.Type().Elem()).Elem().Interface().(Modeler); ok == false {
258 err = fmt.Errorf("rel/reverse:many slice element must be implements Modeler")
259 goto end
260 }
261 } 235 }
262 } 236 }
263 237
...@@ -269,7 +243,7 @@ checkType: ...@@ -269,7 +243,7 @@ checkType:
269 fi.fieldType = fieldType 243 fi.fieldType = fieldType
270 fi.name = sf.Name 244 fi.name = sf.Name
271 fi.column = getColumnName(fieldType, addrField, sf, tags["column"]) 245 fi.column = getColumnName(fieldType, addrField, sf, tags["column"])
272 fi.addrValue = &addrField 246 fi.addrValue = addrField
273 fi.sf = &sf 247 fi.sf = &sf
274 fi.fullName = mi.fullName + "." + sf.Name 248 fi.fullName = mi.fullName + "." + sf.Name
275 249
...@@ -306,7 +280,7 @@ checkType: ...@@ -306,7 +280,7 @@ checkType:
306 switch onDelete { 280 switch onDelete {
307 case od_CASCADE, od_DO_NOTHING: 281 case od_CASCADE, od_DO_NOTHING:
308 case od_SET_DEFAULT: 282 case od_SET_DEFAULT:
309 if tags["default"] == "" { 283 if initial.Exist() == false {
310 err = errors.New("on_delete: set_default need set field a default value") 284 err = errors.New("on_delete: set_default need set field a default value")
311 goto end 285 goto end
312 } 286 }
...@@ -397,31 +371,13 @@ checkType: ...@@ -397,31 +371,13 @@ checkType:
397 fi.index = false 371 fi.index = false
398 } 372 }
399 373
400 parts = strings.Split(tags["choices"], ",")
401 if len(parts) > 1 {
402 for _, v := range parts {
403 choices.Add(StrTo(strings.TrimSpace(v)))
404 }
405 }
406
407 initial.Clear()
408 if v, ok := tags["default"]; ok {
409 initial.Set(v)
410 }
411
412 if fi.auto || fi.pk || fi.unique || fieldType == TypeDateField || fieldType == TypeDateTimeField { 374 if fi.auto || fi.pk || fi.unique || fieldType == TypeDateField || fieldType == TypeDateTimeField {
413 // can not set default 375 // can not set default
414 choices.Clear()
415 initial.Clear() 376 initial.Clear()
416 } 377 }
417 378
418 values = choices.Clone()
419
420 if initial.Exist() { 379 if initial.Exist() {
421 values.Add(initial) 380 v := initial
422 }
423
424 for i, v := range values {
425 switch fieldType { 381 switch fieldType {
426 case TypeBooleanField: 382 case TypeBooleanField:
427 _, err = v.Bool() 383 _, err = v.Bool()
...@@ -441,23 +397,11 @@ checkType: ...@@ -441,23 +397,11 @@ checkType:
441 _, err = v.Uint64() 397 _, err = v.Uint64()
442 } 398 }
443 if err != nil { 399 if err != nil {
444 if initial.Exist() && len(values) == i {
445 tag, tagValue = "default", tags["default"] 400 tag, tagValue = "default", tags["default"]
446 } else {
447 tag, tagValue = "choices", tags["choices"]
448 }
449 goto wrongTag 401 goto wrongTag
450 } 402 }
451 } 403 }
452 404
453 if len(choices) > 0 && initial.Exist() {
454 if choices.Have(initial) == false {
455 err = fmt.Errorf("default value `%s` not in choices `%s`", tags["default"], tags["choices"])
456 goto end
457 }
458 }
459
460 fi.choices = choices
461 fi.initial = initial 405 fi.initial = initial
462 end: 406 end:
463 if err != nil { 407 if err != nil {
......
...@@ -12,13 +12,13 @@ type modelInfo struct { ...@@ -12,13 +12,13 @@ type modelInfo struct {
12 name string 12 name string
13 fullName string 13 fullName string
14 table string 14 table string
15 model Modeler 15 model interface{}
16 fields *fields 16 fields *fields
17 manual bool 17 manual bool
18 addrField reflect.Value 18 addrField reflect.Value
19 } 19 }
20 20
21 func newModelInfo(model Modeler) (info *modelInfo) { 21 func newModelInfo(val reflect.Value) (info *modelInfo) {
22 var ( 22 var (
23 err error 23 err error
24 fi *fieldInfo 24 fi *fieldInfo
...@@ -28,26 +28,24 @@ func newModelInfo(model Modeler) (info *modelInfo) { ...@@ -28,26 +28,24 @@ func newModelInfo(model Modeler) (info *modelInfo) {
28 info = &modelInfo{} 28 info = &modelInfo{}
29 info.fields = newFields() 29 info.fields = newFields()
30 30
31 val := reflect.ValueOf(model)
32 ind := reflect.Indirect(val) 31 ind := reflect.Indirect(val)
33 typ := ind.Type() 32 typ := ind.Type()
34 33
35 info.addrField = ind.Addr() 34 info.addrField = ind.Addr()
36 35
37 info.name = typ.Name() 36 info.name = typ.Name()
38 info.fullName = typ.PkgPath() + "." + typ.Name() 37 info.fullName = getFullName(typ)
39 38
40 for i := 0; i < ind.NumField(); i++ { 39 for i := 0; i < ind.NumField(); i++ {
41 field := ind.Field(i) 40 field := ind.Field(i)
42 sf = ind.Type().Field(i) 41 sf = ind.Type().Field(i)
43 if field.CanAddr() {
44 addr := field.Addr()
45 if _, ok := addr.Interface().(*Manager); ok {
46 continue
47 }
48 }
49 fi, err = newFieldInfo(info, field, sf) 42 fi, err = newFieldInfo(info, field, sf)
43
50 if err != nil { 44 if err != nil {
45 if err == errSkipField {
46 err = nil
47 continue
48 }
51 break 49 break
52 } 50 }
53 51
......
1 package orm
2
3 import ()
4
5 type fieldError struct {
6 name string
7 err error
8 }
9
10 func (f *fieldError) Name() string {
11 return f.name
12 }
13
14 func (f *fieldError) Error() error {
15 return f.err
16 }
17
18 func NewFieldError(name string, err error) IFieldError {
19 return &fieldError{name, err}
20 }
21
22 // non cleaned field errors
23 type fieldErrors struct {
24 errors map[string]IFieldError
25 errorList []IFieldError
26 }
27
28 func (fe *fieldErrors) Get(name string) IFieldError {
29 return fe.errors[name]
30 }
31
32 func (fe *fieldErrors) Set(name string, value IFieldError) {
33 fe.errors[name] = value
34 }
35
36 func (fe *fieldErrors) List() []IFieldError {
37 return fe.errorList
38 }
39
40 func NewFieldErrors() IFieldErrors {
41 return &fieldErrors{errors: make(map[string]IFieldError)}
42 }
43
44 type Manager struct {
45 ins Modeler
46 inited bool
47 }
48
49 // func (m *Manager) init(model reflect.Value) {
50 // elm := model.Elem()
51 // for i := 0; i < elm.NumField(); i++ {
52 // field := elm.Field(i)
53 // if _, ok := field.Interface().(Fielder); ok && field.CanSet() {
54 // if field.Elem().Kind() != reflect.Struct {
55 // field.Set(reflect.New(field.Type().Elem()))
56 // }
57 // }
58 // }
59 // }
60
61 func (m *Manager) Init(model Modeler, args ...interface{}) Modeler {
62 if m.inited {
63 return m.ins
64 }
65 m.inited = true
66 m.ins = model
67 skipInitial := false
68 if len(args) > 0 {
69 if b, ok := args[0].(bool); ok && b {
70 skipInitial = true
71 }
72 }
73 _ = skipInitial
74 return model
75 }
76
77 func (m *Manager) IsInited() bool {
78 return m.inited
79 }
80
81 func (m *Manager) Clean() IFieldErrors {
82 return nil
83 }
84
85 func (m *Manager) CleanFields(name string) IFieldErrors {
86 return nil
87 }
88
89 func (m *Manager) GetTableName() string {
90 return getTableName(m.ins)
91 }
...@@ -15,19 +15,18 @@ type User struct { ...@@ -15,19 +15,18 @@ type User struct {
15 UserName string `orm:"size(30);unique"` 15 UserName string `orm:"size(30);unique"`
16 Email string `orm:"size(100)"` 16 Email string `orm:"size(100)"`
17 Password string `orm:"size(100)"` 17 Password string `orm:"size(100)"`
18 Status int16 `orm:"choices(0,1,2,3);defalut(0)"` 18 Status int16
19 IsStaff bool `orm:"default(false)"` 19 IsStaff bool
20 IsActive bool `orm:"default(1)"` 20 IsActive bool `orm:"default(1)"`
21 Created time.Time `orm:"auto_now_add;type(date)"` 21 Created time.Time `orm:"auto_now_add;type(date)"`
22 Updated time.Time `orm:"auto_now"` 22 Updated time.Time `orm:"auto_now"`
23 Profile *Profile `orm:"null;rel(one);on_delete(set_null)"` 23 Profile *Profile `orm:"null;rel(one);on_delete(set_null)"`
24 Posts []*Post `orm:"reverse(many)" json:"-"` 24 Posts []*Post `orm:"reverse(many)" json:"-"`
25 Manager `json:"-"` 25 ShouldSkip string `orm:"-"`
26 } 26 }
27 27
28 func NewUser() *User { 28 func NewUser() *User {
29 obj := new(User) 29 obj := new(User)
30 obj.Manager.Init(obj)
31 return obj 30 return obj
32 } 31 }
33 32
...@@ -36,7 +35,6 @@ type Profile struct { ...@@ -36,7 +35,6 @@ type Profile struct {
36 Age int16 `` 35 Age int16 ``
37 Money float64 `` 36 Money float64 ``
38 User *User `orm:"reverse(one)" json:"-"` 37 User *User `orm:"reverse(one)" json:"-"`
39 Manager `json:"-"`
40 } 38 }
41 39
42 func (u *Profile) TableName() string { 40 func (u *Profile) TableName() string {
...@@ -45,7 +43,6 @@ func (u *Profile) TableName() string { ...@@ -45,7 +43,6 @@ func (u *Profile) TableName() string {
45 43
46 func NewProfile() *Profile { 44 func NewProfile() *Profile {
47 obj := new(Profile) 45 obj := new(Profile)
48 obj.Manager.Init(obj)
49 return obj 46 return obj
50 } 47 }
51 48
...@@ -57,12 +54,10 @@ type Post struct { ...@@ -57,12 +54,10 @@ type Post struct {
57 Created time.Time `orm:"auto_now_add"` 54 Created time.Time `orm:"auto_now_add"`
58 Updated time.Time `orm:"auto_now"` 55 Updated time.Time `orm:"auto_now"`
59 Tags []*Tag `orm:"rel(m2m)"` 56 Tags []*Tag `orm:"rel(m2m)"`
60 Manager `json:"-"`
61 } 57 }
62 58
63 func NewPost() *Post { 59 func NewPost() *Post {
64 obj := new(Post) 60 obj := new(Post)
65 obj.Manager.Init(obj)
66 return obj 61 return obj
67 } 62 }
68 63
...@@ -70,12 +65,10 @@ type Tag struct { ...@@ -70,12 +65,10 @@ type Tag struct {
70 Id int `orm:"auto"` 65 Id int `orm:"auto"`
71 Name string `orm:"size(30)"` 66 Name string `orm:"size(30)"`
72 Posts []*Post `orm:"reverse(many)" json:"-"` 67 Posts []*Post `orm:"reverse(many)" json:"-"`
73 Manager `json:"-"`
74 } 68 }
75 69
76 func NewTag() *Tag { 70 func NewTag() *Tag {
77 obj := new(Tag) 71 obj := new(Tag)
78 obj.Manager.Init(obj)
79 return obj 72 return obj
80 } 73 }
81 74
...@@ -85,12 +78,10 @@ type Comment struct { ...@@ -85,12 +78,10 @@ type Comment struct {
85 Content string `` 78 Content string ``
86 Parent *Comment `orm:"null;rel(fk)"` 79 Parent *Comment `orm:"null;rel(fk)"`
87 Created time.Time `orm:"auto_now_add"` 80 Created time.Time `orm:"auto_now_add"`
88 Manager `json:"-"`
89 } 81 }
90 82
91 func NewComment() *Comment { 83 func NewComment() *Comment {
92 obj := new(Comment) 84 obj := new(Comment)
93 obj.Manager.Init(obj)
94 return obj 85 return obj
95 } 86 }
96 87
......
...@@ -7,8 +7,11 @@ import ( ...@@ -7,8 +7,11 @@ import (
7 "time" 7 "time"
8 ) 8 )
9 9
10 func getTableName(model Modeler) string { 10 func getFullName(typ reflect.Type) string {
11 val := reflect.ValueOf(model) 11 return typ.PkgPath() + "." + typ.Name()
12 }
13
14 func getTableName(val reflect.Value) string {
12 ind := reflect.Indirect(val) 15 ind := reflect.Indirect(val)
13 fun := val.MethodByName("TableName") 16 fun := val.MethodByName("TableName")
14 if fun.IsValid() { 17 if fun.IsValid() {
...@@ -23,11 +26,6 @@ func getTableName(model Modeler) string { ...@@ -23,11 +26,6 @@ func getTableName(model Modeler) string {
23 return snakeString(ind.Type().Name()) 26 return snakeString(ind.Type().Name())
24 } 27 }
25 28
26 func getPkgPath(model Modeler) string {
27 val := reflect.ValueOf(model)
28 return val.Type().Elem().PkgPath()
29 }
30
31 func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col string) string { 29 func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col string) string {
32 column := strings.ToLower(col) 30 column := strings.ToLower(col)
33 if column == "" { 31 if column == "" {
......
...@@ -39,16 +39,21 @@ type orm struct { ...@@ -39,16 +39,21 @@ type orm struct {
39 39
40 var _ Ormer = new(orm) 40 var _ Ormer = new(orm)
41 41
42 func (o *orm) getMiInd(md Modeler) (mi *modelInfo, ind reflect.Value) { 42 func (o *orm) getMiInd(md interface{}) (mi *modelInfo, ind reflect.Value) {
43 md.Init(md, true) 43 val := reflect.ValueOf(md)
44 name := md.GetTableName() 44 ind = reflect.Indirect(val)
45 if mi, ok := modelCache.get(name); ok { 45 typ := ind.Type()
46 return mi, reflect.Indirect(reflect.ValueOf(md)) 46 if val.Kind() != reflect.Ptr {
47 panic(fmt.Sprintf("<Ormer> cannot use non-ptr model struct `%s`", getFullName(typ)))
48 }
49 name := getFullName(typ)
50 if mi, ok := modelCache.getByFN(name); ok {
51 return mi, ind
47 } 52 }
48 panic(fmt.Sprintf("<orm> table name: `%s` not exists", name)) 53 panic(fmt.Sprintf("<Ormer> table: `%s` not found, maybe not RegisterModel", name))
49 } 54 }
50 55
51 func (o *orm) Read(md Modeler) error { 56 func (o *orm) Read(md interface{}) error {
52 mi, ind := o.getMiInd(md) 57 mi, ind := o.getMiInd(md)
53 err := o.alias.DbBaser.Read(o.db, mi, ind) 58 err := o.alias.DbBaser.Read(o.db, mi, ind)
54 if err != nil { 59 if err != nil {
...@@ -57,7 +62,7 @@ func (o *orm) Read(md Modeler) error { ...@@ -57,7 +62,7 @@ func (o *orm) Read(md Modeler) error {
57 return nil 62 return nil
58 } 63 }
59 64
60 func (o *orm) Insert(md Modeler) (int64, error) { 65 func (o *orm) Insert(md interface{}) (int64, error) {
61 mi, ind := o.getMiInd(md) 66 mi, ind := o.getMiInd(md)
62 id, err := o.alias.DbBaser.Insert(o.db, mi, ind) 67 id, err := o.alias.DbBaser.Insert(o.db, mi, ind)
63 if err != nil { 68 if err != nil {
...@@ -71,7 +76,7 @@ func (o *orm) Insert(md Modeler) (int64, error) { ...@@ -71,7 +76,7 @@ func (o *orm) Insert(md Modeler) (int64, error) {
71 return id, nil 76 return id, nil
72 } 77 }
73 78
74 func (o *orm) Update(md Modeler) (int64, error) { 79 func (o *orm) Update(md interface{}) (int64, error) {
75 mi, ind := o.getMiInd(md) 80 mi, ind := o.getMiInd(md)
76 num, err := o.alias.DbBaser.Update(o.db, mi, ind) 81 num, err := o.alias.DbBaser.Update(o.db, mi, ind)
77 if err != nil { 82 if err != nil {
...@@ -80,7 +85,7 @@ func (o *orm) Update(md Modeler) (int64, error) { ...@@ -80,7 +85,7 @@ func (o *orm) Update(md Modeler) (int64, error) {
80 return num, nil 85 return num, nil
81 } 86 }
82 87
83 func (o *orm) Delete(md Modeler) (int64, error) { 88 func (o *orm) Delete(md interface{}) (int64, error) {
84 mi, ind := o.getMiInd(md) 89 mi, ind := o.getMiInd(md)
85 num, err := o.alias.DbBaser.Delete(o.db, mi, ind) 90 num, err := o.alias.DbBaser.Delete(o.db, mi, ind)
86 if err != nil { 91 if err != nil {
...@@ -94,41 +99,48 @@ func (o *orm) Delete(md Modeler) (int64, error) { ...@@ -94,41 +99,48 @@ func (o *orm) Delete(md Modeler) (int64, error) {
94 return num, nil 99 return num, nil
95 } 100 }
96 101
97 func (o *orm) M2mAdd(md Modeler, name string, mds ...interface{}) (int64, error) { 102 func (o *orm) M2mAdd(md interface{}, name string, mds ...interface{}) (int64, error) {
98 // TODO 103 // TODO
99 panic(ErrNotImplement) 104 panic(ErrNotImplement)
100 return 0, nil 105 return 0, nil
101 } 106 }
102 107
103 func (o *orm) M2mDel(md Modeler, name string, mds ...interface{}) (int64, error) { 108 func (o *orm) M2mDel(md interface{}, name string, mds ...interface{}) (int64, error) {
104 // TODO 109 // TODO
105 panic(ErrNotImplement) 110 panic(ErrNotImplement)
106 return 0, nil 111 return 0, nil
107 } 112 }
108 113
109 func (o *orm) LoadRel(md Modeler, name string) (int64, error) { 114 func (o *orm) LoadRel(md interface{}, name string) (int64, error) {
110 // TODO 115 // TODO
111 panic(ErrNotImplement) 116 panic(ErrNotImplement)
112 return 0, nil 117 return 0, nil
113 } 118 }
114 119
115 func (o *orm) QueryTable(ptrStructOrTableName interface{}) QuerySeter { 120 func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) {
116 name := "" 121 name := ""
117 if table, ok := ptrStructOrTableName.(string); ok { 122 if table, ok := ptrStructOrTableName.(string); ok {
118 name = snakeString(table) 123 name = snakeString(table)
119 } else if md, ok := ptrStructOrTableName.(Modeler); ok {
120 md.Init(md, true)
121 name = md.GetTableName()
122 }
123 if mi, ok := modelCache.get(name); ok { 124 if mi, ok := modelCache.get(name); ok {
124 return newQuerySet(o, mi) 125 qs = newQuerySet(o, mi)
126 }
127 } else {
128 val := reflect.ValueOf(ptrStructOrTableName)
129 ind := reflect.Indirect(val)
130 name = getFullName(ind.Type())
131 if mi, ok := modelCache.getByFN(name); ok {
132 qs = newQuerySet(o, mi)
133 }
134 }
135 if qs == nil {
136 panic(fmt.Sprintf("<Ormer.QueryTable> table name: `%s` not exists", name))
125 } 137 }
126 panic(fmt.Sprintf("<orm.SetTable> table name: `%s` not exists", name)) 138 return
127 } 139 }
128 140
129 func (o *orm) Using(name string) error { 141 func (o *orm) Using(name string) error {
130 if o.isTx { 142 if o.isTx {
131 panic("<orm.Using> transaction has been start, cannot change db") 143 panic("<Ormer.Using> transaction has been start, cannot change db")
132 } 144 }
133 if al, ok := dataBaseCache.get(name); ok { 145 if al, ok := dataBaseCache.get(name); ok {
134 o.alias = al 146 o.alias = al
...@@ -138,7 +150,7 @@ func (o *orm) Using(name string) error { ...@@ -138,7 +150,7 @@ func (o *orm) Using(name string) error {
138 o.db = al.DB 150 o.db = al.DB
139 } 151 }
140 } else { 152 } else {
141 return errors.New(fmt.Sprintf("<orm.Using> unknown db alias name `%s`", name)) 153 return errors.New(fmt.Sprintf("<Ormer.Using> unknown db alias name `%s`", name))
142 } 154 }
143 return nil 155 return nil
144 } 156 }
......
...@@ -14,15 +14,19 @@ type insertSet struct { ...@@ -14,15 +14,19 @@ type insertSet struct {
14 14
15 var _ Inserter = new(insertSet) 15 var _ Inserter = new(insertSet)
16 16
17 func (o *insertSet) Insert(md Modeler) (int64, error) { 17 func (o *insertSet) Insert(md interface{}) (int64, error) {
18 if o.closed { 18 if o.closed {
19 return 0, ErrStmtClosed 19 return 0, ErrStmtClosed
20 } 20 }
21 md.Init(md, true)
22 val := reflect.ValueOf(md) 21 val := reflect.ValueOf(md)
23 ind := reflect.Indirect(val) 22 ind := reflect.Indirect(val)
24 if val.Type() != o.mi.addrField.Type() { 23 typ := ind.Type()
25 panic(fmt.Sprintf("<Inserter.Insert> need type `%s` but found `%s`", o.mi.addrField.Type(), val.Type())) 24 name := getFullName(typ)
25 if val.Kind() != reflect.Ptr {
26 panic(fmt.Sprintf("<Inserter.Insert> cannot use non-ptr model struct `%s`", name))
27 }
28 if name != o.mi.fullName {
29 panic(fmt.Sprintf("<Inserter.Insert> need model `%s` but found `%s`", o.mi.fullName, name))
26 } 30 }
27 id, err := o.orm.alias.DbBaser.InsertStmt(o.stmt, o.mi, ind) 31 id, err := o.orm.alias.DbBaser.InsertStmt(o.stmt, o.mi, ind)
28 if err != nil { 32 if err != nil {
......
...@@ -63,7 +63,7 @@ func (o querySet) RelatedSel(params ...interface{}) QuerySeter { ...@@ -63,7 +63,7 @@ func (o querySet) RelatedSel(params ...interface{}) QuerySeter {
63 case int: 63 case int:
64 o.relDepth = val 64 o.relDepth = val
65 default: 65 default:
66 panic(fmt.Sprintf("<querySet.RelatedSel> wrong param kind: %v", val)) 66 panic(fmt.Sprintf("<QuerySeter.RelatedSel> wrong param kind: %v", val))
67 } 67 }
68 } 68 }
69 } 69 }
...@@ -96,7 +96,7 @@ func (o *querySet) All(container interface{}) (int64, error) { ...@@ -96,7 +96,7 @@ func (o *querySet) All(container interface{}) (int64, error) {
96 return o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container) 96 return o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container)
97 } 97 }
98 98
99 func (o *querySet) One(container Modeler) error { 99 func (o *querySet) One(container interface{}) error {
100 num, err := o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container) 100 num, err := o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container)
101 if err != nil { 101 if err != nil {
102 return err 102 return err
......
...@@ -152,6 +152,14 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) { ...@@ -152,6 +152,14 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) {
152 } 152 }
153 } 153 }
154 154
155 func TestModelSyntax(t *testing.T) {
156 mi, ok := modelCache.get("user")
157 throwFail(t, AssertIs(ok, T_Equal, true))
158 if ok {
159 throwFail(t, AssertIs(mi.fields.GetByName("ShouldSkip") == nil, T_Equal, true))
160 }
161 }
162
155 func TestCRUD(t *testing.T) { 163 func TestCRUD(t *testing.T) {
156 profile := NewProfile() 164 profile := NewProfile()
157 profile.Age = 30 165 profile.Age = 30
......
...@@ -18,22 +18,14 @@ type Fielder interface { ...@@ -18,22 +18,14 @@ type Fielder interface {
18 Clean() error 18 Clean() error
19 } 19 }
20 20
21 type Modeler interface {
22 Init(Modeler, ...interface{}) Modeler
23 IsInited() bool
24 Clean() IFieldErrors
25 CleanFields(string) IFieldErrors
26 GetTableName() string
27 }
28
29 type Ormer interface { 21 type Ormer interface {
30 Read(Modeler) error 22 Read(interface{}) error
31 Insert(Modeler) (int64, error) 23 Insert(interface{}) (int64, error)
32 Update(Modeler) (int64, error) 24 Update(interface{}) (int64, error)
33 Delete(Modeler) (int64, error) 25 Delete(interface{}) (int64, error)
34 M2mAdd(Modeler, string, ...interface{}) (int64, error) 26 M2mAdd(interface{}, string, ...interface{}) (int64, error)
35 M2mDel(Modeler, string, ...interface{}) (int64, error) 27 M2mDel(interface{}, string, ...interface{}) (int64, error)
36 LoadRel(Modeler, string) (int64, error) 28 LoadRel(interface{}, string) (int64, error)
37 QueryTable(interface{}) QuerySeter 29 QueryTable(interface{}) QuerySeter
38 Using(string) error 30 Using(string) error
39 Begin() error 31 Begin() error
...@@ -44,7 +36,7 @@ type Ormer interface { ...@@ -44,7 +36,7 @@ type Ormer interface {
44 } 36 }
45 37
46 type Inserter interface { 38 type Inserter interface {
47 Insert(Modeler) (int64, error) 39 Insert(interface{}) (int64, error)
48 Close() error 40 Close() error
49 } 41 }
50 42
...@@ -61,7 +53,7 @@ type QuerySeter interface { ...@@ -61,7 +53,7 @@ type QuerySeter interface {
61 Delete() (int64, error) 53 Delete() (int64, error)
62 PrepareInsert() (Inserter, error) 54 PrepareInsert() (Inserter, error)
63 All(interface{}) (int64, error) 55 All(interface{}) (int64, error)
64 One(Modeler) error 56 One(interface{}) error
65 Values(*[]Params, ...string) (int64, error) 57 Values(*[]Params, ...string) (int64, error)
66 ValuesList(*[]ParamsList, ...string) (int64, error) 58 ValuesList(*[]ParamsList, ...string) (int64, error)
67 ValuesFlat(*ParamsList, string) (int64, error) 59 ValuesFlat(*ParamsList, string) (int64, error)
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!