9384e870 by slene

orm 1. add api: NewOrmWithDB, AddAliasWthDB; 2. RawSeter -> add api: RowsToMap, …

…RowsToStruct; 3. RawSeter -> change api: Values, ValuesList, ValuesFlat add optional params comumns.
1 parent 8296713b
...@@ -1350,6 +1350,10 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond ...@@ -1350,6 +1350,10 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
1350 return cnt, nil 1350 return cnt, nil
1351 } 1351 }
1352 1352
1353 func (d *dbBase) RowsTo(dbQuerier, *querySet, *modelInfo, *Condition, interface{}, string, string, *time.Location) (int64, error) {
1354 return 0, nil
1355 }
1356
1353 // flag of update joined record. 1357 // flag of update joined record.
1354 func (d *dbBase) SupportUpdateJoin() bool { 1358 func (d *dbBase) SupportUpdateJoin() bool {
1355 return true 1359 return true
......
...@@ -3,7 +3,6 @@ package orm ...@@ -3,7 +3,6 @@ package orm
3 import ( 3 import (
4 "database/sql" 4 "database/sql"
5 "fmt" 5 "fmt"
6 "os"
7 "reflect" 6 "reflect"
8 "sync" 7 "sync"
9 "time" 8 "time"
...@@ -96,40 +95,15 @@ type alias struct { ...@@ -96,40 +95,15 @@ type alias struct {
96 Engine string 95 Engine string
97 } 96 }
98 97
99 // Setting the database connect params. Use the database driver self dataSource args. 98 func detectTZ(al *alias) {
100 func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) {
101 al := new(alias)
102 al.Name = aliasName
103 al.DriverName = driverName
104 al.DataSource = dataSource
105
106 var (
107 err error
108 )
109
110 if dr, ok := drivers[driverName]; ok {
111 al.DbBaser = dbBasers[dr]
112 al.Driver = dr
113 } else {
114 err = fmt.Errorf("driver name `%s` have not registered", driverName)
115 goto end
116 }
117
118 if dataBaseCache.add(aliasName, al) == false {
119 err = fmt.Errorf("db name `%s` already registered, cannot reuse", aliasName)
120 goto end
121 }
122
123 al.DB, err = sql.Open(driverName, dataSource)
124 if err != nil {
125 err = fmt.Errorf("register db `%s`, %s", aliasName, err.Error())
126 goto end
127 }
128
129 // orm timezone system match database 99 // orm timezone system match database
130 // default use Local 100 // default use Local
131 al.TZ = time.Local 101 al.TZ = time.Local
132 102
103 if al.DriverName == "sphinx" {
104 return
105 }
106
133 switch al.Driver { 107 switch al.Driver {
134 case DR_MySQL: 108 case DR_MySQL:
135 row := al.DB.QueryRow("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP)") 109 row := al.DB.QueryRow("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP)")
...@@ -173,6 +147,60 @@ func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) { ...@@ -173,6 +147,60 @@ func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) {
173 DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error()) 147 DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error())
174 } 148 }
175 } 149 }
150 }
151
152 func addAliasWthDB(aliasName, driverName string, db *sql.DB) (*alias, error) {
153 al := new(alias)
154 al.Name = aliasName
155 al.DriverName = driverName
156 al.DB = db
157
158 if dr, ok := drivers[driverName]; ok {
159 al.DbBaser = dbBasers[dr]
160 al.Driver = dr
161 } else {
162 return nil, fmt.Errorf("driver name `%s` have not registered", driverName)
163 }
164
165 err := db.Ping()
166 if err != nil {
167 return nil, fmt.Errorf("register db Ping `%s`, %s", aliasName, err.Error())
168 }
169
170 if dataBaseCache.add(aliasName, al) == false {
171 return nil, fmt.Errorf("db name `%s` already registered, cannot reuse", aliasName)
172 }
173
174 return al, nil
175 }
176
177 func AddAliasWthDB(aliasName, driverName string, db *sql.DB) error {
178 _, err := addAliasWthDB(aliasName, driverName, db)
179 return err
180 }
181
182 // Setting the database connect params. Use the database driver self dataSource args.
183 func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) error {
184 var (
185 err error
186 db *sql.DB
187 al *alias
188 )
189
190 db, err = sql.Open(driverName, dataSource)
191 if err != nil {
192 err = fmt.Errorf("register db `%s`, %s", aliasName, err.Error())
193 goto end
194 }
195
196 al, err = addAliasWthDB(aliasName, driverName, db)
197 if err != nil {
198 goto end
199 }
200
201 al.DataSource = dataSource
202
203 detectTZ(al)
176 204
177 for i, v := range params { 205 for i, v := range params {
178 switch i { 206 switch i {
...@@ -183,39 +211,37 @@ func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) { ...@@ -183,39 +211,37 @@ func RegisterDataBase(aliasName, driverName, dataSource string, params ...int) {
183 } 211 }
184 } 212 }
185 213
186 err = al.DB.Ping()
187 if err != nil {
188 err = fmt.Errorf("register db `%s`, %s", aliasName, err.Error())
189 goto end
190 }
191
192 end: 214 end:
193 if err != nil { 215 if err != nil {
194 fmt.Println(err.Error()) 216 if db != nil {
195 os.Exit(2) 217 db.Close()
196 } 218 }
219 DebugLog.Println(err.Error())
220 }
221
222 return err
197 } 223 }
198 224
199 // Register a database driver use specify driver name, this can be definition the driver is which database type. 225 // Register a database driver use specify driver name, this can be definition the driver is which database type.
200 func RegisterDriver(driverName string, typ DriverType) { 226 func RegisterDriver(driverName string, typ DriverType) error {
201 if t, ok := drivers[driverName]; ok == false { 227 if t, ok := drivers[driverName]; ok == false {
202 drivers[driverName] = typ 228 drivers[driverName] = typ
203 } else { 229 } else {
204 if t != typ { 230 if t != typ {
205 fmt.Sprintf("driverName `%s` db driver already registered and is other type\n", driverName) 231 return fmt.Errorf("driverName `%s` db driver already registered and is other type\n", driverName)
206 os.Exit(2)
207 } 232 }
208 } 233 }
234 return nil
209 } 235 }
210 236
211 // Change the database default used timezone 237 // Change the database default used timezone
212 func SetDataBaseTZ(aliasName string, tz *time.Location) { 238 func SetDataBaseTZ(aliasName string, tz *time.Location) error {
213 if al, ok := dataBaseCache.get(aliasName); ok { 239 if al, ok := dataBaseCache.get(aliasName); ok {
214 al.TZ = tz 240 al.TZ = tz
215 } else { 241 } else {
216 fmt.Sprintf("DataBase name `%s` not registered\n", aliasName) 242 return fmt.Errorf("DataBase name `%s` not registered\n", aliasName)
217 os.Exit(2)
218 } 243 }
244 return nil
219 } 245 }
220 246
221 // Change the max idle conns for *sql.DB, use specify database alias name 247 // Change the max idle conns for *sql.DB, use specify database alias name
......
...@@ -439,6 +439,12 @@ func (o *orm) Driver() Driver { ...@@ -439,6 +439,12 @@ func (o *orm) Driver() Driver {
439 return driver(o.alias.Name) 439 return driver(o.alias.Name)
440 } 440 }
441 441
442 func (o *orm) GetDB() dbQuerier {
443 panic(ErrNotImplement)
444 // not enough
445 return o.db
446 }
447
442 // create new orm 448 // create new orm
443 func NewOrm() Ormer { 449 func NewOrm() Ormer {
444 BootStrap() // execute only once 450 BootStrap() // execute only once
...@@ -450,3 +456,30 @@ func NewOrm() Ormer { ...@@ -450,3 +456,30 @@ func NewOrm() Ormer {
450 } 456 }
451 return o 457 return o
452 } 458 }
459
460 // create a new ormer object with specify *sql.DB for query
461 func NewOrmWithDB(driverName, aliasName string, db *sql.DB) (Ormer, error) {
462 var al *alias
463
464 if dr, ok := drivers[driverName]; ok {
465 al = new(alias)
466 al.DbBaser = dbBasers[dr]
467 al.Driver = dr
468 } else {
469 return nil, fmt.Errorf("driver name `%s` have not registered", driverName)
470 }
471
472 al.Name = aliasName
473 al.DriverName = driverName
474
475 o := new(orm)
476 o.alias = al
477
478 if Debug {
479 o.db = newDbQueryLog(o.alias, db)
480 } else {
481 o.db = db
482 }
483
484 return o, nil
485 }
......
...@@ -197,6 +197,36 @@ func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) { ...@@ -197,6 +197,36 @@ func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) {
197 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)
198 } 198 }
199 199
200 // query all rows into map[string]interface with specify key and value column name.
201 // keyCol = "name", valueCol = "value"
202 // table data
203 // name | value
204 // total | 100
205 // found | 200
206 // to map[string]interface{}{
207 // "total": 100,
208 // "found": 200,
209 // }
210 func (o *querySet) RowsToMap(result *Params, keyCol, valueCol string) (int64, error) {
211 panic(ErrNotImplement)
212 return o.orm.alias.DbBaser.RowsTo(o.orm.db, o, o.mi, o.cond, result, keyCol, valueCol, o.orm.alias.TZ)
213 }
214
215 // query all rows into struct with specify key and value column name.
216 // keyCol = "name", valueCol = "value"
217 // table data
218 // name | value
219 // total | 100
220 // found | 200
221 // to struct {
222 // Total int
223 // Found int
224 // }
225 func (o *querySet) RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error) {
226 panic(ErrNotImplement)
227 return o.orm.alias.DbBaser.RowsTo(o.orm.db, o, o.mi, o.cond, ptrStruct, keyCol, valueCol, o.orm.alias.TZ)
228 }
229
200 // create new QuerySeter. 230 // create new QuerySeter.
201 func newQuerySet(orm *orm, mi *modelInfo) QuerySeter { 231 func newQuerySet(orm *orm, mi *modelInfo) QuerySeter {
202 o := new(querySet) 232 o := new(querySet)
......
...@@ -518,7 +518,7 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { ...@@ -518,7 +518,7 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) {
518 return cnt, nil 518 return cnt, nil
519 } 519 }
520 520
521 func (o *rawSet) readValues(container interface{}) (int64, error) { 521 func (o *rawSet) readValues(container interface{}, needCols []string) (int64, error) {
522 var ( 522 var (
523 maps []Params 523 maps []Params
524 lists []ParamsList 524 lists []ParamsList
...@@ -555,17 +555,35 @@ func (o *rawSet) readValues(container interface{}) (int64, error) { ...@@ -555,17 +555,35 @@ func (o *rawSet) readValues(container interface{}) (int64, error) {
555 refs []interface{} 555 refs []interface{}
556 cnt int64 556 cnt int64
557 cols []string 557 cols []string
558 indexs []int
558 ) 559 )
560
559 for rs.Next() { 561 for rs.Next() {
560 if cnt == 0 { 562 if cnt == 0 {
561 if columns, err := rs.Columns(); err != nil { 563 if columns, err := rs.Columns(); err != nil {
562 return 0, err 564 return 0, err
563 } else { 565 } else {
566 if len(needCols) > 0 {
567 indexs = make([]int, 0, len(needCols))
568 } else {
569 indexs = make([]int, 0, len(columns))
570 }
571
564 cols = columns 572 cols = columns
565 refs = make([]interface{}, len(cols)) 573 refs = make([]interface{}, len(cols))
566 for i, _ := range refs { 574 for i, _ := range refs {
567 var ref sql.NullString 575 var ref sql.NullString
568 refs[i] = &ref 576 refs[i] = &ref
577
578 if len(needCols) > 0 {
579 for _, c := range needCols {
580 if c == cols[i] {
581 indexs = append(indexs, i)
582 }
583 }
584 } else {
585 indexs = append(indexs, i)
586 }
569 } 587 }
570 } 588 }
571 } 589 }
...@@ -577,7 +595,8 @@ func (o *rawSet) readValues(container interface{}) (int64, error) { ...@@ -577,7 +595,8 @@ func (o *rawSet) readValues(container interface{}) (int64, error) {
577 switch typ { 595 switch typ {
578 case 1: 596 case 1:
579 params := make(Params, len(cols)) 597 params := make(Params, len(cols))
580 for i, ref := range refs { 598 for _, i := range indexs {
599 ref := refs[i]
581 value := reflect.Indirect(reflect.ValueOf(ref)).Interface().(sql.NullString) 600 value := reflect.Indirect(reflect.ValueOf(ref)).Interface().(sql.NullString)
582 if value.Valid { 601 if value.Valid {
583 params[cols[i]] = value.String 602 params[cols[i]] = value.String
...@@ -588,7 +607,8 @@ func (o *rawSet) readValues(container interface{}) (int64, error) { ...@@ -588,7 +607,8 @@ func (o *rawSet) readValues(container interface{}) (int64, error) {
588 maps = append(maps, params) 607 maps = append(maps, params)
589 case 2: 608 case 2:
590 params := make(ParamsList, 0, len(cols)) 609 params := make(ParamsList, 0, len(cols))
591 for _, ref := range refs { 610 for _, i := range indexs {
611 ref := refs[i]
592 value := reflect.Indirect(reflect.ValueOf(ref)).Interface().(sql.NullString) 612 value := reflect.Indirect(reflect.ValueOf(ref)).Interface().(sql.NullString)
593 if value.Valid { 613 if value.Valid {
594 params = append(params, value.String) 614 params = append(params, value.String)
...@@ -598,7 +618,8 @@ func (o *rawSet) readValues(container interface{}) (int64, error) { ...@@ -598,7 +618,8 @@ func (o *rawSet) readValues(container interface{}) (int64, error) {
598 } 618 }
599 lists = append(lists, params) 619 lists = append(lists, params)
600 case 3: 620 case 3:
601 for _, ref := range refs { 621 for _, i := range indexs {
622 ref := refs[i]
602 value := reflect.Indirect(reflect.ValueOf(ref)).Interface().(sql.NullString) 623 value := reflect.Indirect(reflect.ValueOf(ref)).Interface().(sql.NullString)
603 if value.Valid { 624 if value.Valid {
604 list = append(list, value.String) 625 list = append(list, value.String)
...@@ -623,19 +644,163 @@ func (o *rawSet) readValues(container interface{}) (int64, error) { ...@@ -623,19 +644,163 @@ func (o *rawSet) readValues(container interface{}) (int64, error) {
623 return cnt, nil 644 return cnt, nil
624 } 645 }
625 646
647 func (o *rawSet) queryRowsTo(container interface{}, keyCol, valueCol string) (int64, error) {
648 var (
649 maps Params
650 ind *reflect.Value
651 )
652
653 typ := 0
654 switch container.(type) {
655 case *Params:
656 typ = 1
657 default:
658 typ = 2
659 vl := reflect.ValueOf(container)
660 id := reflect.Indirect(vl)
661 if vl.Kind() != reflect.Ptr || id.Kind() != reflect.Struct {
662 panic(fmt.Errorf("<RawSeter> RowsTo unsupport type `%T` need ptr struct", container))
663 }
664
665 ind = &id
666 }
667
668 query := o.query
669 o.orm.alias.DbBaser.ReplaceMarks(&query)
670
671 args := getFlatParams(nil, o.args, o.orm.alias.TZ)
672
673 var rs *sql.Rows
674 if r, err := o.orm.db.Query(query, args...); err != nil {
675 return 0, err
676 } else {
677 rs = r
678 }
679
680 defer rs.Close()
681
682 var (
683 refs []interface{}
684 cnt int64
685 cols []string
686 )
687
688 var (
689 keyIndex = -1
690 valueIndex = -1
691 )
692
693 for rs.Next() {
694 if cnt == 0 {
695 if columns, err := rs.Columns(); err != nil {
696 return 0, err
697 } else {
698 cols = columns
699 refs = make([]interface{}, len(cols))
700 for i, _ := range refs {
701 if keyCol == cols[i] {
702 keyIndex = i
703 }
704
705 if typ == 1 || keyIndex == i {
706 var ref sql.NullString
707 refs[i] = &ref
708 } else {
709 var ref interface{}
710 refs[i] = &ref
711 }
712
713 if valueCol == cols[i] {
714 valueIndex = i
715 }
716 }
717
718 if keyIndex == -1 || valueIndex == -1 {
719 panic(fmt.Errorf("<RawSeter> RowsTo unknown key, value column name `%s: %s`", keyCol, valueCol))
720 }
721 }
722 }
723
724 if err := rs.Scan(refs...); err != nil {
725 return 0, err
726 }
727
728 if cnt == 0 {
729 switch typ {
730 case 1:
731 maps = make(Params)
732 }
733 }
734
735 key := reflect.Indirect(reflect.ValueOf(refs[keyIndex])).Interface().(sql.NullString).String
736
737 switch typ {
738 case 1:
739 value := reflect.Indirect(reflect.ValueOf(refs[valueIndex])).Interface().(sql.NullString)
740 if value.Valid {
741 maps[key] = value.String
742 } else {
743 maps[key] = nil
744 }
745
746 default:
747 if id := ind.FieldByName(camelString(key)); id.IsValid() {
748 o.setFieldValue(id, reflect.ValueOf(refs[valueIndex]).Elem().Interface())
749 }
750 }
751
752 cnt++
753 }
754
755 if typ == 1 {
756 v, _ := container.(*Params)
757 *v = maps
758 }
759
760 return cnt, nil
761 }
762
626 // query data to []map[string]interface 763 // query data to []map[string]interface
627 func (o *rawSet) Values(container *[]Params) (int64, error) { 764 func (o *rawSet) Values(container *[]Params, cols ...string) (int64, error) {
628 return o.readValues(container) 765 return o.readValues(container, cols)
629 } 766 }
630 767
631 // query data to [][]interface 768 // query data to [][]interface
632 func (o *rawSet) ValuesList(container *[]ParamsList) (int64, error) { 769 func (o *rawSet) ValuesList(container *[]ParamsList, cols ...string) (int64, error) {
633 return o.readValues(container) 770 return o.readValues(container, cols)
634 } 771 }
635 772
636 // query data to []interface 773 // query data to []interface
637 func (o *rawSet) ValuesFlat(container *ParamsList) (int64, error) { 774 func (o *rawSet) ValuesFlat(container *ParamsList, cols ...string) (int64, error) {
638 return o.readValues(container) 775 return o.readValues(container, cols)
776 }
777
778 // query all rows into map[string]interface with specify key and value column name.
779 // keyCol = "name", valueCol = "value"
780 // table data
781 // name | value
782 // total | 100
783 // found | 200
784 // to map[string]interface{}{
785 // "total": 100,
786 // "found": 200,
787 // }
788 func (o *rawSet) RowsToMap(result *Params, keyCol, valueCol string) (int64, error) {
789 return o.queryRowsTo(result, keyCol, valueCol)
790 }
791
792 // query all rows into struct with specify key and value column name.
793 // keyCol = "name", valueCol = "value"
794 // table data
795 // name | value
796 // total | 100
797 // found | 200
798 // to struct {
799 // Total int
800 // Found int
801 // }
802 func (o *rawSet) RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error) {
803 return o.queryRowsTo(ptrStruct, keyCol, valueCol)
639 } 804 }
640 805
641 // return prepared raw statement for used in times. 806 // return prepared raw statement for used in times.
......
...@@ -37,6 +37,7 @@ type Ormer interface { ...@@ -37,6 +37,7 @@ type Ormer interface {
37 Rollback() error 37 Rollback() error
38 Raw(string, ...interface{}) RawSeter 38 Raw(string, ...interface{}) RawSeter
39 Driver() Driver 39 Driver() Driver
40 GetDB() dbQuerier
40 } 41 }
41 42
42 // insert prepared statement 43 // insert prepared statement
...@@ -64,6 +65,8 @@ type QuerySeter interface { ...@@ -64,6 +65,8 @@ type QuerySeter interface {
64 Values(*[]Params, ...string) (int64, error) 65 Values(*[]Params, ...string) (int64, error)
65 ValuesList(*[]ParamsList, ...string) (int64, error) 66 ValuesList(*[]ParamsList, ...string) (int64, error)
66 ValuesFlat(*ParamsList, string) (int64, error) 67 ValuesFlat(*ParamsList, string) (int64, error)
68 RowsToMap(*Params, string, string) (int64, error)
69 RowsToStruct(interface{}, string, string) (int64, error)
67 } 70 }
68 71
69 // model to model query struct 72 // model to model query struct
...@@ -87,9 +90,11 @@ type RawSeter interface { ...@@ -87,9 +90,11 @@ type RawSeter interface {
87 QueryRow(...interface{}) error 90 QueryRow(...interface{}) error
88 QueryRows(...interface{}) (int64, error) 91 QueryRows(...interface{}) (int64, error)
89 SetArgs(...interface{}) RawSeter 92 SetArgs(...interface{}) RawSeter
90 Values(*[]Params) (int64, error) 93 Values(*[]Params, ...string) (int64, error)
91 ValuesList(*[]ParamsList) (int64, error) 94 ValuesList(*[]ParamsList, ...string) (int64, error)
92 ValuesFlat(*ParamsList) (int64, error) 95 ValuesFlat(*ParamsList, ...string) (int64, error)
96 RowsToMap(*Params, string, string) (int64, error)
97 RowsToStruct(interface{}, string, string) (int64, error)
93 Prepare() (RawPreparer, error) 98 Prepare() (RawPreparer, error)
94 } 99 }
95 100
...@@ -109,6 +114,14 @@ type dbQuerier interface { ...@@ -109,6 +114,14 @@ type dbQuerier interface {
109 QueryRow(query string, args ...interface{}) *sql.Row 114 QueryRow(query string, args ...interface{}) *sql.Row
110 } 115 }
111 116
117 // type DB interface {
118 // Begin() (*sql.Tx, error)
119 // Prepare(query string) (stmtQuerier, error)
120 // Exec(query string, args ...interface{}) (sql.Result, error)
121 // Query(query string, args ...interface{}) (*sql.Rows, error)
122 // QueryRow(query string, args ...interface{}) *sql.Row
123 // }
124
112 // transaction beginner 125 // transaction beginner
113 type txer interface { 126 type txer interface {
114 Begin() (*sql.Tx, error) 127 Begin() (*sql.Tx, error)
...@@ -139,6 +152,7 @@ type dbBaser interface { ...@@ -139,6 +152,7 @@ type dbBaser interface {
139 GenerateOperatorLeftCol(*fieldInfo, string, *string) 152 GenerateOperatorLeftCol(*fieldInfo, string, *string)
140 PrepareInsert(dbQuerier, *modelInfo) (stmtQuerier, string, error) 153 PrepareInsert(dbQuerier, *modelInfo) (stmtQuerier, string, error)
141 ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}, *time.Location) (int64, error) 154 ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}, *time.Location) (int64, error)
155 RowsTo(dbQuerier, *querySet, *modelInfo, *Condition, interface{}, string, string, *time.Location) (int64, error)
142 MaxLimit() uint64 156 MaxLimit() uint64
143 TableQuote() string 157 TableQuote() string
144 ReplaceMarks(*string) 158 ReplaceMarks(*string)
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!