c38abf35 by slene

orm support auto create db

1 parent 1fedaf21
1 package orm
2
3 import (
4 "flag"
5 "fmt"
6 "os"
7 "strings"
8 )
9
10 type commander interface {
11 Parse([]string)
12 Run()
13 }
14
15 var (
16 commands = make(map[string]commander)
17 )
18
19 func printHelp(errs ...string) {
20 content := `orm command usage:
21
22 syncdb - auto create tables
23 sqlall - print sql of create tables
24 help - print this help
25 `
26
27 if len(errs) > 0 {
28 fmt.Println(errs[0])
29 }
30 fmt.Println(content)
31 os.Exit(2)
32 }
33
34 func RunCommand() {
35 if len(os.Args) < 2 || os.Args[1] != "orm" {
36 return
37 }
38
39 BootStrap()
40
41 args := argString(os.Args[2:])
42 name := args.Get(0)
43
44 if name == "help" {
45 printHelp()
46 }
47
48 if cmd, ok := commands[name]; ok {
49 cmd.Parse(os.Args[3:])
50 cmd.Run()
51 os.Exit(0)
52 } else {
53 if name == "" {
54 printHelp()
55 } else {
56 printHelp(fmt.Sprintf("unknown command %s", name))
57 }
58 }
59 }
60
61 type commandSyncDb struct {
62 al *alias
63 force bool
64 verbose bool
65 }
66
67 func (d *commandSyncDb) Parse(args []string) {
68 var name string
69
70 flagSet := flag.NewFlagSet("orm command: syncdb", flag.ExitOnError)
71 flagSet.StringVar(&name, "db", "default", "DataBase alias name")
72 flagSet.BoolVar(&d.force, "force", false, "drop tables before create")
73 flagSet.BoolVar(&d.verbose, "v", false, "verbose info")
74 flagSet.Parse(args)
75
76 d.al = getDbAlias(name)
77 }
78
79 func (d *commandSyncDb) Run() {
80 var drops []string
81 if d.force {
82 drops = getDbDropSql(d.al)
83 }
84
85 db := d.al.DB
86
87 if d.force {
88 for i, mi := range modelCache.allOrdered() {
89 query := drops[i]
90 _, err := db.Exec(query)
91 result := ""
92 if err != nil {
93 result = err.Error()
94 }
95 fmt.Printf("drop table `%s` %s\n", mi.table, result)
96 if d.verbose {
97 fmt.Printf(" %s\n\n", query)
98 }
99 }
100 }
101
102 tables := getDbCreateSql(d.al)
103
104 for i, mi := range modelCache.allOrdered() {
105 query := tables[i]
106 _, err := db.Exec(query)
107 fmt.Printf("create table `%s` \n", mi.table)
108 if d.verbose {
109 query = " " + strings.Join(strings.Split(query, "\n"), "\n ")
110 fmt.Println(query)
111 }
112 if err != nil {
113 fmt.Printf(" %s\n", err.Error())
114 }
115 if d.verbose {
116 fmt.Println("")
117 }
118 }
119 }
120
121 type commandSqlAll struct {
122 al *alias
123 }
124
125 func (d *commandSqlAll) Parse(args []string) {
126 var name string
127
128 flagSet := flag.NewFlagSet("orm command: sqlall", flag.ExitOnError)
129 flagSet.StringVar(&name, "db", "default", "DataBase alias name")
130 flagSet.Parse(args)
131
132 d.al = getDbAlias(name)
133 }
134
135 func (d *commandSqlAll) Run() {
136 sqls := getDbCreateSql(d.al)
137 sql := strings.Join(sqls, "\n\n")
138 fmt.Println(sql)
139 }
140
141 func init() {
142 commands["syncdb"] = new(commandSyncDb)
143 commands["sqlall"] = new(commandSqlAll)
144 }
1 package orm
2
3 import (
4 "fmt"
5 "os"
6 "strings"
7 )
8
9 func getDbAlias(name string) *alias {
10 if al, ok := dataBaseCache.get(name); ok {
11 return al
12 } else {
13 fmt.Println(fmt.Sprintf("unknown DataBase alias name %s", name))
14 os.Exit(2)
15 }
16
17 return nil
18 }
19
20 func getDbDropSql(al *alias) (sqls []string) {
21 if len(modelCache.cache) == 0 {
22 fmt.Println("no Model found, need register your model")
23 os.Exit(2)
24 }
25
26 Q := al.DbBaser.TableQuote()
27
28 for _, mi := range modelCache.allOrdered() {
29 sqls = append(sqls, fmt.Sprintf(`DROP TABLE IF EXISTS %s%s%s`, Q, mi.table, Q))
30 }
31 return sqls
32 }
33
34 func getDbCreateSql(al *alias) (sqls []string) {
35 if len(modelCache.cache) == 0 {
36 fmt.Println("no Model found, need register your model")
37 os.Exit(2)
38 }
39
40 Q := al.DbBaser.TableQuote()
41 T := al.DbBaser.DbTypes()
42
43 for _, mi := range modelCache.allOrdered() {
44 sql := fmt.Sprintf("-- %s\n", strings.Repeat("-", 50))
45 sql += fmt.Sprintf("-- Table Structure for `%s`\n", mi.fullName)
46 sql += fmt.Sprintf("-- %s\n", strings.Repeat("-", 50))
47
48 sql += fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s%s%s (\n", Q, mi.table, Q)
49
50 columns := make([]string, 0, len(mi.fields.fieldsDB))
51
52 for _, fi := range mi.fields.fieldsDB {
53
54 fieldType := fi.fieldType
55 column := fmt.Sprintf(" %s%s%s ", Q, fi.column, Q)
56 col := ""
57
58 checkColumn:
59 switch fieldType {
60 case TypeBooleanField:
61 col = T["bool"]
62 case TypeCharField:
63 col = fmt.Sprintf(T["string"], fi.size)
64 case TypeTextField:
65 col = T["string-text"]
66 case TypeDateField:
67 col = T["time.Time-date"]
68 case TypeDateTimeField:
69 col = T["time.Time"]
70 case TypeBitField:
71 col = T["int8"]
72 case TypeSmallIntegerField:
73 col = T["int16"]
74 case TypeIntegerField:
75 col = T["int32"]
76 case TypeBigIntegerField:
77 if al.Driver == DR_Sqlite {
78 fieldType = TypeIntegerField
79 goto checkColumn
80 }
81 col = T["int64"]
82 case TypePositiveBitField:
83 col = T["uint8"]
84 case TypePositiveSmallIntegerField:
85 col = T["uint16"]
86 case TypePositiveIntegerField:
87 col = T["uint32"]
88 case TypePositiveBigIntegerField:
89 col = T["uint64"]
90 case TypeFloatField:
91 col = T["float64"]
92 case TypeDecimalField:
93 s := T["float64-decimal"]
94 if strings.Index(s, "%d") == -1 {
95 col = s
96 } else {
97 col = fmt.Sprintf(s, fi.digits, fi.decimals)
98 }
99 case RelForeignKey, RelOneToOne:
100 fieldType = fi.relModelInfo.fields.pk.fieldType
101 goto checkColumn
102 }
103
104 if fi.auto {
105 if al.Driver == DR_Postgres {
106 column += T["auto"]
107 } else {
108 column += col + " " + T["auto"]
109 }
110 } else if fi.pk {
111 column += col + " " + T["pk"]
112 } else {
113 column += col
114
115 if fi.null == false {
116 column += " " + "NOT NULL"
117 }
118
119 if fi.unique {
120 column += " " + "UNIQUE"
121 }
122 }
123
124 if strings.Index(column, "%COL%") != -1 {
125 column = strings.Replace(column, "%COL%", fi.column, -1)
126 }
127
128 columns = append(columns, column)
129 }
130
131 sql += strings.Join(columns, ",\n")
132 sql += "\n)"
133
134 if al.Driver == DR_MySQL {
135 sql += " ENGINE=INNODB"
136 }
137
138 sqls = append(sqls, sql)
139 }
140
141 return sqls
142 }
1 package orm
2
3 import (
4 "flag"
5 "fmt"
6 "os"
7 )
8
9 func printHelp() {
10
11 }
12
13 func getSqlAll() (sql string) {
14 for _, mi := range modelCache.allOrdered() {
15 _ = mi
16 }
17 return
18 }
19
20 func runCommand() {
21 if len(os.Args) < 2 || os.Args[1] != "orm" {
22 return
23 }
24
25 _ = flag.NewFlagSet("orm command", flag.ExitOnError)
26
27 args := argString(os.Args[2:])
28 cmd := args.Get(0)
29
30 switch cmd {
31 case "syncdb":
32 case "sqlall":
33 sql := getSqlAll()
34 fmt.Println(sql)
35 default:
36 if cmd != "" {
37 fmt.Printf("unknown command %s", cmd)
38 } else {
39 printHelp()
40 }
41
42 os.Exit(2)
43 }
44 }
...@@ -805,7 +805,7 @@ setValue: ...@@ -805,7 +805,7 @@ setValue:
805 _, err = str.Int32() 805 _, err = str.Int32()
806 case TypeBigIntegerField: 806 case TypeBigIntegerField:
807 _, err = str.Int64() 807 _, err = str.Int64()
808 case TypePostiveBitField: 808 case TypePositiveBitField:
809 _, err = str.Uint8() 809 _, err = str.Uint8()
810 case TypePositiveSmallIntegerField: 810 case TypePositiveSmallIntegerField:
811 _, err = str.Uint16() 811 _, err = str.Uint16()
...@@ -1112,3 +1112,7 @@ func (d *dbBase) TimeFromDB(t *time.Time, tz *time.Location) { ...@@ -1112,3 +1112,7 @@ func (d *dbBase) TimeFromDB(t *time.Time, tz *time.Location) {
1112 func (d *dbBase) TimeToDB(t *time.Time, tz *time.Location) { 1112 func (d *dbBase) TimeToDB(t *time.Time, tz *time.Location) {
1113 *t = t.In(tz) 1113 *t = t.In(tz)
1114 } 1114 }
1115
1116 func (d *dbBase) DbTypes() map[string]string {
1117 return nil
1118 }
......
...@@ -17,6 +17,26 @@ var mysqlOperators = map[string]string{ ...@@ -17,6 +17,26 @@ var mysqlOperators = map[string]string{
17 "iendswith": "LIKE ?", 17 "iendswith": "LIKE ?",
18 } 18 }
19 19
20 var mysqlTypes = map[string]string{
21 "auto": "AUTO_INCREMENT NOT NULL PRIMARY KEY",
22 "pk": "NOT NULL PRIMARY KEY",
23 "bool": "bool",
24 "string": "varchar(%d)",
25 "string-text": "longtext",
26 "time.Time-date": "date",
27 "time.Time": "datetime",
28 "int8": "tinyint",
29 "int16": "smallint",
30 "int32": "integer",
31 "int64": "bigint",
32 "uint8": "tinyint unsigned",
33 "uint16": "smallint unsigned",
34 "uint32": "integer unsigned",
35 "uint64": "bigint unsigned",
36 "float64": "double precision",
37 "float64-decimal": "numeric(%d, %d)",
38 }
39
20 type dbBaseMysql struct { 40 type dbBaseMysql struct {
21 dbBase 41 dbBase
22 } 42 }
...@@ -27,6 +47,10 @@ func (d *dbBaseMysql) OperatorSql(operator string) string { ...@@ -27,6 +47,10 @@ func (d *dbBaseMysql) OperatorSql(operator string) string {
27 return mysqlOperators[operator] 47 return mysqlOperators[operator]
28 } 48 }
29 49
50 func (d *dbBaseMysql) DbTypes() map[string]string {
51 return mysqlTypes
52 }
53
30 func newdbBaseMysql() dbBaser { 54 func newdbBaseMysql() dbBaser {
31 b := new(dbBaseMysql) 55 b := new(dbBaseMysql)
32 b.ins = b 56 b.ins = b
......
...@@ -20,6 +20,26 @@ var postgresOperators = map[string]string{ ...@@ -20,6 +20,26 @@ var postgresOperators = map[string]string{
20 "iendswith": "LIKE UPPER(?)", 20 "iendswith": "LIKE UPPER(?)",
21 } 21 }
22 22
23 var postgresTypes = map[string]string{
24 "auto": "serial NOT NULL PRIMARY KEY",
25 "pk": "NOT NULL PRIMARY KEY",
26 "bool": "bool",
27 "string": "varchar(%d)",
28 "string-text": "text",
29 "time.Time-date": "date",
30 "time.Time": "timestamp with time zone",
31 "int8": `smallint CHECK("%COL%" >= -127 AND "%COL%" <= 128)`,
32 "int16": "smallint",
33 "int32": "integer",
34 "int64": "bigint",
35 "uint8": `smallint CHECK("%COL%" >= 0 AND "%COL%" <= 255)`,
36 "uint16": `integer CHECK("%COL%" >= 0)`,
37 "uint32": `bigint CHECK("%COL%" >= 0)`,
38 "uint64": `bigint CHECK("%COL%" >= 0)`,
39 "float64": "double precision",
40 "float64-decimal": "numeric(%d, %d)",
41 }
42
23 type dbBasePostgres struct { 43 type dbBasePostgres struct {
24 dbBase 44 dbBase
25 } 45 }
...@@ -87,6 +107,10 @@ func (d *dbBasePostgres) HasReturningID(mi *modelInfo, query *string) (has bool) ...@@ -87,6 +107,10 @@ func (d *dbBasePostgres) HasReturningID(mi *modelInfo, query *string) (has bool)
87 return 107 return
88 } 108 }
89 109
110 func (d *dbBasePostgres) DbTypes() map[string]string {
111 return postgresTypes
112 }
113
90 func newdbBasePostgres() dbBaser { 114 func newdbBasePostgres() dbBaser {
91 b := new(dbBasePostgres) 115 b := new(dbBasePostgres)
92 b.ins = b 116 b.ins = b
......
...@@ -19,6 +19,26 @@ var sqliteOperators = map[string]string{ ...@@ -19,6 +19,26 @@ var sqliteOperators = map[string]string{
19 "iendswith": "LIKE ? ESCAPE '\\'", 19 "iendswith": "LIKE ? ESCAPE '\\'",
20 } 20 }
21 21
22 var sqliteTypes = map[string]string{
23 "auto": "NOT NULL PRIMARY KEY AUTOINCREMENT",
24 "pk": "NOT NULL PRIMARY KEY",
25 "bool": "bool",
26 "string": "varchar(%d)",
27 "string-text": "text",
28 "time.Time-date": "date",
29 "time.Time": "datetime",
30 "int8": "tinyint",
31 "int16": "smallint",
32 "int32": "integer",
33 "int64": "bigint",
34 "uint8": "tinyint unsigned",
35 "uint16": "smallint unsigned",
36 "uint32": "integer unsigned",
37 "uint64": "bigint unsigned",
38 "float64": "real",
39 "float64-decimal": "decimal",
40 }
41
22 type dbBaseSqlite struct { 42 type dbBaseSqlite struct {
23 dbBase 43 dbBase
24 } 44 }
...@@ -43,6 +63,10 @@ func (d *dbBaseSqlite) MaxLimit() uint64 { ...@@ -43,6 +63,10 @@ func (d *dbBaseSqlite) MaxLimit() uint64 {
43 return 9223372036854775807 63 return 9223372036854775807
44 } 64 }
45 65
66 func (d *dbBaseSqlite) DbTypes() map[string]string {
67 return sqliteTypes
68 }
69
46 func newdbBaseSqlite() dbBaser { 70 func newdbBaseSqlite() dbBaser {
47 b := new(dbBaseSqlite) 71 b := new(dbBaseSqlite)
48 b.ins = b 72 b.ins = b
......
...@@ -84,3 +84,10 @@ func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo { ...@@ -84,3 +84,10 @@ func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo {
84 } 84 }
85 return mii 85 return mii
86 } 86 }
87
88 func (mc *_modelCache) clean() {
89 mc.orders = make([]string, 0)
90 mc.cache = make(map[string]*modelInfo)
91 mc.cacheByFN = make(map[string]*modelInfo)
92 mc.done = false
93 }
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
8 "strings" 8 "strings"
9 ) 9 )
10 10
11 func registerModel(model interface{}) { 11 func registerModel(model interface{}, prefix string) {
12 val := reflect.ValueOf(model) 12 val := reflect.ValueOf(model)
13 ind := reflect.Indirect(val) 13 ind := reflect.Indirect(val)
14 typ := ind.Type() 14 typ := ind.Type()
...@@ -17,20 +17,25 @@ func registerModel(model interface{}) { ...@@ -17,20 +17,25 @@ func registerModel(model interface{}) {
17 panic(fmt.Sprintf("<orm.RegisterModel> cannot use non-ptr model struct `%s`", getFullName(typ))) 17 panic(fmt.Sprintf("<orm.RegisterModel> cannot use non-ptr model struct `%s`", getFullName(typ)))
18 } 18 }
19 19
20 info := newModelInfo(val) 20 table := getTableName(val)
21
22 if prefix != "" {
23 table = prefix + table
24 }
21 25
22 name := getFullName(typ) 26 name := getFullName(typ)
23 if _, ok := modelCache.getByFN(name); ok { 27 if _, ok := modelCache.getByFN(name); ok {
24 fmt.Printf("<orm.RegisterModel> model `%s` redeclared, must be unique\n", name) 28 fmt.Printf("<orm.RegisterModel> model `%s` repeat register, must be unique\n", name)
25 os.Exit(2) 29 os.Exit(2)
26 } 30 }
27 31
28 table := getTableName(val)
29 if _, ok := modelCache.get(table); ok { 32 if _, ok := modelCache.get(table); ok {
30 fmt.Printf("<orm.RegisterModel> table name `%s` redeclared, must be unique\n", table) 33 fmt.Printf("<orm.RegisterModel> table name `%s` repeat register, must be unique\n", table)
31 os.Exit(2) 34 os.Exit(2)
32 } 35 }
33 36
37 info := newModelInfo(val)
38
34 if info.fields.pk == nil { 39 if info.fields.pk == nil {
35 outFor: 40 outFor:
36 for _, fi := range info.fields.fieldsDB { 41 for _, fi := range info.fields.fieldsDB {
...@@ -58,6 +63,7 @@ func registerModel(model interface{}) { ...@@ -58,6 +63,7 @@ func registerModel(model interface{}) {
58 info.pkg = typ.PkgPath() 63 info.pkg = typ.PkgPath()
59 info.model = model 64 info.model = model
60 info.manual = true 65 info.manual = true
66
61 modelCache.set(table, info) 67 modelCache.set(table, info)
62 } 68 }
63 69
...@@ -72,7 +78,7 @@ func bootStrap() { ...@@ -72,7 +78,7 @@ func bootStrap() {
72 ) 78 )
73 79
74 if dataBaseCache.getDefault() == nil { 80 if dataBaseCache.getDefault() == nil {
75 err = fmt.Errorf("must have one register alias named `default`") 81 err = fmt.Errorf("must have one register DataBase alias named `default`")
76 goto end 82 goto end
77 } 83 }
78 84
...@@ -97,7 +103,7 @@ func bootStrap() { ...@@ -97,7 +103,7 @@ func bootStrap() {
97 switch fi.fieldType { 103 switch fi.fieldType {
98 case RelManyToMany: 104 case RelManyToMany:
99 if fi.relThrough != "" { 105 if fi.relThrough != "" {
100 msg := fmt.Sprintf("filed `%s` wrong rel_through value `%s`", fi.fullName, fi.relThrough) 106 msg := fmt.Sprintf("field `%s` wrong rel_through value `%s`", fi.fullName, fi.relThrough)
101 if i := strings.LastIndex(fi.relThrough, "."); i != -1 && len(fi.relThrough) > (i+1) { 107 if i := strings.LastIndex(fi.relThrough, "."); i != -1 && len(fi.relThrough) > (i+1) {
102 pn := fi.relThrough[:i] 108 pn := fi.relThrough[:i]
103 mn := fi.relThrough[i+1:] 109 mn := fi.relThrough[i+1:]
...@@ -238,11 +244,22 @@ end: ...@@ -238,11 +244,22 @@ end:
238 244
239 func RegisterModel(models ...interface{}) { 245 func RegisterModel(models ...interface{}) {
240 if modelCache.done { 246 if modelCache.done {
241 panic(fmt.Errorf("RegisterModel must be run begore BootStrap")) 247 panic(fmt.Errorf("RegisterModel must be run before BootStrap"))
248 }
249
250 for _, model := range models {
251 registerModel(model, "")
252 }
253 }
254
255 // register model with a prefix
256 func RegisterModelWithPrefix(prefix string, models ...interface{}) {
257 if modelCache.done {
258 panic(fmt.Errorf("RegisterModel must be run before BootStrap"))
242 } 259 }
243 260
244 for _, model := range models { 261 for _, model := range models {
245 registerModel(model) 262 registerModel(model, prefix)
246 } 263 }
247 } 264 }
248 265
......
...@@ -31,7 +31,7 @@ const ( ...@@ -31,7 +31,7 @@ const (
31 // int64 31 // int64
32 TypeBigIntegerField 32 TypeBigIntegerField
33 // uint8 33 // uint8
34 TypePostiveBitField 34 TypePositiveBitField
35 // uint16 35 // uint16
36 TypePositiveSmallIntegerField 36 TypePositiveSmallIntegerField
37 // uint32 37 // uint32
......
...@@ -399,7 +399,7 @@ checkType: ...@@ -399,7 +399,7 @@ checkType:
399 _, err = v.Int32() 399 _, err = v.Int32()
400 case TypeBigIntegerField: 400 case TypeBigIntegerField:
401 _, err = v.Int64() 401 _, err = v.Int64()
402 case TypePostiveBitField: 402 case TypePositiveBitField:
403 _, err = v.Uint8() 403 _, err = v.Uint8()
404 case TypePositiveSmallIntegerField: 404 case TypePositiveSmallIntegerField:
405 _, err = v.Uint16() 405 _, err = v.Uint16()
......
...@@ -90,6 +90,9 @@ func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) { ...@@ -90,6 +90,9 @@ func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) {
90 fa.auto = true 90 fa.auto = true
91 fa.pk = true 91 fa.pk = true
92 fa.dbcol = true 92 fa.dbcol = true
93 fa.name = "Id"
94 fa.column = "id"
95 fa.fullName = info.fullName + "." + fa.name
93 96
94 f1.dbcol = true 97 f1.dbcol = true
95 f2.dbcol = true 98 f2.dbcol = true
......
...@@ -52,7 +52,7 @@ func getFieldType(val reflect.Value) (ft int, err error) { ...@@ -52,7 +52,7 @@ func getFieldType(val reflect.Value) (ft int, err error) {
52 case reflect.Int64: 52 case reflect.Int64:
53 ft = TypeBigIntegerField 53 ft = TypeBigIntegerField
54 case reflect.Uint8: 54 case reflect.Uint8:
55 ft = TypePostiveBitField 55 ft = TypePositiveBitField
56 case reflect.Uint16: 56 case reflect.Uint16:
57 ft = TypePositiveSmallIntegerField 57 ft = TypePositiveSmallIntegerField
58 case reflect.Uint32, reflect.Uint: 58 case reflect.Uint32, reflect.Uint:
......
...@@ -189,6 +189,47 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) { ...@@ -189,6 +189,47 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) {
189 } 189 }
190 } 190 }
191 191
192 func TestSyncDb(t *testing.T) {
193 RegisterModel(new(Data), new(DataNull))
194 RegisterModel(new(User))
195 RegisterModel(new(Profile))
196 RegisterModel(new(Post))
197 RegisterModel(new(Tag))
198 RegisterModel(new(Comment))
199
200 BootStrap()
201
202 al := dataBaseCache.getDefault()
203 db := al.DB
204
205 drops := getDbDropSql(al)
206 for _, query := range drops {
207 _, err := db.Exec(query)
208 throwFailNow(t, err, query)
209 }
210
211 tables := getDbCreateSql(al)
212 for _, query := range tables {
213 _, err := db.Exec(query)
214 throwFailNow(t, err, query)
215 }
216
217 modelCache.clean()
218 }
219
220 func TestRegisterModels(t *testing.T) {
221 RegisterModel(new(Data), new(DataNull))
222 RegisterModel(new(User))
223 RegisterModel(new(Profile))
224 RegisterModel(new(Post))
225 RegisterModel(new(Tag))
226 RegisterModel(new(Comment))
227
228 BootStrap()
229
230 dORM = NewOrm()
231 }
232
192 func TestModelSyntax(t *testing.T) { 233 func TestModelSyntax(t *testing.T) {
193 user := &User{} 234 user := &User{}
194 ind := reflect.ValueOf(user).Elem() 235 ind := reflect.ValueOf(user).Elem()
......
...@@ -132,4 +132,5 @@ type dbBaser interface { ...@@ -132,4 +132,5 @@ type dbBaser interface {
132 HasReturningID(*modelInfo, *string) bool 132 HasReturningID(*modelInfo, *string) bool
133 TimeFromDB(*time.Time, *time.Location) 133 TimeFromDB(*time.Time, *time.Location)
134 TimeToDB(*time.Time, *time.Location) 134 TimeToDB(*time.Time, *time.Location)
135 DbTypes() map[string]string
135 } 136 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!