init orm project, beta, unstable
Showing
23 changed files
with
2229 additions
and
0 deletions
orm/README.md
0 → 100644
orm/command.go
0 → 100644
| 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 | } |
orm/db.go
0 → 100644
This diff is collapsed.
Click to expand it.
orm/db_alias.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "database/sql" | ||
| 5 | "fmt" | ||
| 6 | "os" | ||
| 7 | "sync" | ||
| 8 | ) | ||
| 9 | |||
| 10 | const defaultMaxIdle = 30 | ||
| 11 | |||
| 12 | type driverType int | ||
| 13 | |||
| 14 | const ( | ||
| 15 | _ driverType = iota | ||
| 16 | DR_MySQL | ||
| 17 | DR_Sqlite | ||
| 18 | DR_Oracle | ||
| 19 | DR_Postgres | ||
| 20 | ) | ||
| 21 | |||
| 22 | var ( | ||
| 23 | dataBaseCache = &_dbCache{cache: make(map[string]*alias)} | ||
| 24 | drivers = make(map[string]driverType) | ||
| 25 | dbBasers = map[driverType]dbBaser{ | ||
| 26 | DR_MySQL: newdbBaseMysql(), | ||
| 27 | DR_Sqlite: newdbBaseSqlite(), | ||
| 28 | DR_Oracle: newdbBaseMysql(), | ||
| 29 | DR_Postgres: newdbBasePostgres(), | ||
| 30 | } | ||
| 31 | ) | ||
| 32 | |||
| 33 | type _dbCache struct { | ||
| 34 | mux sync.RWMutex | ||
| 35 | cache map[string]*alias | ||
| 36 | } | ||
| 37 | |||
| 38 | func (ac *_dbCache) add(name string, al *alias) (added bool) { | ||
| 39 | ac.mux.Lock() | ||
| 40 | defer ac.mux.Unlock() | ||
| 41 | if _, ok := ac.cache[name]; ok == false { | ||
| 42 | ac.cache[name] = al | ||
| 43 | added = true | ||
| 44 | } | ||
| 45 | return | ||
| 46 | } | ||
| 47 | |||
| 48 | func (ac *_dbCache) get(name string) (al *alias, ok bool) { | ||
| 49 | ac.mux.RLock() | ||
| 50 | defer ac.mux.RUnlock() | ||
| 51 | al, ok = ac.cache[name] | ||
| 52 | return | ||
| 53 | } | ||
| 54 | |||
| 55 | func (ac *_dbCache) getDefault() (al *alias) { | ||
| 56 | al, _ = ac.get("default") | ||
| 57 | return | ||
| 58 | } | ||
| 59 | |||
| 60 | type alias struct { | ||
| 61 | Name string | ||
| 62 | DriverName string | ||
| 63 | DataSource string | ||
| 64 | MaxIdle int | ||
| 65 | DB *sql.DB | ||
| 66 | DbBaser dbBaser | ||
| 67 | } | ||
| 68 | |||
| 69 | func RegisterDataBase(name, driverName, dataSource string, maxIdle int) { | ||
| 70 | if maxIdle <= 0 { | ||
| 71 | maxIdle = defaultMaxIdle | ||
| 72 | } | ||
| 73 | |||
| 74 | al := new(alias) | ||
| 75 | al.Name = name | ||
| 76 | al.DriverName = driverName | ||
| 77 | al.DataSource = dataSource | ||
| 78 | al.MaxIdle = maxIdle | ||
| 79 | |||
| 80 | var ( | ||
| 81 | err error | ||
| 82 | ) | ||
| 83 | |||
| 84 | if dr, ok := drivers[driverName]; ok { | ||
| 85 | al.DbBaser = dbBasers[dr] | ||
| 86 | } else { | ||
| 87 | err = fmt.Errorf("driver name `%s` have not registered", driverName) | ||
| 88 | goto end | ||
| 89 | } | ||
| 90 | |||
| 91 | if dataBaseCache.add(name, al) == false { | ||
| 92 | err = fmt.Errorf("db name `%s` already registered, cannot reuse", name) | ||
| 93 | goto end | ||
| 94 | } | ||
| 95 | |||
| 96 | al.DB, err = sql.Open(driverName, dataSource) | ||
| 97 | if err != nil { | ||
| 98 | err = fmt.Errorf("register db `%s`, %s", name, err.Error()) | ||
| 99 | goto end | ||
| 100 | } | ||
| 101 | |||
| 102 | err = al.DB.Ping() | ||
| 103 | if err != nil { | ||
| 104 | err = fmt.Errorf("register db `%s`, %s", name, err.Error()) | ||
| 105 | goto end | ||
| 106 | } | ||
| 107 | |||
| 108 | end: | ||
| 109 | if err != nil { | ||
| 110 | fmt.Println(err.Error()) | ||
| 111 | os.Exit(2) | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | func RegisterDriver(name string, typ driverType) { | ||
| 116 | if _, ok := drivers[name]; ok == false { | ||
| 117 | drivers[name] = typ | ||
| 118 | } else { | ||
| 119 | fmt.Println("name `%s` db driver already registered") | ||
| 120 | os.Exit(2) | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | func init() { | ||
| 125 | // RegisterDriver("mysql", DR_MySQL) | ||
| 126 | RegisterDriver("mymysql", DR_MySQL) | ||
| 127 | } |
orm/db_mysql.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | type dbBaseMysql struct { | ||
| 4 | dbBase | ||
| 5 | } | ||
| 6 | |||
| 7 | func (d *dbBaseMysql) GetOperatorSql(mi *modelInfo, operator string, args []interface{}) (sql string, params []interface{}) { | ||
| 8 | return d.dbBase.GetOperatorSql(mi, operator, args) | ||
| 9 | } | ||
| 10 | |||
| 11 | func newdbBaseMysql() dbBaser { | ||
| 12 | b := new(dbBaseMysql) | ||
| 13 | b.ins = b | ||
| 14 | return b | ||
| 15 | } |
orm/db_oracle.go
0 → 100644
orm/db_postgres.go
0 → 100644
orm/db_sqlite.go
0 → 100644
orm/docs/zh/README.md
0 → 100644
File mode changed
orm/models.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "log" | ||
| 5 | "os" | ||
| 6 | "sync" | ||
| 7 | ) | ||
| 8 | |||
| 9 | const ( | ||
| 10 | od_CASCADE = "cascade" | ||
| 11 | od_SET_NULL = "set_null" | ||
| 12 | od_SET_DEFAULT = "set_default" | ||
| 13 | od_DO_NOTHING = "do_nothing" | ||
| 14 | defaultStructTagName = "orm" | ||
| 15 | ) | ||
| 16 | |||
| 17 | var ( | ||
| 18 | errLog *log.Logger | ||
| 19 | modelCache = &_modelCache{cache: make(map[string]*modelInfo)} | ||
| 20 | supportTag = map[string]int{ | ||
| 21 | "null": 1, | ||
| 22 | "blank": 1, | ||
| 23 | "index": 1, | ||
| 24 | "unique": 1, | ||
| 25 | "pk": 1, | ||
| 26 | "auto": 1, | ||
| 27 | "auto_now": 1, | ||
| 28 | "auto_now_add": 1, | ||
| 29 | "max_length": 2, | ||
| 30 | "choices": 2, | ||
| 31 | "column": 2, | ||
| 32 | "default": 2, | ||
| 33 | "rel": 2, | ||
| 34 | "reverse": 2, | ||
| 35 | "rel_table": 2, | ||
| 36 | "rel_through": 2, | ||
| 37 | "digits": 2, | ||
| 38 | "decimals": 2, | ||
| 39 | "on_delete": 2, | ||
| 40 | } | ||
| 41 | ) | ||
| 42 | |||
| 43 | func init() { | ||
| 44 | errLog = log.New(os.Stderr, "[ORM] ", log.Ldate|log.Ltime|log.Lshortfile) | ||
| 45 | } | ||
| 46 | |||
| 47 | type _modelCache struct { | ||
| 48 | sync.RWMutex | ||
| 49 | orders []string | ||
| 50 | cache map[string]*modelInfo | ||
| 51 | } | ||
| 52 | |||
| 53 | func (mc *_modelCache) all() map[string]*modelInfo { | ||
| 54 | m := make(map[string]*modelInfo, len(mc.cache)) | ||
| 55 | for k, v := range mc.cache { | ||
| 56 | m[k] = v | ||
| 57 | } | ||
| 58 | return m | ||
| 59 | } | ||
| 60 | |||
| 61 | func (mc *_modelCache) allOrdered() []*modelInfo { | ||
| 62 | m := make([]*modelInfo, 0, len(mc.orders)) | ||
| 63 | for _, v := range mc.cache { | ||
| 64 | m = append(m, v) | ||
| 65 | } | ||
| 66 | return m | ||
| 67 | } | ||
| 68 | |||
| 69 | func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) { | ||
| 70 | mi, ok = mc.cache[table] | ||
| 71 | return | ||
| 72 | } | ||
| 73 | |||
| 74 | func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo { | ||
| 75 | mii := mc.cache[table] | ||
| 76 | mc.cache[table] = mi | ||
| 77 | if mii == nil { | ||
| 78 | mc.orders = append(mc.orders, table) | ||
| 79 | } | ||
| 80 | return mii | ||
| 81 | } |
orm/models_boot.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "errors" | ||
| 5 | "fmt" | ||
| 6 | "os" | ||
| 7 | "reflect" | ||
| 8 | "strings" | ||
| 9 | ) | ||
| 10 | |||
| 11 | func RegisterModel(model Modeler) { | ||
| 12 | info := newModelInfo(model) | ||
| 13 | model.Init(model) | ||
| 14 | table := model.GetTableName() | ||
| 15 | if _, ok := modelCache.get(table); ok { | ||
| 16 | fmt.Printf("model <%T> redeclared, must be unique\n", model) | ||
| 17 | os.Exit(2) | ||
| 18 | } | ||
| 19 | if info.fields.pk == nil { | ||
| 20 | fmt.Printf("model <%T> need a primary key field\n", model) | ||
| 21 | os.Exit(2) | ||
| 22 | } | ||
| 23 | info.table = table | ||
| 24 | info.pkg = getPkgPath(model) | ||
| 25 | info.model = model | ||
| 26 | info.manual = true | ||
| 27 | modelCache.set(table, info) | ||
| 28 | } | ||
| 29 | |||
| 30 | func BootStrap() { | ||
| 31 | modelCache.Lock() | ||
| 32 | defer modelCache.Unlock() | ||
| 33 | |||
| 34 | var ( | ||
| 35 | err error | ||
| 36 | models map[string]*modelInfo | ||
| 37 | ) | ||
| 38 | |||
| 39 | if dataBaseCache.getDefault() == nil { | ||
| 40 | err = fmt.Errorf("must have one register alias named `default`") | ||
| 41 | goto end | ||
| 42 | } | ||
| 43 | |||
| 44 | models = modelCache.all() | ||
| 45 | for _, mi := range models { | ||
| 46 | for _, fi := range mi.fields.columns { | ||
| 47 | if fi.rel || fi.reverse { | ||
| 48 | elm := fi.addrValue.Type().Elem() | ||
| 49 | switch fi.fieldType { | ||
| 50 | case RelReverseMany, RelManyToMany: | ||
| 51 | elm = elm.Elem() | ||
| 52 | } | ||
| 53 | |||
| 54 | tn := getTableName(reflect.New(elm).Interface().(Modeler)) | ||
| 55 | mii, ok := modelCache.get(tn) | ||
| 56 | if ok == false || mii.pkg != elm.PkgPath() { | ||
| 57 | err = fmt.Errorf("can not found rel in field `%s`, `%s` may be miss register", fi.fullName, elm.String()) | ||
| 58 | goto end | ||
| 59 | } | ||
| 60 | fi.relModelInfo = mii | ||
| 61 | |||
| 62 | if fi.rel { | ||
| 63 | |||
| 64 | if mii.fields.pk.IsMulti() { | ||
| 65 | err = fmt.Errorf("field `%s` unsupport rel to multi primary key field", fi.fullName) | ||
| 66 | goto end | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | switch fi.fieldType { | ||
| 71 | case RelManyToMany: | ||
| 72 | if fi.relThrough != "" { | ||
| 73 | msg := fmt.Sprintf("filed `%s` wrong rel_through value `%s`", fi.fullName, fi.relThrough) | ||
| 74 | if i := strings.LastIndex(fi.relThrough, "."); i != -1 && len(fi.relThrough) > (i+1) { | ||
| 75 | pn := fi.relThrough[:i] | ||
| 76 | mn := fi.relThrough[i+1:] | ||
| 77 | tn := snakeString(mn) | ||
| 78 | rmi, ok := modelCache.get(tn) | ||
| 79 | if ok == false || pn != rmi.pkg { | ||
| 80 | err = errors.New(msg + " cannot find table") | ||
| 81 | goto end | ||
| 82 | } | ||
| 83 | |||
| 84 | fi.relThroughModelInfo = rmi | ||
| 85 | fi.relTable = rmi.table | ||
| 86 | |||
| 87 | } else { | ||
| 88 | err = errors.New(msg) | ||
| 89 | goto end | ||
| 90 | } | ||
| 91 | err = nil | ||
| 92 | } else { | ||
| 93 | i := newM2MModelInfo(mi, mii) | ||
| 94 | if fi.relTable != "" { | ||
| 95 | i.table = fi.relTable | ||
| 96 | } | ||
| 97 | |||
| 98 | if v := modelCache.set(i.table, i); v != nil { | ||
| 99 | err = fmt.Errorf("the rel table name `%s` already registered, cannot be use, please change one", fi.relTable) | ||
| 100 | goto end | ||
| 101 | } | ||
| 102 | fi.relTable = i.table | ||
| 103 | fi.relThroughModelInfo = i | ||
| 104 | } | ||
| 105 | } | ||
| 106 | } | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | models = modelCache.all() | ||
| 111 | for _, mi := range models { | ||
| 112 | for _, fi := range mi.fields.fieldsRel { | ||
| 113 | switch fi.fieldType { | ||
| 114 | case RelForeignKey, RelOneToOne, RelManyToMany: | ||
| 115 | inModel := false | ||
| 116 | for _, ffi := range fi.relModelInfo.fields.fieldsReverse { | ||
| 117 | if ffi.relModelInfo == mi { | ||
| 118 | inModel = true | ||
| 119 | break | ||
| 120 | } | ||
| 121 | } | ||
| 122 | if inModel == false { | ||
| 123 | rmi := fi.relModelInfo | ||
| 124 | ffi := new(fieldInfo) | ||
| 125 | ffi.name = mi.name | ||
| 126 | ffi.column = ffi.name | ||
| 127 | ffi.fullName = rmi.fullName + "." + ffi.name | ||
| 128 | ffi.reverse = true | ||
| 129 | ffi.relModelInfo = mi | ||
| 130 | ffi.mi = rmi | ||
| 131 | if fi.fieldType == RelOneToOne { | ||
| 132 | ffi.fieldType = RelReverseOne | ||
| 133 | } else { | ||
| 134 | ffi.fieldType = RelReverseMany | ||
| 135 | } | ||
| 136 | if rmi.fields.Add(ffi) == false { | ||
| 137 | added := false | ||
| 138 | for cnt := 0; cnt < 5; cnt++ { | ||
| 139 | ffi.name = fmt.Sprintf("%s%d", mi.name, cnt) | ||
| 140 | ffi.column = ffi.name | ||
| 141 | ffi.fullName = rmi.fullName + "." + ffi.name | ||
| 142 | if added = rmi.fields.Add(ffi); added { | ||
| 143 | break | ||
| 144 | } | ||
| 145 | } | ||
| 146 | if added == false { | ||
| 147 | panic(fmt.Sprintf("cannot generate auto reverse field info `%s` to `%s`", fi.fullName, ffi.fullName)) | ||
| 148 | } | ||
| 149 | } | ||
| 150 | } | ||
| 151 | } | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | for _, mi := range models { | ||
| 156 | if fields, ok := mi.fields.fieldsByType[RelReverseOne]; ok { | ||
| 157 | for _, fi := range fields { | ||
| 158 | found := false | ||
| 159 | mForA: | ||
| 160 | for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelOneToOne] { | ||
| 161 | if ffi.relModelInfo == mi { | ||
| 162 | found = true | ||
| 163 | fi.reverseField = ffi.name | ||
| 164 | fi.reverseFieldInfo = ffi | ||
| 165 | break mForA | ||
| 166 | } | ||
| 167 | } | ||
| 168 | if found == false { | ||
| 169 | err = fmt.Errorf("reverse field `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName) | ||
| 170 | goto end | ||
| 171 | } | ||
| 172 | } | ||
| 173 | } | ||
| 174 | if fields, ok := mi.fields.fieldsByType[RelReverseMany]; ok { | ||
| 175 | for _, fi := range fields { | ||
| 176 | found := false | ||
| 177 | mForB: | ||
| 178 | for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelForeignKey] { | ||
| 179 | if ffi.relModelInfo == mi { | ||
| 180 | found = true | ||
| 181 | fi.reverseField = ffi.name | ||
| 182 | fi.reverseFieldInfo = ffi | ||
| 183 | break mForB | ||
| 184 | } | ||
| 185 | } | ||
| 186 | if found == false { | ||
| 187 | mForC: | ||
| 188 | for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelManyToMany] { | ||
| 189 | if ffi.relModelInfo == mi { | ||
| 190 | found = true | ||
| 191 | fi.reverseField = ffi.name | ||
| 192 | fi.reverseFieldInfo = ffi | ||
| 193 | break mForC | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | if found == false { | ||
| 198 | err = fmt.Errorf("reverse field `%s` not found in model `%s`", fi.fullName, fi.relModelInfo.fullName) | ||
| 199 | goto end | ||
| 200 | } | ||
| 201 | } | ||
| 202 | } | ||
| 203 | } | ||
| 204 | |||
| 205 | end: | ||
| 206 | if err != nil { | ||
| 207 | fmt.Println(err) | ||
| 208 | os.Exit(2) | ||
| 209 | } | ||
| 210 | |||
| 211 | runCommand() | ||
| 212 | } |
orm/models_fields.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "errors" | ||
| 5 | "fmt" | ||
| 6 | "strconv" | ||
| 7 | "time" | ||
| 8 | ) | ||
| 9 | |||
| 10 | const ( | ||
| 11 | // bool | ||
| 12 | TypeBooleanField = 1 << iota | ||
| 13 | |||
| 14 | // string | ||
| 15 | TypeCharField | ||
| 16 | |||
| 17 | // string | ||
| 18 | TypeTextField | ||
| 19 | |||
| 20 | // time.Time | ||
| 21 | TypeDateField | ||
| 22 | // time.Time | ||
| 23 | TypeDateTimeField | ||
| 24 | |||
| 25 | // int16 | ||
| 26 | TypeSmallIntegerField | ||
| 27 | // int32 | ||
| 28 | TypeIntegerField | ||
| 29 | // int64 | ||
| 30 | TypeBigIntegerField | ||
| 31 | // uint16 | ||
| 32 | TypePositiveSmallIntegerField | ||
| 33 | // uint32 | ||
| 34 | TypePositiveIntegerField | ||
| 35 | // uint64 | ||
| 36 | TypePositiveBigIntegerField | ||
| 37 | |||
| 38 | // float64 | ||
| 39 | TypeFloatField | ||
| 40 | // float64 | ||
| 41 | TypeDecimalField | ||
| 42 | |||
| 43 | RelForeignKey | ||
| 44 | RelOneToOne | ||
| 45 | RelManyToMany | ||
| 46 | RelReverseOne | ||
| 47 | RelReverseMany | ||
| 48 | ) | ||
| 49 | |||
| 50 | const ( | ||
| 51 | IsIntegerField = ^-TypePositiveBigIntegerField >> 4 << 5 | ||
| 52 | IsPostiveIntegerField = ^-TypePositiveBigIntegerField >> 7 << 8 | ||
| 53 | IsRelField = ^-RelReverseMany >> 12 << 13 | ||
| 54 | IsFieldType = ^-RelReverseMany<<1 + 1 | ||
| 55 | ) | ||
| 56 | |||
| 57 | // A true/false field. | ||
| 58 | type BooleanField bool | ||
| 59 | |||
| 60 | func (e BooleanField) Value() bool { | ||
| 61 | return bool(e) | ||
| 62 | } | ||
| 63 | |||
| 64 | func (e *BooleanField) Set(d bool) { | ||
| 65 | *e = BooleanField(d) | ||
| 66 | } | ||
| 67 | |||
| 68 | func (e *BooleanField) String() string { | ||
| 69 | return strconv.FormatBool(e.Value()) | ||
| 70 | } | ||
| 71 | |||
| 72 | func (e *BooleanField) FieldType() int { | ||
| 73 | return TypeBooleanField | ||
| 74 | } | ||
| 75 | |||
| 76 | func (e *BooleanField) SetRaw(value interface{}) error { | ||
| 77 | switch d := value.(type) { | ||
| 78 | case bool: | ||
| 79 | e.Set(d) | ||
| 80 | case string: | ||
| 81 | v, err := StrTo(d).Bool() | ||
| 82 | if err != nil { | ||
| 83 | e.Set(v) | ||
| 84 | } | ||
| 85 | return err | ||
| 86 | default: | ||
| 87 | return errors.New(fmt.Sprintf("<BooleanField.SetRaw> unknown value `%s`", value)) | ||
| 88 | } | ||
| 89 | return nil | ||
| 90 | } | ||
| 91 | |||
| 92 | func (e *BooleanField) RawValue() interface{} { | ||
| 93 | return e.Value() | ||
| 94 | } | ||
| 95 | |||
| 96 | // A string field | ||
| 97 | // required values tag: max_length | ||
| 98 | // The max_length is enforced at the database level and in models’s validation. | ||
| 99 | // eg: `max_length:"120"` | ||
| 100 | type CharField string | ||
| 101 | |||
| 102 | func (e CharField) Value() string { | ||
| 103 | return string(e) | ||
| 104 | } | ||
| 105 | |||
| 106 | func (e *CharField) Set(d string) { | ||
| 107 | *e = CharField(d) | ||
| 108 | } | ||
| 109 | |||
| 110 | func (e *CharField) String() string { | ||
| 111 | return e.Value() | ||
| 112 | } | ||
| 113 | |||
| 114 | func (e *CharField) FieldType() int { | ||
| 115 | return TypeCharField | ||
| 116 | } | ||
| 117 | |||
| 118 | func (e *CharField) SetRaw(value interface{}) error { | ||
| 119 | switch d := value.(type) { | ||
| 120 | case string: | ||
| 121 | e.Set(d) | ||
| 122 | default: | ||
| 123 | return errors.New(fmt.Sprintf("<CharField.SetRaw> unknown value `%s`", value)) | ||
| 124 | } | ||
| 125 | return nil | ||
| 126 | } | ||
| 127 | |||
| 128 | func (e *CharField) RawValue() interface{} { | ||
| 129 | return e.Value() | ||
| 130 | } | ||
| 131 | |||
| 132 | // A date, represented in go by a time.Time instance. | ||
| 133 | // only date values like 2006-01-02 | ||
| 134 | // Has a few extra, optional attr tag: | ||
| 135 | // | ||
| 136 | // auto_now: | ||
| 137 | // Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps. | ||
| 138 | // Note that the current date is always used; it’s not just a default value that you can override. | ||
| 139 | // | ||
| 140 | // auto_now_add: | ||
| 141 | // Automatically set the field to now when the object is first created. Useful for creation of timestamps. | ||
| 142 | // Note that the current date is always used; it’s not just a default value that you can override. | ||
| 143 | // | ||
| 144 | // eg: `attr:"auto_now"` or `attr:"auto_now_add"` | ||
| 145 | type DateField time.Time | ||
| 146 | |||
| 147 | func (e DateField) Value() time.Time { | ||
| 148 | return time.Time(e) | ||
| 149 | } | ||
| 150 | |||
| 151 | func (e *DateField) Set(d time.Time) { | ||
| 152 | *e = DateField(d) | ||
| 153 | } | ||
| 154 | |||
| 155 | func (e *DateField) String() string { | ||
| 156 | return e.Value().String() | ||
| 157 | } | ||
| 158 | |||
| 159 | func (e *DateField) FieldType() int { | ||
| 160 | return TypeDateField | ||
| 161 | } | ||
| 162 | |||
| 163 | func (e *DateField) SetRaw(value interface{}) error { | ||
| 164 | switch d := value.(type) { | ||
| 165 | case time.Time: | ||
| 166 | e.Set(d) | ||
| 167 | case string: | ||
| 168 | v, err := timeParse(d, format_Date) | ||
| 169 | if err != nil { | ||
| 170 | e.Set(v) | ||
| 171 | } | ||
| 172 | return err | ||
| 173 | default: | ||
| 174 | return errors.New(fmt.Sprintf("<DateField.SetRaw> unknown value `%s`", value)) | ||
| 175 | } | ||
| 176 | return nil | ||
| 177 | } | ||
| 178 | |||
| 179 | func (e *DateField) RawValue() interface{} { | ||
| 180 | return e.Value() | ||
| 181 | } | ||
| 182 | |||
| 183 | // A date, represented in go by a time.Time instance. | ||
| 184 | // datetime values like 2006-01-02 15:04:05 | ||
| 185 | // Takes the same extra arguments as DateField. | ||
| 186 | type DateTimeField time.Time | ||
| 187 | |||
| 188 | func (e DateTimeField) Value() time.Time { | ||
| 189 | return time.Time(e) | ||
| 190 | } | ||
| 191 | |||
| 192 | func (e *DateTimeField) Set(d time.Time) { | ||
| 193 | *e = DateTimeField(d) | ||
| 194 | } | ||
| 195 | |||
| 196 | func (e *DateTimeField) String() string { | ||
| 197 | return e.Value().String() | ||
| 198 | } | ||
| 199 | |||
| 200 | func (e *DateTimeField) FieldType() int { | ||
| 201 | return TypeDateTimeField | ||
| 202 | } | ||
| 203 | |||
| 204 | func (e *DateTimeField) SetRaw(value interface{}) error { | ||
| 205 | switch d := value.(type) { | ||
| 206 | case time.Time: | ||
| 207 | e.Set(d) | ||
| 208 | case string: | ||
| 209 | v, err := timeParse(d, format_DateTime) | ||
| 210 | if err != nil { | ||
| 211 | e.Set(v) | ||
| 212 | } | ||
| 213 | return err | ||
| 214 | default: | ||
| 215 | return errors.New(fmt.Sprintf("<DateTimeField.SetRaw> unknown value `%s`", value)) | ||
| 216 | } | ||
| 217 | return nil | ||
| 218 | } | ||
| 219 | |||
| 220 | func (e *DateTimeField) RawValue() interface{} { | ||
| 221 | return e.Value() | ||
| 222 | } | ||
| 223 | |||
| 224 | // A floating-point number represented in go by a float32 value. | ||
| 225 | type FloatField float64 | ||
| 226 | |||
| 227 | func (e FloatField) Value() float64 { | ||
| 228 | return float64(e) | ||
| 229 | } | ||
| 230 | |||
| 231 | func (e *FloatField) Set(d float64) { | ||
| 232 | *e = FloatField(d) | ||
| 233 | } | ||
| 234 | |||
| 235 | func (e *FloatField) String() string { | ||
| 236 | return ToStr(e.Value(), -1, 32) | ||
| 237 | } | ||
| 238 | |||
| 239 | func (e *FloatField) FieldType() int { | ||
| 240 | return TypeFloatField | ||
| 241 | } | ||
| 242 | |||
| 243 | func (e *FloatField) SetRaw(value interface{}) error { | ||
| 244 | switch d := value.(type) { | ||
| 245 | case float32: | ||
| 246 | e.Set(float64(d)) | ||
| 247 | case float64: | ||
| 248 | e.Set(d) | ||
| 249 | case string: | ||
| 250 | v, err := StrTo(d).Float64() | ||
| 251 | if err != nil { | ||
| 252 | e.Set(v) | ||
| 253 | } | ||
| 254 | default: | ||
| 255 | return errors.New(fmt.Sprintf("<FloatField.SetRaw> unknown value `%s`", value)) | ||
| 256 | } | ||
| 257 | return nil | ||
| 258 | } | ||
| 259 | |||
| 260 | func (e *FloatField) RawValue() interface{} { | ||
| 261 | return e.Value() | ||
| 262 | } | ||
| 263 | |||
| 264 | // -32768 to 32767 | ||
| 265 | type SmallIntegerField int16 | ||
| 266 | |||
| 267 | func (e SmallIntegerField) Value() int16 { | ||
| 268 | return int16(e) | ||
| 269 | } | ||
| 270 | |||
| 271 | func (e *SmallIntegerField) Set(d int16) { | ||
| 272 | *e = SmallIntegerField(d) | ||
| 273 | } | ||
| 274 | |||
| 275 | func (e *SmallIntegerField) String() string { | ||
| 276 | return ToStr(e.Value()) | ||
| 277 | } | ||
| 278 | |||
| 279 | func (e *SmallIntegerField) FieldType() int { | ||
| 280 | return TypeSmallIntegerField | ||
| 281 | } | ||
| 282 | |||
| 283 | func (e *SmallIntegerField) SetRaw(value interface{}) error { | ||
| 284 | switch d := value.(type) { | ||
| 285 | case int16: | ||
| 286 | e.Set(d) | ||
| 287 | case string: | ||
| 288 | v, err := StrTo(d).Int16() | ||
| 289 | if err != nil { | ||
| 290 | e.Set(v) | ||
| 291 | } | ||
| 292 | default: | ||
| 293 | return errors.New(fmt.Sprintf("<SmallIntegerField.SetRaw> unknown value `%s`", value)) | ||
| 294 | } | ||
| 295 | return nil | ||
| 296 | } | ||
| 297 | |||
| 298 | func (e *SmallIntegerField) RawValue() interface{} { | ||
| 299 | return e.Value() | ||
| 300 | } | ||
| 301 | |||
| 302 | // -2147483648 to 2147483647 | ||
| 303 | type IntegerField int32 | ||
| 304 | |||
| 305 | func (e IntegerField) Value() int32 { | ||
| 306 | return int32(e) | ||
| 307 | } | ||
| 308 | |||
| 309 | func (e *IntegerField) Set(d int32) { | ||
| 310 | *e = IntegerField(d) | ||
| 311 | } | ||
| 312 | |||
| 313 | func (e *IntegerField) String() string { | ||
| 314 | return ToStr(e.Value()) | ||
| 315 | } | ||
| 316 | |||
| 317 | func (e *IntegerField) FieldType() int { | ||
| 318 | return TypeIntegerField | ||
| 319 | } | ||
| 320 | |||
| 321 | func (e *IntegerField) SetRaw(value interface{}) error { | ||
| 322 | switch d := value.(type) { | ||
| 323 | case int32: | ||
| 324 | e.Set(d) | ||
| 325 | case string: | ||
| 326 | v, err := StrTo(d).Int32() | ||
| 327 | if err != nil { | ||
| 328 | e.Set(v) | ||
| 329 | } | ||
| 330 | default: | ||
| 331 | return errors.New(fmt.Sprintf("<IntegerField.SetRaw> unknown value `%s`", value)) | ||
| 332 | } | ||
| 333 | return nil | ||
| 334 | } | ||
| 335 | |||
| 336 | func (e *IntegerField) RawValue() interface{} { | ||
| 337 | return e.Value() | ||
| 338 | } | ||
| 339 | |||
| 340 | // -9223372036854775808 to 9223372036854775807. | ||
| 341 | type BigIntegerField int64 | ||
| 342 | |||
| 343 | func (e BigIntegerField) Value() int64 { | ||
| 344 | return int64(e) | ||
| 345 | } | ||
| 346 | |||
| 347 | func (e *BigIntegerField) Set(d int64) { | ||
| 348 | *e = BigIntegerField(d) | ||
| 349 | } | ||
| 350 | |||
| 351 | func (e *BigIntegerField) String() string { | ||
| 352 | return ToStr(e.Value()) | ||
| 353 | } | ||
| 354 | |||
| 355 | func (e *BigIntegerField) FieldType() int { | ||
| 356 | return TypeBigIntegerField | ||
| 357 | } | ||
| 358 | |||
| 359 | func (e *BigIntegerField) SetRaw(value interface{}) error { | ||
| 360 | switch d := value.(type) { | ||
| 361 | case int64: | ||
| 362 | e.Set(d) | ||
| 363 | case string: | ||
| 364 | v, err := StrTo(d).Int64() | ||
| 365 | if err != nil { | ||
| 366 | e.Set(v) | ||
| 367 | } | ||
| 368 | default: | ||
| 369 | return errors.New(fmt.Sprintf("<BigIntegerField.SetRaw> unknown value `%s`", value)) | ||
| 370 | } | ||
| 371 | return nil | ||
| 372 | } | ||
| 373 | |||
| 374 | func (e *BigIntegerField) RawValue() interface{} { | ||
| 375 | return e.Value() | ||
| 376 | } | ||
| 377 | |||
| 378 | // 0 to 65535 | ||
| 379 | type PositiveSmallIntegerField uint16 | ||
| 380 | |||
| 381 | func (e PositiveSmallIntegerField) Value() uint16 { | ||
| 382 | return uint16(e) | ||
| 383 | } | ||
| 384 | |||
| 385 | func (e *PositiveSmallIntegerField) Set(d uint16) { | ||
| 386 | *e = PositiveSmallIntegerField(d) | ||
| 387 | } | ||
| 388 | |||
| 389 | func (e *PositiveSmallIntegerField) String() string { | ||
| 390 | return ToStr(e.Value()) | ||
| 391 | } | ||
| 392 | |||
| 393 | func (e *PositiveSmallIntegerField) FieldType() int { | ||
| 394 | return TypePositiveSmallIntegerField | ||
| 395 | } | ||
| 396 | |||
| 397 | func (e *PositiveSmallIntegerField) SetRaw(value interface{}) error { | ||
| 398 | switch d := value.(type) { | ||
| 399 | case uint16: | ||
| 400 | e.Set(d) | ||
| 401 | case string: | ||
| 402 | v, err := StrTo(d).Uint16() | ||
| 403 | if err != nil { | ||
| 404 | e.Set(v) | ||
| 405 | } | ||
| 406 | default: | ||
| 407 | return errors.New(fmt.Sprintf("<PositiveSmallIntegerField.SetRaw> unknown value `%s`", value)) | ||
| 408 | } | ||
| 409 | return nil | ||
| 410 | } | ||
| 411 | |||
| 412 | func (e *PositiveSmallIntegerField) RawValue() interface{} { | ||
| 413 | return e.Value() | ||
| 414 | } | ||
| 415 | |||
| 416 | // 0 to 4294967295 | ||
| 417 | type PositiveIntegerField uint32 | ||
| 418 | |||
| 419 | func (e PositiveIntegerField) Value() uint32 { | ||
| 420 | return uint32(e) | ||
| 421 | } | ||
| 422 | |||
| 423 | func (e *PositiveIntegerField) Set(d uint32) { | ||
| 424 | *e = PositiveIntegerField(d) | ||
| 425 | } | ||
| 426 | |||
| 427 | func (e *PositiveIntegerField) String() string { | ||
| 428 | return ToStr(e.Value()) | ||
| 429 | } | ||
| 430 | |||
| 431 | func (e *PositiveIntegerField) FieldType() int { | ||
| 432 | return TypePositiveIntegerField | ||
| 433 | } | ||
| 434 | |||
| 435 | func (e *PositiveIntegerField) SetRaw(value interface{}) error { | ||
| 436 | switch d := value.(type) { | ||
| 437 | case uint32: | ||
| 438 | e.Set(d) | ||
| 439 | case string: | ||
| 440 | v, err := StrTo(d).Uint32() | ||
| 441 | if err != nil { | ||
| 442 | e.Set(v) | ||
| 443 | } | ||
| 444 | default: | ||
| 445 | return errors.New(fmt.Sprintf("<PositiveIntegerField.SetRaw> unknown value `%s`", value)) | ||
| 446 | } | ||
| 447 | return nil | ||
| 448 | } | ||
| 449 | |||
| 450 | func (e *PositiveIntegerField) RawValue() interface{} { | ||
| 451 | return e.Value() | ||
| 452 | } | ||
| 453 | |||
| 454 | // 0 to 18446744073709551615 | ||
| 455 | type PositiveBigIntegerField uint64 | ||
| 456 | |||
| 457 | func (e PositiveBigIntegerField) Value() uint64 { | ||
| 458 | return uint64(e) | ||
| 459 | } | ||
| 460 | |||
| 461 | func (e *PositiveBigIntegerField) Set(d uint64) { | ||
| 462 | *e = PositiveBigIntegerField(d) | ||
| 463 | } | ||
| 464 | |||
| 465 | func (e *PositiveBigIntegerField) String() string { | ||
| 466 | return ToStr(e.Value()) | ||
| 467 | } | ||
| 468 | |||
| 469 | func (e *PositiveBigIntegerField) FieldType() int { | ||
| 470 | return TypePositiveIntegerField | ||
| 471 | } | ||
| 472 | |||
| 473 | func (e *PositiveBigIntegerField) SetRaw(value interface{}) error { | ||
| 474 | switch d := value.(type) { | ||
| 475 | case uint64: | ||
| 476 | e.Set(d) | ||
| 477 | case string: | ||
| 478 | v, err := StrTo(d).Uint64() | ||
| 479 | if err != nil { | ||
| 480 | e.Set(v) | ||
| 481 | } | ||
| 482 | default: | ||
| 483 | return errors.New(fmt.Sprintf("<PositiveBigIntegerField.SetRaw> unknown value `%s`", value)) | ||
| 484 | } | ||
| 485 | return nil | ||
| 486 | } | ||
| 487 | |||
| 488 | func (e *PositiveBigIntegerField) RawValue() interface{} { | ||
| 489 | return e.Value() | ||
| 490 | } | ||
| 491 | |||
| 492 | // A large text field. | ||
| 493 | type TextField string | ||
| 494 | |||
| 495 | func (e TextField) Value() string { | ||
| 496 | return string(e) | ||
| 497 | } | ||
| 498 | |||
| 499 | func (e *TextField) Set(d string) { | ||
| 500 | *e = TextField(d) | ||
| 501 | } | ||
| 502 | |||
| 503 | func (e *TextField) String() string { | ||
| 504 | return e.Value() | ||
| 505 | } | ||
| 506 | |||
| 507 | func (e *TextField) FieldType() int { | ||
| 508 | return TypeTextField | ||
| 509 | } | ||
| 510 | |||
| 511 | func (e *TextField) SetRaw(value interface{}) error { | ||
| 512 | switch d := value.(type) { | ||
| 513 | case string: | ||
| 514 | e.Set(d) | ||
| 515 | default: | ||
| 516 | return errors.New(fmt.Sprintf("<TextField.SetRaw> unknown value `%s`", value)) | ||
| 517 | } | ||
| 518 | return nil | ||
| 519 | } | ||
| 520 | |||
| 521 | func (e *TextField) RawValue() interface{} { | ||
| 522 | return e.Value() | ||
| 523 | } |
orm/models_info_f.go
0 → 100644
This diff is collapsed.
Click to expand it.
orm/models_info_m.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "errors" | ||
| 5 | "fmt" | ||
| 6 | "os" | ||
| 7 | "reflect" | ||
| 8 | ) | ||
| 9 | |||
| 10 | type modelInfo struct { | ||
| 11 | pkg string | ||
| 12 | name string | ||
| 13 | fullName string | ||
| 14 | table string | ||
| 15 | model Modeler | ||
| 16 | fields *fields | ||
| 17 | manual bool | ||
| 18 | addrField reflect.Value | ||
| 19 | } | ||
| 20 | |||
| 21 | func newModelInfo(model Modeler) (info *modelInfo) { | ||
| 22 | var ( | ||
| 23 | err error | ||
| 24 | fi *fieldInfo | ||
| 25 | sf reflect.StructField | ||
| 26 | ) | ||
| 27 | |||
| 28 | info = &modelInfo{} | ||
| 29 | info.fields = newFields() | ||
| 30 | |||
| 31 | val := reflect.ValueOf(model) | ||
| 32 | ind := reflect.Indirect(val) | ||
| 33 | typ := ind.Type() | ||
| 34 | |||
| 35 | info.addrField = ind.Addr() | ||
| 36 | |||
| 37 | info.name = typ.Name() | ||
| 38 | info.fullName = typ.PkgPath() + "." + typ.Name() | ||
| 39 | |||
| 40 | for i := 0; i < ind.NumField(); i++ { | ||
| 41 | field := ind.Field(i) | ||
| 42 | 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) | ||
| 50 | if err != nil { | ||
| 51 | break | ||
| 52 | } | ||
| 53 | added := info.fields.Add(fi) | ||
| 54 | if added == false { | ||
| 55 | err = errors.New(fmt.Sprintf("duplicate column name: %s", fi.column)) | ||
| 56 | break | ||
| 57 | } | ||
| 58 | if fi.pk { | ||
| 59 | if info.fields.pk != nil { | ||
| 60 | err = errors.New(fmt.Sprintf("one model must have one pk field only")) | ||
| 61 | break | ||
| 62 | } else { | ||
| 63 | info.fields.pk.Add(fi) | ||
| 64 | } | ||
| 65 | } | ||
| 66 | if fi.auto { | ||
| 67 | info.fields.auto = fi | ||
| 68 | } | ||
| 69 | fi.fieldIndex = i | ||
| 70 | fi.mi = info | ||
| 71 | } | ||
| 72 | |||
| 73 | if _, ok := info.fields.pk.Exist(info.fields.auto); info.fields.auto != nil && ok == false { | ||
| 74 | err = errors.New(fmt.Sprintf("when auto field exists, you cannot set other pk field")) | ||
| 75 | goto end | ||
| 76 | } | ||
| 77 | |||
| 78 | if err != nil { | ||
| 79 | fmt.Println(fmt.Errorf("field: %s.%s, %s", ind.Type(), sf.Name, err)) | ||
| 80 | os.Exit(2) | ||
| 81 | } | ||
| 82 | |||
| 83 | end: | ||
| 84 | if err != nil { | ||
| 85 | fmt.Println(err) | ||
| 86 | os.Exit(2) | ||
| 87 | } | ||
| 88 | return | ||
| 89 | } | ||
| 90 | |||
| 91 | func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) { | ||
| 92 | info = new(modelInfo) | ||
| 93 | info.fields = newFields() | ||
| 94 | info.table = m1.table + "_" + m2.table + "_rel" | ||
| 95 | info.name = camelString(info.table) | ||
| 96 | info.fullName = m1.pkg + "." + info.name | ||
| 97 | |||
| 98 | fa := new(fieldInfo) | ||
| 99 | f1 := new(fieldInfo) | ||
| 100 | f2 := new(fieldInfo) | ||
| 101 | fa.fieldType = TypeBigIntegerField | ||
| 102 | fa.auto = true | ||
| 103 | fa.pk = true | ||
| 104 | fa.dbcol = true | ||
| 105 | |||
| 106 | f1.dbcol = true | ||
| 107 | f2.dbcol = true | ||
| 108 | f1.fieldType = RelForeignKey | ||
| 109 | f2.fieldType = RelForeignKey | ||
| 110 | f1.name = camelString(m1.table) | ||
| 111 | f2.name = camelString(m2.table) | ||
| 112 | f1.fullName = info.fullName + "." + f1.name | ||
| 113 | f2.fullName = info.fullName + "." + f2.name | ||
| 114 | f1.column = m1.table + "_id" | ||
| 115 | f2.column = m2.table + "_id" | ||
| 116 | f1.rel = true | ||
| 117 | f2.rel = true | ||
| 118 | f1.relTable = m1.table | ||
| 119 | f2.relTable = m2.table | ||
| 120 | f1.relModelInfo = m1 | ||
| 121 | f2.relModelInfo = m2 | ||
| 122 | f1.mi = info | ||
| 123 | f2.mi = info | ||
| 124 | |||
| 125 | info.fields.Add(fa) | ||
| 126 | info.fields.Add(f1) | ||
| 127 | info.fields.Add(f2) | ||
| 128 | info.fields.pk.Add(fa) | ||
| 129 | return | ||
| 130 | } |
orm/models_manager.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import () | ||
| 4 | |||
| 5 | // non cleaned field errors | ||
| 6 | type FieldErrors map[string]error | ||
| 7 | |||
| 8 | func (fe FieldErrors) Get(name string) error { | ||
| 9 | return fe[name] | ||
| 10 | } | ||
| 11 | |||
| 12 | func (fe FieldErrors) Set(name string, value error) { | ||
| 13 | fe[name] = value | ||
| 14 | } | ||
| 15 | |||
| 16 | type Manager struct { | ||
| 17 | ins Modeler | ||
| 18 | inited bool | ||
| 19 | } | ||
| 20 | |||
| 21 | // func (m *Manager) init(model reflect.Value) { | ||
| 22 | // elm := model.Elem() | ||
| 23 | // for i := 0; i < elm.NumField(); i++ { | ||
| 24 | // field := elm.Field(i) | ||
| 25 | // if _, ok := field.Interface().(Fielder); ok && field.CanSet() { | ||
| 26 | // if field.Elem().Kind() != reflect.Struct { | ||
| 27 | // field.Set(reflect.New(field.Type().Elem())) | ||
| 28 | // } | ||
| 29 | // } | ||
| 30 | // } | ||
| 31 | // } | ||
| 32 | |||
| 33 | func (m *Manager) Init(model Modeler) Modeler { | ||
| 34 | if m.inited { | ||
| 35 | return m.ins | ||
| 36 | } | ||
| 37 | m.inited = true | ||
| 38 | m.ins = model | ||
| 39 | return model | ||
| 40 | } | ||
| 41 | |||
| 42 | func (m *Manager) IsInited() bool { | ||
| 43 | return m.inited | ||
| 44 | } | ||
| 45 | |||
| 46 | func (m *Manager) Clean() FieldErrors { | ||
| 47 | return nil | ||
| 48 | } | ||
| 49 | |||
| 50 | func (m *Manager) CleanFields(name string) FieldErrors { | ||
| 51 | return nil | ||
| 52 | } | ||
| 53 | |||
| 54 | func (m *Manager) GetTableName() string { | ||
| 55 | return getTableName(m.ins) | ||
| 56 | } |
orm/models_utils.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "reflect" | ||
| 6 | "strings" | ||
| 7 | "time" | ||
| 8 | ) | ||
| 9 | |||
| 10 | func getTableName(model Modeler) string { | ||
| 11 | val := reflect.ValueOf(model) | ||
| 12 | ind := reflect.Indirect(val) | ||
| 13 | fun := val.MethodByName("TableName") | ||
| 14 | if fun.IsValid() { | ||
| 15 | vals := fun.Call([]reflect.Value{}) | ||
| 16 | if len(vals) > 0 { | ||
| 17 | val := vals[0] | ||
| 18 | if val.Kind() == reflect.String { | ||
| 19 | return val.String() | ||
| 20 | } | ||
| 21 | } | ||
| 22 | } | ||
| 23 | return snakeString(ind.Type().Name()) | ||
| 24 | } | ||
| 25 | |||
| 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 { | ||
| 32 | column := strings.ToLower(col) | ||
| 33 | if column == "" { | ||
| 34 | column = snakeString(sf.Name) | ||
| 35 | } | ||
| 36 | switch ft { | ||
| 37 | case RelForeignKey, RelOneToOne: | ||
| 38 | column = column + "_id" | ||
| 39 | case RelManyToMany, RelReverseMany, RelReverseOne: | ||
| 40 | column = sf.Name | ||
| 41 | } | ||
| 42 | return column | ||
| 43 | } | ||
| 44 | |||
| 45 | func getFieldType(val reflect.Value) (ft int, err error) { | ||
| 46 | elm := reflect.Indirect(val) | ||
| 47 | switch elm.Kind() { | ||
| 48 | case reflect.Int16: | ||
| 49 | ft = TypeSmallIntegerField | ||
| 50 | case reflect.Int32, reflect.Int: | ||
| 51 | ft = TypeIntegerField | ||
| 52 | case reflect.Int64: | ||
| 53 | ft = TypeBigIntegerField | ||
| 54 | case reflect.Uint16: | ||
| 55 | ft = TypePositiveSmallIntegerField | ||
| 56 | case reflect.Uint32: | ||
| 57 | ft = TypePositiveIntegerField | ||
| 58 | case reflect.Uint64: | ||
| 59 | ft = TypePositiveBigIntegerField | ||
| 60 | case reflect.Float32, reflect.Float64: | ||
| 61 | ft = TypeFloatField | ||
| 62 | case reflect.Bool: | ||
| 63 | ft = TypeBooleanField | ||
| 64 | case reflect.String: | ||
| 65 | ft = TypeTextField | ||
| 66 | case reflect.Invalid: | ||
| 67 | default: | ||
| 68 | if elm.CanInterface() { | ||
| 69 | if _, ok := elm.Interface().(time.Time); ok { | ||
| 70 | ft = TypeDateTimeField | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | if ft&IsFieldType == 0 { | ||
| 75 | err = fmt.Errorf("unsupport field type %s, may be miss setting tag", val) | ||
| 76 | } | ||
| 77 | return | ||
| 78 | } | ||
| 79 | |||
| 80 | func parseStructTag(data string, attrs *map[string]bool, tags *map[string]string) { | ||
| 81 | attr := make(map[string]bool) | ||
| 82 | tag := make(map[string]string) | ||
| 83 | for _, v := range strings.Split(data, ";") { | ||
| 84 | v = strings.TrimSpace(v) | ||
| 85 | if supportTag[v] == 1 { | ||
| 86 | attr[v] = true | ||
| 87 | } else if i := strings.Index(v, "("); i > 0 && strings.Index(v, ")") == len(v)-1 { | ||
| 88 | name := v[:i] | ||
| 89 | if supportTag[name] == 2 { | ||
| 90 | v = v[i+1 : len(v)-1] | ||
| 91 | tag[name] = v | ||
| 92 | } | ||
| 93 | } | ||
| 94 | } | ||
| 95 | *attrs = attr | ||
| 96 | *tags = tag | ||
| 97 | } |
orm/orm.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "database/sql" | ||
| 5 | "errors" | ||
| 6 | "fmt" | ||
| 7 | "time" | ||
| 8 | ) | ||
| 9 | |||
| 10 | var ( | ||
| 11 | ErrTXHasBegin = errors.New("<Ormer.Begin> transaction already begin") | ||
| 12 | ErrTXNotBegin = errors.New("<Ormer.Commit/Rollback> transaction not begin") | ||
| 13 | ErrMultiRows = errors.New("<QuerySeter.One> return multi rows") | ||
| 14 | ErrStmtClosed = errors.New("<QuerySeter.Insert> stmt already closed") | ||
| 15 | DefaultRowsLimit = 1000 | ||
| 16 | DefaultRelsDepth = 5 | ||
| 17 | DefaultTimeLoc = time.Local | ||
| 18 | ) | ||
| 19 | |||
| 20 | type Params map[string]interface{} | ||
| 21 | type ParamsList []interface{} | ||
| 22 | |||
| 23 | type orm struct { | ||
| 24 | alias *alias | ||
| 25 | db dbQuerier | ||
| 26 | isTx bool | ||
| 27 | } | ||
| 28 | |||
| 29 | func (o *orm) Object(md Modeler) ObjectSeter { | ||
| 30 | name := md.GetTableName() | ||
| 31 | if mi, ok := modelCache.get(name); ok { | ||
| 32 | return newObject(o, mi, md) | ||
| 33 | } | ||
| 34 | panic(fmt.Sprintf("<orm.Object> table name: `%s` not exists", name)) | ||
| 35 | } | ||
| 36 | |||
| 37 | func (o *orm) QueryTable(ptrStructOrTableName interface{}) QuerySeter { | ||
| 38 | name := "" | ||
| 39 | if table, ok := ptrStructOrTableName.(string); ok { | ||
| 40 | name = snakeString(table) | ||
| 41 | } else if m, ok := ptrStructOrTableName.(Modeler); ok { | ||
| 42 | name = m.GetTableName() | ||
| 43 | } | ||
| 44 | if mi, ok := modelCache.get(name); ok { | ||
| 45 | return newQuerySet(o, mi) | ||
| 46 | } | ||
| 47 | panic(fmt.Sprintf("<orm.SetTable> table name: `%s` not exists", name)) | ||
| 48 | } | ||
| 49 | |||
| 50 | func (o *orm) Using(name string) error { | ||
| 51 | if o.isTx { | ||
| 52 | panic("<orm.Using> transaction has been start, cannot change db") | ||
| 53 | } | ||
| 54 | if al, ok := dataBaseCache.get(name); ok { | ||
| 55 | o.alias = al | ||
| 56 | o.db = al.DB | ||
| 57 | } else { | ||
| 58 | return errors.New(fmt.Sprintf("<orm.Using> unknown db alias name `%s`", name)) | ||
| 59 | } | ||
| 60 | return nil | ||
| 61 | } | ||
| 62 | |||
| 63 | func (o *orm) Begin() error { | ||
| 64 | if o.isTx { | ||
| 65 | return ErrTXHasBegin | ||
| 66 | } | ||
| 67 | tx, err := o.alias.DB.Begin() | ||
| 68 | if err != nil { | ||
| 69 | return err | ||
| 70 | } | ||
| 71 | o.isTx = true | ||
| 72 | o.db = tx | ||
| 73 | return nil | ||
| 74 | } | ||
| 75 | |||
| 76 | func (o *orm) Commit() error { | ||
| 77 | if o.isTx == false { | ||
| 78 | return ErrTXNotBegin | ||
| 79 | } | ||
| 80 | err := o.db.(*sql.Tx).Commit() | ||
| 81 | if err == nil { | ||
| 82 | o.isTx = false | ||
| 83 | o.db = o.alias.DB | ||
| 84 | } | ||
| 85 | return err | ||
| 86 | } | ||
| 87 | |||
| 88 | func (o *orm) Rollback() error { | ||
| 89 | if o.isTx == false { | ||
| 90 | return ErrTXNotBegin | ||
| 91 | } | ||
| 92 | err := o.db.(*sql.Tx).Rollback() | ||
| 93 | if err == nil { | ||
| 94 | o.isTx = false | ||
| 95 | o.db = o.alias.DB | ||
| 96 | } | ||
| 97 | return err | ||
| 98 | } | ||
| 99 | |||
| 100 | func (o *orm) Raw(query string, args ...interface{}) RawSeter { | ||
| 101 | return newRawSet(o, query, args) | ||
| 102 | } | ||
| 103 | |||
| 104 | func NewOrm() Ormer { | ||
| 105 | o := new(orm) | ||
| 106 | err := o.Using("default") | ||
| 107 | if err != nil { | ||
| 108 | panic(err) | ||
| 109 | } | ||
| 110 | return o | ||
| 111 | } |
orm/orm_conds.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "strings" | ||
| 5 | ) | ||
| 6 | |||
| 7 | const ( | ||
| 8 | ExprSep = "__" | ||
| 9 | ) | ||
| 10 | |||
| 11 | type condValue struct { | ||
| 12 | exprs []string | ||
| 13 | args []interface{} | ||
| 14 | cond *Condition | ||
| 15 | isOr bool | ||
| 16 | isNot bool | ||
| 17 | isCond bool | ||
| 18 | } | ||
| 19 | |||
| 20 | type Condition struct { | ||
| 21 | params []condValue | ||
| 22 | } | ||
| 23 | |||
| 24 | func NewCondition() *Condition { | ||
| 25 | c := &Condition{} | ||
| 26 | return c | ||
| 27 | } | ||
| 28 | |||
| 29 | func (c *Condition) And(expr string, args ...interface{}) *Condition { | ||
| 30 | if expr == "" || len(args) == 0 { | ||
| 31 | panic("<Condition.And> args cannot empty") | ||
| 32 | } | ||
| 33 | c.params = append(c.params, condValue{exprs: strings.Split(expr, ExprSep), args: args}) | ||
| 34 | return c | ||
| 35 | } | ||
| 36 | |||
| 37 | func (c *Condition) AndNot(expr string, args ...interface{}) *Condition { | ||
| 38 | if expr == "" || len(args) == 0 { | ||
| 39 | panic("<Condition.AndNot> args cannot empty") | ||
| 40 | } | ||
| 41 | c.params = append(c.params, condValue{exprs: strings.Split(expr, ExprSep), args: args, isNot: true}) | ||
| 42 | return c | ||
| 43 | } | ||
| 44 | |||
| 45 | func (c *Condition) AndCond(cond *Condition) *Condition { | ||
| 46 | if c == cond { | ||
| 47 | panic("cannot use self as sub cond") | ||
| 48 | } | ||
| 49 | if cond != nil { | ||
| 50 | c.params = append(c.params, condValue{cond: cond, isCond: true}) | ||
| 51 | } | ||
| 52 | return c | ||
| 53 | } | ||
| 54 | |||
| 55 | func (c *Condition) Or(expr string, args ...interface{}) *Condition { | ||
| 56 | if expr == "" || len(args) == 0 { | ||
| 57 | panic("<Condition.Or> args cannot empty") | ||
| 58 | } | ||
| 59 | c.params = append(c.params, condValue{exprs: strings.Split(expr, ExprSep), args: args, isOr: true}) | ||
| 60 | return c | ||
| 61 | } | ||
| 62 | |||
| 63 | func (c *Condition) OrNot(expr string, args ...interface{}) *Condition { | ||
| 64 | if expr == "" || len(args) == 0 { | ||
| 65 | panic("<Condition.OrNot> args cannot empty") | ||
| 66 | } | ||
| 67 | c.params = append(c.params, condValue{exprs: strings.Split(expr, ExprSep), args: args, isNot: true, isOr: true}) | ||
| 68 | return c | ||
| 69 | } | ||
| 70 | |||
| 71 | func (c *Condition) OrCond(cond *Condition) *Condition { | ||
| 72 | if c == cond { | ||
| 73 | panic("cannot use self as sub cond") | ||
| 74 | } | ||
| 75 | if cond != nil { | ||
| 76 | c.params = append(c.params, condValue{cond: cond, isCond: true, isOr: true}) | ||
| 77 | } | ||
| 78 | return c | ||
| 79 | } | ||
| 80 | |||
| 81 | func (c *Condition) IsEmpty() bool { | ||
| 82 | return len(c.params) == 0 | ||
| 83 | } | ||
| 84 | |||
| 85 | func (c Condition) Clone() *Condition { | ||
| 86 | params := c.params | ||
| 87 | c.params = make([]condValue, len(params)) | ||
| 88 | copy(c.params, params) | ||
| 89 | return &c | ||
| 90 | } | ||
| 91 | |||
| 92 | func (c *Condition) Merge() (expr string, args []interface{}) { | ||
| 93 | return expr, args | ||
| 94 | } |
orm/orm_object.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "database/sql" | ||
| 5 | "fmt" | ||
| 6 | "reflect" | ||
| 7 | ) | ||
| 8 | |||
| 9 | type insertSet struct { | ||
| 10 | mi *modelInfo | ||
| 11 | orm *orm | ||
| 12 | stmt *sql.Stmt | ||
| 13 | closed bool | ||
| 14 | } | ||
| 15 | |||
| 16 | func (o *insertSet) Insert(md Modeler) (int64, error) { | ||
| 17 | if o.closed { | ||
| 18 | return 0, ErrStmtClosed | ||
| 19 | } | ||
| 20 | val := reflect.ValueOf(md) | ||
| 21 | ind := reflect.Indirect(val) | ||
| 22 | if val.Type() != o.mi.addrField.Type() { | ||
| 23 | panic(fmt.Sprintf("<Inserter.Insert> need type `%s` but found `%s`", o.mi.addrField.Type(), val.Type())) | ||
| 24 | } | ||
| 25 | id, err := o.orm.alias.DbBaser.InsertStmt(o.stmt, o.mi, ind) | ||
| 26 | if err != nil { | ||
| 27 | return id, err | ||
| 28 | } | ||
| 29 | if id > 0 { | ||
| 30 | if o.mi.fields.auto != nil { | ||
| 31 | ind.Field(o.mi.fields.auto.fieldIndex).SetInt(id) | ||
| 32 | } | ||
| 33 | } | ||
| 34 | return id, nil | ||
| 35 | } | ||
| 36 | |||
| 37 | func (o *insertSet) Close() error { | ||
| 38 | o.closed = true | ||
| 39 | return o.stmt.Close() | ||
| 40 | } | ||
| 41 | |||
| 42 | func newInsertSet(orm *orm, mi *modelInfo) (Inserter, error) { | ||
| 43 | bi := new(insertSet) | ||
| 44 | bi.orm = orm | ||
| 45 | bi.mi = mi | ||
| 46 | st, err := orm.alias.DbBaser.PrepareInsert(orm.db, mi) | ||
| 47 | if err != nil { | ||
| 48 | return nil, err | ||
| 49 | } | ||
| 50 | bi.stmt = st | ||
| 51 | return bi, nil | ||
| 52 | } | ||
| 53 | |||
| 54 | type object struct { | ||
| 55 | ind reflect.Value | ||
| 56 | mi *modelInfo | ||
| 57 | orm *orm | ||
| 58 | } | ||
| 59 | |||
| 60 | func (o *object) Insert() (int64, error) { | ||
| 61 | id, err := o.orm.alias.DbBaser.Insert(o.orm.db, o.mi, o.ind) | ||
| 62 | if err != nil { | ||
| 63 | return id, err | ||
| 64 | } | ||
| 65 | if id > 0 { | ||
| 66 | if o.mi.fields.auto != nil { | ||
| 67 | o.ind.Field(o.mi.fields.auto.fieldIndex).SetInt(id) | ||
| 68 | } | ||
| 69 | } | ||
| 70 | return id, nil | ||
| 71 | } | ||
| 72 | |||
| 73 | func (o *object) Update() (int64, error) { | ||
| 74 | num, err := o.orm.alias.DbBaser.Update(o.orm.db, o.mi, o.ind) | ||
| 75 | if err != nil { | ||
| 76 | return num, err | ||
| 77 | } | ||
| 78 | return 0, nil | ||
| 79 | } | ||
| 80 | |||
| 81 | func (o *object) Delete() (int64, error) { | ||
| 82 | return o.orm.alias.DbBaser.Delete(o.orm.db, o.mi, o.ind) | ||
| 83 | } | ||
| 84 | |||
| 85 | func newObject(orm *orm, mi *modelInfo, md Modeler) ObjectSeter { | ||
| 86 | o := new(object) | ||
| 87 | ind := reflect.Indirect(reflect.ValueOf(md)) | ||
| 88 | o.ind = ind | ||
| 89 | o.mi = mi | ||
| 90 | o.orm = orm | ||
| 91 | return o | ||
| 92 | } |
orm/orm_queryset.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | ) | ||
| 6 | |||
| 7 | type querySet struct { | ||
| 8 | mi *modelInfo | ||
| 9 | cond *Condition | ||
| 10 | related []string | ||
| 11 | relDepth int | ||
| 12 | limit int | ||
| 13 | offset int64 | ||
| 14 | orders []string | ||
| 15 | orm *orm | ||
| 16 | } | ||
| 17 | |||
| 18 | func (o *querySet) Filter(expr string, args ...interface{}) QuerySeter { | ||
| 19 | if o.cond == nil { | ||
| 20 | o.cond = NewCondition() | ||
| 21 | } | ||
| 22 | o.cond.And(expr, args...) | ||
| 23 | return o.Clone() | ||
| 24 | } | ||
| 25 | |||
| 26 | func (o *querySet) Exclude(expr string, args ...interface{}) QuerySeter { | ||
| 27 | if o.cond == nil { | ||
| 28 | o.cond = NewCondition() | ||
| 29 | } | ||
| 30 | o.cond.AndNot(expr, args...) | ||
| 31 | return o.Clone() | ||
| 32 | } | ||
| 33 | |||
| 34 | func (o *querySet) Limit(limit int, args ...int64) QuerySeter { | ||
| 35 | o.limit = limit | ||
| 36 | if len(args) > 0 { | ||
| 37 | o.offset = args[0] | ||
| 38 | } | ||
| 39 | return o.Clone() | ||
| 40 | } | ||
| 41 | |||
| 42 | func (o *querySet) Offset(offset int64) QuerySeter { | ||
| 43 | o.offset = offset | ||
| 44 | return o.Clone() | ||
| 45 | } | ||
| 46 | |||
| 47 | func (o *querySet) OrderBy(orders ...string) QuerySeter { | ||
| 48 | o.orders = orders | ||
| 49 | return o.Clone() | ||
| 50 | } | ||
| 51 | |||
| 52 | func (o *querySet) RelatedSel(params ...interface{}) QuerySeter { | ||
| 53 | var related []string | ||
| 54 | if len(params) == 0 { | ||
| 55 | o.relDepth = DefaultRelsDepth | ||
| 56 | } else { | ||
| 57 | for _, p := range params { | ||
| 58 | switch val := p.(type) { | ||
| 59 | case string: | ||
| 60 | related = append(o.related, val) | ||
| 61 | case int: | ||
| 62 | o.relDepth = val | ||
| 63 | default: | ||
| 64 | panic(fmt.Sprintf("<querySet.RelatedSel> wrong param kind: %v", val)) | ||
| 65 | } | ||
| 66 | } | ||
| 67 | } | ||
| 68 | o.related = related | ||
| 69 | return o.Clone() | ||
| 70 | } | ||
| 71 | |||
| 72 | func (o querySet) Clone() QuerySeter { | ||
| 73 | if o.cond != nil { | ||
| 74 | o.cond = o.cond.Clone() | ||
| 75 | } | ||
| 76 | return &o | ||
| 77 | } | ||
| 78 | |||
| 79 | func (o *querySet) SetCond(cond *Condition) error { | ||
| 80 | o.cond = cond | ||
| 81 | return nil | ||
| 82 | } | ||
| 83 | |||
| 84 | func (o *querySet) Count() (int64, error) { | ||
| 85 | return o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond) | ||
| 86 | } | ||
| 87 | |||
| 88 | func (o *querySet) Update(values Params) (int64, error) { | ||
| 89 | return o.orm.alias.DbBaser.UpdateBatch(o.orm.db, o, o.mi, o.cond, values) | ||
| 90 | } | ||
| 91 | |||
| 92 | func (o *querySet) Delete() (int64, error) { | ||
| 93 | return o.orm.alias.DbBaser.DeleteBatch(o.orm.db, o, o.mi, o.cond) | ||
| 94 | } | ||
| 95 | |||
| 96 | func (o *querySet) PrepareInsert() (Inserter, error) { | ||
| 97 | return newInsertSet(o.orm, o.mi) | ||
| 98 | } | ||
| 99 | |||
| 100 | func (o *querySet) All(container interface{}) (int64, error) { | ||
| 101 | return o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container) | ||
| 102 | } | ||
| 103 | |||
| 104 | func (o *querySet) One(container Modeler) error { | ||
| 105 | num, err := o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container) | ||
| 106 | if err != nil { | ||
| 107 | return err | ||
| 108 | } | ||
| 109 | if num > 1 { | ||
| 110 | return ErrMultiRows | ||
| 111 | } | ||
| 112 | return nil | ||
| 113 | } | ||
| 114 | |||
| 115 | func (o *querySet) Values(results *[]Params, args ...string) (int64, error) { | ||
| 116 | return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, args, results) | ||
| 117 | } | ||
| 118 | |||
| 119 | func (o *querySet) ValuesList(results *[]ParamsList, args ...string) (int64, error) { | ||
| 120 | return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, args, results) | ||
| 121 | } | ||
| 122 | |||
| 123 | func (o *querySet) ValuesFlat(result *ParamsList, arg string) (int64, error) { | ||
| 124 | return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, []string{arg}, result) | ||
| 125 | } | ||
| 126 | |||
| 127 | func newQuerySet(orm *orm, mi *modelInfo) QuerySeter { | ||
| 128 | o := new(querySet) | ||
| 129 | o.mi = mi | ||
| 130 | o.orm = orm | ||
| 131 | return o | ||
| 132 | } |
orm/orm_raw.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "database/sql" | ||
| 5 | "fmt" | ||
| 6 | "reflect" | ||
| 7 | ) | ||
| 8 | |||
| 9 | func getResult(res sql.Result) (int64, error) { | ||
| 10 | if num, err := res.LastInsertId(); err != nil { | ||
| 11 | return 0, err | ||
| 12 | } else { | ||
| 13 | if num > 0 { | ||
| 14 | return num, nil | ||
| 15 | } | ||
| 16 | } | ||
| 17 | if num, err := res.RowsAffected(); err != nil { | ||
| 18 | return num, err | ||
| 19 | } else { | ||
| 20 | if num > 0 { | ||
| 21 | return num, nil | ||
| 22 | } | ||
| 23 | } | ||
| 24 | return 0, nil | ||
| 25 | } | ||
| 26 | |||
| 27 | type rawPrepare struct { | ||
| 28 | rs *rawSet | ||
| 29 | stmt *sql.Stmt | ||
| 30 | closed bool | ||
| 31 | } | ||
| 32 | |||
| 33 | func (o *rawPrepare) Exec(args ...interface{}) (int64, error) { | ||
| 34 | if o.closed { | ||
| 35 | return 0, ErrStmtClosed | ||
| 36 | } | ||
| 37 | res, err := o.stmt.Exec(args...) | ||
| 38 | if err != nil { | ||
| 39 | return 0, err | ||
| 40 | } | ||
| 41 | return getResult(res) | ||
| 42 | } | ||
| 43 | |||
| 44 | func (o *rawPrepare) Close() error { | ||
| 45 | o.closed = true | ||
| 46 | return o.stmt.Close() | ||
| 47 | } | ||
| 48 | |||
| 49 | func newRawPreparer(rs *rawSet) (RawPreparer, error) { | ||
| 50 | o := new(rawPrepare) | ||
| 51 | o.rs = rs | ||
| 52 | st, err := rs.orm.db.Prepare(rs.query) | ||
| 53 | if err != nil { | ||
| 54 | return nil, err | ||
| 55 | } | ||
| 56 | o.stmt = st | ||
| 57 | return o, nil | ||
| 58 | } | ||
| 59 | |||
| 60 | type rawSet struct { | ||
| 61 | query string | ||
| 62 | args []interface{} | ||
| 63 | orm *orm | ||
| 64 | } | ||
| 65 | |||
| 66 | func (o rawSet) SetArgs(args ...interface{}) RawSeter { | ||
| 67 | o.args = args | ||
| 68 | return &o | ||
| 69 | } | ||
| 70 | |||
| 71 | func (o *rawSet) Exec() (int64, error) { | ||
| 72 | res, err := o.orm.db.Exec(o.query, o.args...) | ||
| 73 | if err != nil { | ||
| 74 | return 0, err | ||
| 75 | } | ||
| 76 | return getResult(res) | ||
| 77 | } | ||
| 78 | |||
| 79 | func (o *rawSet) Mapper(...interface{}) (int64, error) { | ||
| 80 | //TODO | ||
| 81 | return 0, nil | ||
| 82 | } | ||
| 83 | |||
| 84 | func (o *rawSet) readValues(container interface{}) (int64, error) { | ||
| 85 | var ( | ||
| 86 | maps []Params | ||
| 87 | lists []ParamsList | ||
| 88 | list ParamsList | ||
| 89 | ) | ||
| 90 | |||
| 91 | typ := 0 | ||
| 92 | switch container.(type) { | ||
| 93 | case *[]Params: | ||
| 94 | typ = 1 | ||
| 95 | case *[]ParamsList: | ||
| 96 | typ = 2 | ||
| 97 | case *ParamsList: | ||
| 98 | typ = 3 | ||
| 99 | default: | ||
| 100 | panic(fmt.Sprintf("unsupport read values type `%T`", container)) | ||
| 101 | } | ||
| 102 | |||
| 103 | var rs *sql.Rows | ||
| 104 | if r, err := o.orm.db.Query(o.query, o.args...); err != nil { | ||
| 105 | return 0, err | ||
| 106 | } else { | ||
| 107 | rs = r | ||
| 108 | } | ||
| 109 | |||
| 110 | var ( | ||
| 111 | refs []interface{} | ||
| 112 | cnt int64 | ||
| 113 | cols []string | ||
| 114 | ) | ||
| 115 | for rs.Next() { | ||
| 116 | if cnt == 0 { | ||
| 117 | if columns, err := rs.Columns(); err != nil { | ||
| 118 | return 0, err | ||
| 119 | } else { | ||
| 120 | cols = columns | ||
| 121 | refs = make([]interface{}, len(cols)) | ||
| 122 | for i, _ := range refs { | ||
| 123 | var ref string | ||
| 124 | refs[i] = &ref | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | if err := rs.Scan(refs...); err != nil { | ||
| 130 | return 0, err | ||
| 131 | } | ||
| 132 | |||
| 133 | switch typ { | ||
| 134 | case 1: | ||
| 135 | params := make(Params, len(cols)) | ||
| 136 | for i, ref := range refs { | ||
| 137 | value := reflect.Indirect(reflect.ValueOf(ref)).Interface() | ||
| 138 | params[cols[i]] = value | ||
| 139 | } | ||
| 140 | maps = append(maps, params) | ||
| 141 | case 2: | ||
| 142 | params := make(ParamsList, 0, len(cols)) | ||
| 143 | for _, ref := range refs { | ||
| 144 | value := reflect.Indirect(reflect.ValueOf(ref)).Interface() | ||
| 145 | params = append(params, value) | ||
| 146 | } | ||
| 147 | lists = append(lists, params) | ||
| 148 | case 3: | ||
| 149 | for _, ref := range refs { | ||
| 150 | value := reflect.Indirect(reflect.ValueOf(ref)).Interface() | ||
| 151 | list = append(list, value) | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | cnt++ | ||
| 156 | } | ||
| 157 | |||
| 158 | switch v := container.(type) { | ||
| 159 | case *[]Params: | ||
| 160 | *v = maps | ||
| 161 | case *[]ParamsList: | ||
| 162 | *v = lists | ||
| 163 | case *ParamsList: | ||
| 164 | *v = list | ||
| 165 | } | ||
| 166 | |||
| 167 | return cnt, nil | ||
| 168 | } | ||
| 169 | |||
| 170 | func (o *rawSet) Values(container *[]Params) (int64, error) { | ||
| 171 | return o.readValues(container) | ||
| 172 | } | ||
| 173 | |||
| 174 | func (o *rawSet) ValuesList(container *[]ParamsList) (int64, error) { | ||
| 175 | return o.readValues(container) | ||
| 176 | } | ||
| 177 | |||
| 178 | func (o *rawSet) ValuesFlat(container *ParamsList) (int64, error) { | ||
| 179 | return o.readValues(container) | ||
| 180 | } | ||
| 181 | |||
| 182 | func (o *rawSet) Prepare() (RawPreparer, error) { | ||
| 183 | return newRawPreparer(o) | ||
| 184 | } | ||
| 185 | |||
| 186 | func newRawSet(orm *orm, query string, args []interface{}) RawSeter { | ||
| 187 | o := new(rawSet) | ||
| 188 | o.query = query | ||
| 189 | o.args = args | ||
| 190 | o.orm = orm | ||
| 191 | return o | ||
| 192 | } |
orm/types.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "database/sql" | ||
| 5 | "reflect" | ||
| 6 | ) | ||
| 7 | |||
| 8 | type Fielder interface { | ||
| 9 | String() string | ||
| 10 | FieldType() int | ||
| 11 | SetRaw(interface{}) error | ||
| 12 | RawValue() interface{} | ||
| 13 | } | ||
| 14 | |||
| 15 | type Modeler interface { | ||
| 16 | Init(Modeler) Modeler | ||
| 17 | IsInited() bool | ||
| 18 | Clean() FieldErrors | ||
| 19 | CleanFields(string) FieldErrors | ||
| 20 | GetTableName() string | ||
| 21 | } | ||
| 22 | |||
| 23 | type Ormer interface { | ||
| 24 | Object(Modeler) ObjectSeter | ||
| 25 | QueryTable(interface{}) QuerySeter | ||
| 26 | Using(string) error | ||
| 27 | Begin() error | ||
| 28 | Commit() error | ||
| 29 | Rollback() error | ||
| 30 | Raw(string, ...interface{}) RawSeter | ||
| 31 | } | ||
| 32 | |||
| 33 | type ObjectSeter interface { | ||
| 34 | Insert() (int64, error) | ||
| 35 | Update() (int64, error) | ||
| 36 | Delete() (int64, error) | ||
| 37 | } | ||
| 38 | |||
| 39 | type Inserter interface { | ||
| 40 | Insert(Modeler) (int64, error) | ||
| 41 | Close() error | ||
| 42 | } | ||
| 43 | |||
| 44 | type QuerySeter interface { | ||
| 45 | Filter(string, ...interface{}) QuerySeter | ||
| 46 | Exclude(string, ...interface{}) QuerySeter | ||
| 47 | Limit(int, ...int64) QuerySeter | ||
| 48 | Offset(int64) QuerySeter | ||
| 49 | OrderBy(...string) QuerySeter | ||
| 50 | RelatedSel(...interface{}) QuerySeter | ||
| 51 | Clone() QuerySeter | ||
| 52 | SetCond(*Condition) error | ||
| 53 | Count() (int64, error) | ||
| 54 | Update(Params) (int64, error) | ||
| 55 | Delete() (int64, error) | ||
| 56 | PrepareInsert() (Inserter, error) | ||
| 57 | |||
| 58 | All(interface{}) (int64, error) | ||
| 59 | One(Modeler) error | ||
| 60 | Values(*[]Params, ...string) (int64, error) | ||
| 61 | ValuesList(*[]ParamsList, ...string) (int64, error) | ||
| 62 | ValuesFlat(*ParamsList, string) (int64, error) | ||
| 63 | } | ||
| 64 | |||
| 65 | type RawPreparer interface { | ||
| 66 | Close() error | ||
| 67 | } | ||
| 68 | |||
| 69 | type RawSeter interface { | ||
| 70 | Exec() (int64, error) | ||
| 71 | Mapper(...interface{}) (int64, error) | ||
| 72 | Values(*[]Params) (int64, error) | ||
| 73 | ValuesList(*[]ParamsList) (int64, error) | ||
| 74 | ValuesFlat(*ParamsList) (int64, error) | ||
| 75 | Prepare() (RawPreparer, error) | ||
| 76 | } | ||
| 77 | |||
| 78 | type dbQuerier interface { | ||
| 79 | Prepare(query string) (*sql.Stmt, error) | ||
| 80 | Exec(query string, args ...interface{}) (sql.Result, error) | ||
| 81 | Query(query string, args ...interface{}) (*sql.Rows, error) | ||
| 82 | QueryRow(query string, args ...interface{}) *sql.Row | ||
| 83 | } | ||
| 84 | |||
| 85 | type dbBaser interface { | ||
| 86 | Insert(dbQuerier, *modelInfo, reflect.Value) (int64, error) | ||
| 87 | InsertStmt(*sql.Stmt, *modelInfo, reflect.Value) (int64, error) | ||
| 88 | Update(dbQuerier, *modelInfo, reflect.Value) (int64, error) | ||
| 89 | Delete(dbQuerier, *modelInfo, reflect.Value) (int64, error) | ||
| 90 | ReadBatch(dbQuerier, *querySet, *modelInfo, *Condition, interface{}) (int64, error) | ||
| 91 | UpdateBatch(dbQuerier, *querySet, *modelInfo, *Condition, Params) (int64, error) | ||
| 92 | DeleteBatch(dbQuerier, *querySet, *modelInfo, *Condition) (int64, error) | ||
| 93 | Count(dbQuerier, *querySet, *modelInfo, *Condition) (int64, error) | ||
| 94 | GetOperatorSql(*modelInfo, string, []interface{}) (string, []interface{}) | ||
| 95 | PrepareInsert(dbQuerier, *modelInfo) (*sql.Stmt, error) | ||
| 96 | ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}) (int64, error) | ||
| 97 | } |
orm/utils.go
0 → 100644
| 1 | package orm | ||
| 2 | |||
| 3 | import ( | ||
| 4 | "fmt" | ||
| 5 | "strconv" | ||
| 6 | "strings" | ||
| 7 | "time" | ||
| 8 | ) | ||
| 9 | |||
| 10 | type StrTo string | ||
| 11 | |||
| 12 | func (f *StrTo) Set(v string) { | ||
| 13 | if v != "" { | ||
| 14 | *f = StrTo(v) | ||
| 15 | } else { | ||
| 16 | f.Clear() | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | func (f *StrTo) Clear() { | ||
| 21 | *f = StrTo(0x1E) | ||
| 22 | } | ||
| 23 | |||
| 24 | func (f StrTo) Exist() bool { | ||
| 25 | return string(f) != string(0x1E) | ||
| 26 | } | ||
| 27 | |||
| 28 | func (f StrTo) Bool() (bool, error) { | ||
| 29 | return strconv.ParseBool(f.String()) | ||
| 30 | } | ||
| 31 | |||
| 32 | func (f StrTo) Float32() (float32, error) { | ||
| 33 | v, err := strconv.ParseFloat(f.String(), 32) | ||
| 34 | return float32(v), err | ||
| 35 | } | ||
| 36 | |||
| 37 | func (f StrTo) Float64() (float64, error) { | ||
| 38 | return strconv.ParseFloat(f.String(), 64) | ||
| 39 | } | ||
| 40 | |||
| 41 | func (f StrTo) Int16() (int16, error) { | ||
| 42 | v, err := strconv.ParseInt(f.String(), 10, 16) | ||
| 43 | return int16(v), err | ||
| 44 | } | ||
| 45 | |||
| 46 | func (f StrTo) Int32() (int32, error) { | ||
| 47 | v, err := strconv.ParseInt(f.String(), 10, 32) | ||
| 48 | return int32(v), err | ||
| 49 | } | ||
| 50 | |||
| 51 | func (f StrTo) Int64() (int64, error) { | ||
| 52 | v, err := strconv.ParseInt(f.String(), 10, 64) | ||
| 53 | return int64(v), err | ||
| 54 | } | ||
| 55 | |||
| 56 | func (f StrTo) Uint16() (uint16, error) { | ||
| 57 | v, err := strconv.ParseUint(f.String(), 10, 16) | ||
| 58 | return uint16(v), err | ||
| 59 | } | ||
| 60 | |||
| 61 | func (f StrTo) Uint32() (uint32, error) { | ||
| 62 | v, err := strconv.ParseUint(f.String(), 10, 32) | ||
| 63 | return uint32(v), err | ||
| 64 | } | ||
| 65 | |||
| 66 | func (f StrTo) Uint64() (uint64, error) { | ||
| 67 | v, err := strconv.ParseUint(f.String(), 10, 64) | ||
| 68 | return uint64(v), err | ||
| 69 | } | ||
| 70 | |||
| 71 | func (f StrTo) String() string { | ||
| 72 | if f.Exist() { | ||
| 73 | return string(f) | ||
| 74 | } | ||
| 75 | return "" | ||
| 76 | } | ||
| 77 | |||
| 78 | func ToStr(value interface{}, args ...int) (s string) { | ||
| 79 | switch v := value.(type) { | ||
| 80 | case bool: | ||
| 81 | s = strconv.FormatBool(v) | ||
| 82 | case float32: | ||
| 83 | s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32)) | ||
| 84 | case float64: | ||
| 85 | s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64)) | ||
| 86 | case int: | ||
| 87 | s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) | ||
| 88 | case int16: | ||
| 89 | s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) | ||
| 90 | case int32: | ||
| 91 | s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) | ||
| 92 | case int64: | ||
| 93 | s = strconv.FormatInt(v, argInt(args).Get(0, 10)) | ||
| 94 | case uint: | ||
| 95 | s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) | ||
| 96 | case uint16: | ||
| 97 | s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) | ||
| 98 | case uint32: | ||
| 99 | s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) | ||
| 100 | case uint64: | ||
| 101 | s = strconv.FormatUint(v, argInt(args).Get(0, 10)) | ||
| 102 | case string: | ||
| 103 | s = v | ||
| 104 | default: | ||
| 105 | s = fmt.Sprintf("%v", v) | ||
| 106 | } | ||
| 107 | return s | ||
| 108 | } | ||
| 109 | |||
| 110 | func snakeString(s string) string { | ||
| 111 | data := make([]byte, 0, len(s)*2) | ||
| 112 | j := false | ||
| 113 | num := len(s) | ||
| 114 | for i := 0; i < num; i++ { | ||
| 115 | d := s[i] | ||
| 116 | if i > 0 && d >= 'A' && d <= 'Z' && j { | ||
| 117 | data = append(data, '_') | ||
| 118 | } | ||
| 119 | if d != '_' { | ||
| 120 | j = true | ||
| 121 | } | ||
| 122 | data = append(data, d) | ||
| 123 | } | ||
| 124 | return strings.ToLower(string(data[:len(data)])) | ||
| 125 | } | ||
| 126 | |||
| 127 | func camelString(s string) string { | ||
| 128 | data := make([]byte, 0, len(s)) | ||
| 129 | j := false | ||
| 130 | k := false | ||
| 131 | num := len(s) - 1 | ||
| 132 | for i := 0; i <= num; i++ { | ||
| 133 | d := s[i] | ||
| 134 | if k == false && d >= 'A' && d <= 'Z' { | ||
| 135 | k = true | ||
| 136 | } | ||
| 137 | if d >= 'a' && d <= 'z' && (j || k == false) { | ||
| 138 | d = d - 32 | ||
| 139 | j = false | ||
| 140 | k = true | ||
| 141 | } | ||
| 142 | if k && d == '_' && num > i && s[i+1] >= 'a' && s[i+1] <= 'z' { | ||
| 143 | j = true | ||
| 144 | continue | ||
| 145 | } | ||
| 146 | data = append(data, d) | ||
| 147 | } | ||
| 148 | return string(data[:len(data)]) | ||
| 149 | } | ||
| 150 | |||
| 151 | type argString []string | ||
| 152 | |||
| 153 | func (a argString) Get(i int, args ...string) (r string) { | ||
| 154 | if i >= 0 && i < len(a) { | ||
| 155 | r = a[i] | ||
| 156 | } else if len(args) > 0 { | ||
| 157 | r = args[0] | ||
| 158 | } | ||
| 159 | return | ||
| 160 | } | ||
| 161 | |||
| 162 | type argInt []int | ||
| 163 | |||
| 164 | func (a argInt) Get(i int, args ...int) (r int) { | ||
| 165 | if i >= 0 && i < len(a) { | ||
| 166 | r = a[i] | ||
| 167 | } | ||
| 168 | if len(args) > 0 { | ||
| 169 | r = args[0] | ||
| 170 | } | ||
| 171 | return | ||
| 172 | } | ||
| 173 | |||
| 174 | func timeParse(dateString, format string) (time.Time, error) { | ||
| 175 | tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) | ||
| 176 | return tp, err | ||
| 177 | } | ||
| 178 | |||
| 179 | func timeFormat(t time.Time, format string) string { | ||
| 180 | return t.Format(format) | ||
| 181 | } |
-
Please register or sign in to post a comment