orm full remove orm.Manager for simple use, add struct tag `-` for skip struct field
Showing
16 changed files
with
144 additions
and
284 deletions
| ... | @@ -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 | ... | ... |
orm/models_manager.go
deleted
100644 → 0
| 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) | ... | ... |
-
Please register or sign in to post a comment