orm support auto create db
Showing
16 changed files
with
468 additions
and
395 deletions
orm/cmd.go
0 → 100644
| 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 | } |
orm/cmd_utils.go
0 → 100644
| 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 | } |
orm/command.go
deleted
100644 → 0
| 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 | ... | ... |
| ... | @@ -3,10 +3,8 @@ package orm | ... | @@ -3,10 +3,8 @@ package orm |
| 3 | import ( | 3 | import ( |
| 4 | "fmt" | 4 | "fmt" |
| 5 | "os" | 5 | "os" |
| 6 | "strings" | ||
| 7 | "time" | 6 | "time" |
| 8 | 7 | ||
| 9 | // _ "github.com/bylevel/pq" | ||
| 10 | _ "github.com/go-sql-driver/mysql" | 8 | _ "github.com/go-sql-driver/mysql" |
| 11 | _ "github.com/lib/pq" | 9 | _ "github.com/lib/pq" |
| 12 | _ "github.com/mattn/go-sqlite3" | 10 | _ "github.com/mattn/go-sqlite3" |
| ... | @@ -153,325 +151,7 @@ var ( | ... | @@ -153,325 +151,7 @@ var ( |
| 153 | 151 | ||
| 154 | var dORM Ormer | 152 | var dORM Ormer |
| 155 | 153 | ||
| 156 | var initSQLs = map[string]string{ | ||
| 157 | "mysql": "DROP TABLE IF EXISTS `user_profile`;\n" + | ||
| 158 | "DROP TABLE IF EXISTS `user`;\n" + | ||
| 159 | "DROP TABLE IF EXISTS `post`;\n" + | ||
| 160 | "DROP TABLE IF EXISTS `tag`;\n" + | ||
| 161 | "DROP TABLE IF EXISTS `post_tags`;\n" + | ||
| 162 | "DROP TABLE IF EXISTS `comment`;\n" + | ||
| 163 | "DROP TABLE IF EXISTS `data`;\n" + | ||
| 164 | "DROP TABLE IF EXISTS `data_null`;\n" + | ||
| 165 | "CREATE TABLE `user_profile` (\n" + | ||
| 166 | " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" + | ||
| 167 | " `age` smallint NOT NULL,\n" + | ||
| 168 | " `money` double precision NOT NULL\n" + | ||
| 169 | ") ENGINE=INNODB;\n" + | ||
| 170 | "CREATE TABLE `user` (\n" + | ||
| 171 | " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" + | ||
| 172 | " `user_name` varchar(30) NOT NULL UNIQUE,\n" + | ||
| 173 | " `email` varchar(100) NOT NULL,\n" + | ||
| 174 | " `password` varchar(100) NOT NULL,\n" + | ||
| 175 | " `status` smallint NOT NULL,\n" + | ||
| 176 | " `is_staff` bool NOT NULL,\n" + | ||
| 177 | " `is_active` bool NOT NULL,\n" + | ||
| 178 | " `created` date NOT NULL,\n" + | ||
| 179 | " `updated` datetime NOT NULL,\n" + | ||
| 180 | " `profile_id` integer\n" + | ||
| 181 | ") ENGINE=INNODB;\n" + | ||
| 182 | "CREATE TABLE `post` (\n" + | ||
| 183 | " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" + | ||
| 184 | " `user_id` integer NOT NULL,\n" + | ||
| 185 | " `title` varchar(60) NOT NULL,\n" + | ||
| 186 | " `content` longtext NOT NULL,\n" + | ||
| 187 | " `created` datetime NOT NULL,\n" + | ||
| 188 | " `updated` datetime NOT NULL\n" + | ||
| 189 | ") ENGINE=INNODB;\n" + | ||
| 190 | "CREATE TABLE `tag` (\n" + | ||
| 191 | " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" + | ||
| 192 | " `name` varchar(30) NOT NULL\n" + | ||
| 193 | ") ENGINE=INNODB;\n" + | ||
| 194 | "CREATE TABLE `post_tags` (\n" + | ||
| 195 | " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" + | ||
| 196 | " `post_id` integer NOT NULL,\n" + | ||
| 197 | " `tag_id` integer NOT NULL,\n" + | ||
| 198 | " UNIQUE (`post_id`, `tag_id`)\n" + | ||
| 199 | ") ENGINE=INNODB;\n" + | ||
| 200 | "CREATE TABLE `comment` (\n" + | ||
| 201 | " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" + | ||
| 202 | " `post_id` integer NOT NULL,\n" + | ||
| 203 | " `content` longtext NOT NULL,\n" + | ||
| 204 | " `parent_id` integer,\n" + | ||
| 205 | " `created` datetime NOT NULL\n" + | ||
| 206 | ") ENGINE=INNODB;\n" + | ||
| 207 | "CREATE TABLE `data` (\n" + | ||
| 208 | " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" + | ||
| 209 | " `boolean` bool NOT NULL,\n" + | ||
| 210 | " `char` varchar(50) NOT NULL,\n" + | ||
| 211 | " `text` longtext NOT NULL,\n" + | ||
| 212 | " `date` date NOT NULL,\n" + | ||
| 213 | " `date_time` datetime NOT NULL,\n" + | ||
| 214 | " `byte` tinyint unsigned NOT NULL,\n" + | ||
| 215 | " `rune` integer NOT NULL,\n" + | ||
| 216 | " `int` integer NOT NULL,\n" + | ||
| 217 | " `int8` tinyint NOT NULL,\n" + | ||
| 218 | " `int16` smallint NOT NULL,\n" + | ||
| 219 | " `int32` integer NOT NULL,\n" + | ||
| 220 | " `int64` bigint NOT NULL,\n" + | ||
| 221 | " `uint` integer unsigned NOT NULL,\n" + | ||
| 222 | " `uint8` tinyint unsigned NULL,\n" + | ||
| 223 | " `uint16` smallint unsigned NOT NULL,\n" + | ||
| 224 | " `uint32` integer unsigned NOT NULL,\n" + | ||
| 225 | " `uint64` bigint unsigned NOT NULL,\n" + | ||
| 226 | " `float32` double precision NOT NULL,\n" + | ||
| 227 | " `float64` double precision NOT NULL,\n" + | ||
| 228 | " `decimal` numeric(8,4) NOT NULL\n" + | ||
| 229 | ") ENGINE=INNODB;\n" + | ||
| 230 | "CREATE TABLE `data_null` (\n" + | ||
| 231 | " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" + | ||
| 232 | " `boolean` bool,\n" + | ||
| 233 | " `char` varchar(50),\n" + | ||
| 234 | " `text` longtext,\n" + | ||
| 235 | " `date` date,\n" + | ||
| 236 | " `date_time` datetime,\n" + | ||
| 237 | " `byte` tinyint unsigned,\n" + | ||
| 238 | " `rune` integer,\n" + | ||
| 239 | " `int` integer,\n" + | ||
| 240 | " `int8` tinyint,\n" + | ||
| 241 | " `int16` smallint,\n" + | ||
| 242 | " `int32` integer,\n" + | ||
| 243 | " `int64` bigint,\n" + | ||
| 244 | " `uint` integer unsigned,\n" + | ||
| 245 | " `uint8` tinyint unsigned,\n" + | ||
| 246 | " `uint16` smallint unsigned,\n" + | ||
| 247 | " `uint32` integer unsigned,\n" + | ||
| 248 | " `uint64` bigint unsigned,\n" + | ||
| 249 | " `float32` double precision,\n" + | ||
| 250 | " `float64` double precision,\n" + | ||
| 251 | " `decimal` numeric(8,4)\n" + | ||
| 252 | ") ENGINE=INNODB;\n" + | ||
| 253 | "CREATE INDEX `user_141c6eec` ON `user` (`profile_id`);\n" + | ||
| 254 | "CREATE INDEX `post_fbfc09f1` ON `post` (`user_id`);\n" + | ||
| 255 | "CREATE INDEX `comment_699ae8ca` ON `comment` (`post_id`);\n" + | ||
| 256 | "CREATE INDEX `comment_63f17a16` ON `comment` (`parent_id`);", | ||
| 257 | |||
| 258 | "sqlite3": ` | ||
| 259 | DROP TABLE IF EXISTS "user_profile"; | ||
| 260 | DROP TABLE IF EXISTS "user"; | ||
| 261 | DROP TABLE IF EXISTS "post"; | ||
| 262 | DROP TABLE IF EXISTS "tag"; | ||
| 263 | DROP TABLE IF EXISTS "post_tags"; | ||
| 264 | DROP TABLE IF EXISTS "comment"; | ||
| 265 | DROP TABLE IF EXISTS "data"; | ||
| 266 | DROP TABLE IF EXISTS "data_null"; | ||
| 267 | CREATE TABLE "user_profile" ( | ||
| 268 | "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
| 269 | "age" smallint NOT NULL, | ||
| 270 | "money" real NOT NULL | ||
| 271 | ); | ||
| 272 | CREATE TABLE "user" ( | ||
| 273 | "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
| 274 | "user_name" varchar(30) NOT NULL UNIQUE, | ||
| 275 | "email" varchar(100) NOT NULL, | ||
| 276 | "password" varchar(100) NOT NULL, | ||
| 277 | "status" smallint NOT NULL, | ||
| 278 | "is_staff" bool NOT NULL, | ||
| 279 | "is_active" bool NOT NULL, | ||
| 280 | "created" date NOT NULL, | ||
| 281 | "updated" datetime NOT NULL, | ||
| 282 | "profile_id" integer | ||
| 283 | ); | ||
| 284 | CREATE TABLE "post" ( | ||
| 285 | "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
| 286 | "user_id" integer NOT NULL, | ||
| 287 | "title" varchar(60) NOT NULL, | ||
| 288 | "content" text NOT NULL, | ||
| 289 | "created" datetime NOT NULL, | ||
| 290 | "updated" datetime NOT NULL | ||
| 291 | ); | ||
| 292 | CREATE TABLE "tag" ( | ||
| 293 | "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
| 294 | "name" varchar(30) NOT NULL | ||
| 295 | ); | ||
| 296 | CREATE TABLE "post_tags" ( | ||
| 297 | "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
| 298 | "post_id" integer NOT NULL, | ||
| 299 | "tag_id" integer NOT NULL, | ||
| 300 | UNIQUE ("post_id", "tag_id") | ||
| 301 | ); | ||
| 302 | CREATE TABLE "comment" ( | ||
| 303 | "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
| 304 | "post_id" integer NOT NULL, | ||
| 305 | "content" text NOT NULL, | ||
| 306 | "parent_id" integer, | ||
| 307 | "created" datetime NOT NULL | ||
| 308 | ); | ||
| 309 | CREATE TABLE "data" ( | ||
| 310 | "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
| 311 | "boolean" bool NOT NULL, | ||
| 312 | "char" varchar(50) NOT NULL, | ||
| 313 | "text" text NOT NULL, | ||
| 314 | "date" date NOT NULL, | ||
| 315 | "date_time" datetime NOT NULL, | ||
| 316 | "byte" tinyint unsigned NOT NULL, | ||
| 317 | "rune" integer NOT NULL, | ||
| 318 | "int" integer NOT NULL, | ||
| 319 | "int8" tinyint NOT NULL, | ||
| 320 | "int16" smallint NOT NULL, | ||
| 321 | "int32" integer NOT NULL, | ||
| 322 | "int64" bigint NOT NULL, | ||
| 323 | "uint" integer unsigned NOT NULL, | ||
| 324 | "uint8" tinyint unsigned NOT NULL, | ||
| 325 | "uint16" smallint unsigned NOT NULL, | ||
| 326 | "uint32" integer unsigned NOT NULL, | ||
| 327 | "uint64" bigint unsigned NOT NULL, | ||
| 328 | "float32" real NOT NULL, | ||
| 329 | "float64" real NOT NULL, | ||
| 330 | "decimal" decimal | ||
| 331 | ); | ||
| 332 | CREATE TABLE "data_null" ( | ||
| 333 | "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, | ||
| 334 | "boolean" bool, | ||
| 335 | "char" varchar(50), | ||
| 336 | "text" text, | ||
| 337 | "date" date, | ||
| 338 | "date_time" datetime, | ||
| 339 | "byte" tinyint unsigned, | ||
| 340 | "rune" integer, | ||
| 341 | "int" integer, | ||
| 342 | "int8" tinyint, | ||
| 343 | "int16" smallint, | ||
| 344 | "int32" integer, | ||
| 345 | "int64" bigint, | ||
| 346 | "uint" integer unsigned, | ||
| 347 | "uint8" tinyint unsigned, | ||
| 348 | "uint16" smallint unsigned, | ||
| 349 | "uint32" integer unsigned, | ||
| 350 | "uint64" bigint unsigned, | ||
| 351 | "float32" real, | ||
| 352 | "float64" real, | ||
| 353 | "decimal" decimal | ||
| 354 | ); | ||
| 355 | CREATE INDEX "user_141c6eec" ON "user" ("profile_id"); | ||
| 356 | CREATE INDEX "post_fbfc09f1" ON "post" ("user_id"); | ||
| 357 | CREATE INDEX "comment_699ae8ca" ON "comment" ("post_id"); | ||
| 358 | CREATE INDEX "comment_63f17a16" ON "comment" ("parent_id"); | ||
| 359 | `, | ||
| 360 | |||
| 361 | "postgres": ` | ||
| 362 | DROP TABLE IF EXISTS "user_profile"; | ||
| 363 | DROP TABLE IF EXISTS "user"; | ||
| 364 | DROP TABLE IF EXISTS "post"; | ||
| 365 | DROP TABLE IF EXISTS "tag"; | ||
| 366 | DROP TABLE IF EXISTS "post_tags"; | ||
| 367 | DROP TABLE IF EXISTS "comment"; | ||
| 368 | DROP TABLE IF EXISTS "data"; | ||
| 369 | DROP TABLE IF EXISTS "data_null"; | ||
| 370 | CREATE TABLE "user_profile" ( | ||
| 371 | "id" serial NOT NULL PRIMARY KEY, | ||
| 372 | "age" smallint NOT NULL, | ||
| 373 | "money" double precision NOT NULL | ||
| 374 | ); | ||
| 375 | CREATE TABLE "user" ( | ||
| 376 | "id" serial NOT NULL PRIMARY KEY, | ||
| 377 | "user_name" varchar(30) NOT NULL UNIQUE, | ||
| 378 | "email" varchar(100) NOT NULL, | ||
| 379 | "password" varchar(100) NOT NULL, | ||
| 380 | "status" smallint NOT NULL, | ||
| 381 | "is_staff" boolean NOT NULL, | ||
| 382 | "is_active" boolean NOT NULL, | ||
| 383 | "created" date NOT NULL, | ||
| 384 | "updated" timestamp with time zone NOT NULL, | ||
| 385 | "profile_id" integer | ||
| 386 | ); | ||
| 387 | CREATE TABLE "post" ( | ||
| 388 | "id" serial NOT NULL PRIMARY KEY, | ||
| 389 | "user_id" integer NOT NULL, | ||
| 390 | "title" varchar(60) NOT NULL, | ||
| 391 | "content" text NOT NULL, | ||
| 392 | "created" timestamp with time zone NOT NULL, | ||
| 393 | "updated" timestamp with time zone NOT NULL | ||
| 394 | ); | ||
| 395 | CREATE TABLE "tag" ( | ||
| 396 | "id" serial NOT NULL PRIMARY KEY, | ||
| 397 | "name" varchar(30) NOT NULL | ||
| 398 | ); | ||
| 399 | CREATE TABLE "post_tags" ( | ||
| 400 | "id" serial NOT NULL PRIMARY KEY, | ||
| 401 | "post_id" integer NOT NULL, | ||
| 402 | "tag_id" integer NOT NULL, | ||
| 403 | UNIQUE ("post_id", "tag_id") | ||
| 404 | ); | ||
| 405 | CREATE TABLE "comment" ( | ||
| 406 | "id" serial NOT NULL PRIMARY KEY, | ||
| 407 | "post_id" integer NOT NULL, | ||
| 408 | "content" text NOT NULL, | ||
| 409 | "parent_id" integer, | ||
| 410 | "created" timestamp with time zone NOT NULL | ||
| 411 | ); | ||
| 412 | CREATE TABLE "data" ( | ||
| 413 | "id" serial NOT NULL PRIMARY KEY, | ||
| 414 | "boolean" bool NOT NULL, | ||
| 415 | "char" varchar(50) NOT NULL, | ||
| 416 | "text" text NOT NULL, | ||
| 417 | "date" date NOT NULL, | ||
| 418 | "date_time" timestamp with time zone NOT NULL, | ||
| 419 | "byte" smallint CHECK("byte" >= 0 AND "byte" <= 255) NOT NULL, | ||
| 420 | "rune" integer NOT NULL, | ||
| 421 | "int" integer NOT NULL, | ||
| 422 | "int8" smallint CHECK("int8" >= -127 AND "int8" <= 128) NOT NULL, | ||
| 423 | "int16" smallint NOT NULL, | ||
| 424 | "int32" integer NOT NULL, | ||
| 425 | "int64" bigint NOT NULL, | ||
| 426 | "uint" bigint CHECK("uint" >= 0) NOT NULL, | ||
| 427 | "uint8" smallint CHECK("uint8" >= 0 AND "uint8" <= 255) NOT NULL, | ||
| 428 | "uint16" integer CHECK("uint16" >= 0) NOT NULL, | ||
| 429 | "uint32" bigint CHECK("uint32" >= 0) NOT NULL, | ||
| 430 | "uint64" bigint CHECK("uint64" >= 0) NOT NULL, | ||
| 431 | "float32" double precision NOT NULL, | ||
| 432 | "float64" double precision NOT NULL, | ||
| 433 | "decimal" numeric(8, 4) | ||
| 434 | ); | ||
| 435 | CREATE TABLE "data_null" ( | ||
| 436 | "id" serial NOT NULL PRIMARY KEY, | ||
| 437 | "boolean" bool, | ||
| 438 | "char" varchar(50), | ||
| 439 | "text" text, | ||
| 440 | "date" date, | ||
| 441 | "date_time" timestamp with time zone, | ||
| 442 | "byte" smallint CHECK("byte" >= 0 AND "byte" <= 255), | ||
| 443 | "rune" integer, | ||
| 444 | "int" integer, | ||
| 445 | "int8" smallint CHECK("int8" >= -127 AND "int8" <= 128), | ||
| 446 | "int16" smallint, | ||
| 447 | "int32" integer, | ||
| 448 | "int64" bigint, | ||
| 449 | "uint" bigint CHECK("uint" >= 0), | ||
| 450 | "uint8" smallint CHECK("uint8" >= 0 AND "uint8" <= 255), | ||
| 451 | "uint16" integer CHECK("uint16" >= 0), | ||
| 452 | "uint32" bigint CHECK("uint32" >= 0), | ||
| 453 | "uint64" bigint CHECK("uint64" >= 0), | ||
| 454 | "float32" double precision, | ||
| 455 | "float64" double precision, | ||
| 456 | "decimal" numeric(8, 4) | ||
| 457 | ); | ||
| 458 | CREATE INDEX "user_profile_id" ON "user" ("profile_id"); | ||
| 459 | CREATE INDEX "post_user_id" ON "post" ("user_id"); | ||
| 460 | CREATE INDEX "comment_post_id" ON "comment" ("post_id"); | ||
| 461 | CREATE INDEX "comment_parent_id" ON "comment" ("parent_id"); | ||
| 462 | `} | ||
| 463 | |||
| 464 | func init() { | 154 | func init() { |
| 465 | // err := os.Setenv("TZ", "+00:00") | ||
| 466 | // fmt.Println(err) | ||
| 467 | |||
| 468 | RegisterModel(new(Data), new(DataNull)) | ||
| 469 | RegisterModel(new(User)) | ||
| 470 | RegisterModel(new(Profile)) | ||
| 471 | RegisterModel(new(Post)) | ||
| 472 | RegisterModel(new(Tag)) | ||
| 473 | RegisterModel(new(Comment)) | ||
| 474 | |||
| 475 | Debug, _ = StrTo(DBARGS.Debug).Bool() | 155 | Debug, _ = StrTo(DBARGS.Debug).Bool() |
| 476 | 156 | ||
| 477 | if DBARGS.Driver == "" || DBARGS.Source == "" { | 157 | if DBARGS.Driver == "" || DBARGS.Source == "" { |
| ... | @@ -484,29 +164,35 @@ Default DB Drivers. | ... | @@ -484,29 +164,35 @@ Default DB Drivers. |
| 484 | sqlite3: https://github.com/mattn/go-sqlite3 | 164 | sqlite3: https://github.com/mattn/go-sqlite3 |
| 485 | postgres: https://github.com/lib/pq | 165 | postgres: https://github.com/lib/pq |
| 486 | 166 | ||
| 487 | eg: mysql | 167 | usage: |
| 488 | ORM_DRIVER=mysql ORM_SOURCE="root:root@/my_db?charset=utf8" go test github.com/astaxie/beego/orm | ||
| 489 | `) | ||
| 490 | os.Exit(2) | ||
| 491 | } | ||
| 492 | 168 | ||
| 493 | RegisterDataBase("default", DBARGS.Driver, DBARGS.Source, 20) | 169 | go get -u github.com/astaxie/beego/orm |
| 170 | go get -u github.com/go-sql-driver/mysql | ||
| 171 | go get -u github.com/mattn/go-sqlite3 | ||
| 172 | go get -u github.com/lib/pq | ||
| 494 | 173 | ||
| 495 | BootStrap() | 174 | #### MySQL |
| 175 | mysql -u root -e 'create database orm_test;' | ||
| 176 | export ORM_DRIVER=mysql | ||
| 177 | export ORM_SOURCE="root:@/orm_test?charset=utf8" | ||
| 178 | go test -v github.com/astaxie/beego/orm | ||
| 496 | 179 | ||
| 497 | dORM = NewOrm() | ||
| 498 | 180 | ||
| 499 | queries := strings.Split(initSQLs[DBARGS.Driver], ";") | 181 | #### Sqlite3 |
| 182 | touch /path/to/orm_test.db | ||
| 183 | export ORM_DRIVER=sqlite3 | ||
| 184 | export ORM_SOURCE=/path/to/orm_test.db | ||
| 185 | go test -v github.com/astaxie/beego/orm | ||
| 500 | 186 | ||
| 501 | for _, query := range queries { | 187 | |
| 502 | query = strings.TrimSpace(query) | 188 | #### PostgreSQL |
| 503 | if len(query) == 0 { | 189 | psql -c 'create database orm_test;' -U postgres |
| 504 | continue | 190 | export ORM_DRIVER=postgres |
| 505 | } | 191 | export ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable" |
| 506 | _, err := dORM.Raw(query).Exec() | 192 | go test -v github.com/astaxie/beego/orm |
| 507 | if err != nil { | 193 | `) |
| 508 | fmt.Println(err) | ||
| 509 | os.Exit(2) | 194 | os.Exit(2) |
| 510 | } | 195 | } |
| 511 | } | 196 | |
| 197 | RegisterDataBase("default", DBARGS.Driver, DBARGS.Source, 20) | ||
| 512 | } | 198 | } | ... | ... |
| ... | @@ -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 | } | ... | ... |
-
Please register or sign in to post a comment