Merge pull request #470 from fuxiaohei/develop
add comments for orm and middleware packages.
Showing
27 changed files
with
339 additions
and
14 deletions
| ... | @@ -221,7 +221,7 @@ func Run() { | ... | @@ -221,7 +221,7 @@ func Run() { |
| 221 | 221 | ||
| 222 | middleware.VERSION = VERSION | 222 | middleware.VERSION = VERSION |
| 223 | middleware.AppName = AppName | 223 | middleware.AppName = AppName |
| 224 | middleware.RegisterErrorHander() | 224 | middleware.RegisterErrorHandler() |
| 225 | 225 | ||
| 226 | if EnableAdmin { | 226 | if EnableAdmin { |
| 227 | go BeeAdminApp.Run() | 227 | go BeeAdminApp.Run() | ... | ... |
| ... | @@ -61,6 +61,7 @@ var tpl = ` | ... | @@ -61,6 +61,7 @@ var tpl = ` |
| 61 | </html> | 61 | </html> |
| 62 | ` | 62 | ` |
| 63 | 63 | ||
| 64 | // render default application error page with error and stack string. | ||
| 64 | func ShowErr(err interface{}, rw http.ResponseWriter, r *http.Request, Stack string) { | 65 | func ShowErr(err interface{}, rw http.ResponseWriter, r *http.Request, Stack string) { |
| 65 | t, _ := template.New("beegoerrortemp").Parse(tpl) | 66 | t, _ := template.New("beegoerrortemp").Parse(tpl) |
| 66 | data := make(map[string]string) | 67 | data := make(map[string]string) |
| ... | @@ -175,13 +176,14 @@ var errtpl = ` | ... | @@ -175,13 +176,14 @@ var errtpl = ` |
| 175 | </html> | 176 | </html> |
| 176 | ` | 177 | ` |
| 177 | 178 | ||
| 179 | // map of http handlers for each error string. | ||
| 178 | var ErrorMaps map[string]http.HandlerFunc | 180 | var ErrorMaps map[string]http.HandlerFunc |
| 179 | 181 | ||
| 180 | func init() { | 182 | func init() { |
| 181 | ErrorMaps = make(map[string]http.HandlerFunc) | 183 | ErrorMaps = make(map[string]http.HandlerFunc) |
| 182 | } | 184 | } |
| 183 | 185 | ||
| 184 | //404 | 186 | // show 404 notfound error. |
| 185 | func NotFound(rw http.ResponseWriter, r *http.Request) { | 187 | func NotFound(rw http.ResponseWriter, r *http.Request) { |
| 186 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | 188 | t, _ := template.New("beegoerrortemp").Parse(errtpl) |
| 187 | data := make(map[string]interface{}) | 189 | data := make(map[string]interface{}) |
| ... | @@ -199,7 +201,7 @@ func NotFound(rw http.ResponseWriter, r *http.Request) { | ... | @@ -199,7 +201,7 @@ func NotFound(rw http.ResponseWriter, r *http.Request) { |
| 199 | t.Execute(rw, data) | 201 | t.Execute(rw, data) |
| 200 | } | 202 | } |
| 201 | 203 | ||
| 202 | //401 | 204 | // show 401 unauthorized error. |
| 203 | func Unauthorized(rw http.ResponseWriter, r *http.Request) { | 205 | func Unauthorized(rw http.ResponseWriter, r *http.Request) { |
| 204 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | 206 | t, _ := template.New("beegoerrortemp").Parse(errtpl) |
| 205 | data := make(map[string]interface{}) | 207 | data := make(map[string]interface{}) |
| ... | @@ -215,7 +217,7 @@ func Unauthorized(rw http.ResponseWriter, r *http.Request) { | ... | @@ -215,7 +217,7 @@ func Unauthorized(rw http.ResponseWriter, r *http.Request) { |
| 215 | t.Execute(rw, data) | 217 | t.Execute(rw, data) |
| 216 | } | 218 | } |
| 217 | 219 | ||
| 218 | //403 | 220 | // show 403 forbidden error. |
| 219 | func Forbidden(rw http.ResponseWriter, r *http.Request) { | 221 | func Forbidden(rw http.ResponseWriter, r *http.Request) { |
| 220 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | 222 | t, _ := template.New("beegoerrortemp").Parse(errtpl) |
| 221 | data := make(map[string]interface{}) | 223 | data := make(map[string]interface{}) |
| ... | @@ -232,7 +234,7 @@ func Forbidden(rw http.ResponseWriter, r *http.Request) { | ... | @@ -232,7 +234,7 @@ func Forbidden(rw http.ResponseWriter, r *http.Request) { |
| 232 | t.Execute(rw, data) | 234 | t.Execute(rw, data) |
| 233 | } | 235 | } |
| 234 | 236 | ||
| 235 | //503 | 237 | // show 503 service unavailable error. |
| 236 | func ServiceUnavailable(rw http.ResponseWriter, r *http.Request) { | 238 | func ServiceUnavailable(rw http.ResponseWriter, r *http.Request) { |
| 237 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | 239 | t, _ := template.New("beegoerrortemp").Parse(errtpl) |
| 238 | data := make(map[string]interface{}) | 240 | data := make(map[string]interface{}) |
| ... | @@ -248,7 +250,7 @@ func ServiceUnavailable(rw http.ResponseWriter, r *http.Request) { | ... | @@ -248,7 +250,7 @@ func ServiceUnavailable(rw http.ResponseWriter, r *http.Request) { |
| 248 | t.Execute(rw, data) | 250 | t.Execute(rw, data) |
| 249 | } | 251 | } |
| 250 | 252 | ||
| 251 | //500 | 253 | // show 500 internal server error. |
| 252 | func InternalServerError(rw http.ResponseWriter, r *http.Request) { | 254 | func InternalServerError(rw http.ResponseWriter, r *http.Request) { |
| 253 | t, _ := template.New("beegoerrortemp").Parse(errtpl) | 255 | t, _ := template.New("beegoerrortemp").Parse(errtpl) |
| 254 | data := make(map[string]interface{}) | 256 | data := make(map[string]interface{}) |
| ... | @@ -262,15 +264,18 @@ func InternalServerError(rw http.ResponseWriter, r *http.Request) { | ... | @@ -262,15 +264,18 @@ func InternalServerError(rw http.ResponseWriter, r *http.Request) { |
| 262 | t.Execute(rw, data) | 264 | t.Execute(rw, data) |
| 263 | } | 265 | } |
| 264 | 266 | ||
| 267 | // show 500 internal error with simple text string. | ||
| 265 | func SimpleServerError(rw http.ResponseWriter, r *http.Request) { | 268 | func SimpleServerError(rw http.ResponseWriter, r *http.Request) { |
| 266 | http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) | 269 | http.Error(rw, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) |
| 267 | } | 270 | } |
| 268 | 271 | ||
| 272 | // add http handler for given error string. | ||
| 269 | func Errorhandler(err string, h http.HandlerFunc) { | 273 | func Errorhandler(err string, h http.HandlerFunc) { |
| 270 | ErrorMaps[err] = h | 274 | ErrorMaps[err] = h |
| 271 | } | 275 | } |
| 272 | 276 | ||
| 273 | func RegisterErrorHander() { | 277 | // register default error http handlers, 404,401,403,500 and 503. |
| 278 | func RegisterErrorHandler() { | ||
| 274 | if _, ok := ErrorMaps["404"]; !ok { | 279 | if _, ok := ErrorMaps["404"]; !ok { |
| 275 | ErrorMaps["404"] = NotFound | 280 | ErrorMaps["404"] = NotFound |
| 276 | } | 281 | } |
| ... | @@ -292,6 +297,8 @@ func RegisterErrorHander() { | ... | @@ -292,6 +297,8 @@ func RegisterErrorHander() { |
| 292 | } | 297 | } |
| 293 | } | 298 | } |
| 294 | 299 | ||
| 300 | // show error string as simple text message. | ||
| 301 | // if error string is empty, show 500 error as default. | ||
| 295 | func Exception(errcode string, w http.ResponseWriter, r *http.Request, msg string) { | 302 | func Exception(errcode string, w http.ResponseWriter, r *http.Request, msg string) { |
| 296 | if h, ok := ErrorMaps[errcode]; ok { | 303 | if h, ok := ErrorMaps[errcode]; ok { |
| 297 | isint, err := strconv.Atoi(errcode) | 304 | isint, err := strconv.Atoi(errcode) | ... | ... |
| ... | @@ -2,16 +2,19 @@ package middleware | ... | @@ -2,16 +2,19 @@ package middleware |
| 2 | 2 | ||
| 3 | import "fmt" | 3 | import "fmt" |
| 4 | 4 | ||
| 5 | // http exceptions | ||
| 5 | type HTTPException struct { | 6 | type HTTPException struct { |
| 6 | StatusCode int // http status code 4xx, 5xx | 7 | StatusCode int // http status code 4xx, 5xx |
| 7 | Description string | 8 | Description string |
| 8 | } | 9 | } |
| 9 | 10 | ||
| 11 | // return http exception error string, e.g. "400 Bad Request". | ||
| 10 | func (e *HTTPException) Error() string { | 12 | func (e *HTTPException) Error() string { |
| 11 | // return `status description`, e.g. `400 Bad Request` | ||
| 12 | return fmt.Sprintf("%d %s", e.StatusCode, e.Description) | 13 | return fmt.Sprintf("%d %s", e.StatusCode, e.Description) |
| 13 | } | 14 | } |
| 14 | 15 | ||
| 16 | // map of http exceptions for each http status code int. | ||
| 17 | // defined 400,401,403,404,405,500,502,503 and 504 default. | ||
| 15 | var HTTPExceptionMaps map[int]HTTPException | 18 | var HTTPExceptionMaps map[int]HTTPException |
| 16 | 19 | ||
| 17 | func init() { | 20 | func init() { | ... | ... |
| ... | @@ -16,6 +16,7 @@ var ( | ... | @@ -16,6 +16,7 @@ var ( |
| 16 | commands = make(map[string]commander) | 16 | commands = make(map[string]commander) |
| 17 | ) | 17 | ) |
| 18 | 18 | ||
| 19 | // print help. | ||
| 19 | func printHelp(errs ...string) { | 20 | func printHelp(errs ...string) { |
| 20 | content := `orm command usage: | 21 | content := `orm command usage: |
| 21 | 22 | ||
| ... | @@ -31,6 +32,7 @@ func printHelp(errs ...string) { | ... | @@ -31,6 +32,7 @@ func printHelp(errs ...string) { |
| 31 | os.Exit(2) | 32 | os.Exit(2) |
| 32 | } | 33 | } |
| 33 | 34 | ||
| 35 | // listen for orm command and then run it if command arguments passed. | ||
| 34 | func RunCommand() { | 36 | func RunCommand() { |
| 35 | if len(os.Args) < 2 || os.Args[1] != "orm" { | 37 | if len(os.Args) < 2 || os.Args[1] != "orm" { |
| 36 | return | 38 | return |
| ... | @@ -58,6 +60,7 @@ func RunCommand() { | ... | @@ -58,6 +60,7 @@ func RunCommand() { |
| 58 | } | 60 | } |
| 59 | } | 61 | } |
| 60 | 62 | ||
| 63 | // sync database struct command interface. | ||
| 61 | type commandSyncDb struct { | 64 | type commandSyncDb struct { |
| 62 | al *alias | 65 | al *alias |
| 63 | force bool | 66 | force bool |
| ... | @@ -66,6 +69,7 @@ type commandSyncDb struct { | ... | @@ -66,6 +69,7 @@ type commandSyncDb struct { |
| 66 | rtOnError bool | 69 | rtOnError bool |
| 67 | } | 70 | } |
| 68 | 71 | ||
| 72 | // parse orm command line arguments. | ||
| 69 | func (d *commandSyncDb) Parse(args []string) { | 73 | func (d *commandSyncDb) Parse(args []string) { |
| 70 | var name string | 74 | var name string |
| 71 | 75 | ||
| ... | @@ -78,6 +82,7 @@ func (d *commandSyncDb) Parse(args []string) { | ... | @@ -78,6 +82,7 @@ func (d *commandSyncDb) Parse(args []string) { |
| 78 | d.al = getDbAlias(name) | 82 | d.al = getDbAlias(name) |
| 79 | } | 83 | } |
| 80 | 84 | ||
| 85 | // run orm line command. | ||
| 81 | func (d *commandSyncDb) Run() error { | 86 | func (d *commandSyncDb) Run() error { |
| 82 | var drops []string | 87 | var drops []string |
| 83 | if d.force { | 88 | if d.force { |
| ... | @@ -208,10 +213,12 @@ func (d *commandSyncDb) Run() error { | ... | @@ -208,10 +213,12 @@ func (d *commandSyncDb) Run() error { |
| 208 | return nil | 213 | return nil |
| 209 | } | 214 | } |
| 210 | 215 | ||
| 216 | // database creation commander interface implement. | ||
| 211 | type commandSqlAll struct { | 217 | type commandSqlAll struct { |
| 212 | al *alias | 218 | al *alias |
| 213 | } | 219 | } |
| 214 | 220 | ||
| 221 | // parse orm command line arguments. | ||
| 215 | func (d *commandSqlAll) Parse(args []string) { | 222 | func (d *commandSqlAll) Parse(args []string) { |
| 216 | var name string | 223 | var name string |
| 217 | 224 | ||
| ... | @@ -222,6 +229,7 @@ func (d *commandSqlAll) Parse(args []string) { | ... | @@ -222,6 +229,7 @@ func (d *commandSqlAll) Parse(args []string) { |
| 222 | d.al = getDbAlias(name) | 229 | d.al = getDbAlias(name) |
| 223 | } | 230 | } |
| 224 | 231 | ||
| 232 | // run orm line command. | ||
| 225 | func (d *commandSqlAll) Run() error { | 233 | func (d *commandSqlAll) Run() error { |
| 226 | sqls, indexes := getDbCreateSql(d.al) | 234 | sqls, indexes := getDbCreateSql(d.al) |
| 227 | var all []string | 235 | var all []string |
| ... | @@ -243,6 +251,10 @@ func init() { | ... | @@ -243,6 +251,10 @@ func init() { |
| 243 | commands["sqlall"] = new(commandSqlAll) | 251 | commands["sqlall"] = new(commandSqlAll) |
| 244 | } | 252 | } |
| 245 | 253 | ||
| 254 | // run syncdb command line. | ||
| 255 | // name means table's alias name. default is "default". | ||
| 256 | // force means run next sql if the current is error. | ||
| 257 | // verbose means show all info when running command or not. | ||
| 246 | func RunSyncdb(name string, force bool, verbose bool) error { | 258 | func RunSyncdb(name string, force bool, verbose bool) error { |
| 247 | BootStrap() | 259 | BootStrap() |
| 248 | 260 | ... | ... |
| ... | @@ -12,6 +12,7 @@ type dbIndex struct { | ... | @@ -12,6 +12,7 @@ type dbIndex struct { |
| 12 | Sql string | 12 | Sql string |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | // create database drop sql. | ||
| 15 | func getDbDropSql(al *alias) (sqls []string) { | 16 | func getDbDropSql(al *alias) (sqls []string) { |
| 16 | if len(modelCache.cache) == 0 { | 17 | if len(modelCache.cache) == 0 { |
| 17 | fmt.Println("no Model found, need register your model") | 18 | fmt.Println("no Model found, need register your model") |
| ... | @@ -26,6 +27,7 @@ func getDbDropSql(al *alias) (sqls []string) { | ... | @@ -26,6 +27,7 @@ func getDbDropSql(al *alias) (sqls []string) { |
| 26 | return sqls | 27 | return sqls |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 30 | // get database column type string. | ||
| 29 | func getColumnTyp(al *alias, fi *fieldInfo) (col string) { | 31 | func getColumnTyp(al *alias, fi *fieldInfo) (col string) { |
| 30 | T := al.DbBaser.DbTypes() | 32 | T := al.DbBaser.DbTypes() |
| 31 | fieldType := fi.fieldType | 33 | fieldType := fi.fieldType |
| ... | @@ -79,6 +81,7 @@ checkColumn: | ... | @@ -79,6 +81,7 @@ checkColumn: |
| 79 | return | 81 | return |
| 80 | } | 82 | } |
| 81 | 83 | ||
| 84 | // create alter sql string. | ||
| 82 | func getColumnAddQuery(al *alias, fi *fieldInfo) string { | 85 | func getColumnAddQuery(al *alias, fi *fieldInfo) string { |
| 83 | Q := al.DbBaser.TableQuote() | 86 | Q := al.DbBaser.TableQuote() |
| 84 | typ := getColumnTyp(al, fi) | 87 | typ := getColumnTyp(al, fi) |
| ... | @@ -90,6 +93,7 @@ func getColumnAddQuery(al *alias, fi *fieldInfo) string { | ... | @@ -90,6 +93,7 @@ func getColumnAddQuery(al *alias, fi *fieldInfo) string { |
| 90 | return fmt.Sprintf("ALTER TABLE %s%s%s ADD COLUMN %s%s%s %s", Q, fi.mi.table, Q, Q, fi.column, Q, typ) | 93 | return fmt.Sprintf("ALTER TABLE %s%s%s ADD COLUMN %s%s%s %s", Q, fi.mi.table, Q, Q, fi.column, Q, typ) |
| 91 | } | 94 | } |
| 92 | 95 | ||
| 96 | // create database creation string. | ||
| 93 | func getDbCreateSql(al *alias) (sqls []string, tableIndexes map[string][]dbIndex) { | 97 | func getDbCreateSql(al *alias) (sqls []string, tableIndexes map[string][]dbIndex) { |
| 94 | if len(modelCache.cache) == 0 { | 98 | if len(modelCache.cache) == 0 { |
| 95 | fmt.Println("no Model found, need register your model") | 99 | fmt.Println("no Model found, need register your model") | ... | ... |
| ... | @@ -15,7 +15,7 @@ const ( | ... | @@ -15,7 +15,7 @@ const ( |
| 15 | ) | 15 | ) |
| 16 | 16 | ||
| 17 | var ( | 17 | var ( |
| 18 | ErrMissPK = errors.New("missed pk value") | 18 | ErrMissPK = errors.New("missed pk value") // missing pk error |
| 19 | ) | 19 | ) |
| 20 | 20 | ||
| 21 | var ( | 21 | var ( |
| ... | @@ -45,12 +45,15 @@ var ( | ... | @@ -45,12 +45,15 @@ var ( |
| 45 | } | 45 | } |
| 46 | ) | 46 | ) |
| 47 | 47 | ||
| 48 | // an instance of dbBaser interface/ | ||
| 48 | type dbBase struct { | 49 | type dbBase struct { |
| 49 | ins dbBaser | 50 | ins dbBaser |
| 50 | } | 51 | } |
| 51 | 52 | ||
| 53 | // check dbBase implements dbBaser interface. | ||
| 52 | var _ dbBaser = new(dbBase) | 54 | var _ dbBaser = new(dbBase) |
| 53 | 55 | ||
| 56 | // get struct columns values as interface slice. | ||
| 54 | func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string, skipAuto bool, insert bool, names *[]string, tz *time.Location) (values []interface{}, err error) { | 57 | func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string, skipAuto bool, insert bool, names *[]string, tz *time.Location) (values []interface{}, err error) { |
| 55 | var columns []string | 58 | var columns []string |
| 56 | 59 | ||
| ... | @@ -87,6 +90,7 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string, | ... | @@ -87,6 +90,7 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, cols []string, |
| 87 | return | 90 | return |
| 88 | } | 91 | } |
| 89 | 92 | ||
| 93 | // get one field value in struct column as interface. | ||
| 90 | func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Value, insert bool, tz *time.Location) (interface{}, error) { | 94 | func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Value, insert bool, tz *time.Location) (interface{}, error) { |
| 91 | var value interface{} | 95 | var value interface{} |
| 92 | if fi.pk { | 96 | if fi.pk { |
| ... | @@ -155,6 +159,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val | ... | @@ -155,6 +159,7 @@ func (d *dbBase) collectFieldValue(mi *modelInfo, fi *fieldInfo, ind reflect.Val |
| 155 | return value, nil | 159 | return value, nil |
| 156 | } | 160 | } |
| 157 | 161 | ||
| 162 | // create insert sql preparation statement object. | ||
| 158 | func (d *dbBase) PrepareInsert(q dbQuerier, mi *modelInfo) (stmtQuerier, string, error) { | 163 | func (d *dbBase) PrepareInsert(q dbQuerier, mi *modelInfo) (stmtQuerier, string, error) { |
| 159 | Q := d.ins.TableQuote() | 164 | Q := d.ins.TableQuote() |
| 160 | 165 | ||
| ... | @@ -180,6 +185,7 @@ func (d *dbBase) PrepareInsert(q dbQuerier, mi *modelInfo) (stmtQuerier, string, | ... | @@ -180,6 +185,7 @@ func (d *dbBase) PrepareInsert(q dbQuerier, mi *modelInfo) (stmtQuerier, string, |
| 180 | return stmt, query, err | 185 | return stmt, query, err |
| 181 | } | 186 | } |
| 182 | 187 | ||
| 188 | // insert struct with prepared statement and given struct reflect value. | ||
| 183 | func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { | 189 | func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { |
| 184 | values, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, nil, tz) | 190 | values, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, nil, tz) |
| 185 | if err != nil { | 191 | if err != nil { |
| ... | @@ -200,6 +206,7 @@ func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value, | ... | @@ -200,6 +206,7 @@ func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value, |
| 200 | } | 206 | } |
| 201 | } | 207 | } |
| 202 | 208 | ||
| 209 | // query sql ,read records and persist in dbBaser. | ||
| 203 | func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) error { | 210 | func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) error { |
| 204 | var whereCols []string | 211 | var whereCols []string |
| 205 | var args []interface{} | 212 | var args []interface{} |
| ... | @@ -259,6 +266,7 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Lo | ... | @@ -259,6 +266,7 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Lo |
| 259 | return nil | 266 | return nil |
| 260 | } | 267 | } |
| 261 | 268 | ||
| 269 | // execute insert sql dbQuerier with given struct reflect.Value. | ||
| 262 | func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { | 270 | func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { |
| 263 | names := make([]string, 0, len(mi.fields.dbcols)-1) | 271 | names := make([]string, 0, len(mi.fields.dbcols)-1) |
| 264 | values, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, &names, tz) | 272 | values, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, &names, tz) |
| ... | @@ -269,6 +277,7 @@ func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. | ... | @@ -269,6 +277,7 @@ func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. |
| 269 | return d.InsertValue(q, mi, false, names, values) | 277 | return d.InsertValue(q, mi, false, names, values) |
| 270 | } | 278 | } |
| 271 | 279 | ||
| 280 | // multi-insert sql with given slice struct reflect.Value. | ||
| 272 | func (d *dbBase) InsertMulti(q dbQuerier, mi *modelInfo, sind reflect.Value, bulk int, tz *time.Location) (int64, error) { | 281 | func (d *dbBase) InsertMulti(q dbQuerier, mi *modelInfo, sind reflect.Value, bulk int, tz *time.Location) (int64, error) { |
| 273 | var ( | 282 | var ( |
| 274 | cnt int64 | 283 | cnt int64 |
| ... | @@ -325,6 +334,8 @@ func (d *dbBase) InsertMulti(q dbQuerier, mi *modelInfo, sind reflect.Value, bul | ... | @@ -325,6 +334,8 @@ func (d *dbBase) InsertMulti(q dbQuerier, mi *modelInfo, sind reflect.Value, bul |
| 325 | return cnt, nil | 334 | return cnt, nil |
| 326 | } | 335 | } |
| 327 | 336 | ||
| 337 | // execute insert sql with given struct and given values. | ||
| 338 | // insert the given values, not the field values in struct. | ||
| 328 | func (d *dbBase) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, names []string, values []interface{}) (int64, error) { | 339 | func (d *dbBase) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, names []string, values []interface{}) (int64, error) { |
| 329 | Q := d.ins.TableQuote() | 340 | Q := d.ins.TableQuote() |
| 330 | 341 | ||
| ... | @@ -364,6 +375,7 @@ func (d *dbBase) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, names []s | ... | @@ -364,6 +375,7 @@ func (d *dbBase) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, names []s |
| 364 | } | 375 | } |
| 365 | } | 376 | } |
| 366 | 377 | ||
| 378 | // execute update sql dbQuerier with given struct reflect.Value. | ||
| 367 | func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) { | 379 | func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location, cols []string) (int64, error) { |
| 368 | pkName, pkValue, ok := getExistPk(mi, ind) | 380 | pkName, pkValue, ok := getExistPk(mi, ind) |
| 369 | if ok == false { | 381 | if ok == false { |
| ... | @@ -404,6 +416,8 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. | ... | @@ -404,6 +416,8 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. |
| 404 | return 0, nil | 416 | return 0, nil |
| 405 | } | 417 | } |
| 406 | 418 | ||
| 419 | // execute delete sql dbQuerier with given struct reflect.Value. | ||
| 420 | // delete index is pk. | ||
| 407 | func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { | 421 | func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) { |
| 408 | pkName, pkValue, ok := getExistPk(mi, ind) | 422 | pkName, pkValue, ok := getExistPk(mi, ind) |
| 409 | if ok == false { | 423 | if ok == false { |
| ... | @@ -445,6 +459,8 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. | ... | @@ -445,6 +459,8 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. |
| 445 | return 0, nil | 459 | return 0, nil |
| 446 | } | 460 | } |
| 447 | 461 | ||
| 462 | // update table-related record by querySet. | ||
| 463 | // need querySet not struct reflect.Value to update related records. | ||
| 448 | func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, params Params, tz *time.Location) (int64, error) { | 464 | func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, params Params, tz *time.Location) (int64, error) { |
| 449 | columns := make([]string, 0, len(params)) | 465 | columns := make([]string, 0, len(params)) |
| 450 | values := make([]interface{}, 0, len(params)) | 466 | values := make([]interface{}, 0, len(params)) |
| ... | @@ -520,6 +536,8 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con | ... | @@ -520,6 +536,8 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con |
| 520 | return 0, nil | 536 | return 0, nil |
| 521 | } | 537 | } |
| 522 | 538 | ||
| 539 | // delete related records. | ||
| 540 | // do UpdateBanch or DeleteBanch by condition of tables' relationship. | ||
| 523 | func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}, tz *time.Location) error { | 541 | func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}, tz *time.Location) error { |
| 524 | for _, fi := range mi.fields.fieldsReverse { | 542 | for _, fi := range mi.fields.fieldsReverse { |
| 525 | fi = fi.reverseFieldInfo | 543 | fi = fi.reverseFieldInfo |
| ... | @@ -546,6 +564,7 @@ func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}, tz * | ... | @@ -546,6 +564,7 @@ func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}, tz * |
| 546 | return nil | 564 | return nil |
| 547 | } | 565 | } |
| 548 | 566 | ||
| 567 | // delete table-related records. | ||
| 549 | func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (int64, error) { | 568 | func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (int64, error) { |
| 550 | tables := newDbTables(mi, d.ins) | 569 | tables := newDbTables(mi, d.ins) |
| 551 | tables.skipEnd = true | 570 | tables.skipEnd = true |
| ... | @@ -623,6 +642,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con | ... | @@ -623,6 +642,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con |
| 623 | return 0, nil | 642 | return 0, nil |
| 624 | } | 643 | } |
| 625 | 644 | ||
| 645 | // read related records. | ||
| 626 | func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, container interface{}, tz *time.Location, cols []string) (int64, error) { | 646 | func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, container interface{}, tz *time.Location, cols []string) (int64, error) { |
| 627 | 647 | ||
| 628 | val := reflect.ValueOf(container) | 648 | val := reflect.ValueOf(container) |
| ... | @@ -832,6 +852,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi | ... | @@ -832,6 +852,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi |
| 832 | return cnt, nil | 852 | return cnt, nil |
| 833 | } | 853 | } |
| 834 | 854 | ||
| 855 | // excute count sql and return count result int64. | ||
| 835 | func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (cnt int64, err error) { | 856 | func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (cnt int64, err error) { |
| 836 | tables := newDbTables(mi, d.ins) | 857 | tables := newDbTables(mi, d.ins) |
| 837 | tables.parseRelated(qs.related, qs.relDepth) | 858 | tables.parseRelated(qs.related, qs.relDepth) |
| ... | @@ -852,6 +873,7 @@ func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition | ... | @@ -852,6 +873,7 @@ func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition |
| 852 | return | 873 | return |
| 853 | } | 874 | } |
| 854 | 875 | ||
| 876 | // generate sql with replacing operator string placeholders and replaced values. | ||
| 855 | func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator string, args []interface{}, tz *time.Location) (string, []interface{}) { | 877 | func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator string, args []interface{}, tz *time.Location) (string, []interface{}) { |
| 856 | sql := "" | 878 | sql := "" |
| 857 | params := getFlatParams(fi, args, tz) | 879 | params := getFlatParams(fi, args, tz) |
| ... | @@ -905,10 +927,12 @@ func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator stri | ... | @@ -905,10 +927,12 @@ func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator stri |
| 905 | return sql, params | 927 | return sql, params |
| 906 | } | 928 | } |
| 907 | 929 | ||
| 930 | // gernerate sql string with inner function, such as UPPER(text). | ||
| 908 | func (d *dbBase) GenerateOperatorLeftCol(*fieldInfo, string, *string) { | 931 | func (d *dbBase) GenerateOperatorLeftCol(*fieldInfo, string, *string) { |
| 909 | // default not use | 932 | // default not use |
| 910 | } | 933 | } |
| 911 | 934 | ||
| 935 | // set values to struct column. | ||
| 912 | func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, values []interface{}, tz *time.Location) { | 936 | func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, values []interface{}, tz *time.Location) { |
| 913 | for i, column := range cols { | 937 | for i, column := range cols { |
| 914 | val := reflect.Indirect(reflect.ValueOf(values[i])).Interface() | 938 | val := reflect.Indirect(reflect.ValueOf(values[i])).Interface() |
| ... | @@ -930,6 +954,7 @@ func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, | ... | @@ -930,6 +954,7 @@ func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, |
| 930 | } | 954 | } |
| 931 | } | 955 | } |
| 932 | 956 | ||
| 957 | // convert value from database result to value following in field type. | ||
| 933 | func (d *dbBase) convertValueFromDB(fi *fieldInfo, val interface{}, tz *time.Location) (interface{}, error) { | 958 | func (d *dbBase) convertValueFromDB(fi *fieldInfo, val interface{}, tz *time.Location) (interface{}, error) { |
| 934 | if val == nil { | 959 | if val == nil { |
| 935 | return nil, nil | 960 | return nil, nil |
| ... | @@ -1082,6 +1107,7 @@ end: | ... | @@ -1082,6 +1107,7 @@ end: |
| 1082 | 1107 | ||
| 1083 | } | 1108 | } |
| 1084 | 1109 | ||
| 1110 | // set one value to struct column field. | ||
| 1085 | func (d *dbBase) setFieldValue(fi *fieldInfo, value interface{}, field reflect.Value) (interface{}, error) { | 1111 | func (d *dbBase) setFieldValue(fi *fieldInfo, value interface{}, field reflect.Value) (interface{}, error) { |
| 1086 | 1112 | ||
| 1087 | fieldType := fi.fieldType | 1113 | fieldType := fi.fieldType |
| ... | @@ -1156,6 +1182,7 @@ setValue: | ... | @@ -1156,6 +1182,7 @@ setValue: |
| 1156 | return value, nil | 1182 | return value, nil |
| 1157 | } | 1183 | } |
| 1158 | 1184 | ||
| 1185 | // query sql, read values , save to *[]ParamList. | ||
| 1159 | func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, exprs []string, container interface{}, tz *time.Location) (int64, error) { | 1186 | func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, exprs []string, container interface{}, tz *time.Location) (int64, error) { |
| 1160 | 1187 | ||
| 1161 | var ( | 1188 | var ( |
| ... | @@ -1323,6 +1350,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond | ... | @@ -1323,6 +1350,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond |
| 1323 | return cnt, nil | 1350 | return cnt, nil |
| 1324 | } | 1351 | } |
| 1325 | 1352 | ||
| 1353 | // flag of update joined record. | ||
| 1326 | func (d *dbBase) SupportUpdateJoin() bool { | 1354 | func (d *dbBase) SupportUpdateJoin() bool { |
| 1327 | return true | 1355 | return true |
| 1328 | } | 1356 | } |
| ... | @@ -1331,30 +1359,37 @@ func (d *dbBase) MaxLimit() uint64 { | ... | @@ -1331,30 +1359,37 @@ func (d *dbBase) MaxLimit() uint64 { |
| 1331 | return 18446744073709551615 | 1359 | return 18446744073709551615 |
| 1332 | } | 1360 | } |
| 1333 | 1361 | ||
| 1362 | // return quote. | ||
| 1334 | func (d *dbBase) TableQuote() string { | 1363 | func (d *dbBase) TableQuote() string { |
| 1335 | return "`" | 1364 | return "`" |
| 1336 | } | 1365 | } |
| 1337 | 1366 | ||
| 1367 | // replace value placeholer in parametered sql string. | ||
| 1338 | func (d *dbBase) ReplaceMarks(query *string) { | 1368 | func (d *dbBase) ReplaceMarks(query *string) { |
| 1339 | // default use `?` as mark, do nothing | 1369 | // default use `?` as mark, do nothing |
| 1340 | } | 1370 | } |
| 1341 | 1371 | ||
| 1372 | // flag of RETURNING sql. | ||
| 1342 | func (d *dbBase) HasReturningID(*modelInfo, *string) bool { | 1373 | func (d *dbBase) HasReturningID(*modelInfo, *string) bool { |
| 1343 | return false | 1374 | return false |
| 1344 | } | 1375 | } |
| 1345 | 1376 | ||
| 1377 | // convert time from db. | ||
| 1346 | func (d *dbBase) TimeFromDB(t *time.Time, tz *time.Location) { | 1378 | func (d *dbBase) TimeFromDB(t *time.Time, tz *time.Location) { |
| 1347 | *t = t.In(tz) | 1379 | *t = t.In(tz) |
| 1348 | } | 1380 | } |
| 1349 | 1381 | ||
| 1382 | // convert time to db. | ||
| 1350 | func (d *dbBase) TimeToDB(t *time.Time, tz *time.Location) { | 1383 | func (d *dbBase) TimeToDB(t *time.Time, tz *time.Location) { |
| 1351 | *t = t.In(tz) | 1384 | *t = t.In(tz) |
| 1352 | } | 1385 | } |
| 1353 | 1386 | ||
| 1387 | // get database types. | ||
| 1354 | func (d *dbBase) DbTypes() map[string]string { | 1388 | func (d *dbBase) DbTypes() map[string]string { |
| 1355 | return nil | 1389 | return nil |
| 1356 | } | 1390 | } |
| 1357 | 1391 | ||
| 1392 | // gt all tables. | ||
| 1358 | func (d *dbBase) GetTables(db dbQuerier) (map[string]bool, error) { | 1393 | func (d *dbBase) GetTables(db dbQuerier) (map[string]bool, error) { |
| 1359 | tables := make(map[string]bool) | 1394 | tables := make(map[string]bool) |
| 1360 | query := d.ins.ShowTablesQuery() | 1395 | query := d.ins.ShowTablesQuery() |
| ... | @@ -1379,6 +1414,7 @@ func (d *dbBase) GetTables(db dbQuerier) (map[string]bool, error) { | ... | @@ -1379,6 +1414,7 @@ func (d *dbBase) GetTables(db dbQuerier) (map[string]bool, error) { |
| 1379 | return tables, nil | 1414 | return tables, nil |
| 1380 | } | 1415 | } |
| 1381 | 1416 | ||
| 1417 | // get all cloumns in table. | ||
| 1382 | func (d *dbBase) GetColumns(db dbQuerier, table string) (map[string][3]string, error) { | 1418 | func (d *dbBase) GetColumns(db dbQuerier, table string) (map[string][3]string, error) { |
| 1383 | columns := make(map[string][3]string) | 1419 | columns := make(map[string][3]string) |
| 1384 | query := d.ins.ShowColumnsQuery(table) | 1420 | query := d.ins.ShowColumnsQuery(table) |
| ... | @@ -1405,18 +1441,22 @@ func (d *dbBase) GetColumns(db dbQuerier, table string) (map[string][3]string, e | ... | @@ -1405,18 +1441,22 @@ func (d *dbBase) GetColumns(db dbQuerier, table string) (map[string][3]string, e |
| 1405 | return columns, nil | 1441 | return columns, nil |
| 1406 | } | 1442 | } |
| 1407 | 1443 | ||
| 1444 | // not implement. | ||
| 1408 | func (d *dbBase) OperatorSql(operator string) string { | 1445 | func (d *dbBase) OperatorSql(operator string) string { |
| 1409 | panic(ErrNotImplement) | 1446 | panic(ErrNotImplement) |
| 1410 | } | 1447 | } |
| 1411 | 1448 | ||
| 1449 | // not implement. | ||
| 1412 | func (d *dbBase) ShowTablesQuery() string { | 1450 | func (d *dbBase) ShowTablesQuery() string { |
| 1413 | panic(ErrNotImplement) | 1451 | panic(ErrNotImplement) |
| 1414 | } | 1452 | } |
| 1415 | 1453 | ||
| 1454 | // not implement. | ||
| 1416 | func (d *dbBase) ShowColumnsQuery(table string) string { | 1455 | func (d *dbBase) ShowColumnsQuery(table string) string { |
| 1417 | panic(ErrNotImplement) | 1456 | panic(ErrNotImplement) |
| 1418 | } | 1457 | } |
| 1419 | 1458 | ||
| 1459 | // not implement. | ||
| 1420 | func (d *dbBase) IndexExists(dbQuerier, string, string) bool { | 1460 | func (d *dbBase) IndexExists(dbQuerier, string, string) bool { |
| 1421 | panic(ErrNotImplement) | 1461 | panic(ErrNotImplement) |
| 1422 | } | 1462 | } | ... | ... |
| ... | @@ -9,27 +9,32 @@ import ( | ... | @@ -9,27 +9,32 @@ import ( |
| 9 | "time" | 9 | "time" |
| 10 | ) | 10 | ) |
| 11 | 11 | ||
| 12 | // database driver constant int. | ||
| 12 | type DriverType int | 13 | type DriverType int |
| 13 | 14 | ||
| 14 | const ( | 15 | const ( |
| 15 | _ DriverType = iota | 16 | _ DriverType = iota // int enum type |
| 16 | DR_MySQL | 17 | DR_MySQL // mysql |
| 17 | DR_Sqlite | 18 | DR_Sqlite // sqlite |
| 18 | DR_Oracle | 19 | DR_Oracle // oracle |
| 19 | DR_Postgres | 20 | DR_Postgres // pgsql |
| 20 | ) | 21 | ) |
| 21 | 22 | ||
| 23 | // database driver string. | ||
| 22 | type driver string | 24 | type driver string |
| 23 | 25 | ||
| 26 | // get type constant int of current driver.. | ||
| 24 | func (d driver) Type() DriverType { | 27 | func (d driver) Type() DriverType { |
| 25 | a, _ := dataBaseCache.get(string(d)) | 28 | a, _ := dataBaseCache.get(string(d)) |
| 26 | return a.Driver | 29 | return a.Driver |
| 27 | } | 30 | } |
| 28 | 31 | ||
| 32 | // get name of current driver | ||
| 29 | func (d driver) Name() string { | 33 | func (d driver) Name() string { |
| 30 | return string(d) | 34 | return string(d) |
| 31 | } | 35 | } |
| 32 | 36 | ||
| 37 | // check driver iis implemented Driver interface or not. | ||
| 33 | var _ Driver = new(driver) | 38 | var _ Driver = new(driver) |
| 34 | 39 | ||
| 35 | var ( | 40 | var ( |
| ... | @@ -47,11 +52,13 @@ var ( | ... | @@ -47,11 +52,13 @@ var ( |
| 47 | } | 52 | } |
| 48 | ) | 53 | ) |
| 49 | 54 | ||
| 55 | // database alias cacher. | ||
| 50 | type _dbCache struct { | 56 | type _dbCache struct { |
| 51 | mux sync.RWMutex | 57 | mux sync.RWMutex |
| 52 | cache map[string]*alias | 58 | cache map[string]*alias |
| 53 | } | 59 | } |
| 54 | 60 | ||
| 61 | // add database alias with original name. | ||
| 55 | func (ac *_dbCache) add(name string, al *alias) (added bool) { | 62 | func (ac *_dbCache) add(name string, al *alias) (added bool) { |
| 56 | ac.mux.Lock() | 63 | ac.mux.Lock() |
| 57 | defer ac.mux.Unlock() | 64 | defer ac.mux.Unlock() |
| ... | @@ -62,6 +69,7 @@ func (ac *_dbCache) add(name string, al *alias) (added bool) { | ... | @@ -62,6 +69,7 @@ func (ac *_dbCache) add(name string, al *alias) (added bool) { |
| 62 | return | 69 | return |
| 63 | } | 70 | } |
| 64 | 71 | ||
| 72 | // get database alias if cached. | ||
| 65 | func (ac *_dbCache) get(name string) (al *alias, ok bool) { | 73 | func (ac *_dbCache) get(name string) (al *alias, ok bool) { |
| 66 | ac.mux.RLock() | 74 | ac.mux.RLock() |
| 67 | defer ac.mux.RUnlock() | 75 | defer ac.mux.RUnlock() |
| ... | @@ -69,6 +77,7 @@ func (ac *_dbCache) get(name string) (al *alias, ok bool) { | ... | @@ -69,6 +77,7 @@ func (ac *_dbCache) get(name string) (al *alias, ok bool) { |
| 69 | return | 77 | return |
| 70 | } | 78 | } |
| 71 | 79 | ||
| 80 | // get default alias. | ||
| 72 | func (ac *_dbCache) getDefault() (al *alias) { | 81 | func (ac *_dbCache) getDefault() (al *alias) { |
| 73 | al, _ = ac.get("default") | 82 | al, _ = ac.get("default") |
| 74 | return | 83 | return | ... | ... |
| ... | @@ -4,6 +4,7 @@ import ( | ... | @@ -4,6 +4,7 @@ import ( |
| 4 | "fmt" | 4 | "fmt" |
| 5 | ) | 5 | ) |
| 6 | 6 | ||
| 7 | // mysql operators. | ||
| 7 | var mysqlOperators = map[string]string{ | 8 | var mysqlOperators = map[string]string{ |
| 8 | "exact": "= ?", | 9 | "exact": "= ?", |
| 9 | "iexact": "LIKE ?", | 10 | "iexact": "LIKE ?", |
| ... | @@ -21,6 +22,7 @@ var mysqlOperators = map[string]string{ | ... | @@ -21,6 +22,7 @@ var mysqlOperators = map[string]string{ |
| 21 | "iendswith": "LIKE ?", | 22 | "iendswith": "LIKE ?", |
| 22 | } | 23 | } |
| 23 | 24 | ||
| 25 | // mysql column field types. | ||
| 24 | var mysqlTypes = map[string]string{ | 26 | var mysqlTypes = map[string]string{ |
| 25 | "auto": "AUTO_INCREMENT NOT NULL PRIMARY KEY", | 27 | "auto": "AUTO_INCREMENT NOT NULL PRIMARY KEY", |
| 26 | "pk": "NOT NULL PRIMARY KEY", | 28 | "pk": "NOT NULL PRIMARY KEY", |
| ... | @@ -41,29 +43,35 @@ var mysqlTypes = map[string]string{ | ... | @@ -41,29 +43,35 @@ var mysqlTypes = map[string]string{ |
| 41 | "float64-decimal": "numeric(%d, %d)", | 43 | "float64-decimal": "numeric(%d, %d)", |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 46 | // mysql dbBaser implementation. | ||
| 44 | type dbBaseMysql struct { | 47 | type dbBaseMysql struct { |
| 45 | dbBase | 48 | dbBase |
| 46 | } | 49 | } |
| 47 | 50 | ||
| 48 | var _ dbBaser = new(dbBaseMysql) | 51 | var _ dbBaser = new(dbBaseMysql) |
| 49 | 52 | ||
| 53 | // get mysql operator. | ||
| 50 | func (d *dbBaseMysql) OperatorSql(operator string) string { | 54 | func (d *dbBaseMysql) OperatorSql(operator string) string { |
| 51 | return mysqlOperators[operator] | 55 | return mysqlOperators[operator] |
| 52 | } | 56 | } |
| 53 | 57 | ||
| 58 | // get mysql table field types. | ||
| 54 | func (d *dbBaseMysql) DbTypes() map[string]string { | 59 | func (d *dbBaseMysql) DbTypes() map[string]string { |
| 55 | return mysqlTypes | 60 | return mysqlTypes |
| 56 | } | 61 | } |
| 57 | 62 | ||
| 63 | // show table sql for mysql. | ||
| 58 | func (d *dbBaseMysql) ShowTablesQuery() string { | 64 | func (d *dbBaseMysql) ShowTablesQuery() string { |
| 59 | return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema = DATABASE()" | 65 | return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema = DATABASE()" |
| 60 | } | 66 | } |
| 61 | 67 | ||
| 68 | // show columns sql of table for mysql. | ||
| 62 | func (d *dbBaseMysql) ShowColumnsQuery(table string) string { | 69 | func (d *dbBaseMysql) ShowColumnsQuery(table string) string { |
| 63 | return fmt.Sprintf("SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE FROM information_schema.columns "+ | 70 | return fmt.Sprintf("SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE FROM information_schema.columns "+ |
| 64 | "WHERE table_schema = DATABASE() AND table_name = '%s'", table) | 71 | "WHERE table_schema = DATABASE() AND table_name = '%s'", table) |
| 65 | } | 72 | } |
| 66 | 73 | ||
| 74 | // execute sql to check index exist. | ||
| 67 | func (d *dbBaseMysql) IndexExists(db dbQuerier, table string, name string) bool { | 75 | func (d *dbBaseMysql) IndexExists(db dbQuerier, table string, name string) bool { |
| 68 | row := db.QueryRow("SELECT count(*) FROM information_schema.statistics "+ | 76 | row := db.QueryRow("SELECT count(*) FROM information_schema.statistics "+ |
| 69 | "WHERE table_schema = DATABASE() AND table_name = ? AND index_name = ?", table, name) | 77 | "WHERE table_schema = DATABASE() AND table_name = ? AND index_name = ?", table, name) |
| ... | @@ -72,6 +80,7 @@ func (d *dbBaseMysql) IndexExists(db dbQuerier, table string, name string) bool | ... | @@ -72,6 +80,7 @@ func (d *dbBaseMysql) IndexExists(db dbQuerier, table string, name string) bool |
| 72 | return cnt > 0 | 80 | return cnt > 0 |
| 73 | } | 81 | } |
| 74 | 82 | ||
| 83 | // create new mysql dbBaser. | ||
| 75 | func newdbBaseMysql() dbBaser { | 84 | func newdbBaseMysql() dbBaser { |
| 76 | b := new(dbBaseMysql) | 85 | b := new(dbBaseMysql) |
| 77 | b.ins = b | 86 | b.ins = b | ... | ... |
| 1 | package orm | 1 | package orm |
| 2 | 2 | ||
| 3 | // oracle dbBaser | ||
| 3 | type dbBaseOracle struct { | 4 | type dbBaseOracle struct { |
| 4 | dbBase | 5 | dbBase |
| 5 | } | 6 | } |
| 6 | 7 | ||
| 7 | var _ dbBaser = new(dbBaseOracle) | 8 | var _ dbBaser = new(dbBaseOracle) |
| 8 | 9 | ||
| 10 | // create oracle dbBaser. | ||
| 9 | func newdbBaseOracle() dbBaser { | 11 | func newdbBaseOracle() dbBaser { |
| 10 | b := new(dbBaseOracle) | 12 | b := new(dbBaseOracle) |
| 11 | b.ins = b | 13 | b.ins = b | ... | ... |
| ... | @@ -5,6 +5,7 @@ import ( | ... | @@ -5,6 +5,7 @@ import ( |
| 5 | "strconv" | 5 | "strconv" |
| 6 | ) | 6 | ) |
| 7 | 7 | ||
| 8 | // postgresql operators. | ||
| 8 | var postgresOperators = map[string]string{ | 9 | var postgresOperators = map[string]string{ |
| 9 | "exact": "= ?", | 10 | "exact": "= ?", |
| 10 | "iexact": "= UPPER(?)", | 11 | "iexact": "= UPPER(?)", |
| ... | @@ -20,6 +21,7 @@ var postgresOperators = map[string]string{ | ... | @@ -20,6 +21,7 @@ var postgresOperators = map[string]string{ |
| 20 | "iendswith": "LIKE UPPER(?)", | 21 | "iendswith": "LIKE UPPER(?)", |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 24 | // postgresql column field types. | ||
| 23 | var postgresTypes = map[string]string{ | 25 | var postgresTypes = map[string]string{ |
| 24 | "auto": "serial NOT NULL PRIMARY KEY", | 26 | "auto": "serial NOT NULL PRIMARY KEY", |
| 25 | "pk": "NOT NULL PRIMARY KEY", | 27 | "pk": "NOT NULL PRIMARY KEY", |
| ... | @@ -40,16 +42,19 @@ var postgresTypes = map[string]string{ | ... | @@ -40,16 +42,19 @@ var postgresTypes = map[string]string{ |
| 40 | "float64-decimal": "numeric(%d, %d)", | 42 | "float64-decimal": "numeric(%d, %d)", |
| 41 | } | 43 | } |
| 42 | 44 | ||
| 45 | // postgresql dbBaser. | ||
| 43 | type dbBasePostgres struct { | 46 | type dbBasePostgres struct { |
| 44 | dbBase | 47 | dbBase |
| 45 | } | 48 | } |
| 46 | 49 | ||
| 47 | var _ dbBaser = new(dbBasePostgres) | 50 | var _ dbBaser = new(dbBasePostgres) |
| 48 | 51 | ||
| 52 | // get postgresql operator. | ||
| 49 | func (d *dbBasePostgres) OperatorSql(operator string) string { | 53 | func (d *dbBasePostgres) OperatorSql(operator string) string { |
| 50 | return postgresOperators[operator] | 54 | return postgresOperators[operator] |
| 51 | } | 55 | } |
| 52 | 56 | ||
| 57 | // generate functioned sql string, such as contains(text). | ||
| 53 | func (d *dbBasePostgres) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) { | 58 | func (d *dbBasePostgres) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) { |
| 54 | switch operator { | 59 | switch operator { |
| 55 | case "contains", "startswith", "endswith": | 60 | case "contains", "startswith", "endswith": |
| ... | @@ -59,6 +64,7 @@ func (d *dbBasePostgres) GenerateOperatorLeftCol(fi *fieldInfo, operator string, | ... | @@ -59,6 +64,7 @@ func (d *dbBasePostgres) GenerateOperatorLeftCol(fi *fieldInfo, operator string, |
| 59 | } | 64 | } |
| 60 | } | 65 | } |
| 61 | 66 | ||
| 67 | // postgresql unsupports updating joined record. | ||
| 62 | func (d *dbBasePostgres) SupportUpdateJoin() bool { | 68 | func (d *dbBasePostgres) SupportUpdateJoin() bool { |
| 63 | return false | 69 | return false |
| 64 | } | 70 | } |
| ... | @@ -67,10 +73,13 @@ func (d *dbBasePostgres) MaxLimit() uint64 { | ... | @@ -67,10 +73,13 @@ func (d *dbBasePostgres) MaxLimit() uint64 { |
| 67 | return 0 | 73 | return 0 |
| 68 | } | 74 | } |
| 69 | 75 | ||
| 76 | // postgresql quote is ". | ||
| 70 | func (d *dbBasePostgres) TableQuote() string { | 77 | func (d *dbBasePostgres) TableQuote() string { |
| 71 | return `"` | 78 | return `"` |
| 72 | } | 79 | } |
| 73 | 80 | ||
| 81 | // postgresql value placeholder is $n. | ||
| 82 | // replace default ? to $n. | ||
| 74 | func (d *dbBasePostgres) ReplaceMarks(query *string) { | 83 | func (d *dbBasePostgres) ReplaceMarks(query *string) { |
| 75 | q := *query | 84 | q := *query |
| 76 | num := 0 | 85 | num := 0 |
| ... | @@ -97,6 +106,7 @@ func (d *dbBasePostgres) ReplaceMarks(query *string) { | ... | @@ -97,6 +106,7 @@ func (d *dbBasePostgres) ReplaceMarks(query *string) { |
| 97 | *query = string(data) | 106 | *query = string(data) |
| 98 | } | 107 | } |
| 99 | 108 | ||
| 109 | // make returning sql support for postgresql. | ||
| 100 | func (d *dbBasePostgres) HasReturningID(mi *modelInfo, query *string) (has bool) { | 110 | func (d *dbBasePostgres) HasReturningID(mi *modelInfo, query *string) (has bool) { |
| 101 | if mi.fields.pk.auto { | 111 | if mi.fields.pk.auto { |
| 102 | if query != nil { | 112 | if query != nil { |
| ... | @@ -107,18 +117,22 @@ func (d *dbBasePostgres) HasReturningID(mi *modelInfo, query *string) (has bool) | ... | @@ -107,18 +117,22 @@ func (d *dbBasePostgres) HasReturningID(mi *modelInfo, query *string) (has bool) |
| 107 | return | 117 | return |
| 108 | } | 118 | } |
| 109 | 119 | ||
| 120 | // show table sql for postgresql. | ||
| 110 | func (d *dbBasePostgres) ShowTablesQuery() string { | 121 | func (d *dbBasePostgres) ShowTablesQuery() string { |
| 111 | return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')" | 122 | return "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' AND table_schema NOT IN ('pg_catalog', 'information_schema')" |
| 112 | } | 123 | } |
| 113 | 124 | ||
| 125 | // show table columns sql for postgresql. | ||
| 114 | func (d *dbBasePostgres) ShowColumnsQuery(table string) string { | 126 | func (d *dbBasePostgres) ShowColumnsQuery(table string) string { |
| 115 | return fmt.Sprintf("SELECT column_name, data_type, is_nullable FROM information_schema.columns where table_schema NOT IN ('pg_catalog', 'information_schema') and table_name = '%s'", table) | 127 | return fmt.Sprintf("SELECT column_name, data_type, is_nullable FROM information_schema.columns where table_schema NOT IN ('pg_catalog', 'information_schema') and table_name = '%s'", table) |
| 116 | } | 128 | } |
| 117 | 129 | ||
| 130 | // get column types of postgresql. | ||
| 118 | func (d *dbBasePostgres) DbTypes() map[string]string { | 131 | func (d *dbBasePostgres) DbTypes() map[string]string { |
| 119 | return postgresTypes | 132 | return postgresTypes |
| 120 | } | 133 | } |
| 121 | 134 | ||
| 135 | // check index exist in postgresql. | ||
| 122 | func (d *dbBasePostgres) IndexExists(db dbQuerier, table string, name string) bool { | 136 | func (d *dbBasePostgres) IndexExists(db dbQuerier, table string, name string) bool { |
| 123 | query := fmt.Sprintf("SELECT COUNT(*) FROM pg_indexes WHERE tablename = '%s' AND indexname = '%s'", table, name) | 137 | query := fmt.Sprintf("SELECT COUNT(*) FROM pg_indexes WHERE tablename = '%s' AND indexname = '%s'", table, name) |
| 124 | row := db.QueryRow(query) | 138 | row := db.QueryRow(query) |
| ... | @@ -127,6 +141,7 @@ func (d *dbBasePostgres) IndexExists(db dbQuerier, table string, name string) bo | ... | @@ -127,6 +141,7 @@ func (d *dbBasePostgres) IndexExists(db dbQuerier, table string, name string) bo |
| 127 | return cnt > 0 | 141 | return cnt > 0 |
| 128 | } | 142 | } |
| 129 | 143 | ||
| 144 | // create new postgresql dbBaser. | ||
| 130 | func newdbBasePostgres() dbBaser { | 145 | func newdbBasePostgres() dbBaser { |
| 131 | b := new(dbBasePostgres) | 146 | b := new(dbBasePostgres) |
| 132 | b.ins = b | 147 | b.ins = b | ... | ... |
| ... | @@ -5,6 +5,7 @@ import ( | ... | @@ -5,6 +5,7 @@ import ( |
| 5 | "fmt" | 5 | "fmt" |
| 6 | ) | 6 | ) |
| 7 | 7 | ||
| 8 | // sqlite operators. | ||
| 8 | var sqliteOperators = map[string]string{ | 9 | var sqliteOperators = map[string]string{ |
| 9 | "exact": "= ?", | 10 | "exact": "= ?", |
| 10 | "iexact": "LIKE ? ESCAPE '\\'", | 11 | "iexact": "LIKE ? ESCAPE '\\'", |
| ... | @@ -20,6 +21,7 @@ var sqliteOperators = map[string]string{ | ... | @@ -20,6 +21,7 @@ var sqliteOperators = map[string]string{ |
| 20 | "iendswith": "LIKE ? ESCAPE '\\'", | 21 | "iendswith": "LIKE ? ESCAPE '\\'", |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 24 | // sqlite column types. | ||
| 23 | var sqliteTypes = map[string]string{ | 25 | var sqliteTypes = map[string]string{ |
| 24 | "auto": "integer NOT NULL PRIMARY KEY AUTOINCREMENT", | 26 | "auto": "integer NOT NULL PRIMARY KEY AUTOINCREMENT", |
| 25 | "pk": "NOT NULL PRIMARY KEY", | 27 | "pk": "NOT NULL PRIMARY KEY", |
| ... | @@ -40,38 +42,47 @@ var sqliteTypes = map[string]string{ | ... | @@ -40,38 +42,47 @@ var sqliteTypes = map[string]string{ |
| 40 | "float64-decimal": "decimal", | 42 | "float64-decimal": "decimal", |
| 41 | } | 43 | } |
| 42 | 44 | ||
| 45 | // sqlite dbBaser. | ||
| 43 | type dbBaseSqlite struct { | 46 | type dbBaseSqlite struct { |
| 44 | dbBase | 47 | dbBase |
| 45 | } | 48 | } |
| 46 | 49 | ||
| 47 | var _ dbBaser = new(dbBaseSqlite) | 50 | var _ dbBaser = new(dbBaseSqlite) |
| 48 | 51 | ||
| 52 | // get sqlite operator. | ||
| 49 | func (d *dbBaseSqlite) OperatorSql(operator string) string { | 53 | func (d *dbBaseSqlite) OperatorSql(operator string) string { |
| 50 | return sqliteOperators[operator] | 54 | return sqliteOperators[operator] |
| 51 | } | 55 | } |
| 52 | 56 | ||
| 57 | // generate functioned sql for sqlite. | ||
| 58 | // only support DATE(text). | ||
| 53 | func (d *dbBaseSqlite) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) { | 59 | func (d *dbBaseSqlite) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) { |
| 54 | if fi.fieldType == TypeDateField { | 60 | if fi.fieldType == TypeDateField { |
| 55 | *leftCol = fmt.Sprintf("DATE(%s)", *leftCol) | 61 | *leftCol = fmt.Sprintf("DATE(%s)", *leftCol) |
| 56 | } | 62 | } |
| 57 | } | 63 | } |
| 58 | 64 | ||
| 65 | // unable updating joined record in sqlite. | ||
| 59 | func (d *dbBaseSqlite) SupportUpdateJoin() bool { | 66 | func (d *dbBaseSqlite) SupportUpdateJoin() bool { |
| 60 | return false | 67 | return false |
| 61 | } | 68 | } |
| 62 | 69 | ||
| 70 | // max int in sqlite. | ||
| 63 | func (d *dbBaseSqlite) MaxLimit() uint64 { | 71 | func (d *dbBaseSqlite) MaxLimit() uint64 { |
| 64 | return 9223372036854775807 | 72 | return 9223372036854775807 |
| 65 | } | 73 | } |
| 66 | 74 | ||
| 75 | // get column types in sqlite. | ||
| 67 | func (d *dbBaseSqlite) DbTypes() map[string]string { | 76 | func (d *dbBaseSqlite) DbTypes() map[string]string { |
| 68 | return sqliteTypes | 77 | return sqliteTypes |
| 69 | } | 78 | } |
| 70 | 79 | ||
| 80 | // get show tables sql in sqlite. | ||
| 71 | func (d *dbBaseSqlite) ShowTablesQuery() string { | 81 | func (d *dbBaseSqlite) ShowTablesQuery() string { |
| 72 | return "SELECT name FROM sqlite_master WHERE type = 'table'" | 82 | return "SELECT name FROM sqlite_master WHERE type = 'table'" |
| 73 | } | 83 | } |
| 74 | 84 | ||
| 85 | // get columns in sqlite. | ||
| 75 | func (d *dbBaseSqlite) GetColumns(db dbQuerier, table string) (map[string][3]string, error) { | 86 | func (d *dbBaseSqlite) GetColumns(db dbQuerier, table string) (map[string][3]string, error) { |
| 76 | query := d.ins.ShowColumnsQuery(table) | 87 | query := d.ins.ShowColumnsQuery(table) |
| 77 | rows, err := db.Query(query) | 88 | rows, err := db.Query(query) |
| ... | @@ -92,10 +103,12 @@ func (d *dbBaseSqlite) GetColumns(db dbQuerier, table string) (map[string][3]str | ... | @@ -92,10 +103,12 @@ func (d *dbBaseSqlite) GetColumns(db dbQuerier, table string) (map[string][3]str |
| 92 | return columns, nil | 103 | return columns, nil |
| 93 | } | 104 | } |
| 94 | 105 | ||
| 106 | // get show columns sql in sqlite. | ||
| 95 | func (d *dbBaseSqlite) ShowColumnsQuery(table string) string { | 107 | func (d *dbBaseSqlite) ShowColumnsQuery(table string) string { |
| 96 | return fmt.Sprintf("pragma table_info('%s')", table) | 108 | return fmt.Sprintf("pragma table_info('%s')", table) |
| 97 | } | 109 | } |
| 98 | 110 | ||
| 111 | // check index exist in sqlite. | ||
| 99 | func (d *dbBaseSqlite) IndexExists(db dbQuerier, table string, name string) bool { | 112 | func (d *dbBaseSqlite) IndexExists(db dbQuerier, table string, name string) bool { |
| 100 | query := fmt.Sprintf("PRAGMA index_list('%s')", table) | 113 | query := fmt.Sprintf("PRAGMA index_list('%s')", table) |
| 101 | rows, err := db.Query(query) | 114 | rows, err := db.Query(query) |
| ... | @@ -113,6 +126,7 @@ func (d *dbBaseSqlite) IndexExists(db dbQuerier, table string, name string) bool | ... | @@ -113,6 +126,7 @@ func (d *dbBaseSqlite) IndexExists(db dbQuerier, table string, name string) bool |
| 113 | return false | 126 | return false |
| 114 | } | 127 | } |
| 115 | 128 | ||
| 129 | // create new sqlite dbBaser. | ||
| 116 | func newdbBaseSqlite() dbBaser { | 130 | func newdbBaseSqlite() dbBaser { |
| 117 | b := new(dbBaseSqlite) | 131 | b := new(dbBaseSqlite) |
| 118 | b.ins = b | 132 | b.ins = b | ... | ... |
| ... | @@ -6,6 +6,7 @@ import ( | ... | @@ -6,6 +6,7 @@ import ( |
| 6 | "time" | 6 | "time" |
| 7 | ) | 7 | ) |
| 8 | 8 | ||
| 9 | // table info struct. | ||
| 9 | type dbTable struct { | 10 | type dbTable struct { |
| 10 | id int | 11 | id int |
| 11 | index string | 12 | index string |
| ... | @@ -18,6 +19,7 @@ type dbTable struct { | ... | @@ -18,6 +19,7 @@ type dbTable struct { |
| 18 | jtl *dbTable | 19 | jtl *dbTable |
| 19 | } | 20 | } |
| 20 | 21 | ||
| 22 | // tables collection struct, contains some tables. | ||
| 21 | type dbTables struct { | 23 | type dbTables struct { |
| 22 | tablesM map[string]*dbTable | 24 | tablesM map[string]*dbTable |
| 23 | tables []*dbTable | 25 | tables []*dbTable |
| ... | @@ -26,6 +28,8 @@ type dbTables struct { | ... | @@ -26,6 +28,8 @@ type dbTables struct { |
| 26 | skipEnd bool | 28 | skipEnd bool |
| 27 | } | 29 | } |
| 28 | 30 | ||
| 31 | // set table info to collection. | ||
| 32 | // if not exist, create new. | ||
| 29 | func (t *dbTables) set(names []string, mi *modelInfo, fi *fieldInfo, inner bool) *dbTable { | 33 | func (t *dbTables) set(names []string, mi *modelInfo, fi *fieldInfo, inner bool) *dbTable { |
| 30 | name := strings.Join(names, ExprSep) | 34 | name := strings.Join(names, ExprSep) |
| 31 | if j, ok := t.tablesM[name]; ok { | 35 | if j, ok := t.tablesM[name]; ok { |
| ... | @@ -42,6 +46,7 @@ func (t *dbTables) set(names []string, mi *modelInfo, fi *fieldInfo, inner bool) | ... | @@ -42,6 +46,7 @@ func (t *dbTables) set(names []string, mi *modelInfo, fi *fieldInfo, inner bool) |
| 42 | return t.tablesM[name] | 46 | return t.tablesM[name] |
| 43 | } | 47 | } |
| 44 | 48 | ||
| 49 | // add table info to collection. | ||
| 45 | func (t *dbTables) add(names []string, mi *modelInfo, fi *fieldInfo, inner bool) (*dbTable, bool) { | 50 | func (t *dbTables) add(names []string, mi *modelInfo, fi *fieldInfo, inner bool) (*dbTable, bool) { |
| 46 | name := strings.Join(names, ExprSep) | 51 | name := strings.Join(names, ExprSep) |
| 47 | if _, ok := t.tablesM[name]; ok == false { | 52 | if _, ok := t.tablesM[name]; ok == false { |
| ... | @@ -54,11 +59,14 @@ func (t *dbTables) add(names []string, mi *modelInfo, fi *fieldInfo, inner bool) | ... | @@ -54,11 +59,14 @@ func (t *dbTables) add(names []string, mi *modelInfo, fi *fieldInfo, inner bool) |
| 54 | return t.tablesM[name], false | 59 | return t.tablesM[name], false |
| 55 | } | 60 | } |
| 56 | 61 | ||
| 62 | // get table info in collection. | ||
| 57 | func (t *dbTables) get(name string) (*dbTable, bool) { | 63 | func (t *dbTables) get(name string) (*dbTable, bool) { |
| 58 | j, ok := t.tablesM[name] | 64 | j, ok := t.tablesM[name] |
| 59 | return j, ok | 65 | return j, ok |
| 60 | } | 66 | } |
| 61 | 67 | ||
| 68 | // get related fields info in recursive depth loop. | ||
| 69 | // loop once, depth decreases one. | ||
| 62 | func (t *dbTables) loopDepth(depth int, prefix string, fi *fieldInfo, related []string) []string { | 70 | func (t *dbTables) loopDepth(depth int, prefix string, fi *fieldInfo, related []string) []string { |
| 63 | if depth < 0 || fi.fieldType == RelManyToMany { | 71 | if depth < 0 || fi.fieldType == RelManyToMany { |
| 64 | return related | 72 | return related |
| ... | @@ -79,6 +87,7 @@ func (t *dbTables) loopDepth(depth int, prefix string, fi *fieldInfo, related [] | ... | @@ -79,6 +87,7 @@ func (t *dbTables) loopDepth(depth int, prefix string, fi *fieldInfo, related [] |
| 79 | return related | 87 | return related |
| 80 | } | 88 | } |
| 81 | 89 | ||
| 90 | // parse related fields. | ||
| 82 | func (t *dbTables) parseRelated(rels []string, depth int) { | 91 | func (t *dbTables) parseRelated(rels []string, depth int) { |
| 83 | 92 | ||
| 84 | relsNum := len(rels) | 93 | relsNum := len(rels) |
| ... | @@ -140,6 +149,7 @@ func (t *dbTables) parseRelated(rels []string, depth int) { | ... | @@ -140,6 +149,7 @@ func (t *dbTables) parseRelated(rels []string, depth int) { |
| 140 | } | 149 | } |
| 141 | } | 150 | } |
| 142 | 151 | ||
| 152 | // generate join string. | ||
| 143 | func (t *dbTables) getJoinSql() (join string) { | 153 | func (t *dbTables) getJoinSql() (join string) { |
| 144 | Q := t.base.TableQuote() | 154 | Q := t.base.TableQuote() |
| 145 | 155 | ||
| ... | @@ -186,6 +196,7 @@ func (t *dbTables) getJoinSql() (join string) { | ... | @@ -186,6 +196,7 @@ func (t *dbTables) getJoinSql() (join string) { |
| 186 | return | 196 | return |
| 187 | } | 197 | } |
| 188 | 198 | ||
| 199 | // parse orm model struct field tag expression. | ||
| 189 | func (t *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string, info *fieldInfo, success bool) { | 200 | func (t *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string, info *fieldInfo, success bool) { |
| 190 | var ( | 201 | var ( |
| 191 | jtl *dbTable | 202 | jtl *dbTable |
| ... | @@ -300,6 +311,7 @@ loopFor: | ... | @@ -300,6 +311,7 @@ loopFor: |
| 300 | return | 311 | return |
| 301 | } | 312 | } |
| 302 | 313 | ||
| 314 | // generate condition sql. | ||
| 303 | func (t *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (where string, params []interface{}) { | 315 | func (t *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (where string, params []interface{}) { |
| 304 | if cond == nil || cond.IsEmpty() { | 316 | if cond == nil || cond.IsEmpty() { |
| 305 | return | 317 | return |
| ... | @@ -364,6 +376,7 @@ func (t *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe | ... | @@ -364,6 +376,7 @@ func (t *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (whe |
| 364 | return | 376 | return |
| 365 | } | 377 | } |
| 366 | 378 | ||
| 379 | // generate order sql. | ||
| 367 | func (t *dbTables) getOrderSql(orders []string) (orderSql string) { | 380 | func (t *dbTables) getOrderSql(orders []string) (orderSql string) { |
| 368 | if len(orders) == 0 { | 381 | if len(orders) == 0 { |
| 369 | return | 382 | return |
| ... | @@ -392,6 +405,7 @@ func (t *dbTables) getOrderSql(orders []string) (orderSql string) { | ... | @@ -392,6 +405,7 @@ func (t *dbTables) getOrderSql(orders []string) (orderSql string) { |
| 392 | return | 405 | return |
| 393 | } | 406 | } |
| 394 | 407 | ||
| 408 | // generate limit sql. | ||
| 395 | func (t *dbTables) getLimitSql(mi *modelInfo, offset int64, limit int64) (limits string) { | 409 | func (t *dbTables) getLimitSql(mi *modelInfo, offset int64, limit int64) (limits string) { |
| 396 | if limit == 0 { | 410 | if limit == 0 { |
| 397 | limit = int64(DefaultRowsLimit) | 411 | limit = int64(DefaultRowsLimit) |
| ... | @@ -414,6 +428,7 @@ func (t *dbTables) getLimitSql(mi *modelInfo, offset int64, limit int64) (limits | ... | @@ -414,6 +428,7 @@ func (t *dbTables) getLimitSql(mi *modelInfo, offset int64, limit int64) (limits |
| 414 | return | 428 | return |
| 415 | } | 429 | } |
| 416 | 430 | ||
| 431 | // crete new tables collection. | ||
| 417 | func newDbTables(mi *modelInfo, base dbBaser) *dbTables { | 432 | func newDbTables(mi *modelInfo, base dbBaser) *dbTables { |
| 418 | tables := &dbTables{} | 433 | tables := &dbTables{} |
| 419 | tables.tablesM = make(map[string]*dbTable) | 434 | tables.tablesM = make(map[string]*dbTable) | ... | ... |
| ... | @@ -6,6 +6,7 @@ import ( | ... | @@ -6,6 +6,7 @@ import ( |
| 6 | "time" | 6 | "time" |
| 7 | ) | 7 | ) |
| 8 | 8 | ||
| 9 | // get table alias. | ||
| 9 | func getDbAlias(name string) *alias { | 10 | func getDbAlias(name string) *alias { |
| 10 | if al, ok := dataBaseCache.get(name); ok { | 11 | if al, ok := dataBaseCache.get(name); ok { |
| 11 | return al | 12 | return al |
| ... | @@ -15,6 +16,7 @@ func getDbAlias(name string) *alias { | ... | @@ -15,6 +16,7 @@ func getDbAlias(name string) *alias { |
| 15 | return nil | 16 | return nil |
| 16 | } | 17 | } |
| 17 | 18 | ||
| 19 | // get pk column info. | ||
| 18 | func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interface{}, exist bool) { | 20 | func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interface{}, exist bool) { |
| 19 | fi := mi.fields.pk | 21 | fi := mi.fields.pk |
| 20 | 22 | ||
| ... | @@ -37,6 +39,7 @@ func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interfac | ... | @@ -37,6 +39,7 @@ func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interfac |
| 37 | return | 39 | return |
| 38 | } | 40 | } |
| 39 | 41 | ||
| 42 | // get fields description as flatted string. | ||
| 40 | func getFlatParams(fi *fieldInfo, args []interface{}, tz *time.Location) (params []interface{}) { | 43 | func getFlatParams(fi *fieldInfo, args []interface{}, tz *time.Location) (params []interface{}) { |
| 41 | 44 | ||
| 42 | outFor: | 45 | outFor: | ... | ... |
| ... | @@ -41,6 +41,7 @@ var ( | ... | @@ -41,6 +41,7 @@ var ( |
| 41 | } | 41 | } |
| 42 | ) | 42 | ) |
| 43 | 43 | ||
| 44 | // model info collection | ||
| 44 | type _modelCache struct { | 45 | type _modelCache struct { |
| 45 | sync.RWMutex | 46 | sync.RWMutex |
| 46 | orders []string | 47 | orders []string |
| ... | @@ -49,6 +50,7 @@ type _modelCache struct { | ... | @@ -49,6 +50,7 @@ type _modelCache struct { |
| 49 | done bool | 50 | done bool |
| 50 | } | 51 | } |
| 51 | 52 | ||
| 53 | // get all model info | ||
| 52 | func (mc *_modelCache) all() map[string]*modelInfo { | 54 | func (mc *_modelCache) all() map[string]*modelInfo { |
| 53 | m := make(map[string]*modelInfo, len(mc.cache)) | 55 | m := make(map[string]*modelInfo, len(mc.cache)) |
| 54 | for k, v := range mc.cache { | 56 | for k, v := range mc.cache { |
| ... | @@ -57,6 +59,7 @@ func (mc *_modelCache) all() map[string]*modelInfo { | ... | @@ -57,6 +59,7 @@ func (mc *_modelCache) all() map[string]*modelInfo { |
| 57 | return m | 59 | return m |
| 58 | } | 60 | } |
| 59 | 61 | ||
| 62 | // get orderd model info | ||
| 60 | func (mc *_modelCache) allOrdered() []*modelInfo { | 63 | func (mc *_modelCache) allOrdered() []*modelInfo { |
| 61 | m := make([]*modelInfo, 0, len(mc.orders)) | 64 | m := make([]*modelInfo, 0, len(mc.orders)) |
| 62 | for _, table := range mc.orders { | 65 | for _, table := range mc.orders { |
| ... | @@ -65,16 +68,19 @@ func (mc *_modelCache) allOrdered() []*modelInfo { | ... | @@ -65,16 +68,19 @@ func (mc *_modelCache) allOrdered() []*modelInfo { |
| 65 | return m | 68 | return m |
| 66 | } | 69 | } |
| 67 | 70 | ||
| 71 | // get model info by table name | ||
| 68 | func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) { | 72 | func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) { |
| 69 | mi, ok = mc.cache[table] | 73 | mi, ok = mc.cache[table] |
| 70 | return | 74 | return |
| 71 | } | 75 | } |
| 72 | 76 | ||
| 77 | // get model info by field name | ||
| 73 | func (mc *_modelCache) getByFN(name string) (mi *modelInfo, ok bool) { | 78 | func (mc *_modelCache) getByFN(name string) (mi *modelInfo, ok bool) { |
| 74 | mi, ok = mc.cacheByFN[name] | 79 | mi, ok = mc.cacheByFN[name] |
| 75 | return | 80 | return |
| 76 | } | 81 | } |
| 77 | 82 | ||
| 83 | // set model info to collection | ||
| 78 | func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo { | 84 | func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo { |
| 79 | mii := mc.cache[table] | 85 | mii := mc.cache[table] |
| 80 | mc.cache[table] = mi | 86 | mc.cache[table] = mi |
| ... | @@ -85,6 +91,7 @@ func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo { | ... | @@ -85,6 +91,7 @@ func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo { |
| 85 | return mii | 91 | return mii |
| 86 | } | 92 | } |
| 87 | 93 | ||
| 94 | // clean all model info. | ||
| 88 | func (mc *_modelCache) clean() { | 95 | func (mc *_modelCache) clean() { |
| 89 | mc.orders = make([]string, 0) | 96 | mc.orders = make([]string, 0) |
| 90 | mc.cache = make(map[string]*modelInfo) | 97 | mc.cache = make(map[string]*modelInfo) | ... | ... |
| ... | @@ -8,6 +8,8 @@ import ( | ... | @@ -8,6 +8,8 @@ import ( |
| 8 | "strings" | 8 | "strings" |
| 9 | ) | 9 | ) |
| 10 | 10 | ||
| 11 | // register models. | ||
| 12 | // prefix means table name prefix. | ||
| 11 | func registerModel(model interface{}, prefix string) { | 13 | func registerModel(model interface{}, prefix string) { |
| 12 | val := reflect.ValueOf(model) | 14 | val := reflect.ValueOf(model) |
| 13 | ind := reflect.Indirect(val) | 15 | ind := reflect.Indirect(val) |
| ... | @@ -67,6 +69,7 @@ func registerModel(model interface{}, prefix string) { | ... | @@ -67,6 +69,7 @@ func registerModel(model interface{}, prefix string) { |
| 67 | modelCache.set(table, info) | 69 | modelCache.set(table, info) |
| 68 | } | 70 | } |
| 69 | 71 | ||
| 72 | // boostrap models | ||
| 70 | func bootStrap() { | 73 | func bootStrap() { |
| 71 | if modelCache.done { | 74 | if modelCache.done { |
| 72 | return | 75 | return |
| ... | @@ -281,6 +284,7 @@ end: | ... | @@ -281,6 +284,7 @@ end: |
| 281 | } | 284 | } |
| 282 | } | 285 | } |
| 283 | 286 | ||
| 287 | // register models | ||
| 284 | func RegisterModel(models ...interface{}) { | 288 | func RegisterModel(models ...interface{}) { |
| 285 | if modelCache.done { | 289 | if modelCache.done { |
| 286 | panic(fmt.Errorf("RegisterModel must be run before BootStrap")) | 290 | panic(fmt.Errorf("RegisterModel must be run before BootStrap")) |
| ... | @@ -302,6 +306,8 @@ func RegisterModelWithPrefix(prefix string, models ...interface{}) { | ... | @@ -302,6 +306,8 @@ func RegisterModelWithPrefix(prefix string, models ...interface{}) { |
| 302 | } | 306 | } |
| 303 | } | 307 | } |
| 304 | 308 | ||
| 309 | // bootrap models. | ||
| 310 | // make all model parsed and can not add more models | ||
| 305 | func BootStrap() { | 311 | func BootStrap() { |
| 306 | if modelCache.done { | 312 | if modelCache.done { |
| 307 | return | 313 | return | ... | ... |
| ... | @@ -9,6 +9,7 @@ import ( | ... | @@ -9,6 +9,7 @@ import ( |
| 9 | 9 | ||
| 10 | var errSkipField = errors.New("skip field") | 10 | var errSkipField = errors.New("skip field") |
| 11 | 11 | ||
| 12 | // field info collection | ||
| 12 | type fields struct { | 13 | type fields struct { |
| 13 | pk *fieldInfo | 14 | pk *fieldInfo |
| 14 | columns map[string]*fieldInfo | 15 | columns map[string]*fieldInfo |
| ... | @@ -23,6 +24,7 @@ type fields struct { | ... | @@ -23,6 +24,7 @@ type fields struct { |
| 23 | dbcols []string | 24 | dbcols []string |
| 24 | } | 25 | } |
| 25 | 26 | ||
| 27 | // add field info | ||
| 26 | func (f *fields) Add(fi *fieldInfo) (added bool) { | 28 | func (f *fields) Add(fi *fieldInfo) (added bool) { |
| 27 | if f.fields[fi.name] == nil && f.columns[fi.column] == nil { | 29 | if f.fields[fi.name] == nil && f.columns[fi.column] == nil { |
| 28 | f.columns[fi.column] = fi | 30 | f.columns[fi.column] = fi |
| ... | @@ -49,14 +51,17 @@ func (f *fields) Add(fi *fieldInfo) (added bool) { | ... | @@ -49,14 +51,17 @@ func (f *fields) Add(fi *fieldInfo) (added bool) { |
| 49 | return true | 51 | return true |
| 50 | } | 52 | } |
| 51 | 53 | ||
| 54 | // get field info by name | ||
| 52 | func (f *fields) GetByName(name string) *fieldInfo { | 55 | func (f *fields) GetByName(name string) *fieldInfo { |
| 53 | return f.fields[name] | 56 | return f.fields[name] |
| 54 | } | 57 | } |
| 55 | 58 | ||
| 59 | // get field info by column name | ||
| 56 | func (f *fields) GetByColumn(column string) *fieldInfo { | 60 | func (f *fields) GetByColumn(column string) *fieldInfo { |
| 57 | return f.columns[column] | 61 | return f.columns[column] |
| 58 | } | 62 | } |
| 59 | 63 | ||
| 64 | // get field info by string, name is prior | ||
| 60 | func (f *fields) GetByAny(name string) (*fieldInfo, bool) { | 65 | func (f *fields) GetByAny(name string) (*fieldInfo, bool) { |
| 61 | if fi, ok := f.fields[name]; ok { | 66 | if fi, ok := f.fields[name]; ok { |
| 62 | return fi, ok | 67 | return fi, ok |
| ... | @@ -70,6 +75,7 @@ func (f *fields) GetByAny(name string) (*fieldInfo, bool) { | ... | @@ -70,6 +75,7 @@ func (f *fields) GetByAny(name string) (*fieldInfo, bool) { |
| 70 | return nil, false | 75 | return nil, false |
| 71 | } | 76 | } |
| 72 | 77 | ||
| 78 | // create new field info collection | ||
| 73 | func newFields() *fields { | 79 | func newFields() *fields { |
| 74 | f := new(fields) | 80 | f := new(fields) |
| 75 | f.fields = make(map[string]*fieldInfo) | 81 | f.fields = make(map[string]*fieldInfo) |
| ... | @@ -79,6 +85,7 @@ func newFields() *fields { | ... | @@ -79,6 +85,7 @@ func newFields() *fields { |
| 79 | return f | 85 | return f |
| 80 | } | 86 | } |
| 81 | 87 | ||
| 88 | // single field info | ||
| 82 | type fieldInfo struct { | 89 | type fieldInfo struct { |
| 83 | mi *modelInfo | 90 | mi *modelInfo |
| 84 | fieldIndex int | 91 | fieldIndex int |
| ... | @@ -115,6 +122,7 @@ type fieldInfo struct { | ... | @@ -115,6 +122,7 @@ type fieldInfo struct { |
| 115 | onDelete string | 122 | onDelete string |
| 116 | } | 123 | } |
| 117 | 124 | ||
| 125 | // new field info | ||
| 118 | func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField) (fi *fieldInfo, err error) { | 126 | func newFieldInfo(mi *modelInfo, field reflect.Value, sf reflect.StructField) (fi *fieldInfo, err error) { |
| 119 | var ( | 127 | var ( |
| 120 | tag string | 128 | tag string | ... | ... |
| ... | @@ -7,6 +7,7 @@ import ( | ... | @@ -7,6 +7,7 @@ import ( |
| 7 | "reflect" | 7 | "reflect" |
| 8 | ) | 8 | ) |
| 9 | 9 | ||
| 10 | // single model info | ||
| 10 | type modelInfo struct { | 11 | type modelInfo struct { |
| 11 | pkg string | 12 | pkg string |
| 12 | name string | 13 | name string |
| ... | @@ -20,6 +21,7 @@ type modelInfo struct { | ... | @@ -20,6 +21,7 @@ type modelInfo struct { |
| 20 | isThrough bool | 21 | isThrough bool |
| 21 | } | 22 | } |
| 22 | 23 | ||
| 24 | // new model info | ||
| 23 | func newModelInfo(val reflect.Value) (info *modelInfo) { | 25 | func newModelInfo(val reflect.Value) (info *modelInfo) { |
| 24 | var ( | 26 | var ( |
| 25 | err error | 27 | err error |
| ... | @@ -79,6 +81,8 @@ func newModelInfo(val reflect.Value) (info *modelInfo) { | ... | @@ -79,6 +81,8 @@ func newModelInfo(val reflect.Value) (info *modelInfo) { |
| 79 | return | 81 | return |
| 80 | } | 82 | } |
| 81 | 83 | ||
| 84 | // combine related model info to new model info. | ||
| 85 | // prepare for relation models query. | ||
| 82 | func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) { | 86 | func newM2MModelInfo(m1, m2 *modelInfo) (info *modelInfo) { |
| 83 | info = new(modelInfo) | 87 | info = new(modelInfo) |
| 84 | info.fields = newFields() | 88 | info.fields = newFields() | ... | ... |
| ... | @@ -7,10 +7,12 @@ import ( | ... | @@ -7,10 +7,12 @@ import ( |
| 7 | "time" | 7 | "time" |
| 8 | ) | 8 | ) |
| 9 | 9 | ||
| 10 | // get reflect.Type name with package path. | ||
| 10 | func getFullName(typ reflect.Type) string { | 11 | func getFullName(typ reflect.Type) string { |
| 11 | return typ.PkgPath() + "." + typ.Name() | 12 | return typ.PkgPath() + "." + typ.Name() |
| 12 | } | 13 | } |
| 13 | 14 | ||
| 15 | // get table name. method, or field name. auto snaked. | ||
| 14 | func getTableName(val reflect.Value) string { | 16 | func getTableName(val reflect.Value) string { |
| 15 | ind := reflect.Indirect(val) | 17 | ind := reflect.Indirect(val) |
| 16 | fun := val.MethodByName("TableName") | 18 | fun := val.MethodByName("TableName") |
| ... | @@ -26,6 +28,7 @@ func getTableName(val reflect.Value) string { | ... | @@ -26,6 +28,7 @@ func getTableName(val reflect.Value) string { |
| 26 | return snakeString(ind.Type().Name()) | 28 | return snakeString(ind.Type().Name()) |
| 27 | } | 29 | } |
| 28 | 30 | ||
| 31 | // get table engine, mysiam or innodb. | ||
| 29 | func getTableEngine(val reflect.Value) string { | 32 | func getTableEngine(val reflect.Value) string { |
| 30 | fun := val.MethodByName("TableEngine") | 33 | fun := val.MethodByName("TableEngine") |
| 31 | if fun.IsValid() { | 34 | if fun.IsValid() { |
| ... | @@ -40,6 +43,7 @@ func getTableEngine(val reflect.Value) string { | ... | @@ -40,6 +43,7 @@ func getTableEngine(val reflect.Value) string { |
| 40 | return "" | 43 | return "" |
| 41 | } | 44 | } |
| 42 | 45 | ||
| 46 | // get table index from method. | ||
| 43 | func getTableIndex(val reflect.Value) [][]string { | 47 | func getTableIndex(val reflect.Value) [][]string { |
| 44 | fun := val.MethodByName("TableIndex") | 48 | fun := val.MethodByName("TableIndex") |
| 45 | if fun.IsValid() { | 49 | if fun.IsValid() { |
| ... | @@ -56,6 +60,7 @@ func getTableIndex(val reflect.Value) [][]string { | ... | @@ -56,6 +60,7 @@ func getTableIndex(val reflect.Value) [][]string { |
| 56 | return nil | 60 | return nil |
| 57 | } | 61 | } |
| 58 | 62 | ||
| 63 | // get table unique from method | ||
| 59 | func getTableUnique(val reflect.Value) [][]string { | 64 | func getTableUnique(val reflect.Value) [][]string { |
| 60 | fun := val.MethodByName("TableUnique") | 65 | fun := val.MethodByName("TableUnique") |
| 61 | if fun.IsValid() { | 66 | if fun.IsValid() { |
| ... | @@ -72,6 +77,7 @@ func getTableUnique(val reflect.Value) [][]string { | ... | @@ -72,6 +77,7 @@ func getTableUnique(val reflect.Value) [][]string { |
| 72 | return nil | 77 | return nil |
| 73 | } | 78 | } |
| 74 | 79 | ||
| 80 | // get snaked column name | ||
| 75 | func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col string) string { | 81 | func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col string) string { |
| 76 | col = strings.ToLower(col) | 82 | col = strings.ToLower(col) |
| 77 | column := col | 83 | column := col |
| ... | @@ -89,6 +95,7 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col | ... | @@ -89,6 +95,7 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col |
| 89 | return column | 95 | return column |
| 90 | } | 96 | } |
| 91 | 97 | ||
| 98 | // return field type as type constant from reflect.Value | ||
| 92 | func getFieldType(val reflect.Value) (ft int, err error) { | 99 | func getFieldType(val reflect.Value) (ft int, err error) { |
| 93 | elm := reflect.Indirect(val) | 100 | elm := reflect.Indirect(val) |
| 94 | switch elm.Kind() { | 101 | switch elm.Kind() { |
| ... | @@ -128,6 +135,7 @@ func getFieldType(val reflect.Value) (ft int, err error) { | ... | @@ -128,6 +135,7 @@ func getFieldType(val reflect.Value) (ft int, err error) { |
| 128 | return | 135 | return |
| 129 | } | 136 | } |
| 130 | 137 | ||
| 138 | // parse struct tag string | ||
| 131 | func parseStructTag(data string, attrs *map[string]bool, tags *map[string]string) { | 139 | func parseStructTag(data string, attrs *map[string]bool, tags *map[string]string) { |
| 132 | attr := make(map[string]bool) | 140 | attr := make(map[string]bool) |
| 133 | tag := make(map[string]string) | 141 | tag := make(map[string]string) | ... | ... |
| ... | @@ -40,6 +40,7 @@ type orm struct { | ... | @@ -40,6 +40,7 @@ type orm struct { |
| 40 | 40 | ||
| 41 | var _ Ormer = new(orm) | 41 | var _ Ormer = new(orm) |
| 42 | 42 | ||
| 43 | // get model info and model reflect value | ||
| 43 | func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect.Value) { | 44 | func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect.Value) { |
| 44 | val := reflect.ValueOf(md) | 45 | val := reflect.ValueOf(md) |
| 45 | ind = reflect.Indirect(val) | 46 | ind = reflect.Indirect(val) |
| ... | @@ -54,6 +55,7 @@ func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect | ... | @@ -54,6 +55,7 @@ func (o *orm) getMiInd(md interface{}, needPtr bool) (mi *modelInfo, ind reflect |
| 54 | panic(fmt.Errorf("<Ormer> table: `%s` not found, maybe not RegisterModel", name)) | 55 | panic(fmt.Errorf("<Ormer> table: `%s` not found, maybe not RegisterModel", name)) |
| 55 | } | 56 | } |
| 56 | 57 | ||
| 58 | // get field info from model info by given field name | ||
| 57 | func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo { | 59 | func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo { |
| 58 | fi, ok := mi.fields.GetByAny(name) | 60 | fi, ok := mi.fields.GetByAny(name) |
| 59 | if !ok { | 61 | if !ok { |
| ... | @@ -62,6 +64,7 @@ func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo { | ... | @@ -62,6 +64,7 @@ func (o *orm) getFieldInfo(mi *modelInfo, name string) *fieldInfo { |
| 62 | return fi | 64 | return fi |
| 63 | } | 65 | } |
| 64 | 66 | ||
| 67 | // read data to model | ||
| 65 | func (o *orm) Read(md interface{}, cols ...string) error { | 68 | func (o *orm) Read(md interface{}, cols ...string) error { |
| 66 | mi, ind := o.getMiInd(md, true) | 69 | mi, ind := o.getMiInd(md, true) |
| 67 | err := o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols) | 70 | err := o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ, cols) |
| ... | @@ -71,6 +74,7 @@ func (o *orm) Read(md interface{}, cols ...string) error { | ... | @@ -71,6 +74,7 @@ func (o *orm) Read(md interface{}, cols ...string) error { |
| 71 | return nil | 74 | return nil |
| 72 | } | 75 | } |
| 73 | 76 | ||
| 77 | // insert model data to database | ||
| 74 | func (o *orm) Insert(md interface{}) (int64, error) { | 78 | func (o *orm) Insert(md interface{}) (int64, error) { |
| 75 | mi, ind := o.getMiInd(md, true) | 79 | mi, ind := o.getMiInd(md, true) |
| 76 | id, err := o.alias.DbBaser.Insert(o.db, mi, ind, o.alias.TZ) | 80 | id, err := o.alias.DbBaser.Insert(o.db, mi, ind, o.alias.TZ) |
| ... | @@ -83,6 +87,7 @@ func (o *orm) Insert(md interface{}) (int64, error) { | ... | @@ -83,6 +87,7 @@ func (o *orm) Insert(md interface{}) (int64, error) { |
| 83 | return id, nil | 87 | return id, nil |
| 84 | } | 88 | } |
| 85 | 89 | ||
| 90 | // set auto pk field | ||
| 86 | func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) { | 91 | func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) { |
| 87 | if mi.fields.pk.auto { | 92 | if mi.fields.pk.auto { |
| 88 | if mi.fields.pk.fieldType&IsPostiveIntegerField > 0 { | 93 | if mi.fields.pk.fieldType&IsPostiveIntegerField > 0 { |
| ... | @@ -93,6 +98,7 @@ func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) { | ... | @@ -93,6 +98,7 @@ func (o *orm) setPk(mi *modelInfo, ind reflect.Value, id int64) { |
| 93 | } | 98 | } |
| 94 | } | 99 | } |
| 95 | 100 | ||
| 101 | // insert some models to database | ||
| 96 | func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) { | 102 | func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) { |
| 97 | var cnt int64 | 103 | var cnt int64 |
| 98 | 104 | ||
| ... | @@ -127,6 +133,8 @@ func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) { | ... | @@ -127,6 +133,8 @@ func (o *orm) InsertMulti(bulk int, mds interface{}) (int64, error) { |
| 127 | return cnt, nil | 133 | return cnt, nil |
| 128 | } | 134 | } |
| 129 | 135 | ||
| 136 | // update model to database. | ||
| 137 | // cols set the columns those want to update. | ||
| 130 | func (o *orm) Update(md interface{}, cols ...string) (int64, error) { | 138 | func (o *orm) Update(md interface{}, cols ...string) (int64, error) { |
| 131 | mi, ind := o.getMiInd(md, true) | 139 | mi, ind := o.getMiInd(md, true) |
| 132 | num, err := o.alias.DbBaser.Update(o.db, mi, ind, o.alias.TZ, cols) | 140 | num, err := o.alias.DbBaser.Update(o.db, mi, ind, o.alias.TZ, cols) |
| ... | @@ -136,6 +144,7 @@ func (o *orm) Update(md interface{}, cols ...string) (int64, error) { | ... | @@ -136,6 +144,7 @@ func (o *orm) Update(md interface{}, cols ...string) (int64, error) { |
| 136 | return num, nil | 144 | return num, nil |
| 137 | } | 145 | } |
| 138 | 146 | ||
| 147 | // delete model in database | ||
| 139 | func (o *orm) Delete(md interface{}) (int64, error) { | 148 | func (o *orm) Delete(md interface{}) (int64, error) { |
| 140 | mi, ind := o.getMiInd(md, true) | 149 | mi, ind := o.getMiInd(md, true) |
| 141 | num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ) | 150 | num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ) |
| ... | @@ -148,6 +157,7 @@ func (o *orm) Delete(md interface{}) (int64, error) { | ... | @@ -148,6 +157,7 @@ func (o *orm) Delete(md interface{}) (int64, error) { |
| 148 | return num, nil | 157 | return num, nil |
| 149 | } | 158 | } |
| 150 | 159 | ||
| 160 | // create a models to models queryer | ||
| 151 | func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer { | 161 | func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer { |
| 152 | mi, ind := o.getMiInd(md, true) | 162 | mi, ind := o.getMiInd(md, true) |
| 153 | fi := o.getFieldInfo(mi, name) | 163 | fi := o.getFieldInfo(mi, name) |
| ... | @@ -162,6 +172,14 @@ func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer { | ... | @@ -162,6 +172,14 @@ func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer { |
| 162 | return newQueryM2M(md, o, mi, fi, ind) | 172 | return newQueryM2M(md, o, mi, fi, ind) |
| 163 | } | 173 | } |
| 164 | 174 | ||
| 175 | // load related models to md model. | ||
| 176 | // args are limit, offset int and order string. | ||
| 177 | // | ||
| 178 | // example: | ||
| 179 | // orm.LoadRelated(post,"Tags") | ||
| 180 | // for _,tag := range post.Tags{...} | ||
| 181 | // | ||
| 182 | // make sure the relation is defined in model struct tags. | ||
| 165 | func (o *orm) LoadRelated(md interface{}, name string, args ...interface{}) (int64, error) { | 183 | func (o *orm) LoadRelated(md interface{}, name string, args ...interface{}) (int64, error) { |
| 166 | _, fi, ind, qseter := o.queryRelated(md, name) | 184 | _, fi, ind, qseter := o.queryRelated(md, name) |
| 167 | 185 | ||
| ... | @@ -223,12 +241,19 @@ func (o *orm) LoadRelated(md interface{}, name string, args ...interface{}) (int | ... | @@ -223,12 +241,19 @@ func (o *orm) LoadRelated(md interface{}, name string, args ...interface{}) (int |
| 223 | return nums, err | 241 | return nums, err |
| 224 | } | 242 | } |
| 225 | 243 | ||
| 244 | // return a QuerySeter for related models to md model. | ||
| 245 | // it can do all, update, delete in QuerySeter. | ||
| 246 | // example: | ||
| 247 | // qs := orm.QueryRelated(post,"Tag") | ||
| 248 | // qs.All(&[]*Tag{}) | ||
| 249 | // | ||
| 226 | func (o *orm) QueryRelated(md interface{}, name string) QuerySeter { | 250 | func (o *orm) QueryRelated(md interface{}, name string) QuerySeter { |
| 227 | // is this api needed ? | 251 | // is this api needed ? |
| 228 | _, _, _, qs := o.queryRelated(md, name) | 252 | _, _, _, qs := o.queryRelated(md, name) |
| 229 | return qs | 253 | return qs |
| 230 | } | 254 | } |
| 231 | 255 | ||
| 256 | // get QuerySeter for related models to md model | ||
| 232 | func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, reflect.Value, QuerySeter) { | 257 | func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, reflect.Value, QuerySeter) { |
| 233 | mi, ind := o.getMiInd(md, true) | 258 | mi, ind := o.getMiInd(md, true) |
| 234 | fi := o.getFieldInfo(mi, name) | 259 | fi := o.getFieldInfo(mi, name) |
| ... | @@ -260,6 +285,7 @@ func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, | ... | @@ -260,6 +285,7 @@ func (o *orm) queryRelated(md interface{}, name string) (*modelInfo, *fieldInfo, |
| 260 | return mi, fi, ind, qs | 285 | return mi, fi, ind, qs |
| 261 | } | 286 | } |
| 262 | 287 | ||
| 288 | // get reverse relation QuerySeter | ||
| 263 | func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { | 289 | func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { |
| 264 | switch fi.fieldType { | 290 | switch fi.fieldType { |
| 265 | case RelReverseOne, RelReverseMany: | 291 | case RelReverseOne, RelReverseMany: |
| ... | @@ -280,6 +306,7 @@ func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *queryS | ... | @@ -280,6 +306,7 @@ func (o *orm) getReverseQs(md interface{}, mi *modelInfo, fi *fieldInfo) *queryS |
| 280 | return q | 306 | return q |
| 281 | } | 307 | } |
| 282 | 308 | ||
| 309 | // get relation QuerySeter | ||
| 283 | func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { | 310 | func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { |
| 284 | switch fi.fieldType { | 311 | switch fi.fieldType { |
| 285 | case RelOneToOne, RelForeignKey, RelManyToMany: | 312 | case RelOneToOne, RelForeignKey, RelManyToMany: |
| ... | @@ -299,6 +326,9 @@ func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { | ... | @@ -299,6 +326,9 @@ func (o *orm) getRelQs(md interface{}, mi *modelInfo, fi *fieldInfo) *querySet { |
| 299 | return q | 326 | return q |
| 300 | } | 327 | } |
| 301 | 328 | ||
| 329 | // return a QuerySeter for table operations. | ||
| 330 | // table name can be string or struct. | ||
| 331 | // e.g. QueryTable("user"), QueryTable(&user{}) or QueryTable((*User)(nil)), | ||
| 302 | func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { | 332 | func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { |
| 303 | name := "" | 333 | name := "" |
| 304 | if table, ok := ptrStructOrTableName.(string); ok { | 334 | if table, ok := ptrStructOrTableName.(string); ok { |
| ... | @@ -318,6 +348,7 @@ func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { | ... | @@ -318,6 +348,7 @@ func (o *orm) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { |
| 318 | return | 348 | return |
| 319 | } | 349 | } |
| 320 | 350 | ||
| 351 | // switch to another registered database driver by given name. | ||
| 321 | func (o *orm) Using(name string) error { | 352 | func (o *orm) Using(name string) error { |
| 322 | if o.isTx { | 353 | if o.isTx { |
| 323 | panic(fmt.Errorf("<Ormer.Using> transaction has been start, cannot change db")) | 354 | panic(fmt.Errorf("<Ormer.Using> transaction has been start, cannot change db")) |
| ... | @@ -335,6 +366,7 @@ func (o *orm) Using(name string) error { | ... | @@ -335,6 +366,7 @@ func (o *orm) Using(name string) error { |
| 335 | return nil | 366 | return nil |
| 336 | } | 367 | } |
| 337 | 368 | ||
| 369 | // begin transaction | ||
| 338 | func (o *orm) Begin() error { | 370 | func (o *orm) Begin() error { |
| 339 | if o.isTx { | 371 | if o.isTx { |
| 340 | return ErrTxHasBegan | 372 | return ErrTxHasBegan |
| ... | @@ -353,6 +385,7 @@ func (o *orm) Begin() error { | ... | @@ -353,6 +385,7 @@ func (o *orm) Begin() error { |
| 353 | return nil | 385 | return nil |
| 354 | } | 386 | } |
| 355 | 387 | ||
| 388 | // commit transaction | ||
| 356 | func (o *orm) Commit() error { | 389 | func (o *orm) Commit() error { |
| 357 | if o.isTx == false { | 390 | if o.isTx == false { |
| 358 | return ErrTxDone | 391 | return ErrTxDone |
| ... | @@ -367,6 +400,7 @@ func (o *orm) Commit() error { | ... | @@ -367,6 +400,7 @@ func (o *orm) Commit() error { |
| 367 | return err | 400 | return err |
| 368 | } | 401 | } |
| 369 | 402 | ||
| 403 | // rollback transaction | ||
| 370 | func (o *orm) Rollback() error { | 404 | func (o *orm) Rollback() error { |
| 371 | if o.isTx == false { | 405 | if o.isTx == false { |
| 372 | return ErrTxDone | 406 | return ErrTxDone |
| ... | @@ -381,14 +415,17 @@ func (o *orm) Rollback() error { | ... | @@ -381,14 +415,17 @@ func (o *orm) Rollback() error { |
| 381 | return err | 415 | return err |
| 382 | } | 416 | } |
| 383 | 417 | ||
| 418 | // return a raw query seter for raw sql string. | ||
| 384 | func (o *orm) Raw(query string, args ...interface{}) RawSeter { | 419 | func (o *orm) Raw(query string, args ...interface{}) RawSeter { |
| 385 | return newRawSet(o, query, args) | 420 | return newRawSet(o, query, args) |
| 386 | } | 421 | } |
| 387 | 422 | ||
| 423 | // return current using database Driver | ||
| 388 | func (o *orm) Driver() Driver { | 424 | func (o *orm) Driver() Driver { |
| 389 | return driver(o.alias.Name) | 425 | return driver(o.alias.Name) |
| 390 | } | 426 | } |
| 391 | 427 | ||
| 428 | // create new orm | ||
| 392 | func NewOrm() Ormer { | 429 | func NewOrm() Ormer { |
| 393 | BootStrap() // execute only once | 430 | BootStrap() // execute only once |
| 394 | 431 | ... | ... |
| ... | @@ -18,15 +18,19 @@ type condValue struct { | ... | @@ -18,15 +18,19 @@ type condValue struct { |
| 18 | isCond bool | 18 | isCond bool |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | // condition struct. | ||
| 22 | // work for WHERE conditions. | ||
| 21 | type Condition struct { | 23 | type Condition struct { |
| 22 | params []condValue | 24 | params []condValue |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 27 | // return new condition struct | ||
| 25 | func NewCondition() *Condition { | 28 | func NewCondition() *Condition { |
| 26 | c := &Condition{} | 29 | c := &Condition{} |
| 27 | return c | 30 | return c |
| 28 | } | 31 | } |
| 29 | 32 | ||
| 33 | // add expression to condition | ||
| 30 | func (c Condition) And(expr string, args ...interface{}) *Condition { | 34 | func (c Condition) And(expr string, args ...interface{}) *Condition { |
| 31 | if expr == "" || len(args) == 0 { | 35 | if expr == "" || len(args) == 0 { |
| 32 | panic(fmt.Errorf("<Condition.And> args cannot empty")) | 36 | panic(fmt.Errorf("<Condition.And> args cannot empty")) |
| ... | @@ -35,6 +39,7 @@ func (c Condition) And(expr string, args ...interface{}) *Condition { | ... | @@ -35,6 +39,7 @@ func (c Condition) And(expr string, args ...interface{}) *Condition { |
| 35 | return &c | 39 | return &c |
| 36 | } | 40 | } |
| 37 | 41 | ||
| 42 | // add NOT expression to condition | ||
| 38 | func (c Condition) AndNot(expr string, args ...interface{}) *Condition { | 43 | func (c Condition) AndNot(expr string, args ...interface{}) *Condition { |
| 39 | if expr == "" || len(args) == 0 { | 44 | if expr == "" || len(args) == 0 { |
| 40 | panic(fmt.Errorf("<Condition.AndNot> args cannot empty")) | 45 | panic(fmt.Errorf("<Condition.AndNot> args cannot empty")) |
| ... | @@ -43,6 +48,7 @@ func (c Condition) AndNot(expr string, args ...interface{}) *Condition { | ... | @@ -43,6 +48,7 @@ func (c Condition) AndNot(expr string, args ...interface{}) *Condition { |
| 43 | return &c | 48 | return &c |
| 44 | } | 49 | } |
| 45 | 50 | ||
| 51 | // combine a condition to current condition | ||
| 46 | func (c *Condition) AndCond(cond *Condition) *Condition { | 52 | func (c *Condition) AndCond(cond *Condition) *Condition { |
| 47 | c = c.clone() | 53 | c = c.clone() |
| 48 | if c == cond { | 54 | if c == cond { |
| ... | @@ -54,6 +60,7 @@ func (c *Condition) AndCond(cond *Condition) *Condition { | ... | @@ -54,6 +60,7 @@ func (c *Condition) AndCond(cond *Condition) *Condition { |
| 54 | return c | 60 | return c |
| 55 | } | 61 | } |
| 56 | 62 | ||
| 63 | // add OR expression to condition | ||
| 57 | func (c Condition) Or(expr string, args ...interface{}) *Condition { | 64 | func (c Condition) Or(expr string, args ...interface{}) *Condition { |
| 58 | if expr == "" || len(args) == 0 { | 65 | if expr == "" || len(args) == 0 { |
| 59 | panic(fmt.Errorf("<Condition.Or> args cannot empty")) | 66 | panic(fmt.Errorf("<Condition.Or> args cannot empty")) |
| ... | @@ -62,6 +69,7 @@ func (c Condition) Or(expr string, args ...interface{}) *Condition { | ... | @@ -62,6 +69,7 @@ func (c Condition) Or(expr string, args ...interface{}) *Condition { |
| 62 | return &c | 69 | return &c |
| 63 | } | 70 | } |
| 64 | 71 | ||
| 72 | // add OR NOT expression to condition | ||
| 65 | func (c Condition) OrNot(expr string, args ...interface{}) *Condition { | 73 | func (c Condition) OrNot(expr string, args ...interface{}) *Condition { |
| 66 | if expr == "" || len(args) == 0 { | 74 | if expr == "" || len(args) == 0 { |
| 67 | panic(fmt.Errorf("<Condition.OrNot> args cannot empty")) | 75 | panic(fmt.Errorf("<Condition.OrNot> args cannot empty")) |
| ... | @@ -70,6 +78,7 @@ func (c Condition) OrNot(expr string, args ...interface{}) *Condition { | ... | @@ -70,6 +78,7 @@ func (c Condition) OrNot(expr string, args ...interface{}) *Condition { |
| 70 | return &c | 78 | return &c |
| 71 | } | 79 | } |
| 72 | 80 | ||
| 81 | // combine a OR condition to current condition | ||
| 73 | func (c *Condition) OrCond(cond *Condition) *Condition { | 82 | func (c *Condition) OrCond(cond *Condition) *Condition { |
| 74 | c = c.clone() | 83 | c = c.clone() |
| 75 | if c == cond { | 84 | if c == cond { |
| ... | @@ -81,10 +90,12 @@ func (c *Condition) OrCond(cond *Condition) *Condition { | ... | @@ -81,10 +90,12 @@ func (c *Condition) OrCond(cond *Condition) *Condition { |
| 81 | return c | 90 | return c |
| 82 | } | 91 | } |
| 83 | 92 | ||
| 93 | // check the condition arguments are empty or not. | ||
| 84 | func (c *Condition) IsEmpty() bool { | 94 | func (c *Condition) IsEmpty() bool { |
| 85 | return len(c.params) == 0 | 95 | return len(c.params) == 0 |
| 86 | } | 96 | } |
| 87 | 97 | ||
| 98 | // clone a condition | ||
| 88 | func (c Condition) clone() *Condition { | 99 | func (c Condition) clone() *Condition { |
| 89 | return &c | 100 | return &c |
| 90 | } | 101 | } | ... | ... |
| ... | @@ -13,6 +13,7 @@ type Log struct { | ... | @@ -13,6 +13,7 @@ type Log struct { |
| 13 | *log.Logger | 13 | *log.Logger |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | // set io.Writer to create a Logger. | ||
| 16 | func NewLog(out io.Writer) *Log { | 17 | func NewLog(out io.Writer) *Log { |
| 17 | d := new(Log) | 18 | d := new(Log) |
| 18 | d.Logger = log.New(out, "[ORM]", 1e9) | 19 | d.Logger = log.New(out, "[ORM]", 1e9) |
| ... | @@ -40,6 +41,8 @@ func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error | ... | @@ -40,6 +41,8 @@ func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error |
| 40 | DebugLog.Println(con) | 41 | DebugLog.Println(con) |
| 41 | } | 42 | } |
| 42 | 43 | ||
| 44 | // statement query logger struct. | ||
| 45 | // if dev mode, use stmtQueryLog, or use stmtQuerier. | ||
| 43 | type stmtQueryLog struct { | 46 | type stmtQueryLog struct { |
| 44 | alias *alias | 47 | alias *alias |
| 45 | query string | 48 | query string |
| ... | @@ -84,6 +87,8 @@ func newStmtQueryLog(alias *alias, stmt stmtQuerier, query string) stmtQuerier { | ... | @@ -84,6 +87,8 @@ func newStmtQueryLog(alias *alias, stmt stmtQuerier, query string) stmtQuerier { |
| 84 | return d | 87 | return d |
| 85 | } | 88 | } |
| 86 | 89 | ||
| 90 | // database query logger struct. | ||
| 91 | // if dev mode, use dbQueryLog, or use dbQuerier. | ||
| 87 | type dbQueryLog struct { | 92 | type dbQueryLog struct { |
| 88 | alias *alias | 93 | alias *alias |
| 89 | db dbQuerier | 94 | db dbQuerier | ... | ... |
| ... | @@ -5,6 +5,7 @@ import ( | ... | @@ -5,6 +5,7 @@ import ( |
| 5 | "reflect" | 5 | "reflect" |
| 6 | ) | 6 | ) |
| 7 | 7 | ||
| 8 | // an insert queryer struct | ||
| 8 | type insertSet struct { | 9 | type insertSet struct { |
| 9 | mi *modelInfo | 10 | mi *modelInfo |
| 10 | orm *orm | 11 | orm *orm |
| ... | @@ -14,6 +15,7 @@ type insertSet struct { | ... | @@ -14,6 +15,7 @@ type insertSet struct { |
| 14 | 15 | ||
| 15 | var _ Inserter = new(insertSet) | 16 | var _ Inserter = new(insertSet) |
| 16 | 17 | ||
| 18 | // insert model ignore it's registered or not. | ||
| 17 | func (o *insertSet) Insert(md interface{}) (int64, error) { | 19 | func (o *insertSet) Insert(md interface{}) (int64, error) { |
| 18 | if o.closed { | 20 | if o.closed { |
| 19 | return 0, ErrStmtClosed | 21 | return 0, ErrStmtClosed |
| ... | @@ -44,6 +46,7 @@ func (o *insertSet) Insert(md interface{}) (int64, error) { | ... | @@ -44,6 +46,7 @@ func (o *insertSet) Insert(md interface{}) (int64, error) { |
| 44 | return id, nil | 46 | return id, nil |
| 45 | } | 47 | } |
| 46 | 48 | ||
| 49 | // close insert queryer statement | ||
| 47 | func (o *insertSet) Close() error { | 50 | func (o *insertSet) Close() error { |
| 48 | if o.closed { | 51 | if o.closed { |
| 49 | return ErrStmtClosed | 52 | return ErrStmtClosed |
| ... | @@ -52,6 +55,7 @@ func (o *insertSet) Close() error { | ... | @@ -52,6 +55,7 @@ func (o *insertSet) Close() error { |
| 52 | return o.stmt.Close() | 55 | return o.stmt.Close() |
| 53 | } | 56 | } |
| 54 | 57 | ||
| 58 | // create new insert queryer. | ||
| 55 | func newInsertSet(orm *orm, mi *modelInfo) (Inserter, error) { | 59 | func newInsertSet(orm *orm, mi *modelInfo) (Inserter, error) { |
| 56 | bi := new(insertSet) | 60 | bi := new(insertSet) |
| 57 | bi.orm = orm | 61 | bi.orm = orm | ... | ... |
| ... | @@ -4,6 +4,7 @@ import ( | ... | @@ -4,6 +4,7 @@ import ( |
| 4 | "reflect" | 4 | "reflect" |
| 5 | ) | 5 | ) |
| 6 | 6 | ||
| 7 | // model to model struct | ||
| 7 | type queryM2M struct { | 8 | type queryM2M struct { |
| 8 | md interface{} | 9 | md interface{} |
| 9 | mi *modelInfo | 10 | mi *modelInfo |
| ... | @@ -12,6 +13,13 @@ type queryM2M struct { | ... | @@ -12,6 +13,13 @@ type queryM2M struct { |
| 12 | ind reflect.Value | 13 | ind reflect.Value |
| 13 | } | 14 | } |
| 14 | 15 | ||
| 16 | // add models to origin models when creating queryM2M. | ||
| 17 | // example: | ||
| 18 | // m2m := orm.QueryM2M(post,"Tag") | ||
| 19 | // m2m.Add(&Tag1{},&Tag2{}) | ||
| 20 | // for _,tag := range post.Tags{} | ||
| 21 | // | ||
| 22 | // make sure the relation is defined in post model struct tag. | ||
| 15 | func (o *queryM2M) Add(mds ...interface{}) (int64, error) { | 23 | func (o *queryM2M) Add(mds ...interface{}) (int64, error) { |
| 16 | fi := o.fi | 24 | fi := o.fi |
| 17 | mi := fi.relThroughModelInfo | 25 | mi := fi.relThroughModelInfo |
| ... | @@ -67,6 +75,7 @@ func (o *queryM2M) Add(mds ...interface{}) (int64, error) { | ... | @@ -67,6 +75,7 @@ func (o *queryM2M) Add(mds ...interface{}) (int64, error) { |
| 67 | return dbase.InsertValue(orm.db, mi, true, names, values) | 75 | return dbase.InsertValue(orm.db, mi, true, names, values) |
| 68 | } | 76 | } |
| 69 | 77 | ||
| 78 | // remove models following the origin model relationship | ||
| 70 | func (o *queryM2M) Remove(mds ...interface{}) (int64, error) { | 79 | func (o *queryM2M) Remove(mds ...interface{}) (int64, error) { |
| 71 | fi := o.fi | 80 | fi := o.fi |
| 72 | qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md) | 81 | qs := o.qs.Filter(fi.reverseFieldInfo.name, o.md) |
| ... | @@ -78,17 +87,20 @@ func (o *queryM2M) Remove(mds ...interface{}) (int64, error) { | ... | @@ -78,17 +87,20 @@ func (o *queryM2M) Remove(mds ...interface{}) (int64, error) { |
| 78 | return nums, nil | 87 | return nums, nil |
| 79 | } | 88 | } |
| 80 | 89 | ||
| 90 | // check model is existed in relationship of origin model | ||
| 81 | func (o *queryM2M) Exist(md interface{}) bool { | 91 | func (o *queryM2M) Exist(md interface{}) bool { |
| 82 | fi := o.fi | 92 | fi := o.fi |
| 83 | return o.qs.Filter(fi.reverseFieldInfo.name, o.md). | 93 | return o.qs.Filter(fi.reverseFieldInfo.name, o.md). |
| 84 | Filter(fi.reverseFieldInfoTwo.name, md).Exist() | 94 | Filter(fi.reverseFieldInfoTwo.name, md).Exist() |
| 85 | } | 95 | } |
| 86 | 96 | ||
| 97 | // clean all models in related of origin model | ||
| 87 | func (o *queryM2M) Clear() (int64, error) { | 98 | func (o *queryM2M) Clear() (int64, error) { |
| 88 | fi := o.fi | 99 | fi := o.fi |
| 89 | return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Delete() | 100 | return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Delete() |
| 90 | } | 101 | } |
| 91 | 102 | ||
| 103 | // count all related models of origin model | ||
| 92 | func (o *queryM2M) Count() (int64, error) { | 104 | func (o *queryM2M) Count() (int64, error) { |
| 93 | fi := o.fi | 105 | fi := o.fi |
| 94 | return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Count() | 106 | return o.qs.Filter(fi.reverseFieldInfo.name, o.md).Count() |
| ... | @@ -96,6 +108,7 @@ func (o *queryM2M) Count() (int64, error) { | ... | @@ -96,6 +108,7 @@ func (o *queryM2M) Count() (int64, error) { |
| 96 | 108 | ||
| 97 | var _ QueryM2Mer = new(queryM2M) | 109 | var _ QueryM2Mer = new(queryM2M) |
| 98 | 110 | ||
| 111 | // create new M2M queryer. | ||
| 99 | func newQueryM2M(md interface{}, o *orm, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer { | 112 | func newQueryM2M(md interface{}, o *orm, mi *modelInfo, fi *fieldInfo, ind reflect.Value) QueryM2Mer { |
| 100 | qm2m := new(queryM2M) | 113 | qm2m := new(queryM2M) |
| 101 | qm2m.md = md | 114 | qm2m.md = md | ... | ... |
| ... | @@ -18,6 +18,10 @@ const ( | ... | @@ -18,6 +18,10 @@ const ( |
| 18 | Col_Except | 18 | Col_Except |
| 19 | ) | 19 | ) |
| 20 | 20 | ||
| 21 | // ColValue do the field raw changes. e.g Nums = Nums + 10. usage: | ||
| 22 | // Params{ | ||
| 23 | // "Nums": ColValue(Col_Add, 10), | ||
| 24 | // } | ||
| 21 | func ColValue(opt operator, value interface{}) interface{} { | 25 | func ColValue(opt operator, value interface{}) interface{} { |
| 22 | switch opt { | 26 | switch opt { |
| 23 | case Col_Add, Col_Minus, Col_Multiply, Col_Except: | 27 | case Col_Add, Col_Minus, Col_Multiply, Col_Except: |
| ... | @@ -34,6 +38,7 @@ func ColValue(opt operator, value interface{}) interface{} { | ... | @@ -34,6 +38,7 @@ func ColValue(opt operator, value interface{}) interface{} { |
| 34 | return val | 38 | return val |
| 35 | } | 39 | } |
| 36 | 40 | ||
| 41 | // real query struct | ||
| 37 | type querySet struct { | 42 | type querySet struct { |
| 38 | mi *modelInfo | 43 | mi *modelInfo |
| 39 | cond *Condition | 44 | cond *Condition |
| ... | @@ -47,6 +52,7 @@ type querySet struct { | ... | @@ -47,6 +52,7 @@ type querySet struct { |
| 47 | 52 | ||
| 48 | var _ QuerySeter = new(querySet) | 53 | var _ QuerySeter = new(querySet) |
| 49 | 54 | ||
| 55 | // add condition expression to QuerySeter. | ||
| 50 | func (o querySet) Filter(expr string, args ...interface{}) QuerySeter { | 56 | func (o querySet) Filter(expr string, args ...interface{}) QuerySeter { |
| 51 | if o.cond == nil { | 57 | if o.cond == nil { |
| 52 | o.cond = NewCondition() | 58 | o.cond = NewCondition() |
| ... | @@ -55,6 +61,7 @@ func (o querySet) Filter(expr string, args ...interface{}) QuerySeter { | ... | @@ -55,6 +61,7 @@ func (o querySet) Filter(expr string, args ...interface{}) QuerySeter { |
| 55 | return &o | 61 | return &o |
| 56 | } | 62 | } |
| 57 | 63 | ||
| 64 | // add NOT condition to querySeter. | ||
| 58 | func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { | 65 | func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { |
| 59 | if o.cond == nil { | 66 | if o.cond == nil { |
| 60 | o.cond = NewCondition() | 67 | o.cond = NewCondition() |
| ... | @@ -63,10 +70,13 @@ func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { | ... | @@ -63,10 +70,13 @@ func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { |
| 63 | return &o | 70 | return &o |
| 64 | } | 71 | } |
| 65 | 72 | ||
| 73 | // set offset number | ||
| 66 | func (o *querySet) setOffset(num interface{}) { | 74 | func (o *querySet) setOffset(num interface{}) { |
| 67 | o.offset = ToInt64(num) | 75 | o.offset = ToInt64(num) |
| 68 | } | 76 | } |
| 69 | 77 | ||
| 78 | // add LIMIT value. | ||
| 79 | // args[0] means offset, e.g. LIMIT num,offset. | ||
| 70 | func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter { | 80 | func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter { |
| 71 | o.limit = ToInt64(limit) | 81 | o.limit = ToInt64(limit) |
| 72 | if len(args) > 0 { | 82 | if len(args) > 0 { |
| ... | @@ -75,16 +85,21 @@ func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter { | ... | @@ -75,16 +85,21 @@ func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter { |
| 75 | return &o | 85 | return &o |
| 76 | } | 86 | } |
| 77 | 87 | ||
| 88 | // add OFFSET value | ||
| 78 | func (o querySet) Offset(offset interface{}) QuerySeter { | 89 | func (o querySet) Offset(offset interface{}) QuerySeter { |
| 79 | o.setOffset(offset) | 90 | o.setOffset(offset) |
| 80 | return &o | 91 | return &o |
| 81 | } | 92 | } |
| 82 | 93 | ||
| 94 | // add ORDER expression. | ||
| 95 | // "column" means ASC, "-column" means DESC. | ||
| 83 | func (o querySet) OrderBy(exprs ...string) QuerySeter { | 96 | func (o querySet) OrderBy(exprs ...string) QuerySeter { |
| 84 | o.orders = exprs | 97 | o.orders = exprs |
| 85 | return &o | 98 | return &o |
| 86 | } | 99 | } |
| 87 | 100 | ||
| 101 | // set relation model to query together. | ||
| 102 | // it will query relation models and assign to parent model. | ||
| 88 | func (o querySet) RelatedSel(params ...interface{}) QuerySeter { | 103 | func (o querySet) RelatedSel(params ...interface{}) QuerySeter { |
| 89 | var related []string | 104 | var related []string |
| 90 | if len(params) == 0 { | 105 | if len(params) == 0 { |
| ... | @@ -105,36 +120,50 @@ func (o querySet) RelatedSel(params ...interface{}) QuerySeter { | ... | @@ -105,36 +120,50 @@ func (o querySet) RelatedSel(params ...interface{}) QuerySeter { |
| 105 | return &o | 120 | return &o |
| 106 | } | 121 | } |
| 107 | 122 | ||
| 123 | // set condition to QuerySeter. | ||
| 108 | func (o querySet) SetCond(cond *Condition) QuerySeter { | 124 | func (o querySet) SetCond(cond *Condition) QuerySeter { |
| 109 | o.cond = cond | 125 | o.cond = cond |
| 110 | return &o | 126 | return &o |
| 111 | } | 127 | } |
| 112 | 128 | ||
| 129 | // return QuerySeter execution result number | ||
| 113 | func (o *querySet) Count() (int64, error) { | 130 | func (o *querySet) Count() (int64, error) { |
| 114 | return o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) | 131 | return o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) |
| 115 | } | 132 | } |
| 116 | 133 | ||
| 134 | // check result empty or not after QuerySeter executed | ||
| 117 | func (o *querySet) Exist() bool { | 135 | func (o *querySet) Exist() bool { |
| 118 | cnt, _ := o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) | 136 | cnt, _ := o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) |
| 119 | return cnt > 0 | 137 | return cnt > 0 |
| 120 | } | 138 | } |
| 121 | 139 | ||
| 140 | // execute update with parameters | ||
| 122 | func (o *querySet) Update(values Params) (int64, error) { | 141 | func (o *querySet) Update(values Params) (int64, error) { |
| 123 | return o.orm.alias.DbBaser.UpdateBatch(o.orm.db, o, o.mi, o.cond, values, o.orm.alias.TZ) | 142 | return o.orm.alias.DbBaser.UpdateBatch(o.orm.db, o, o.mi, o.cond, values, o.orm.alias.TZ) |
| 124 | } | 143 | } |
| 125 | 144 | ||
| 145 | // execute delete | ||
| 126 | func (o *querySet) Delete() (int64, error) { | 146 | func (o *querySet) Delete() (int64, error) { |
| 127 | return o.orm.alias.DbBaser.DeleteBatch(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) | 147 | return o.orm.alias.DbBaser.DeleteBatch(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) |
| 128 | } | 148 | } |
| 129 | 149 | ||
| 150 | // return a insert queryer. | ||
| 151 | // it can be used in times. | ||
| 152 | // example: | ||
| 153 | // i,err := sq.PrepareInsert() | ||
| 154 | // i.Add(&user1{},&user2{}) | ||
| 130 | func (o *querySet) PrepareInsert() (Inserter, error) { | 155 | func (o *querySet) PrepareInsert() (Inserter, error) { |
| 131 | return newInsertSet(o.orm, o.mi) | 156 | return newInsertSet(o.orm, o.mi) |
| 132 | } | 157 | } |
| 133 | 158 | ||
| 159 | // query all data and map to containers. | ||
| 160 | // cols means the columns when querying. | ||
| 134 | func (o *querySet) All(container interface{}, cols ...string) (int64, error) { | 161 | func (o *querySet) All(container interface{}, cols ...string) (int64, error) { |
| 135 | return o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) | 162 | return o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) |
| 136 | } | 163 | } |
| 137 | 164 | ||
| 165 | // query one row data and map to containers. | ||
| 166 | // cols means the columns when querying. | ||
| 138 | func (o *querySet) One(container interface{}, cols ...string) error { | 167 | func (o *querySet) One(container interface{}, cols ...string) error { |
| 139 | num, err := o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) | 168 | num, err := o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ, cols) |
| 140 | if err != nil { | 169 | if err != nil { |
| ... | @@ -149,18 +178,26 @@ func (o *querySet) One(container interface{}, cols ...string) error { | ... | @@ -149,18 +178,26 @@ func (o *querySet) One(container interface{}, cols ...string) error { |
| 149 | return nil | 178 | return nil |
| 150 | } | 179 | } |
| 151 | 180 | ||
| 181 | // query all data and map to []map[string]interface. | ||
| 182 | // expres means condition expression. | ||
| 183 | // it converts data to []map[column]value. | ||
| 152 | func (o *querySet) Values(results *[]Params, exprs ...string) (int64, error) { | 184 | func (o *querySet) Values(results *[]Params, exprs ...string) (int64, error) { |
| 153 | return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) | 185 | return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) |
| 154 | } | 186 | } |
| 155 | 187 | ||
| 188 | // query all data and map to [][]interface | ||
| 189 | // it converts data to [][column_index]value | ||
| 156 | func (o *querySet) ValuesList(results *[]ParamsList, exprs ...string) (int64, error) { | 190 | func (o *querySet) ValuesList(results *[]ParamsList, exprs ...string) (int64, error) { |
| 157 | return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) | 191 | return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ) |
| 158 | } | 192 | } |
| 159 | 193 | ||
| 194 | // query all data and map to []interface. | ||
| 195 | // it's designed for one row record set, auto change to []value, not [][column]value. | ||
| 160 | func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) { | 196 | func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) { |
| 161 | return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, []string{expr}, result, o.orm.alias.TZ) | 197 | return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, []string{expr}, result, o.orm.alias.TZ) |
| 162 | } | 198 | } |
| 163 | 199 | ||
| 200 | // create new QuerySeter. | ||
| 164 | func newQuerySet(orm *orm, mi *modelInfo) QuerySeter { | 201 | func newQuerySet(orm *orm, mi *modelInfo) QuerySeter { |
| 165 | o := new(querySet) | 202 | o := new(querySet) |
| 166 | o.mi = mi | 203 | o.mi = mi | ... | ... |
| ... | @@ -7,6 +7,7 @@ import ( | ... | @@ -7,6 +7,7 @@ import ( |
| 7 | "time" | 7 | "time" |
| 8 | ) | 8 | ) |
| 9 | 9 | ||
| 10 | // raw sql string prepared statement | ||
| 10 | type rawPrepare struct { | 11 | type rawPrepare struct { |
| 11 | rs *rawSet | 12 | rs *rawSet |
| 12 | stmt stmtQuerier | 13 | stmt stmtQuerier |
| ... | @@ -44,6 +45,7 @@ func newRawPreparer(rs *rawSet) (RawPreparer, error) { | ... | @@ -44,6 +45,7 @@ func newRawPreparer(rs *rawSet) (RawPreparer, error) { |
| 44 | return o, nil | 45 | return o, nil |
| 45 | } | 46 | } |
| 46 | 47 | ||
| 48 | // raw query seter | ||
| 47 | type rawSet struct { | 49 | type rawSet struct { |
| 48 | query string | 50 | query string |
| 49 | args []interface{} | 51 | args []interface{} |
| ... | @@ -52,11 +54,13 @@ type rawSet struct { | ... | @@ -52,11 +54,13 @@ type rawSet struct { |
| 52 | 54 | ||
| 53 | var _ RawSeter = new(rawSet) | 55 | var _ RawSeter = new(rawSet) |
| 54 | 56 | ||
| 57 | // set args for every query | ||
| 55 | func (o rawSet) SetArgs(args ...interface{}) RawSeter { | 58 | func (o rawSet) SetArgs(args ...interface{}) RawSeter { |
| 56 | o.args = args | 59 | o.args = args |
| 57 | return &o | 60 | return &o |
| 58 | } | 61 | } |
| 59 | 62 | ||
| 63 | // execute raw sql and return sql.Result | ||
| 60 | func (o *rawSet) Exec() (sql.Result, error) { | 64 | func (o *rawSet) Exec() (sql.Result, error) { |
| 61 | query := o.query | 65 | query := o.query |
| 62 | o.orm.alias.DbBaser.ReplaceMarks(&query) | 66 | o.orm.alias.DbBaser.ReplaceMarks(&query) |
| ... | @@ -65,6 +69,7 @@ func (o *rawSet) Exec() (sql.Result, error) { | ... | @@ -65,6 +69,7 @@ func (o *rawSet) Exec() (sql.Result, error) { |
| 65 | return o.orm.db.Exec(query, args...) | 69 | return o.orm.db.Exec(query, args...) |
| 66 | } | 70 | } |
| 67 | 71 | ||
| 72 | // set field value to row container | ||
| 68 | func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { | 73 | func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { |
| 69 | switch ind.Kind() { | 74 | switch ind.Kind() { |
| 70 | case reflect.Bool: | 75 | case reflect.Bool: |
| ... | @@ -163,6 +168,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { | ... | @@ -163,6 +168,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { |
| 163 | } | 168 | } |
| 164 | } | 169 | } |
| 165 | 170 | ||
| 171 | // set field value in loop for slice container | ||
| 166 | func (o *rawSet) loopSetRefs(refs []interface{}, sInds []reflect.Value, nIndsPtr *[]reflect.Value, eTyps []reflect.Type, init bool) { | 172 | func (o *rawSet) loopSetRefs(refs []interface{}, sInds []reflect.Value, nIndsPtr *[]reflect.Value, eTyps []reflect.Type, init bool) { |
| 167 | nInds := *nIndsPtr | 173 | nInds := *nIndsPtr |
| 168 | 174 | ||
| ... | @@ -233,6 +239,7 @@ func (o *rawSet) loopSetRefs(refs []interface{}, sInds []reflect.Value, nIndsPtr | ... | @@ -233,6 +239,7 @@ func (o *rawSet) loopSetRefs(refs []interface{}, sInds []reflect.Value, nIndsPtr |
| 233 | } | 239 | } |
| 234 | } | 240 | } |
| 235 | 241 | ||
| 242 | // query data and map to container | ||
| 236 | func (o *rawSet) QueryRow(containers ...interface{}) error { | 243 | func (o *rawSet) QueryRow(containers ...interface{}) error { |
| 237 | refs := make([]interface{}, 0, len(containers)) | 244 | refs := make([]interface{}, 0, len(containers)) |
| 238 | sInds := make([]reflect.Value, 0) | 245 | sInds := make([]reflect.Value, 0) |
| ... | @@ -362,6 +369,7 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { | ... | @@ -362,6 +369,7 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { |
| 362 | return nil | 369 | return nil |
| 363 | } | 370 | } |
| 364 | 371 | ||
| 372 | // query data rows and map to container | ||
| 365 | func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { | 373 | func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { |
| 366 | refs := make([]interface{}, 0, len(containers)) | 374 | refs := make([]interface{}, 0, len(containers)) |
| 367 | sInds := make([]reflect.Value, 0) | 375 | sInds := make([]reflect.Value, 0) |
| ... | @@ -615,18 +623,22 @@ func (o *rawSet) readValues(container interface{}) (int64, error) { | ... | @@ -615,18 +623,22 @@ func (o *rawSet) readValues(container interface{}) (int64, error) { |
| 615 | return cnt, nil | 623 | return cnt, nil |
| 616 | } | 624 | } |
| 617 | 625 | ||
| 626 | // query data to []map[string]interface | ||
| 618 | func (o *rawSet) Values(container *[]Params) (int64, error) { | 627 | func (o *rawSet) Values(container *[]Params) (int64, error) { |
| 619 | return o.readValues(container) | 628 | return o.readValues(container) |
| 620 | } | 629 | } |
| 621 | 630 | ||
| 631 | // query data to [][]interface | ||
| 622 | func (o *rawSet) ValuesList(container *[]ParamsList) (int64, error) { | 632 | func (o *rawSet) ValuesList(container *[]ParamsList) (int64, error) { |
| 623 | return o.readValues(container) | 633 | return o.readValues(container) |
| 624 | } | 634 | } |
| 625 | 635 | ||
| 636 | // query data to []interface | ||
| 626 | func (o *rawSet) ValuesFlat(container *ParamsList) (int64, error) { | 637 | func (o *rawSet) ValuesFlat(container *ParamsList) (int64, error) { |
| 627 | return o.readValues(container) | 638 | return o.readValues(container) |
| 628 | } | 639 | } |
| 629 | 640 | ||
| 641 | // return prepared raw statement for used in times. | ||
| 630 | func (o *rawSet) Prepare() (RawPreparer, error) { | 642 | func (o *rawSet) Prepare() (RawPreparer, error) { |
| 631 | return newRawPreparer(o) | 643 | return newRawPreparer(o) |
| 632 | } | 644 | } | ... | ... |
| ... | @@ -6,11 +6,13 @@ import ( | ... | @@ -6,11 +6,13 @@ import ( |
| 6 | "time" | 6 | "time" |
| 7 | ) | 7 | ) |
| 8 | 8 | ||
| 9 | // database driver | ||
| 9 | type Driver interface { | 10 | type Driver interface { |
| 10 | Name() string | 11 | Name() string |
| 11 | Type() DriverType | 12 | Type() DriverType |
| 12 | } | 13 | } |
| 13 | 14 | ||
| 15 | // field info | ||
| 14 | type Fielder interface { | 16 | type Fielder interface { |
| 15 | String() string | 17 | String() string |
| 16 | FieldType() int | 18 | FieldType() int |
| ... | @@ -18,6 +20,7 @@ type Fielder interface { | ... | @@ -18,6 +20,7 @@ type Fielder interface { |
| 18 | RawValue() interface{} | 20 | RawValue() interface{} |
| 19 | } | 21 | } |
| 20 | 22 | ||
| 23 | // orm struct | ||
| 21 | type Ormer interface { | 24 | type Ormer interface { |
| 22 | Read(interface{}, ...string) error | 25 | Read(interface{}, ...string) error |
| 23 | Insert(interface{}) (int64, error) | 26 | Insert(interface{}) (int64, error) |
| ... | @@ -35,11 +38,13 @@ type Ormer interface { | ... | @@ -35,11 +38,13 @@ type Ormer interface { |
| 35 | Driver() Driver | 38 | Driver() Driver |
| 36 | } | 39 | } |
| 37 | 40 | ||
| 41 | // insert prepared statement | ||
| 38 | type Inserter interface { | 42 | type Inserter interface { |
| 39 | Insert(interface{}) (int64, error) | 43 | Insert(interface{}) (int64, error) |
| 40 | Close() error | 44 | Close() error |
| 41 | } | 45 | } |
| 42 | 46 | ||
| 47 | // query seter | ||
| 43 | type QuerySeter interface { | 48 | type QuerySeter interface { |
| 44 | Filter(string, ...interface{}) QuerySeter | 49 | Filter(string, ...interface{}) QuerySeter |
| 45 | Exclude(string, ...interface{}) QuerySeter | 50 | Exclude(string, ...interface{}) QuerySeter |
| ... | @@ -60,6 +65,7 @@ type QuerySeter interface { | ... | @@ -60,6 +65,7 @@ type QuerySeter interface { |
| 60 | ValuesFlat(*ParamsList, string) (int64, error) | 65 | ValuesFlat(*ParamsList, string) (int64, error) |
| 61 | } | 66 | } |
| 62 | 67 | ||
| 68 | // model to model query struct | ||
| 63 | type QueryM2Mer interface { | 69 | type QueryM2Mer interface { |
| 64 | Add(...interface{}) (int64, error) | 70 | Add(...interface{}) (int64, error) |
| 65 | Remove(...interface{}) (int64, error) | 71 | Remove(...interface{}) (int64, error) |
| ... | @@ -68,11 +74,13 @@ type QueryM2Mer interface { | ... | @@ -68,11 +74,13 @@ type QueryM2Mer interface { |
| 68 | Count() (int64, error) | 74 | Count() (int64, error) |
| 69 | } | 75 | } |
| 70 | 76 | ||
| 77 | // raw query statement | ||
| 71 | type RawPreparer interface { | 78 | type RawPreparer interface { |
| 72 | Exec(...interface{}) (sql.Result, error) | 79 | Exec(...interface{}) (sql.Result, error) |
| 73 | Close() error | 80 | Close() error |
| 74 | } | 81 | } |
| 75 | 82 | ||
| 83 | // raw query seter | ||
| 76 | type RawSeter interface { | 84 | type RawSeter interface { |
| 77 | Exec() (sql.Result, error) | 85 | Exec() (sql.Result, error) |
| 78 | QueryRow(...interface{}) error | 86 | QueryRow(...interface{}) error |
| ... | @@ -84,6 +92,7 @@ type RawSeter interface { | ... | @@ -84,6 +92,7 @@ type RawSeter interface { |
| 84 | Prepare() (RawPreparer, error) | 92 | Prepare() (RawPreparer, error) |
| 85 | } | 93 | } |
| 86 | 94 | ||
| 95 | // statement querier | ||
| 87 | type stmtQuerier interface { | 96 | type stmtQuerier interface { |
| 88 | Close() error | 97 | Close() error |
| 89 | Exec(args ...interface{}) (sql.Result, error) | 98 | Exec(args ...interface{}) (sql.Result, error) |
| ... | @@ -91,6 +100,7 @@ type stmtQuerier interface { | ... | @@ -91,6 +100,7 @@ type stmtQuerier interface { |
| 91 | QueryRow(args ...interface{}) *sql.Row | 100 | QueryRow(args ...interface{}) *sql.Row |
| 92 | } | 101 | } |
| 93 | 102 | ||
| 103 | // db querier | ||
| 94 | type dbQuerier interface { | 104 | type dbQuerier interface { |
| 95 | Prepare(query string) (*sql.Stmt, error) | 105 | Prepare(query string) (*sql.Stmt, error) |
| 96 | Exec(query string, args ...interface{}) (sql.Result, error) | 106 | Exec(query string, args ...interface{}) (sql.Result, error) |
| ... | @@ -98,15 +108,18 @@ type dbQuerier interface { | ... | @@ -98,15 +108,18 @@ type dbQuerier interface { |
| 98 | QueryRow(query string, args ...interface{}) *sql.Row | 108 | QueryRow(query string, args ...interface{}) *sql.Row |
| 99 | } | 109 | } |
| 100 | 110 | ||
| 111 | // transaction beginner | ||
| 101 | type txer interface { | 112 | type txer interface { |
| 102 | Begin() (*sql.Tx, error) | 113 | Begin() (*sql.Tx, error) |
| 103 | } | 114 | } |
| 104 | 115 | ||
| 116 | // transaction ending | ||
| 105 | type txEnder interface { | 117 | type txEnder interface { |
| 106 | Commit() error | 118 | Commit() error |
| 107 | Rollback() error | 119 | Rollback() error |
| 108 | } | 120 | } |
| 109 | 121 | ||
| 122 | // base database struct | ||
| 110 | type dbBaser interface { | 123 | type dbBaser interface { |
| 111 | Read(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) error | 124 | Read(dbQuerier, *modelInfo, reflect.Value, *time.Location, []string) error |
| 112 | Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error) | 125 | Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error) | ... | ... |
| ... | @@ -10,6 +10,7 @@ import ( | ... | @@ -10,6 +10,7 @@ import ( |
| 10 | 10 | ||
| 11 | type StrTo string | 11 | type StrTo string |
| 12 | 12 | ||
| 13 | // set string | ||
| 13 | func (f *StrTo) Set(v string) { | 14 | func (f *StrTo) Set(v string) { |
| 14 | if v != "" { | 15 | if v != "" { |
| 15 | *f = StrTo(v) | 16 | *f = StrTo(v) |
| ... | @@ -18,77 +19,93 @@ func (f *StrTo) Set(v string) { | ... | @@ -18,77 +19,93 @@ func (f *StrTo) Set(v string) { |
| 18 | } | 19 | } |
| 19 | } | 20 | } |
| 20 | 21 | ||
| 22 | // clean string | ||
| 21 | func (f *StrTo) Clear() { | 23 | func (f *StrTo) Clear() { |
| 22 | *f = StrTo(0x1E) | 24 | *f = StrTo(0x1E) |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 27 | // check string exist | ||
| 25 | func (f StrTo) Exist() bool { | 28 | func (f StrTo) Exist() bool { |
| 26 | return string(f) != string(0x1E) | 29 | return string(f) != string(0x1E) |
| 27 | } | 30 | } |
| 28 | 31 | ||
| 32 | // string to bool | ||
| 29 | func (f StrTo) Bool() (bool, error) { | 33 | func (f StrTo) Bool() (bool, error) { |
| 30 | return strconv.ParseBool(f.String()) | 34 | return strconv.ParseBool(f.String()) |
| 31 | } | 35 | } |
| 32 | 36 | ||
| 37 | // string to float32 | ||
| 33 | func (f StrTo) Float32() (float32, error) { | 38 | func (f StrTo) Float32() (float32, error) { |
| 34 | v, err := strconv.ParseFloat(f.String(), 32) | 39 | v, err := strconv.ParseFloat(f.String(), 32) |
| 35 | return float32(v), err | 40 | return float32(v), err |
| 36 | } | 41 | } |
| 37 | 42 | ||
| 43 | // string to float64 | ||
| 38 | func (f StrTo) Float64() (float64, error) { | 44 | func (f StrTo) Float64() (float64, error) { |
| 39 | return strconv.ParseFloat(f.String(), 64) | 45 | return strconv.ParseFloat(f.String(), 64) |
| 40 | } | 46 | } |
| 41 | 47 | ||
| 48 | // string to int | ||
| 42 | func (f StrTo) Int() (int, error) { | 49 | func (f StrTo) Int() (int, error) { |
| 43 | v, err := strconv.ParseInt(f.String(), 10, 32) | 50 | v, err := strconv.ParseInt(f.String(), 10, 32) |
| 44 | return int(v), err | 51 | return int(v), err |
| 45 | } | 52 | } |
| 46 | 53 | ||
| 54 | // string to int8 | ||
| 47 | func (f StrTo) Int8() (int8, error) { | 55 | func (f StrTo) Int8() (int8, error) { |
| 48 | v, err := strconv.ParseInt(f.String(), 10, 8) | 56 | v, err := strconv.ParseInt(f.String(), 10, 8) |
| 49 | return int8(v), err | 57 | return int8(v), err |
| 50 | } | 58 | } |
| 51 | 59 | ||
| 60 | // string to int16 | ||
| 52 | func (f StrTo) Int16() (int16, error) { | 61 | func (f StrTo) Int16() (int16, error) { |
| 53 | v, err := strconv.ParseInt(f.String(), 10, 16) | 62 | v, err := strconv.ParseInt(f.String(), 10, 16) |
| 54 | return int16(v), err | 63 | return int16(v), err |
| 55 | } | 64 | } |
| 56 | 65 | ||
| 66 | // string to int32 | ||
| 57 | func (f StrTo) Int32() (int32, error) { | 67 | func (f StrTo) Int32() (int32, error) { |
| 58 | v, err := strconv.ParseInt(f.String(), 10, 32) | 68 | v, err := strconv.ParseInt(f.String(), 10, 32) |
| 59 | return int32(v), err | 69 | return int32(v), err |
| 60 | } | 70 | } |
| 61 | 71 | ||
| 72 | // string to int64 | ||
| 62 | func (f StrTo) Int64() (int64, error) { | 73 | func (f StrTo) Int64() (int64, error) { |
| 63 | v, err := strconv.ParseInt(f.String(), 10, 64) | 74 | v, err := strconv.ParseInt(f.String(), 10, 64) |
| 64 | return int64(v), err | 75 | return int64(v), err |
| 65 | } | 76 | } |
| 66 | 77 | ||
| 78 | // string to uint | ||
| 67 | func (f StrTo) Uint() (uint, error) { | 79 | func (f StrTo) Uint() (uint, error) { |
| 68 | v, err := strconv.ParseUint(f.String(), 10, 32) | 80 | v, err := strconv.ParseUint(f.String(), 10, 32) |
| 69 | return uint(v), err | 81 | return uint(v), err |
| 70 | } | 82 | } |
| 71 | 83 | ||
| 84 | // string to uint8 | ||
| 72 | func (f StrTo) Uint8() (uint8, error) { | 85 | func (f StrTo) Uint8() (uint8, error) { |
| 73 | v, err := strconv.ParseUint(f.String(), 10, 8) | 86 | v, err := strconv.ParseUint(f.String(), 10, 8) |
| 74 | return uint8(v), err | 87 | return uint8(v), err |
| 75 | } | 88 | } |
| 76 | 89 | ||
| 90 | // string to uint16 | ||
| 77 | func (f StrTo) Uint16() (uint16, error) { | 91 | func (f StrTo) Uint16() (uint16, error) { |
| 78 | v, err := strconv.ParseUint(f.String(), 10, 16) | 92 | v, err := strconv.ParseUint(f.String(), 10, 16) |
| 79 | return uint16(v), err | 93 | return uint16(v), err |
| 80 | } | 94 | } |
| 81 | 95 | ||
| 96 | // string to uint31 | ||
| 82 | func (f StrTo) Uint32() (uint32, error) { | 97 | func (f StrTo) Uint32() (uint32, error) { |
| 83 | v, err := strconv.ParseUint(f.String(), 10, 32) | 98 | v, err := strconv.ParseUint(f.String(), 10, 32) |
| 84 | return uint32(v), err | 99 | return uint32(v), err |
| 85 | } | 100 | } |
| 86 | 101 | ||
| 102 | // string to uint64 | ||
| 87 | func (f StrTo) Uint64() (uint64, error) { | 103 | func (f StrTo) Uint64() (uint64, error) { |
| 88 | v, err := strconv.ParseUint(f.String(), 10, 64) | 104 | v, err := strconv.ParseUint(f.String(), 10, 64) |
| 89 | return uint64(v), err | 105 | return uint64(v), err |
| 90 | } | 106 | } |
| 91 | 107 | ||
| 108 | // string to string | ||
| 92 | func (f StrTo) String() string { | 109 | func (f StrTo) String() string { |
| 93 | if f.Exist() { | 110 | if f.Exist() { |
| 94 | return string(f) | 111 | return string(f) |
| ... | @@ -96,6 +113,7 @@ func (f StrTo) String() string { | ... | @@ -96,6 +113,7 @@ func (f StrTo) String() string { |
| 96 | return "" | 113 | return "" |
| 97 | } | 114 | } |
| 98 | 115 | ||
| 116 | // interface to string | ||
| 99 | func ToStr(value interface{}, args ...int) (s string) { | 117 | func ToStr(value interface{}, args ...int) (s string) { |
| 100 | switch v := value.(type) { | 118 | switch v := value.(type) { |
| 101 | case bool: | 119 | case bool: |
| ... | @@ -134,6 +152,7 @@ func ToStr(value interface{}, args ...int) (s string) { | ... | @@ -134,6 +152,7 @@ func ToStr(value interface{}, args ...int) (s string) { |
| 134 | return s | 152 | return s |
| 135 | } | 153 | } |
| 136 | 154 | ||
| 155 | // interface to int64 | ||
| 137 | func ToInt64(value interface{}) (d int64) { | 156 | func ToInt64(value interface{}) (d int64) { |
| 138 | val := reflect.ValueOf(value) | 157 | val := reflect.ValueOf(value) |
| 139 | switch value.(type) { | 158 | switch value.(type) { |
| ... | @@ -147,6 +166,7 @@ func ToInt64(value interface{}) (d int64) { | ... | @@ -147,6 +166,7 @@ func ToInt64(value interface{}) (d int64) { |
| 147 | return | 166 | return |
| 148 | } | 167 | } |
| 149 | 168 | ||
| 169 | // snake string, XxYy to xx_yy | ||
| 150 | func snakeString(s string) string { | 170 | func snakeString(s string) string { |
| 151 | data := make([]byte, 0, len(s)*2) | 171 | data := make([]byte, 0, len(s)*2) |
| 152 | j := false | 172 | j := false |
| ... | @@ -164,6 +184,7 @@ func snakeString(s string) string { | ... | @@ -164,6 +184,7 @@ func snakeString(s string) string { |
| 164 | return strings.ToLower(string(data[:len(data)])) | 184 | return strings.ToLower(string(data[:len(data)])) |
| 165 | } | 185 | } |
| 166 | 186 | ||
| 187 | // camel string, xx_yy to XxYy | ||
| 167 | func camelString(s string) string { | 188 | func camelString(s string) string { |
| 168 | data := make([]byte, 0, len(s)) | 189 | data := make([]byte, 0, len(s)) |
| 169 | j := false | 190 | j := false |
| ... | @@ -190,6 +211,7 @@ func camelString(s string) string { | ... | @@ -190,6 +211,7 @@ func camelString(s string) string { |
| 190 | 211 | ||
| 191 | type argString []string | 212 | type argString []string |
| 192 | 213 | ||
| 214 | // get string by index from string slice | ||
| 193 | func (a argString) Get(i int, args ...string) (r string) { | 215 | func (a argString) Get(i int, args ...string) (r string) { |
| 194 | if i >= 0 && i < len(a) { | 216 | if i >= 0 && i < len(a) { |
| 195 | r = a[i] | 217 | r = a[i] |
| ... | @@ -201,6 +223,7 @@ func (a argString) Get(i int, args ...string) (r string) { | ... | @@ -201,6 +223,7 @@ func (a argString) Get(i int, args ...string) (r string) { |
| 201 | 223 | ||
| 202 | type argInt []int | 224 | type argInt []int |
| 203 | 225 | ||
| 226 | // get int by index from int slice | ||
| 204 | func (a argInt) Get(i int, args ...int) (r int) { | 227 | func (a argInt) Get(i int, args ...int) (r int) { |
| 205 | if i >= 0 && i < len(a) { | 228 | if i >= 0 && i < len(a) { |
| 206 | r = a[i] | 229 | r = a[i] |
| ... | @@ -213,6 +236,7 @@ func (a argInt) Get(i int, args ...int) (r int) { | ... | @@ -213,6 +236,7 @@ func (a argInt) Get(i int, args ...int) (r int) { |
| 213 | 236 | ||
| 214 | type argAny []interface{} | 237 | type argAny []interface{} |
| 215 | 238 | ||
| 239 | // get interface by index from interface slice | ||
| 216 | func (a argAny) Get(i int, args ...interface{}) (r interface{}) { | 240 | func (a argAny) Get(i int, args ...interface{}) (r interface{}) { |
| 217 | if i >= 0 && i < len(a) { | 241 | if i >= 0 && i < len(a) { |
| 218 | r = a[i] | 242 | r = a[i] |
| ... | @@ -223,15 +247,18 @@ func (a argAny) Get(i int, args ...interface{}) (r interface{}) { | ... | @@ -223,15 +247,18 @@ func (a argAny) Get(i int, args ...interface{}) (r interface{}) { |
| 223 | return | 247 | return |
| 224 | } | 248 | } |
| 225 | 249 | ||
| 250 | // parse time to string with location | ||
| 226 | func timeParse(dateString, format string) (time.Time, error) { | 251 | func timeParse(dateString, format string) (time.Time, error) { |
| 227 | tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) | 252 | tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) |
| 228 | return tp, err | 253 | return tp, err |
| 229 | } | 254 | } |
| 230 | 255 | ||
| 256 | // format time string | ||
| 231 | func timeFormat(t time.Time, format string) string { | 257 | func timeFormat(t time.Time, format string) string { |
| 232 | return t.Format(format) | 258 | return t.Format(format) |
| 233 | } | 259 | } |
| 234 | 260 | ||
| 261 | // get pointer indirect type | ||
| 235 | func indirectType(v reflect.Type) reflect.Type { | 262 | func indirectType(v reflect.Type) reflect.Type { |
| 236 | switch v.Kind() { | 263 | switch v.Kind() { |
| 237 | case reflect.Ptr: | 264 | case reflect.Ptr: | ... | ... |
-
Please register or sign in to post a comment