├── LICENSE ├── README.md ├── cache.go ├── cache_test.go ├── consistent.go ├── docs └── mode.md ├── logo.jpg ├── marsharl_driver_mysql.go ├── marsharl_driver_postgres.go ├── marsharl_driver_sql.go ├── marsharl_driver_sqlite.go ├── mode.go ├── params.go ├── params_test.go └── redis.go /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Able 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##About 2 | 3 | ![server-nado](./logo.jpg) 4 | 5 | 一个数据库ORM. 6 | 7 | Please go to [http://github.com/server-nado/orm](http://github.com/server-nado/orm) ! 8 | 9 | 代码已经转移到 [http://github.com/server-nado/orm](http://github.com/server-nado/orm) ! 10 | 11 | ## How to use? 12 | 13 | ### Insert 14 | go get github.com/server-nado/orm 15 | 16 | 17 | 18 | ## Super database 19 | 20 | sqlite3 "github.com/mattn/go-sqlite3" 21 | mysql "github.com/go-sql-driver/mysql" 22 | postgree "github.com/lib/pq" 23 | 24 | ##数据库Model 建立方法 25 | 26 | //引用模块 27 | import "github.com/ablegao/orm" 28 | 29 | //mysql 驱动 30 | import _ "github.com/go-sql-driver/mysql" 31 | 32 | //建立连接 33 | // 参数分别为 名称 , 驱动, 连接字符串 34 | // 注:必须包含一个default 连接, 作为默认连接。 35 | orm.NewDatabase("default" , "mysql" , "user:passwd@ip/database?charset=utf8&parseTime=true") 36 | 37 | 38 | //建立一个数据模型。 39 | type UserInfo struct**** { 40 | orm.Object 41 | Id int64 `field:"id" auto:"true" index:"pk"` 42 | Name string `field:"username"` 43 | Passwd string `field:"password"` 44 | } 45 | 46 | [更多信息>>](docs/mode.md) 47 | 48 | ##新增 CacheModel 模型, 支持分布式redis作为数据库缓存。 49 | 50 | import "github.com/ablegao/orm" 51 | import _ "github.com/go-sql-driver/mysql" 52 | 53 | type userB struct { 54 | CacheModule 55 | Uid int64 `field:"Id" index:"pk" cache:"user" ` 56 | Alias string `field:"Alias"` 57 | Money int64 `field:"money" ` 58 | } 59 | 60 | func main(){ 61 | orm.CacheConsistent.Add("127.0.0.1:6379") //添加多个redis服务器 62 | orm.SetCachePrefix("nado") //默认nado . 将作为redis key 的前缀 63 | NewDatabase("default", "mysql", "happy:passwd@tcp(127.0.0.1:3306)/mydatabase?charset=utf8&parseTime=true") 64 | 65 | 66 | b := new(userB) 67 | b.Uid = 10000 68 | err:=b.Objects(b).One() 69 | if err!= nil { 70 | panic(err) 71 | } 72 | fmt.Println(b.Uid ,b.Alias ,b.Money) 73 | 74 | b.Incrby("Money" , 100) 75 | fmt.Println(b.Money) 76 | b.Save() //不执行不会保存到数据库 只会修改redis数据。 77 | 78 | 79 | } -------------------------------------------------------------------------------- /cache.go: -------------------------------------------------------------------------------- 1 | //Cache,用来沟通第一层cache 和同步数据到数据库 2 | 3 | package orm 4 | 5 | import ( 6 | "errors" 7 | "log" 8 | "os" 9 | "reflect" 10 | "sort" 11 | "strconv" 12 | "time" 13 | ) 14 | 15 | var Debug = log.New(os.Stdout, "ORM-DEBUG", log.Lshortfile|log.LstdFlags) 16 | var Error = log.New(os.Stdout, "ORM-ERROR", log.Lshortfile|log.LstdFlags) 17 | var cache_prefix []byte = []byte("nado") 18 | var cache_db = 0 19 | var st []byte = []byte("*") 20 | 21 | var ( 22 | ErrKeyNotExist = errors.New("keys not exists") 23 | ) 24 | 25 | func SetCachePrefix(str string) { 26 | cache_prefix = []byte(str) 27 | 28 | } 29 | func SetDefaultCacheDb(db int) { 30 | cache_db = db 31 | } 32 | 33 | var debug_sql bool = false 34 | 35 | func SetDebug(b bool) { 36 | debug_sql = b 37 | } 38 | 39 | type Cache interface { 40 | Set(key string, b []byte) error 41 | Get(key string) ([]byte, error) 42 | Keys(key string) ([]string, error) 43 | //Incy(key string) (int64, error) 44 | Incrby(key string, n int64) (int64, error) 45 | Hset(key, field string, b []byte) (bool, error) 46 | Hmset(key string, maping interface{}) error 47 | Hget(key, field string) ([]byte, error) 48 | Hincrby(key, filed string, n int64) (int64, error) 49 | Exists(key string) (bool, error) 50 | Del(key string) (bool, error) 51 | } 52 | 53 | func CacheMode(mode Module) (cache *CacheModule) { 54 | cache = new(CacheModule) 55 | cache.CacheFileds = []string{} 56 | cache.CacheNames = []string{} 57 | cache.Object.Objects(mode) 58 | typeOf := reflect.TypeOf(cache.mode).Elem() 59 | for i := 0; i < typeOf.NumField(); i++ { 60 | field := typeOf.Field(i) 61 | if name := field.Tag.Get("cache"); len(name) > 0 { 62 | cache.CacheFileds = append(cache.CacheFileds, field.Tag.Get("field")) 63 | cache.CacheNames = append(cache.CacheNames, name) 64 | } 65 | if prefix := field.Tag.Get("cache_prefix"); len(prefix) > 0 { 66 | cache.cache_prefix = prefix 67 | } 68 | } 69 | cache.Cache = GetRedisClient("default") 70 | return 71 | } 72 | 73 | type CacheModuleInteerface interface { 74 | Objects(Module) CacheModuleInteerface 75 | Ca(interface{}) CacheModuleInteerface //一致性hash 默认处理方式 76 | Db(string) CacheModuleInteerface //数据库连接 77 | Filter(name string, val interface{}) CacheModuleInteerface 78 | GetCacheKey() string 79 | Incrby(string, int64) (int64, error) 80 | Incry(string) (int64, error) 81 | Set(string, interface{}) error 82 | Save() (bool, int64, error) 83 | One() error 84 | SaveToCache() error 85 | All() ([]interface{}, error) 86 | AllCache() ([]interface{}, error) 87 | } 88 | 89 | type CacheModule struct { 90 | Cache 91 | Object 92 | cachekey string 93 | CacheFileds []string 94 | CacheNames []string 95 | cache_prefix string 96 | cache_address string 97 | } 98 | 99 | func (self *CacheModule) Objects(mode Module) *CacheModule { 100 | self.CacheFileds = []string{} 101 | self.CacheNames = []string{} 102 | self.Object.Objects(mode) 103 | typeOf := reflect.TypeOf(self.mode).Elem() 104 | for i := 0; i < typeOf.NumField(); i++ { 105 | field := typeOf.Field(i) 106 | if name := field.Tag.Get("cache"); len(name) > 0 { 107 | self.CacheFileds = append(self.CacheFileds, field.Tag.Get("field")) 108 | self.CacheNames = append(self.CacheNames, name) 109 | } 110 | if prefix := field.Tag.Get("cache_prefix"); len(prefix) > 0 { 111 | self.cache_prefix = prefix 112 | } 113 | 114 | } 115 | self.Cache = GetRedisClient("default") 116 | return self 117 | } 118 | 119 | func (self *CacheModule) Db(name string) *CacheModule { 120 | self.Params.Db(name) 121 | return self 122 | } 123 | 124 | func GetCacheConn(key interface{}) (address string, c Cache) { 125 | value := reflect.ValueOf(key) 126 | typeOf := reflect.TypeOf(key) 127 | b := []byte{} 128 | switch typeOf.Kind() { 129 | case reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uint8, reflect.Uint16: 130 | b = strconv.AppendUint(b, value.Uint(), 10) 131 | case reflect.Int32, reflect.Int64, reflect.Int, reflect.Int8, reflect.Int16: 132 | b = strconv.AppendInt(b, value.Int(), 10) 133 | case reflect.Float32, reflect.Float64: 134 | b = strconv.AppendFloat(b, value.Float(), 'f', 0, 64) 135 | case reflect.String: 136 | b = append(b, []byte(value.String())...) 137 | case reflect.Bool: 138 | b = strconv.AppendBool(b, value.Bool()) 139 | } 140 | address = string(b) 141 | c = GetRedisClient(address) 142 | return 143 | } 144 | 145 | func (self *CacheModule) Ca(key interface{}) *CacheModule { 146 | self.cache_address, self.Cache = GetCacheConn(key) 147 | return self 148 | } 149 | 150 | func (self *CacheModule) GetCacheKey() string { 151 | 152 | value := reflect.ValueOf(self.mode).Elem() 153 | typeOf := reflect.TypeOf(self.mode).Elem() 154 | str := cache_prefix 155 | str = append(str, []byte(self.cache_prefix)...) 156 | 157 | for i := 0; i < value.NumField(); i++ { 158 | field := typeOf.Field(i) 159 | self.CacheFileds = append(self.CacheFileds, field.Name) 160 | if name := field.Tag.Get("cache"); len(name) > 0 { 161 | val := value.Field(i) 162 | str = append(str, []byte(":")...) 163 | str = append(str, self.fieldToByte(val.Interface())...) 164 | str = append(str, []byte(":"+name)...) 165 | } 166 | } 167 | return string(str) 168 | } 169 | func (self *CacheModule) setModeFieldUint(field string, val interface{}) { 170 | 171 | value := reflect.ValueOf(self.mode).Elem() 172 | item := value.FieldByName(field) 173 | switch item.Type().Kind() { 174 | case reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uint8, reflect.Uint16: 175 | item.SetUint(uint64(val.(int64))) 176 | case reflect.Int32, reflect.Int64, reflect.Int, reflect.Int8, reflect.Int16: 177 | item.SetInt(val.(int64)) 178 | default: 179 | Error.Println("(CacheModule) setModeFieldUint", field, item.Type().Kind()) 180 | } 181 | } 182 | 183 | func (self *CacheModule) Incrby(key string, val int64) (ret int64, err error) { 184 | if self.cachekey == "" { 185 | self.cachekey = self.GetCacheKey() 186 | } 187 | ret, err = self.Cache.Hincrby(self.cachekey, key, val) 188 | 189 | if val >= 0 { 190 | self.Object.Change(key+"__add", val) 191 | } else if val < 0 { 192 | self.Object.Change(key+"__sub", val) 193 | } 194 | self.setModeFieldUint(key, ret) 195 | //go self.Object.Save() 196 | return 197 | } 198 | 199 | func (self *CacheModule) Incry(key string) (val int64, err error) { 200 | val, err = self.Incrby(key, 1) 201 | 202 | return 203 | } 204 | 205 | func (self *CacheModule) Set(key string, val interface{}) (err error) { 206 | 207 | b := []byte{} 208 | field := reflect.ValueOf(self.mode).Elem().FieldByName(key) 209 | switch val.(type) { 210 | case uint32, uint64, uint16, uint8, uint: 211 | val := reflect.ValueOf(val).Uint() 212 | b = strconv.AppendUint(b, val, 10) 213 | field.SetUint(val) 214 | case string: 215 | b = append(b, []byte(val.(string))...) 216 | field.SetString(val.(string)) 217 | 218 | case int32, int64, int16, int8, int: 219 | val := reflect.ValueOf(val).Int() 220 | b = strconv.AppendInt(b, val, 10) 221 | field.SetInt(val) 222 | case float32, float64: 223 | val := reflect.ValueOf(val).Float() 224 | b = strconv.AppendFloat(b, val, 'f', 0, 64) 225 | field.SetFloat(val) 226 | case bool: 227 | b = strconv.AppendBool(b, val.(bool)) 228 | field.SetBool(val.(bool)) 229 | case time.Time: 230 | field.Set(reflect.ValueOf(val)) 231 | b = append(b, []byte(val.(time.Time).Format(time.RFC1123Z))...) 232 | default: 233 | Error.Println("undefined val type") 234 | } 235 | if self.cachekey == "" { 236 | self.cachekey = self.GetCacheKey() 237 | } 238 | 239 | var over bool 240 | over, err = self.Cache.Hset(self.cachekey, key, b) 241 | if err != nil { 242 | return 243 | } 244 | if over == false { 245 | return errors.New(self.cachekey + " hset " + key + " error !") 246 | } 247 | self.Object.Change(key, val) 248 | //go self.Object.Change(key, val).Save() 249 | 250 | return 251 | } 252 | 253 | func (self *CacheModule) Save() (isnew bool, id int64, err error) { 254 | 255 | key := self.GetCacheKey() 256 | if i, err := self.Exists(key); err == nil && i == false { 257 | self.SaveToCache() 258 | } 259 | return self.Object.Save() 260 | } 261 | 262 | func (self *CacheModule) Filter(name string, val interface{}) *CacheModule { 263 | self.Object.Filter(name, val) 264 | return self 265 | } 266 | func (self *CacheModule) Orderby(order ...string) *CacheModule { 267 | self.Object.Orderby(order...) 268 | return self 269 | } 270 | func (self *CacheModule) Limit(page, step int) *CacheModule { 271 | self.Object.Limit(page, step) 272 | return self 273 | } 274 | func (self *CacheModule) AllOnCache() ([]interface{}, error) { 275 | key := self.getKey() 276 | if keys, err := self.Keys(key); err == nil && len(keys) > 0 { 277 | //(keys) 278 | sort.Sort(sort.StringSlice(keys)) 279 | if self.limit != NULL_LIMIT { 280 | page := (self.limit[0] - 1) * self.limit[1] 281 | step := self.limit[0] * self.limit[1] 282 | if step > len(keys) { 283 | step = len(keys) 284 | } 285 | if page < len(keys) { 286 | keys = keys[page:step] 287 | vals := make([]interface{}, len(keys)) 288 | for i, k := range keys { 289 | vals[i] = self.key2Mode(k) 290 | } 291 | return vals, nil 292 | } else { 293 | return make([]interface{}, 0), nil 294 | } 295 | } else { 296 | vals := make([]interface{}, len(keys)) 297 | for i, k := range keys { 298 | vals[i] = self.key2Mode(k) 299 | } 300 | return vals, nil 301 | } 302 | } else { 303 | if err == nil { 304 | return []interface{}{}, nil 305 | } 306 | return nil, err 307 | } 308 | } 309 | func (self *CacheModule) All() ([]interface{}, error) { 310 | if rets, err := self.AllOnCache(); err == nil && len(rets) > 0 { 311 | return rets, err 312 | } else { 313 | if debug_sql { 314 | Error.Println("all error:", err, len(rets)) 315 | } 316 | //self.Object.All() 317 | if rets, err := self.Object.All(); err == nil { 318 | for _, item := range rets { 319 | 320 | //Debug.Println(item) 321 | self.saveToCache(item.(Module)) 322 | } 323 | return rets, nil 324 | } else { 325 | return nil, err 326 | } 327 | 328 | } 329 | } 330 | 331 | func (self *CacheModule) DeleteOnCache() error { 332 | if len(self.cachekey) <= 0 { 333 | self.cachekey = self.getKey() 334 | } 335 | if _, err := self.Del(self.cachekey); err != nil { 336 | return err 337 | } 338 | 339 | return nil 340 | } 341 | func (self *CacheModule) OneOnCache() error { 342 | key := self.getKey() 343 | self.cachekey = key 344 | 345 | n, err := self.Exists(key) 346 | if err != nil { 347 | if debug_sql { 348 | Debug.Println(err) 349 | } 350 | return err 351 | } 352 | if debug_sql { 353 | Debug.Println("key ", self.cachekey, " is exists ", n) 354 | } 355 | if n == false { 356 | return ErrKeyNotExist 357 | } 358 | 359 | self.where = self.where[len(self.where):] 360 | val := reflect.ValueOf(self.mode).Elem() 361 | typ := reflect.TypeOf(self.mode).Elem() 362 | for i := 0; i < val.NumField(); i++ { 363 | if b, err := self.Cache.Hget(key, typ.Field(i).Name); err == nil { 364 | switch val.Field(i).Kind() { 365 | case reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uint8, reflect.Uint16: 366 | id, _ := strconv.ParseUint(string(b), 10, 64) 367 | val.Field(i).SetUint(id) 368 | case reflect.Int32, reflect.Int64, reflect.Int, reflect.Int8, reflect.Int16: 369 | id, _ := strconv.ParseInt(string(b), 10, 64) 370 | val.Field(i).SetInt(id) 371 | case reflect.Float32, reflect.Float64: 372 | id, _ := strconv.ParseFloat(string(b), 64) 373 | val.Field(i).SetFloat(id) 374 | case reflect.String: 375 | val.Field(i).SetString(string(b)) 376 | case reflect.Bool: 377 | id, _ := strconv.ParseBool(string(b)) 378 | val.Field(i).SetBool(id) 379 | default: 380 | switch val.Field(i).Interface().(type) { 381 | case time.Time: 382 | if time, e := time.Parse(time.RFC1123Z, string(b)); e == nil { 383 | val.Field(i).Set(reflect.ValueOf(time)) 384 | } 385 | } 386 | } 387 | if index := typ.Field(i).Tag.Get("index"); len(index) > 0 { 388 | self.Object.Filter(typ.Field(i).Name, val.Field(i).Interface()) 389 | } 390 | } 391 | } 392 | self.hasRow = true 393 | return nil 394 | } 395 | 396 | func (self *CacheModule) One() error { 397 | 398 | if err := self.OneOnCache(); err != nil { 399 | //return errors.New("key " + key + " not exists!") 400 | if debug_sql { 401 | Debug.Println("key ", self.cachekey, "error", err) 402 | } 403 | err = self.Object.One() 404 | if err == nil { 405 | defer self.SaveToCache() 406 | } else { 407 | Error.Println(err) 408 | } 409 | return err 410 | } 411 | return nil 412 | } 413 | func (self *CacheModule) CountOnCache() (int64, error) { 414 | if keys, err := self.Cache.Keys(self.getKey()); err == nil { 415 | return int64(len(keys)), nil 416 | } else { 417 | return 0, err 418 | } 419 | } 420 | func (self *CacheModule) Count() (int64, error) { 421 | if keys, err := self.Cache.Keys(self.getKey()); err == nil && len(keys) > 0 { 422 | return int64(len(keys)), nil 423 | } 424 | return self.Object.Count() 425 | } 426 | 427 | func (self *CacheModule) getKey() string { 428 | key := "" 429 | if len(self.where) > 0 { 430 | key = self.where2Key() 431 | } else { 432 | key = self.GetCacheKey() 433 | } 434 | return key 435 | } 436 | func (self *CacheModule) where2Key() string { 437 | str := cache_prefix 438 | str = append(str, []byte(self.cache_prefix)...) 439 | for index, field := range self.CacheFileds { 440 | for _, wh := range self.where { 441 | if wh.name == field { 442 | str = append(str, []byte(":")...) 443 | str = append(str, self.fieldToByte(wh.val)...) 444 | str = append(str, []byte(":"+self.CacheNames[index])...) 445 | goto NEXT 446 | } 447 | 448 | } 449 | str = append(str, []byte(":*:"+self.CacheNames[index])...) 450 | NEXT: 451 | } 452 | return string(str) 453 | } 454 | 455 | func (self *CacheModule) fieldToByte(value interface{}) (str []byte) { 456 | typ := reflect.TypeOf(value) 457 | val := reflect.ValueOf(value) 458 | 459 | switch typ.Kind() { 460 | case reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uint8, reflect.Uint16: 461 | if val.Uint() <= 0 { 462 | str = append(str, st...) 463 | } else { 464 | str = strconv.AppendUint(str, val.Uint(), 10) 465 | } 466 | case reflect.Int32, reflect.Int64, reflect.Int, reflect.Int8, reflect.Int16: 467 | if val.Int() <= 0 { 468 | str = append(str, st...) 469 | } else { 470 | str = strconv.AppendInt(str, val.Int(), 10) 471 | } 472 | case reflect.Float32, reflect.Float64: 473 | if val.Float() == 0.0 { 474 | str = append(str, st...) 475 | } else { 476 | str = strconv.AppendFloat(str, val.Float(), 'f', 0, 64) 477 | } 478 | case reflect.String: 479 | if val.Len() <= 0 { 480 | str = append(str, st...) 481 | } else { 482 | str = append(str, []byte(val.String())...) 483 | } 484 | case reflect.Bool: 485 | switch val.Bool() { 486 | case true: 487 | str = append(str, []byte("true")...) 488 | case false: 489 | str = append(str, []byte("false")...) 490 | } 491 | default: 492 | switch value.(type) { 493 | case time.Time: 494 | str = append(str, []byte(value.(time.Time).Format(time.RFC1123Z))...) 495 | } 496 | } 497 | return 498 | } 499 | 500 | func (self *CacheModule) key2Mode(key string) interface{} { 501 | typ := reflect.TypeOf(self.mode).Elem() 502 | val := reflect.New(typ).Elem() 503 | for i := 0; i < typ.NumField(); i++ { 504 | if b, err := self.Cache.Hget(key, typ.Field(i).Name); err == nil { 505 | switch val.Field(i).Kind() { 506 | case reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uint8, reflect.Uint16: 507 | id, _ := strconv.ParseUint(string(b), 10, 64) 508 | val.Field(i).SetUint(id) 509 | case reflect.Int32, reflect.Int64, reflect.Int, reflect.Int8, reflect.Int16: 510 | id, _ := strconv.ParseInt(string(b), 10, 64) 511 | val.Field(i).SetInt(id) 512 | case reflect.Float32, reflect.Float64: 513 | id, _ := strconv.ParseFloat(string(b), 64) 514 | val.Field(i).SetFloat(id) 515 | case reflect.String: 516 | val.Field(i).SetString(string(b)) 517 | case reflect.Bool: 518 | id, _ := strconv.ParseBool(string(b)) 519 | val.Field(i).SetBool(id) 520 | default: 521 | switch val.Field(i).Interface().(type) { 522 | case time.Time: 523 | //str = append(str, []byte(values.(time.Time).Format(time.RFC1123Z))...) 524 | if time, e := time.Parse(time.RFC1123Z, string(b)); e == nil { 525 | val.Field(i).Set(reflect.ValueOf(time)) 526 | } 527 | } 528 | } 529 | } 530 | } 531 | return val.Addr().Interface() 532 | } 533 | func (self CacheModule) saveToCache(mode Module) error { 534 | return CacheMode(mode).Ca(self.cache_address).SaveToCache() 535 | } 536 | 537 | func (self *CacheModule) SaveToCache() error { 538 | key := self.GetCacheKey() 539 | maping := map[string]interface{}{} 540 | vals := reflect.ValueOf(self.mode).Elem() 541 | typ := reflect.TypeOf(self.mode).Elem() 542 | for i := 0; i < vals.NumField(); i++ { 543 | field := typ.Field(i) 544 | if name := field.Tag.Get("field"); len(name) > 0 { 545 | if nocache := field.Tag.Get("no_cache"); len(nocache) == 0 { 546 | switch vals.Field(i).Interface().(type) { 547 | case time.Time: 548 | maping[field.Name] = vals.Field(i).Interface().(time.Time).Format(time.RFC1123Z) 549 | default: 550 | maping[field.Name] = vals.Field(i).Interface() 551 | } 552 | } 553 | } 554 | 555 | //补充一个仅存在于cache中的字段。 556 | if name := field.Tag.Get("cache_only_field"); len(name) > 0 { 557 | switch vals.Field(i).Interface().(type) { 558 | case time.Time: 559 | maping[field.Name] = vals.Field(i).Interface().(time.Time).Format(time.RFC1123Z) 560 | default: 561 | maping[field.Name] = vals.Field(i).Interface() 562 | } 563 | } 564 | } 565 | return self.Hmset(key, maping) 566 | } 567 | -------------------------------------------------------------------------------- /cache_test.go: -------------------------------------------------------------------------------- 1 | package orm 2 | 3 | import ( 4 | "testing" 5 | 6 | _ "github.com/go-sql-driver/mysql" 7 | ) 8 | 9 | type userB struct { 10 | CacheModule 11 | Uid int64 `field:"Id" index:"pk" cache:"user" ` 12 | Alias string `field:"Alias"` 13 | Lingshi int64 `field:"Lingshi" ` 14 | } 15 | 16 | func (self *userB) GetTableName() string { 17 | return "user_disk" 18 | } 19 | 20 | func Test_connect(t *testing.T) { 21 | 22 | CacheConsistent.Add("127.0.0.1:6379") 23 | 24 | _, err := NewDatabase("default", "mysql", "happy:passwd@tcp(127.0.0.1:3306)/mydatabase?charset=utf8") 25 | if err != nil { 26 | t.Error(err) 27 | } 28 | b := new(userB) 29 | b.Uid = 10000 30 | b.Objects(b).Ca(b.Uid).One() 31 | 32 | if err != nil { 33 | t.Error(err) 34 | } 35 | t.Log(b.Alias, b.Lingshi) 36 | b.Incrby("Lingshi", 10) 37 | b.Save() 38 | t.Log(b.Lingshi) 39 | } 40 | -------------------------------------------------------------------------------- /consistent.go: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2012 Numerotron Inc. 2 | // Use of this source code is governed by an MIT-style license 3 | // that can be found in the LICENSE file. 4 | 5 | // Package consistent provides a consistent hashing function. 6 | // 7 | // Consistent hashing is often used to distribute requests to a changing set of servers. For example, 8 | // say you have some cache servers cacheA, cacheB, and cacheC. You want to decide which cache server 9 | // to use to look up information on a user. 10 | // 11 | // You could use a typical hash table and hash the user id 12 | // to one of cacheA, cacheB, or cacheC. But with a typical hash table, if you add or remove a server, 13 | // almost all keys will get remapped to different results, which basically could bring your service 14 | // to a grinding halt while the caches get rebuilt. 15 | // 16 | // With a consistent hash, adding or removing a server drastically reduces the number of keys that 17 | // get remapped. 18 | // 19 | // Read more about consistent hashing on wikipedia: http://en.wikipedia.org/wiki/Consistent_hashing 20 | // 21 | package orm 22 | 23 | import ( 24 | "errors" 25 | "hash/crc32" 26 | "sort" 27 | "strconv" 28 | "sync" 29 | ) 30 | 31 | type uints []uint32 32 | 33 | // Len returns the length of the uints array. 34 | func (x uints) Len() int { return len(x) } 35 | 36 | // Less returns true if element i is less than element j. 37 | func (x uints) Less(i, j int) bool { return x[i] < x[j] } 38 | 39 | // Swap exchanges elements i and j. 40 | func (x uints) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 41 | 42 | // ErrEmptyCircle is the error returned when trying to get an element when nothing has been added to hash. 43 | var ErrEmptyCircle = errors.New("empty circle") 44 | 45 | // Consistent holds the information about the members of the consistent hash circle. 46 | type Consistent struct { 47 | circle map[uint32]string 48 | members map[string]bool 49 | sortedHashes uints 50 | NumberOfReplicas int 51 | count int64 52 | scratch [64]byte 53 | sync.RWMutex 54 | } 55 | 56 | // New creates a new Consistent object with a default setting of 20 replicas for each entry. 57 | // 58 | // To change the number of replicas, set NumberOfReplicas before adding entries. 59 | func NewConsistent() *Consistent { 60 | c := new(Consistent) 61 | c.NumberOfReplicas = 20 62 | c.circle = make(map[uint32]string) 63 | c.members = make(map[string]bool) 64 | return c 65 | } 66 | func (c Consistent) GetCircle() map[uint32]string { 67 | return c.circle 68 | } 69 | 70 | // eltKey generates a string key for an element with an index. 71 | func (c *Consistent) eltKey(elt string, idx int) string { 72 | return elt + "|" + strconv.Itoa(idx) 73 | } 74 | 75 | // Add inserts a string element in the consistent hash. 76 | func (c *Consistent) Add(elt string) { 77 | c.Lock() 78 | defer c.Unlock() 79 | for i := 0; i < c.NumberOfReplicas; i++ { 80 | c.circle[c.hashKey(c.eltKey(elt, i))] = elt 81 | } 82 | c.members[elt] = true 83 | c.updateSortedHashes() 84 | c.count++ 85 | } 86 | 87 | // Remove removes an element from the hash. 88 | func (c *Consistent) Remove(elt string) { 89 | c.Lock() 90 | defer c.Unlock() 91 | for i := 0; i < c.NumberOfReplicas; i++ { 92 | delete(c.circle, c.hashKey(c.eltKey(elt, i))) 93 | } 94 | delete(c.members, elt) 95 | c.updateSortedHashes() 96 | c.count-- 97 | } 98 | 99 | // Set sets all the elements in the hash. If there are existing elements not present in elts, they will be removed. 100 | func (c *Consistent) Set(elts []string) { 101 | mems := c.Members() 102 | for _, k := range mems { 103 | found := false 104 | for _, v := range elts { 105 | if k == v { 106 | found = true 107 | break 108 | } 109 | } 110 | if !found { 111 | c.Remove(k) 112 | } 113 | } 114 | for _, v := range elts { 115 | c.RLock() 116 | _, exists := c.members[v] 117 | c.RUnlock() 118 | if exists { 119 | continue 120 | } 121 | c.Add(v) 122 | } 123 | } 124 | 125 | func (c *Consistent) Members() []string { 126 | c.RLock() 127 | defer c.RUnlock() 128 | var m []string 129 | for k := range c.members { 130 | m = append(m, k) 131 | } 132 | return m 133 | } 134 | 135 | // Get returns an element close to where name hashes to in the circle. 136 | func (c *Consistent) Get(name string) (string, error) { 137 | c.RLock() 138 | defer c.RUnlock() 139 | if len(c.circle) == 0 { 140 | return "", ErrEmptyCircle 141 | } 142 | key := c.hashKey(name) 143 | i := c.search(key) 144 | return c.circle[c.sortedHashes[i]], nil 145 | } 146 | 147 | func (c *Consistent) search(key uint32) (i int) { 148 | f := func(x int) bool { 149 | return c.sortedHashes[x] > key 150 | } 151 | i = sort.Search(len(c.sortedHashes), f) 152 | if i >= len(c.sortedHashes) { 153 | i = 0 154 | } 155 | return 156 | } 157 | 158 | // GetTwo returns the two closest distinct elements to the name input in the circle. 159 | func (c *Consistent) GetTwo(name string) (string, string, error) { 160 | c.RLock() 161 | defer c.RUnlock() 162 | if len(c.circle) == 0 { 163 | return "", "", ErrEmptyCircle 164 | } 165 | key := c.hashKey(name) 166 | i := c.search(key) 167 | a := c.circle[c.sortedHashes[i]] 168 | 169 | if c.count == 1 { 170 | return a, "", nil 171 | } 172 | 173 | start := i 174 | var b string 175 | for i = start + 1; i != start; i++ { 176 | if i >= len(c.sortedHashes) { 177 | i = 0 178 | } 179 | b = c.circle[c.sortedHashes[i]] 180 | if b != a { 181 | break 182 | } 183 | } 184 | return a, b, nil 185 | } 186 | 187 | // GetN returns the N closest distinct elements to the name input in the circle. 188 | func (c *Consistent) GetN(name string, n int) ([]string, error) { 189 | c.RLock() 190 | defer c.RUnlock() 191 | 192 | if len(c.circle) == 0 { 193 | return nil, ErrEmptyCircle 194 | } 195 | 196 | if c.count < int64(n) { 197 | n = int(c.count) 198 | } 199 | 200 | var ( 201 | key = c.hashKey(name) 202 | i = c.search(key) 203 | start = i 204 | res = make([]string, 0, n) 205 | elem = c.circle[c.sortedHashes[i]] 206 | ) 207 | 208 | res = append(res, elem) 209 | 210 | if len(res) == n { 211 | return res, nil 212 | } 213 | 214 | for i = start + 1; i != start; i++ { 215 | if i >= len(c.sortedHashes) { 216 | i = 0 217 | } 218 | elem = c.circle[c.sortedHashes[i]] 219 | if !sliceContainsMember(res, elem) { 220 | res = append(res, elem) 221 | } 222 | if len(res) == n { 223 | break 224 | } 225 | } 226 | 227 | return res, nil 228 | } 229 | 230 | func (c *Consistent) hashKey(key string) uint32 { 231 | if len(key) < 64 { 232 | var scratch [64]byte 233 | copy(scratch[:], key) 234 | return crc32.ChecksumIEEE(scratch[:len(key)]) 235 | } 236 | return crc32.ChecksumIEEE([]byte(key)) 237 | } 238 | 239 | func (c *Consistent) updateSortedHashes() { 240 | hashes := c.sortedHashes[:0] 241 | //reallocate if we're holding on to too much (1/4th) 242 | if cap(c.sortedHashes)/(c.NumberOfReplicas*4) > len(c.circle) { 243 | hashes = nil 244 | } 245 | for k := range c.circle { 246 | hashes = append(hashes, k) 247 | } 248 | sort.Sort(hashes) 249 | c.sortedHashes = hashes 250 | } 251 | 252 | func sliceContainsMember(set []string, member string) bool { 253 | for _, m := range set { 254 | if m == member { 255 | return true 256 | } 257 | } 258 | return false 259 | } 260 | -------------------------------------------------------------------------------- /docs/mode.md: -------------------------------------------------------------------------------- 1 | 2 | ### 例子 3 | 4 | //引用模块 5 | import "github.com/ablegao/orm" 6 | 7 | //mysql 驱动 8 | import _ "github.com/go-sql-driver/mysql" 9 | 10 | //建立连接 11 | // 参数分别为 名称 , 驱动, 连接字符串 12 | // 注:必须包含一个default 连接, 作为默认连接。 13 | orm.NewDatabase("default" , "mysql" , "user:passwd@ip/database?charset=utf8") 14 | 15 | 16 | //建立一个数据模型。 17 | type UserInfo struct { 18 | orm.Object 19 | Id int64 `field:"id" index:"pk"` 20 | Name string `field:"username"` 21 | Passwd string `field:"password"` 22 | } 23 | 24 | //数据库表名称 25 | func(self *UserInfo) GetTableName()string{ 26 | 27 | return "database.user_info" 28 | } 29 | 30 | //查询一个用户名为 "test1"的账户 31 | user:=new(UserInfo) 32 | err:=user.Objects(user).Filter("Name","test1").One() 33 | fmt.Println(user.Id , user.Passwd , user.Name) 34 | 35 | //Update 36 | user.Name="test2" 37 | user.Objects(user).Save() 38 | // or 39 | user.Objects(user).Filter("Id" , 1).Change("Name" , "test2").Save() 40 | 41 | 42 | //查询id小于10的所有数据 43 | 44 | users , err:=user.Objects(user).Filter("Id__lt",10).All() 45 | if err == nil { 46 | for _,userinfo:= range users{ 47 | u:=userinfo.(*UserInfo) 48 | fmt.Println(u.Id , u.Passwd , u.Name) 49 | } 50 | } 51 | 52 | //Create 53 | user:=new(UserInfo) 54 | user.Name ="test1" 55 | user.Passwd ="123456" 56 | id , err:=user.Objects(user).Save() 57 | 58 | 59 | 60 | //delete 61 | user.Objects(user).Delete() 62 | 63 | // User other Database connect 64 | orm.NewDatabase("other" , "mysql" , "user:passwd@ip/database?charset=utf8") 65 | user.Objects(user).Db("other").Filter(x ,x).Delete() 66 | // or 67 | user.Objects(user).Filter().Db("other").XXX() 68 | 69 | ## Filter or FilterOr 70 | .Filter(fieldname , val ) 71 | 72 | Filter 作为orm 的主要作用是过滤查询条件, 最终将会转换为sql 语句中的where 条件语句。 可以填写多次, 多次数据为and 关系 73 | 74 | FilterOr 作为Orm 的主要过滤查询条件, 最终将妆化为sql 语句的where 条件语句 , 可以填写多次, 多次数据以 or 连接 75 | 76 | user.Objects(user).Filter("Name" , "test1").FilterOr("Name" , "test2").All() 77 | //select id,username,passwd from database.user_info where username='test1' or username='test2' 78 | 79 | ##关于Filter字段的魔法参数 80 | 81 | ###目前支持: 82 | __exact 精确等于 like 'aaa' 83 | __iexact 精确等于 忽略大小写 ilike 'aaa' 84 | __contains 包含 like '%aaa%' 85 | __icontains 包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。 86 | __gt 大于 87 | __gte 大于等于 88 | __ne 不等于 89 | __lt 小于 90 | __lte 小于等于 91 | __startswith 以...开头 92 | __istartswith 以...开头 忽略大小写 93 | __endswith 以...结尾 94 | __iendswith 以...结尾,忽略大小写 95 | 96 | ###尚未支持: 97 | __in 存在于一个list范围内 98 | __range 在...范围内 99 | __year 日期字段的年份 100 | __month 日期字段的月份 101 | __day 日期字段的日 102 | __isnull=True/False 103 | 104 | 105 | ##Change 106 | 107 | 修改数据, 执行时,相当于 sql 语句中的set 108 | 109 | 传入一个结构字段 和值 110 | .Change("Field" , 1) 111 | 112 | update from xxx set field=1 113 | 114 | 可以添加魔法参数: 115 | 116 | .Change("Field__add" ,1 ) 117 | update from xxx set field=field+1 118 | 119 | __add 累加 field=field+1 120 | __sub 累减 field=field-1 121 | __mult 累乘 field=field*1 122 | __div 累计出发 field=field/1 123 | -------------------------------------------------------------------------------- /logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ablegao/orm/4ec8d7d280bc87ba35be7140d2a13fd9d0f960c5/logo.jpg -------------------------------------------------------------------------------- /marsharl_driver_mysql.go: -------------------------------------------------------------------------------- 1 | package orm 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type MysqlModeToSql struct { 9 | Params ParamsInterface 10 | } 11 | 12 | func (self MysqlModeToSql) Instance(param ParamsInterface) { 13 | self.Params = param 14 | } 15 | 16 | /*where 17 | 18 | where 条件: 19 | __exact 精确等于 like 'aaa' 20 | __iexact 精确等于 忽略大小写 ilike 'aaa' 21 | __contains 包含 like '%aaa%' 22 | __icontains 包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。 23 | __gt 大于 24 | __gte 大于等于 25 | __ne 不等于 26 | __lt 小于 27 | __lte 小于等于 28 | __in 存在于一个list范围内 29 | __startswith 以...开头 30 | __istartswith 以...开头 忽略大小写 31 | __endswith 以...结尾 32 | __iendswith 以...结尾,忽略大小写 33 | __range 在...范围内 34 | __year 日期字段的年份 35 | __month 日期字段的月份 36 | __day 日期字段的日 37 | __isnull=True/False 38 | **/ 39 | func (self MysqlModeToSql) _w(a string) string { 40 | typ := "" 41 | if bb := strings.Split(a, "__"); len(bb) > 1 { 42 | a = bb[0] 43 | typ = strings.ToLower(bb[1]) 44 | } 45 | patten := "" 46 | switch typ { 47 | case "iexact": 48 | patten = "`%s` like '?'" 49 | case "exact": 50 | patten = "binary `%s` like '?' " 51 | case "contains": 52 | patten = "binary `%s` like '%?%'" 53 | case "icontains": 54 | patten = "`%s` like '%?%'" 55 | case "startswith": 56 | patten = "binary `%s` like '?%' " 57 | case "istartswith": 58 | patten = "`%s` like '?%' " 59 | case "endswith": 60 | patten = "binary `%s` like '%?' " 61 | case "iendswith": 62 | patten = "`%s` like '%?' " 63 | 64 | case "gt": 65 | patten = "`%s`>?" 66 | case "gte": 67 | patten = "`%s`>=?" 68 | case "lt": 69 | patten = "`%s`?" 74 | case "add": 75 | return fmt.Sprintf("`%s`=`%s`+?", a, a) 76 | case "sub": 77 | return fmt.Sprintf("`%s`=`%s`-?", a, a) 78 | case "mult": 79 | return fmt.Sprintf("`%s`=`%s`*?", a, a) 80 | case "div": 81 | return fmt.Sprintf("`%s`=`%s`/?", a, a) 82 | case "asc": 83 | patten = "`%s` ASC" 84 | case "desc": 85 | patten = "`%s` DESC" 86 | default: 87 | patten = "`%s`=?" 88 | } 89 | return fmt.Sprintf(patten, a) 90 | } 91 | func (self MysqlModeToSql) _where() (sql string, val []interface{}) { 92 | whereLen := self.Params.GetWhereLen() 93 | orLen := self.Params.GetOrLen() 94 | 95 | where := make([]string, whereLen) 96 | or := make([]string, orLen) 97 | 98 | val = make([]interface{}, whereLen+orLen) 99 | 100 | i := 0 101 | for _, w := range self.Params.GetWhere() { 102 | 103 | //where = append(where, self.Params._w(w.name)) 104 | where[i] = self._w(w.name) 105 | val[i] = w.val 106 | i = i + 1 107 | } 108 | 109 | for _, w := range self.Params.GetOr() { 110 | or[i] = self._w(w.name) 111 | val[i] = w.val 112 | i = i + 1 113 | } 114 | 115 | sql = "" 116 | switch { 117 | case whereLen > 0 && orLen > 0: 118 | sql = sql + " WHERE " + strings.Join(where, " AND ") + " OR " + strings.Join(or, " OR ") 119 | case whereLen > 0 && orLen == 0: 120 | sql = sql + " WHERE " + strings.Join(where, " AND ") 121 | case orLen > 0 && whereLen == 0: 122 | sql = sql + " WHERE " + strings.Join(or, " OR ") 123 | } 124 | return 125 | } 126 | func (self MysqlModeToSql) _set() (sql string, val []interface{}) { 127 | sets := self.Params.GetSet() 128 | l := len(sets) 129 | set := make([]string, l) 130 | val = make([]interface{}, l) 131 | for i, v := range sets { 132 | set[i] = self._w(v.name) 133 | val[i] = v.val 134 | } 135 | sql = " SET " + strings.Join(set, ",") 136 | return 137 | } 138 | func (self MysqlModeToSql) Insert() (sql string, val []interface{}) { 139 | sql, val = self._set() 140 | sql = fmt.Sprintf("INSERT INTO %s %s ", 141 | self.Params.GetTableName(), 142 | sql, 143 | ) 144 | return 145 | } 146 | func (self MysqlModeToSql) Update() (sql string, val []interface{}) { 147 | sql, val = self._set() 148 | sql = fmt.Sprintf("UPDATE %s %s ", 149 | self.Params.GetTableName(), 150 | sql, 151 | ) 152 | s, v := self._where() 153 | sql = sql + s 154 | val = append(val, v...) 155 | return 156 | } 157 | 158 | func (self MysqlModeToSql) Delete() (sql string, val []interface{}) { 159 | sql, val = self._where() 160 | 161 | sql = fmt.Sprintf("DELETE FROM %s %s ", 162 | self.Params.GetTableName(), 163 | sql, 164 | ) 165 | 166 | return 167 | } 168 | func (self MysqlModeToSql) Select() (sql string, val []interface{}) { 169 | 170 | sql, val = self._where() 171 | sql = fmt.Sprintf("SELECT `%s` FROM %s %s", 172 | strings.Join(self.Params.GetFields(), "`,`"), 173 | self.Params.GetTableName(), 174 | sql, 175 | ) 176 | order := self.Params.GetOrder() 177 | if len(order) > 0 { 178 | sql = sql + " ORDER BY " 179 | ret := make([]string, len(order)) 180 | for id, v := range order { 181 | ret[id] = self._w(v) 182 | } 183 | sql = sql + strings.Join(ret, ",") 184 | } 185 | limit := self.Params.GetLimit() 186 | if limit != NULL_LIMIT { 187 | 188 | sql = sql + fmt.Sprintf(" LIMIT %d , %d", (limit[0]-1)*limit[1], limit[1]) 189 | } 190 | 191 | return 192 | } 193 | func (self MysqlModeToSql) Count() (sql string, val []interface{}) { 194 | sql, val = self._where() 195 | sql = fmt.Sprintf("SELECT COUNT(*) FROM %s %s ", 196 | self.Params.GetTableName(), 197 | sql, 198 | ) 199 | return 200 | } 201 | -------------------------------------------------------------------------------- /marsharl_driver_postgres.go: -------------------------------------------------------------------------------- 1 | package orm 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | /* 9 | go get github.com/lib/pq 10 | 11 | import ( 12 | "github.com/ablegao/orm" 13 | _ "github.com/lib/pq" 14 | ) 15 | // http://godoc.org/github.com/lib/pq 16 | func main(){ 17 | orm.NewDatabase("default" ,"postgres" ,"user=pqgotest dbname=pqgotest sslmode=verify-full" ) 18 | } 19 | */ 20 | 21 | type PostgressModeToSql struct { 22 | Params ParamsInterface 23 | } 24 | 25 | func (self PostgressModeToSql) Instance(param ParamsInterface) { 26 | self.Params = param 27 | } 28 | 29 | /*where 30 | 31 | where 条件: 32 | __exact 精确等于 like 'aaa' 33 | __iexact 精确等于 忽略大小写 ilike 'aaa' 34 | __contains 包含 like '%aaa%' 35 | __icontains 包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。 36 | __gt 大于 37 | __gte 大于等于 38 | __ne 不等于 39 | __lt 小于 40 | __lte 小于等于 41 | __in 存在于一个list范围内 42 | __startswith 以...开头 43 | __istartswith 以...开头 忽略大小写 44 | __endswith 以...结尾 45 | __iendswith 以...结尾,忽略大小写 46 | __range 在...范围内 47 | __year 日期字段的年份 48 | __month 日期字段的月份 49 | __day 日期字段的日 50 | __isnull=True/False 51 | **/ 52 | func (self PostgressModeToSql) _w(a string) string { 53 | typ := "" 54 | if bb := strings.Split(a, "__"); len(bb) > 1 { 55 | a = bb[0] 56 | typ = strings.ToLower(bb[1]) 57 | } 58 | patten := "" 59 | switch typ { 60 | case "iexact": 61 | patten = "`%s` ilike '?'" 62 | case "exact": 63 | patten = "`%s` like '?' " 64 | case "contains": 65 | patten = "`%s` like '%?%'" 66 | case "icontains": 67 | patten = "`%s` ilike '%?%'" 68 | case "startswith": 69 | patten = "`%s` like '?%' " 70 | case "istartswith": 71 | patten = "`%s` ilike '?%' " 72 | case "endswith": 73 | patten = "`%s` like '%?' " 74 | case "iendswith": 75 | patten = "`%s` ilike '%?' " 76 | 77 | case "gt": 78 | patten = "`%s`>?" 79 | case "gte": 80 | patten = "`%s`>=?" 81 | case "lt": 82 | patten = "`%s`?" 87 | case "add": 88 | return fmt.Sprintf("`%s`=`%s`+?", a, a) 89 | case "sub": 90 | return fmt.Sprintf("`%s`=`%s`-?", a, a) 91 | case "mult": 92 | return fmt.Sprintf("`%s`=`%s`*?", a, a) 93 | case "div": 94 | return fmt.Sprintf("`%s`=`%s`/?", a, a) 95 | case "asc": 96 | patten = "`%s` ASC" 97 | case "desc": 98 | patten = "`%s` DESC" 99 | default: 100 | patten = "`%s`=?" 101 | } 102 | return fmt.Sprintf(patten, a) 103 | } 104 | func (self PostgressModeToSql) _where() (sql string, val []interface{}) { 105 | whereLen := self.Params.GetWhereLen() 106 | orLen := self.Params.GetOrLen() 107 | 108 | where := make([]string, whereLen) 109 | or := make([]string, orLen) 110 | 111 | val = make([]interface{}, whereLen+orLen) 112 | 113 | i := 0 114 | for _, w := range self.Params.GetWhere() { 115 | 116 | //where = append(where, self.Params._w(w.name)) 117 | where[i] = self._w(w.name) 118 | val[i] = w.val 119 | i = i + 1 120 | } 121 | 122 | for _, w := range self.Params.GetOr() { 123 | or[i] = self._w(w.name) 124 | val[i] = w.val 125 | i = i + 1 126 | } 127 | 128 | sql = "" 129 | switch { 130 | case whereLen > 0 && orLen > 0: 131 | sql = sql + " WHERE " + strings.Join(where, " AND ") + " OR " + strings.Join(or, " OR ") 132 | case whereLen > 0 && orLen == 0: 133 | sql = sql + " WHERE " + strings.Join(where, " AND ") 134 | case orLen > 0 && whereLen == 0: 135 | sql = sql + " WHERE " + strings.Join(or, " OR ") 136 | } 137 | return 138 | } 139 | func (self PostgressModeToSql) _set() (sql string, val []interface{}) { 140 | sets := self.Params.GetSet() 141 | l := len(sets) 142 | set := make([]string, l) 143 | val = make([]interface{}, l) 144 | for i, v := range sets { 145 | set[i] = self._w(v.name) 146 | val[i] = v.val 147 | } 148 | sql = " SET " + strings.Join(set, ",") 149 | return 150 | } 151 | func (self PostgressModeToSql) Insert() (sql string, val []interface{}) { 152 | sql, val = self._set() 153 | sql = fmt.Sprintf("INSERT INTO %s %s ", 154 | self.Params.GetTableName(), 155 | sql, 156 | ) 157 | return 158 | } 159 | func (self PostgressModeToSql) Update() (sql string, val []interface{}) { 160 | sql, val = self._set() 161 | sql = fmt.Sprintf("UPDATE %s %s ", 162 | self.Params.GetTableName(), 163 | sql, 164 | ) 165 | s, v := self._where() 166 | sql = sql + s 167 | val = append(val, v...) 168 | return 169 | } 170 | 171 | func (self PostgressModeToSql) Delete() (sql string, val []interface{}) { 172 | sql, val = self._where() 173 | 174 | sql = fmt.Sprintf("DELETE FROM %s %s ", 175 | self.Params.GetTableName(), 176 | sql, 177 | ) 178 | 179 | return 180 | } 181 | func (self PostgressModeToSql) Select() (sql string, val []interface{}) { 182 | 183 | sql, val = self._where() 184 | sql = fmt.Sprintf("SELECT `%s` FROM %s %s", 185 | strings.Join(self.Params.GetFields(), "`,`"), 186 | self.Params.GetTableName(), 187 | sql, 188 | ) 189 | order := self.Params.GetOrder() 190 | if len(order) > 0 { 191 | sql = sql + " ORDER BY " 192 | ret := make([]string, len(order)) 193 | for id, v := range order { 194 | ret[id] = self._w(v) 195 | } 196 | sql = sql + strings.Join(ret, ",") 197 | } 198 | limit := self.Params.GetLimit() 199 | if limit != NULL_LIMIT { 200 | 201 | sql = sql + fmt.Sprintf(" LIMIT %d OFFSET %d", limit[1], (limit[0]-1)*limit[1]) 202 | } 203 | 204 | return 205 | } 206 | func (self PostgressModeToSql) Count() (sql string, val []interface{}) { 207 | sql, val = self._where() 208 | sql = fmt.Sprintf("SELECT COUNT(*) FROM %s %s ", 209 | self.Params.GetTableName(), 210 | sql, 211 | ) 212 | return 213 | } 214 | -------------------------------------------------------------------------------- /marsharl_driver_sql.go: -------------------------------------------------------------------------------- 1 | package orm 2 | 3 | type driversqlType func(param ParamsInterface) ModuleToSql 4 | 5 | var driversql = map[string]driversqlType{ 6 | "mysql": func(param ParamsInterface) ModuleToSql { return MysqlModeToSql{param} }, 7 | "sqlite": func(param ParamsInterface) ModuleToSql { return SqliteModeToSql{param} }, 8 | } 9 | 10 | func NewMarsharlDriverSql(driverName string, fun driversqlType) { 11 | driversql[driverName] = fun 12 | } 13 | 14 | type ModuleToSql interface { 15 | Select() (sql string, val []interface{}) 16 | Delete() (sql string, val []interface{}) 17 | Update() (sql string, val []interface{}) 18 | Insert() (sql string, val []interface{}) 19 | Count() (sql string, val []interface{}) 20 | Instance(ParamsInterface) 21 | } 22 | -------------------------------------------------------------------------------- /marsharl_driver_sqlite.go: -------------------------------------------------------------------------------- 1 | package orm 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type SqliteModeToSql struct { 9 | Params ParamsInterface 10 | } 11 | 12 | func (self SqliteModeToSql) Instance(param ParamsInterface) { 13 | self.Params = param 14 | } 15 | 16 | /*where 17 | 18 | where 条件: 19 | __exact 精确等于 like 'aaa' 20 | __iexact 精确等于 忽略大小写 ilike 'aaa' 21 | __contains 包含 like '%aaa%' 22 | __icontains 包含 忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。 23 | __gt 大于 24 | __gte 大于等于 25 | __ne 不等于 26 | __lt 小于 27 | __lte 小于等于 28 | __in 存在于一个list范围内 29 | __startswith 以...开头 30 | __istartswith 以...开头 忽略大小写 31 | __endswith 以...结尾 32 | __iendswith 以...结尾,忽略大小写 33 | __range 在...范围内 34 | __year 日期字段的年份 35 | __month 日期字段的月份 36 | __day 日期字段的日 37 | __isnull=True/False 38 | **/ 39 | func (self SqliteModeToSql) _w(a string) string { 40 | typ := "" 41 | if bb := strings.Split(a, "__"); len(bb) > 1 { 42 | a = bb[0] 43 | typ = strings.ToLower(bb[1]) 44 | } 45 | patten := "" 46 | switch typ { 47 | case "iexact": 48 | patten = "`%s` like '?'" 49 | case "exact": 50 | patten = "binary `%s` like '?' " 51 | case "contains": 52 | patten = "binary `%s` like '%?%'" 53 | case "icontains": 54 | patten = "`%s` like '%?%'" 55 | case "startswith": 56 | patten = "binary `%s` like '?%' " 57 | case "istartswith": 58 | patten = "`%s` like '?%' " 59 | case "endswith": 60 | patten = "binary `%s` like '%?' " 61 | case "iendswith": 62 | patten = "`%s` like '%?' " 63 | 64 | case "gt": 65 | patten = "`%s`>?" 66 | case "gte": 67 | patten = "`%s`>=?" 68 | case "lt": 69 | patten = "`%s`?" 74 | case "add": 75 | return fmt.Sprintf("`%s`=`%s`+?", a, a) 76 | case "sub": 77 | return fmt.Sprintf("`%s`=`%s`-?", a, a) 78 | case "mult": 79 | return fmt.Sprintf("`%s`=`%s`*?", a, a) 80 | case "div": 81 | return fmt.Sprintf("`%s`=`%s`/?", a, a) 82 | case "asc": 83 | patten = "`%s` ASC" 84 | case "desc": 85 | patten = "`%s` DESC" 86 | default: 87 | patten = "`%s`=?" 88 | } 89 | return fmt.Sprintf(patten, a) 90 | } 91 | func (self SqliteModeToSql) _where() (sql string, val []interface{}) { 92 | whereLen := self.Params.GetWhereLen() 93 | orLen := self.Params.GetOrLen() 94 | 95 | where := make([]string, whereLen) 96 | or := make([]string, orLen) 97 | 98 | val = make([]interface{}, whereLen+orLen) 99 | 100 | i := 0 101 | for _, w := range self.Params.GetWhere() { 102 | 103 | //where = append(where, self.Params._w(w.name)) 104 | where[i] = self._w(w.name) 105 | val[i] = w.val 106 | i = i + 1 107 | } 108 | 109 | for _, w := range self.Params.GetOr() { 110 | or[i] = self._w(w.name) 111 | val[i] = w.val 112 | i = i + 1 113 | } 114 | 115 | sql = "" 116 | switch { 117 | case whereLen > 0 && orLen > 0: 118 | sql = sql + " WHERE " + strings.Join(where, " AND ") + " OR " + strings.Join(or, " OR ") 119 | case whereLen > 0 && orLen == 0: 120 | sql = sql + " WHERE " + strings.Join(where, " AND ") 121 | case orLen > 0 && whereLen == 0: 122 | sql = sql + " WHERE " + strings.Join(or, " OR ") 123 | } 124 | return 125 | } 126 | func (self SqliteModeToSql) _set() (sql string, val []interface{}) { 127 | sets := self.Params.GetSet() 128 | l := len(sets) 129 | set := make([]string, l) 130 | val = make([]interface{}, l) 131 | for i, v := range sets { 132 | set[i] = self._w(v.name) 133 | val[i] = v.val 134 | } 135 | sql = " SET " + strings.Join(set, ",") 136 | return 137 | } 138 | func (self SqliteModeToSql) Insert() (sql string, val []interface{}) { 139 | sql, val = self._set() 140 | sql = fmt.Sprintf("INSERT INTO %s %s ", 141 | self.Params.GetTableName(), 142 | sql, 143 | ) 144 | return 145 | } 146 | func (self SqliteModeToSql) Update() (sql string, val []interface{}) { 147 | sql, val = self._set() 148 | sql = fmt.Sprintf("UPDATE %s %s ", 149 | self.Params.GetTableName(), 150 | sql, 151 | ) 152 | s, v := self._where() 153 | sql = sql + s 154 | val = append(val, v...) 155 | return 156 | } 157 | 158 | func (self SqliteModeToSql) Delete() (sql string, val []interface{}) { 159 | sql, val = self._where() 160 | 161 | sql = fmt.Sprintf("DELETE FROM %s %s ", 162 | self.Params.GetTableName(), 163 | sql, 164 | ) 165 | 166 | return 167 | } 168 | func (self SqliteModeToSql) Select() (sql string, val []interface{}) { 169 | 170 | sql, val = self._where() 171 | sql = fmt.Sprintf("SELECT `%s` FROM %s %s", 172 | strings.Join(self.Params.GetFields(), "`,`"), 173 | self.Params.GetTableName(), 174 | sql, 175 | ) 176 | order := self.Params.GetOrder() 177 | if len(order) > 0 { 178 | sql = sql + " ORDER BY " 179 | ret := make([]string, len(order)) 180 | for id, v := range order { 181 | ret[id] = self._w(v) 182 | } 183 | sql = sql + strings.Join(ret, ",") 184 | } 185 | limit := self.Params.GetLimit() 186 | if limit != NULL_LIMIT { 187 | 188 | sql = sql + fmt.Sprintf(" LIMIT %d OFFSET %d", limit[1], (limit[0]-1)*limit[1]) 189 | } 190 | 191 | return 192 | } 193 | func (self SqliteModeToSql) Count() (sql string, val []interface{}) { 194 | sql, val = self._where() 195 | sql = fmt.Sprintf("SELECT COUNT(*) FROM %s %s ", 196 | self.Params.GetTableName(), 197 | sql, 198 | ) 199 | return 200 | } 201 | -------------------------------------------------------------------------------- /mode.go: -------------------------------------------------------------------------------- 1 | // model解析支持 2 | 3 | package orm 4 | 5 | import ( 6 | "errors" 7 | "reflect" 8 | "strings" 9 | "sync" 10 | "time" 11 | ) 12 | 13 | type Module interface { 14 | GetTableName() string 15 | } 16 | 17 | func Objects(mode Module) Object { 18 | 19 | typ := reflect.TypeOf(mode).Elem() 20 | vals := []string{} 21 | for i := 0; i < typ.NumField(); i++ { 22 | if field := typ.Field(i).Tag.Get("field"); len(field) > 0 { 23 | vals = append(vals, field) 24 | } 25 | } 26 | 27 | obj := Object{} 28 | obj.SetTable(mode.GetTableName()) 29 | obj.mode = mode 30 | obj.Params.Init() 31 | obj.Params.SetField(vals...) 32 | return obj 33 | } 34 | 35 | type Object struct { 36 | sync.RWMutex 37 | Params 38 | mode Module 39 | } 40 | 41 | func (self *Object) Objects(mode Module) *Object { 42 | self.Lock() 43 | defer self.Unlock() 44 | self.SetTable(mode.GetTableName()) 45 | self.Init() 46 | 47 | typ := reflect.TypeOf(mode).Elem() 48 | vals := []string{} 49 | for i := 0; i < typ.NumField(); i++ { 50 | if field := typ.Field(i).Tag.Get("field"); len(field) > 0 { 51 | vals = append(vals, field) 52 | } 53 | } 54 | self.SetField(vals...) 55 | self.mode = mode 56 | return self 57 | } 58 | 59 | //修改数据 60 | // name 结构字段名称 61 | // val 结构数据 62 | func (self *Object) Change(name string, val interface{}) *Object { 63 | self.Lock() 64 | defer self.Unlock() 65 | typ := reflect.TypeOf(self.mode).Elem() 66 | fieldName := strings.Split(name, "__") 67 | if field, ok := typ.FieldByName(fieldName[0]); ok && len(field.Tag.Get("field")) > 0 { 68 | name := field.Tag.Get("field") 69 | if len(fieldName) > 1 { 70 | name = name + "__" + fieldName[1] 71 | } 72 | self.Params.Change(name, val) 73 | } 74 | return self 75 | } 76 | 77 | //条件筛选 78 | // name 结构字段名称 79 | // val 需要过滤的数据值 80 | func (self *Object) Filter(name string, val interface{}) *Object { 81 | self.Lock() 82 | defer self.Unlock() 83 | typ := reflect.TypeOf(self.mode).Elem() 84 | fieldName := strings.Split(name, "__") 85 | if field, ok := typ.FieldByName(fieldName[0]); ok && len(field.Tag.Get("field")) > 0 { 86 | name := field.Tag.Get("field") 87 | if len(fieldName) > 1 { 88 | name = name + "__" + fieldName[1] 89 | } 90 | self.Params.Filter(name, val) 91 | } 92 | return self 93 | } 94 | func (self *Object) FilterOr(name string, val interface{}) *Object { 95 | self.Lock() 96 | defer self.Unlock() 97 | typ := reflect.TypeOf(self.mode).Elem() 98 | fieldName := strings.Split(name, "__") 99 | if field, ok := typ.FieldByName(fieldName[0]); ok && len(field.Tag.Get("field")) > 0 { 100 | name := field.Tag.Get("field") 101 | if len(fieldName) > 1 { 102 | name = name + "__" + fieldName[1] 103 | } 104 | self.Params.FilterOr(name, val) 105 | } 106 | return self 107 | } 108 | 109 | // Filter 的一次传入版本 , 不建议使用 , 因为map 循序不可控 110 | func (self *Object) Filters(filters map[string]interface{}) *Object { 111 | self.Lock() 112 | defer self.Unlock() 113 | for k, v := range filters { 114 | self.Filter(k, v) 115 | } 116 | return self 117 | } 118 | 119 | // Order by 排序 , 120 | // Field__asc Field__desc 121 | func (self *Object) Orderby(names ...string) *Object { 122 | typ := reflect.TypeOf(self.mode).Elem() 123 | for i, name := range names { 124 | fieldName := strings.Split(name, "__") 125 | if field, ok := typ.FieldByName(fieldName[0]); ok && len(field.Tag.Get("field")) > 0 { 126 | if name = field.Tag.Get("field"); len(name) > 0 { 127 | name = name + "__" + fieldName[1] 128 | names[i] = name 129 | } 130 | } 131 | } 132 | self.Params.order = names 133 | return self 134 | } 135 | 136 | // 分页支持 137 | func (self *Object) Limit(page, steq int) *Object { 138 | self.Lock() 139 | defer self.Unlock() 140 | self.Params.limit = [2]int{page, steq} 141 | return self 142 | } 143 | 144 | //选择数据库 145 | func (self *Object) Db(name string) *Object { 146 | self.Params.Db(name) 147 | return self 148 | } 149 | 150 | // 计算数量 151 | func (self *Object) Count() (int64, error) { 152 | self.RLock() 153 | defer self.RUnlock() 154 | return self.Params.Count() 155 | } 156 | 157 | //删除数据 158 | func (self *Object) Delete() (int64, error) { 159 | self.Lock() 160 | defer self.Unlock() 161 | valus := reflect.ValueOf(self.mode).Elem() 162 | for i := 0; i < valus.NumField(); i++ { 163 | typ := valus.Type().Field(i) 164 | val := valus.Field(i) 165 | if typ.Tag.Get("index") == "pk" { 166 | switch val.Kind() { 167 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 168 | if val.Int() > 0 { 169 | self.Params.Filter(typ.Name, val.Int()) 170 | } 171 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 172 | if val.Uint() > 0 { 173 | self.Params.Filter(typ.Name, val.Uint()) 174 | } 175 | case reflect.Float32, reflect.Float64: 176 | if val.Float() > 0.0 { 177 | self.Params.Filter(typ.Tag.Get("field"), val.Float()) 178 | } 179 | case reflect.String: 180 | if len(val.String()) > 0 { 181 | self.Params.Filter(typ.Tag.Get("field"), val.String()) 182 | } 183 | default: 184 | switch val.Interface().(type) { 185 | case time.Time: 186 | self.Params.Filter(typ.Tag.Get("field"), val.Interface()) 187 | } 188 | } 189 | } 190 | } 191 | if len(self.Params.where) > 0 { 192 | res, err := self.Params.Delete() 193 | if err != nil { 194 | return 0, err 195 | } 196 | return res.RowsAffected() 197 | } else { 198 | return 0, errors.New("No Where") 199 | } 200 | 201 | } 202 | 203 | //更新活添加 204 | func (self *Object) Save() (bool, int64, error) { 205 | self.Lock() 206 | defer self.Unlock() 207 | valus := reflect.ValueOf(self.mode).Elem() 208 | if len(self.Params.set) == 0 { 209 | for i := 0; i < valus.NumField(); i++ { 210 | typ := valus.Type().Field(i) 211 | val := valus.Field(i) 212 | if self.hasRow { 213 | if len(typ.Tag.Get("field")) > 0 && typ.Tag.Get("index") != "pk" { 214 | self.Params.Change(typ.Tag.Get("field"), val.Interface()) 215 | } 216 | } else { 217 | if len(typ.Tag.Get("field")) > 0 { 218 | self.Params.Change(typ.Tag.Get("field"), val.Interface()) 219 | } 220 | } 221 | } 222 | } 223 | 224 | self.autoWhere() 225 | isNew, id, err := self.Params.Save() 226 | return isNew, id, err 227 | } 228 | 229 | func (self *Object) autoWhere() { 230 | valus := reflect.ValueOf(self.mode).Elem() 231 | if len(self.Params.where) == 0 { 232 | for i := 0; i < valus.NumField(); i++ { 233 | typ := valus.Type().Field(i) 234 | val := valus.Field(i) 235 | if len(typ.Tag.Get("field")) > 0 && typ.Tag.Get("index") == "pk" { 236 | switch val.Kind() { 237 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 238 | if val.Int() > 0 { 239 | self.Params.Filter(typ.Tag.Get("field"), val.Int()) 240 | } 241 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 242 | if val.Uint() > 0 { 243 | self.Params.Filter(typ.Tag.Get("field"), val.Uint()) 244 | } 245 | case reflect.Float32, reflect.Float64: 246 | if val.Float() > 0.0 { 247 | self.Params.Filter(typ.Tag.Get("field"), val.Float()) 248 | } 249 | case reflect.String: 250 | if len(val.String()) > 0 { 251 | self.Params.Filter(typ.Tag.Get("field"), val.String()) 252 | } 253 | default: 254 | switch val.Interface().(type) { 255 | case time.Time: 256 | self.Params.Filter(typ.Tag.Get("field"), val.Interface()) 257 | } 258 | 259 | } 260 | } 261 | } 262 | } 263 | 264 | } 265 | 266 | //查找数据 267 | func (self *Object) All() ([]interface{}, error) { 268 | self.Lock() 269 | defer self.Unlock() 270 | self.autoWhere() 271 | if rows, err := self.Params.All(); err == nil { 272 | defer rows.Close() 273 | 274 | ret := []interface{}{} 275 | val := []interface{}{} 276 | 277 | for rows.Next() { 278 | m := reflect.New(reflect.TypeOf(self.mode).Elem()).Elem() 279 | val = val[len(val):] 280 | for i := 0; i < m.NumField(); i++ { 281 | if name := m.Type().Field(i).Tag.Get("field"); len(name) > 0 { 282 | val = append(val, m.Field(i).Addr().Interface()) 283 | } 284 | } 285 | 286 | rows.Scan(val...) 287 | ret = append(ret, m.Addr().Interface()) 288 | } 289 | return ret, err 290 | } else { 291 | return nil, err 292 | } 293 | 294 | } 295 | 296 | //提取一个数据 297 | func (self *Object) One() error { 298 | self.RLock() 299 | defer self.RUnlock() 300 | self.autoWhere() 301 | valMode := reflect.ValueOf(self.mode).Elem() 302 | typeMode := reflect.TypeOf(self.mode).Elem() 303 | vals := []interface{}{} 304 | for i := 0; i < valMode.NumField(); i++ { 305 | if name := typeMode.Field(i).Tag.Get("field"); len(name) > 0 { 306 | //vals[i] = valMode.Field(i).Addr().Interface() 307 | vals = append(vals, valMode.Field(i).Addr().Interface()) 308 | } 309 | } 310 | err := self.Params.One(vals...) 311 | if err == nil { 312 | self.where = self.where[len(self.where):] 313 | return nil 314 | } else { 315 | return err 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /params.go: -------------------------------------------------------------------------------- 1 | package orm 2 | 3 | import ( 4 | "database/sql" 5 | "fmt" 6 | "strings" 7 | ) 8 | 9 | var NULL_LIMIT = [2]int{0, 0} 10 | var databases = map[string]*Database{} 11 | 12 | type Database struct { 13 | *sql.DB 14 | Name string 15 | DriverName string 16 | DataSourceName string 17 | } 18 | 19 | func (self *Database) Conn() (err error) { 20 | self.DB, err = sql.Open(self.DriverName, self.DataSourceName) 21 | 22 | return 23 | } 24 | 25 | func NewDatabase(name, driverName, dataSourceName string) (database *Database, err error) { 26 | if database, ok := databases[name]; !ok { 27 | database = new(Database) 28 | database.Name = name 29 | database.DriverName = driverName 30 | database.DataSourceName = dataSourceName 31 | databases[name] = database 32 | err = database.Conn() 33 | } else { 34 | err = database.Ping() 35 | } 36 | return 37 | } 38 | 39 | type ParmaField struct { 40 | name string 41 | val interface{} 42 | } 43 | 44 | type ParamsInterface interface { 45 | GetOrLen() int 46 | GetWhereLen() int 47 | GetSetLen() int 48 | GetOr() []ParmaField 49 | GetWhere() []ParmaField 50 | GetSet() []ParmaField 51 | GetFields() []string 52 | GetOrder() []string 53 | GetLimit() [2]int 54 | GetTableName() string 55 | } 56 | 57 | /** 58 | 传参解析 59 | **/ 60 | type Params struct { 61 | connname string 62 | tbname string 63 | where []ParmaField 64 | or []ParmaField 65 | set []ParmaField 66 | fields []string 67 | order []string 68 | limit [2]int 69 | insertsql string 70 | hasRow bool 71 | } 72 | 73 | func (self Params) GetWhereLen() int { 74 | return len(self.where) 75 | } 76 | func (self Params) GetOrLen() int { 77 | return len(self.or) 78 | } 79 | func (self Params) GetSetLen() int { 80 | return len(self.set) 81 | } 82 | 83 | func (self Params) GetWhere() []ParmaField { 84 | return self.where 85 | } 86 | func (self Params) GetOr() []ParmaField { 87 | return self.or 88 | } 89 | func (self Params) GetSet() []ParmaField { 90 | return self.set 91 | } 92 | 93 | func (self Params) GetFields() []string { 94 | return self.fields 95 | } 96 | func (self Params) GetOrder() []string { 97 | return self.order 98 | } 99 | func (self Params) GetLimit() [2]int { 100 | return self.limit 101 | } 102 | func (self *Params) Init() { 103 | if len(self.connname) == 0 { 104 | self.connname = "default" 105 | } 106 | self.hasRow = false 107 | self.where = self.where[len(self.where):] 108 | self.or = self.or[len(self.or):] 109 | 110 | self.set = self.set[len(self.set):] 111 | self.fields = self.fields[len(self.fields):] 112 | self.order = self.order[len(self.order):] 113 | } 114 | 115 | func (self *Params) SetTable(tbname string) { 116 | self.tbname = tbname 117 | 118 | } 119 | 120 | func (self *Params) SetField(fields ...string) { 121 | self.fields = fields 122 | } 123 | 124 | func (self *Params) Filter(name string, val interface{}) *Params { 125 | self.where = append(self.where, ParmaField{name, val}) 126 | return self 127 | } 128 | func (self *Params) FilterOr(name string, val interface{}) *Params { 129 | self.or = append(self.or, ParmaField{name, val}) 130 | return self 131 | } 132 | 133 | // 添加修改 134 | func (self *Params) Change(name string, val interface{}) { 135 | self.set = append(self.set, ParmaField{name, val}) 136 | } 137 | func (self *Params) Limit(page, step int) *Params { 138 | self.limit[0] = page 139 | self.limit[1] = step 140 | return self 141 | } 142 | func (self *Params) All() (rows *sql.Rows, err error) { 143 | //rows, err = self.db.Query(self.execSelect()) 144 | // self.stmt, err = self.db.Prepare() 145 | if db, ok := databases[self.connname]; !ok { 146 | panic("Database " + self.connname + " not defined.") 147 | return 148 | } else { 149 | 150 | sqls, val := driversql[db.DriverName](*self).Select() 151 | if debug_sql { 152 | Debug.Println("select all ", sqls, val) 153 | } 154 | rows, err = db.Query(sqls, val...) 155 | if err != nil { 156 | panic(err) 157 | } 158 | } 159 | 160 | return 161 | } 162 | func (self *Params) Db(name string) *Params { 163 | self.connname = name 164 | return self 165 | } 166 | func (self *Params) One(vals ...interface{}) error { 167 | //rows, err = self.db.Query(self.execSelect()) 168 | // self.stmt, err = self.db.Prepare() 169 | if db, ok := databases[self.connname]; ok { 170 | sqls, val := driversql[db.DriverName](self).Select() 171 | if debug_sql { 172 | Debug.Println("select One ", sqls, val) 173 | } 174 | err := db.QueryRow(sqls, val...).Scan(vals...) 175 | switch { 176 | case err == sql.ErrNoRows: 177 | return err 178 | case err != nil: 179 | return err 180 | default: 181 | self.hasRow = true 182 | } 183 | } 184 | return nil 185 | } 186 | func (self *Params) Delete() (res sql.Result, err error) { 187 | var stmt *sql.Stmt 188 | if db, ok := databases[self.connname]; ok { 189 | 190 | sqls, val := driversql[db.DriverName](*self).Delete() 191 | if debug_sql { 192 | Debug.Println("delete ", sqls, val) 193 | } 194 | stmt, err = db.Prepare(sqls) 195 | if err == nil { 196 | defer stmt.Close() 197 | } 198 | res, err = stmt.Exec(val...) 199 | if err != nil { 200 | panic(err) 201 | } 202 | } else { 203 | panic("Database " + self.connname + " not defined.") 204 | } 205 | return 206 | } 207 | 208 | func (self *Params) Count() (int64, error) { 209 | if db, ok := databases[self.connname]; ok { 210 | sqls, val := driversql[db.DriverName](*self).Count() 211 | if debug_sql { 212 | Debug.Println("count ", sqls, val) 213 | } 214 | row := db.QueryRow(sqls, val...) 215 | 216 | var c int64 217 | if err := row.Scan(&c); err == nil { 218 | return c, nil 219 | } else { 220 | return 0, err 221 | } 222 | } else { 223 | panic("Database " + self.connname + " not defined.") 224 | } 225 | 226 | return 0, nil 227 | } 228 | 229 | func (self *Params) Save() (bool, int64, error) { 230 | db, ok := databases[self.connname] 231 | if !ok { 232 | panic("Database " + self.connname + " not defined.") 233 | } 234 | defer func() { 235 | self.set = self.set[len(self.set):] 236 | }() 237 | var err error 238 | var stmt *sql.Stmt 239 | var res sql.Result 240 | //var n int64 241 | //if n , err= self.Count();err == nil && n >0 242 | if self.hasRow { 243 | sqls, val := driversql[db.DriverName](*self).Update() 244 | if debug_sql { 245 | Debug.Println("save update ", sqls, val) 246 | } 247 | stmt, err = db.Prepare(sqls) 248 | if err == nil { 249 | defer stmt.Close() 250 | } else { 251 | return false, 0, err 252 | } 253 | res, err = stmt.Exec(val...) 254 | 255 | if err != nil { 256 | return false, 0, err 257 | } 258 | a, b := res.RowsAffected() 259 | return false, a, b 260 | } else { 261 | sqls, val := driversql[db.DriverName](*self).Insert() 262 | if debug_sql { 263 | Debug.Println("save insert ", sqls, val) 264 | } 265 | stmt, err = db.Prepare(sqls) 266 | if err == nil { 267 | defer stmt.Close() 268 | } else { 269 | panic(err) 270 | } 271 | res, err = stmt.Exec(val...) 272 | if err != nil { 273 | return true, 0, err 274 | } 275 | a, b := res.LastInsertId() 276 | self.hasRow = true 277 | return true, a, b 278 | } 279 | 280 | } 281 | 282 | func (self Params) GetTableName() string { 283 | tbname := "" 284 | if tb := strings.Split(self.tbname, "."); len(tb) > 1 { 285 | tbname = fmt.Sprintf("`%s`.`%s`", tb[0], tb[1]) 286 | } else { 287 | tbname = "`" + self.tbname + "`" 288 | } 289 | return tbname 290 | } 291 | -------------------------------------------------------------------------------- /params_test.go: -------------------------------------------------------------------------------- 1 | package orm 2 | 3 | import "testing" 4 | 5 | func Test_execSelect(t *testing.T) { 6 | params := Params{} 7 | params.SetField("a", "b", "c") 8 | params.SetTable("abc.def") 9 | 10 | params.Filter("field__gt", 1) 11 | params.Filter("bbb__lt", 2) 12 | params.Change("a", 1) 13 | params.Change("b__sub", 1) 14 | params.Change("c__div", 1) 15 | //t.Log(params.execSelect()) 16 | str, _ := driversql["mysql"](params).Select() 17 | t.Log(str) 18 | str, _ = driversql["mysql"](params).Delete() 19 | t.Log(str) 20 | str, _ = driversql["mysql"](params).Insert() 21 | t.Log(str) 22 | str, _ = driversql["mysql"](params).Update() 23 | t.Log(str) 24 | str, _ = driversql["mysql"](params).Count() 25 | t.Log(str) 26 | } 27 | -------------------------------------------------------------------------------- /redis.go: -------------------------------------------------------------------------------- 1 | package orm 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/hoisie/redis" 7 | ) 8 | 9 | var CacheConsistent = NewConsistent() 10 | 11 | var ( 12 | getRedis = make(chan *comandGetRedisConn) 13 | 14 | updateRedis = make(chan []string) 15 | RedisServer = map[string]*redis.Client{} 16 | ) 17 | 18 | //获取目标地址的功能 19 | type comandGetRedisConn struct { 20 | Key string 21 | Call chan *redis.Client 22 | } 23 | 24 | func init() { 25 | go goRedisRuntime() 26 | 27 | } 28 | 29 | //守护服务 30 | func goRedisRuntime() { 31 | for { 32 | select { 33 | case mapping := <-updateRedis: 34 | CacheConsistent.Set(mapping) 35 | case t := <-getRedis: 36 | addr, err := getRedisAddrByKey(t.Key) 37 | if err != nil { 38 | t.Call <- nil 39 | return 40 | } 41 | 42 | client, ok := RedisServer[addr] 43 | if !ok { 44 | client = new(redis.Client) 45 | client.Addr = addr 46 | client.Db = cache_db 47 | client.MaxPoolSize = 8 48 | RedisServer[addr] = client 49 | } 50 | t.Call <- client 51 | 52 | } 53 | } 54 | } 55 | 56 | //通过一致性hash服务, 得到当前key应该分配给哪个redis服务器 57 | func getRedisAddrByKey(key string) (string, error) { 58 | return CacheConsistent.Get(key) 59 | } 60 | 61 | func GetRedisClient(key string) *redis.Client { 62 | p := new(comandGetRedisConn) 63 | p.Call = make(chan *redis.Client, 1) 64 | p.Key = key 65 | getRedis <- p 66 | select { 67 | case item := <-p.Call: 68 | return item 69 | case <-time.After(time.Second * 5): 70 | return nil 71 | } 72 | } 73 | --------------------------------------------------------------------------------