1977d87d by benlovell

Merge branch 'master' of https://github.com/astaxie/beego into spelling

2 parents 9cbefacf 42f1d1ae
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
13 "time" 13 "time"
14 ) 14 )
15 15
16 const VERSION = "0.8.0" 16 const VERSION = "0.9.0"
17 17
18 var ( 18 var (
19 BeeApp *App 19 BeeApp *App
......
1 # beego orm 1 # beego orm
2 2
3 a powerful orm framework 3 [![Build Status](https://drone.io/github.com/astaxie/beego/status.png)](https://drone.io/github.com/astaxie/beego/latest)
4
5 A powerful orm framework for go.
6
7 It is heavily influenced by Django ORM, SQLAlchemy.
4 8
5 now, beta, unstable, may be changing some api make your app build failed. 9 now, beta, unstable, may be changing some api make your app build failed.
6 10
...@@ -14,12 +18,25 @@ Passed all test, but need more feedback. ...@@ -14,12 +18,25 @@ Passed all test, but need more feedback.
14 18
15 **Features:** 19 **Features:**
16 20
17 ... 21 * full go type support
22 * easy for usage, simple CRUD operation
23 * auto join with relation table
24 * cross DataBase compatible query
25 * Raw SQL query / mapper without orm model
26 * full test keep stable and strong
27
28 more features please read the docs
18 29
19 **Install:** 30 **Install:**
20 31
21 go get github.com/astaxie/beego/orm 32 go get github.com/astaxie/beego/orm
22 33
34 ## Changelog
35
36 * 2013-08-13: update test for database types
37 * 2013-08-13: go type support, such as int8, uint8, byte, rune
38 * 2013-08-13: date / datetime timezone support very well
39
23 ## Quick Start 40 ## Quick Start
24 41
25 #### Simple Usage 42 #### Simple Usage
...@@ -143,5 +160,3 @@ more details and examples in docs and test ...@@ -143,5 +160,3 @@ more details and examples in docs and test
143 - some unrealized api 160 - some unrealized api
144 - examples 161 - examples
145 - docs 162 - docs
146
147 ##
......
...@@ -49,7 +49,7 @@ type dbBase struct { ...@@ -49,7 +49,7 @@ type dbBase struct {
49 ins dbBaser 49 ins dbBaser
50 } 50 }
51 51
52 func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, skipAuto bool, insert bool) (columns []string, values []interface{}, err error) { 52 func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, skipAuto bool, insert bool, tz *time.Location) (columns []string, values []interface{}, err error) {
53 _, pkValue, _ := getExistPk(mi, ind) 53 _, pkValue, _ := getExistPk(mi, ind)
54 for _, column := range mi.fields.orders { 54 for _, column := range mi.fields.orders {
55 fi := mi.fields.columns[column] 55 fi := mi.fields.columns[column]
...@@ -71,9 +71,22 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, skipAuto bool, ...@@ -71,9 +71,22 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, skipAuto bool,
71 case TypeCharField, TypeTextField: 71 case TypeCharField, TypeTextField:
72 value = field.String() 72 value = field.String()
73 case TypeFloatField, TypeDecimalField: 73 case TypeFloatField, TypeDecimalField:
74 value = field.Float() 74 vu := field.Interface()
75 if _, ok := vu.(float32); ok {
76 value, _ = StrTo(ToStr(vu)).Float64()
77 } else {
78 value = field.Float()
79 }
75 case TypeDateField, TypeDateTimeField: 80 case TypeDateField, TypeDateTimeField:
76 value = field.Interface() 81 value = field.Interface()
82 if t, ok := value.(time.Time); ok {
83 if fi.fieldType == TypeDateField {
84 d.ins.TimeToDB(&t, DefaultTimeLoc)
85 } else {
86 d.ins.TimeToDB(&t, tz)
87 }
88 value = t
89 }
77 default: 90 default:
78 switch { 91 switch {
79 case fi.fieldType&IsPostiveIntegerField > 0: 92 case fi.fieldType&IsPostiveIntegerField > 0:
...@@ -101,15 +114,16 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, skipAuto bool, ...@@ -101,15 +114,16 @@ func (d *dbBase) collectValues(mi *modelInfo, ind reflect.Value, skipAuto bool,
101 if fi.auto_now || fi.auto_now_add && insert { 114 if fi.auto_now || fi.auto_now_add && insert {
102 tnow := time.Now() 115 tnow := time.Now()
103 if fi.fieldType == TypeDateField { 116 if fi.fieldType == TypeDateField {
104 value = timeFormat(tnow, format_Date) 117 d.ins.TimeToDB(&tnow, DefaultTimeLoc)
105 } else { 118 } else {
106 value = timeFormat(tnow, format_DateTime) 119 d.ins.TimeToDB(&tnow, tz)
107 } 120 }
121 value = tnow
108 if fi.isFielder { 122 if fi.isFielder {
109 f := field.Addr().Interface().(Fielder) 123 f := field.Addr().Interface().(Fielder)
110 f.SetRaw(tnow) 124 f.SetRaw(tnow.In(DefaultTimeLoc))
111 } else { 125 } else {
112 field.Set(reflect.ValueOf(tnow)) 126 field.Set(reflect.ValueOf(tnow.In(DefaultTimeLoc)))
113 } 127 }
114 } 128 }
115 } 129 }
...@@ -145,8 +159,8 @@ func (d *dbBase) PrepareInsert(q dbQuerier, mi *modelInfo) (stmtQuerier, string, ...@@ -145,8 +159,8 @@ func (d *dbBase) PrepareInsert(q dbQuerier, mi *modelInfo) (stmtQuerier, string,
145 return stmt, query, err 159 return stmt, query, err
146 } 160 }
147 161
148 func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value) (int64, error) { 162 func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) {
149 _, values, err := d.collectValues(mi, ind, true, true) 163 _, values, err := d.collectValues(mi, ind, true, true, tz)
150 if err != nil { 164 if err != nil {
151 return 0, err 165 return 0, err
152 } 166 }
...@@ -165,7 +179,7 @@ func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value) ...@@ -165,7 +179,7 @@ func (d *dbBase) InsertStmt(stmt stmtQuerier, mi *modelInfo, ind reflect.Value)
165 } 179 }
166 } 180 }
167 181
168 func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value) error { 182 func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) error {
169 pkColumn, pkValue, ok := getExistPk(mi, ind) 183 pkColumn, pkValue, ok := getExistPk(mi, ind)
170 if ok == false { 184 if ok == false {
171 return ErrMissPK 185 return ErrMissPK
...@@ -197,7 +211,7 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value) error { ...@@ -197,7 +211,7 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value) error {
197 elm := reflect.New(mi.addrField.Elem().Type()) 211 elm := reflect.New(mi.addrField.Elem().Type())
198 mind := reflect.Indirect(elm) 212 mind := reflect.Indirect(elm)
199 213
200 d.setColsValues(mi, &mind, mi.fields.dbcols, refs) 214 d.setColsValues(mi, &mind, mi.fields.dbcols, refs, tz)
201 215
202 ind.Set(mind) 216 ind.Set(mind)
203 } 217 }
...@@ -205,8 +219,8 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value) error { ...@@ -205,8 +219,8 @@ func (d *dbBase) Read(q dbQuerier, mi *modelInfo, ind reflect.Value) error {
205 return nil 219 return nil
206 } 220 }
207 221
208 func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, error) { 222 func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) {
209 names, values, err := d.collectValues(mi, ind, true, true) 223 names, values, err := d.collectValues(mi, ind, true, true, tz)
210 if err != nil { 224 if err != nil {
211 return 0, err 225 return 0, err
212 } 226 }
...@@ -240,12 +254,12 @@ func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, e ...@@ -240,12 +254,12 @@ func (d *dbBase) Insert(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, e
240 } 254 }
241 } 255 }
242 256
243 func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, error) { 257 func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) {
244 pkName, pkValue, ok := getExistPk(mi, ind) 258 pkName, pkValue, ok := getExistPk(mi, ind)
245 if ok == false { 259 if ok == false {
246 return 0, ErrMissPK 260 return 0, ErrMissPK
247 } 261 }
248 setNames, setValues, err := d.collectValues(mi, ind, true, false) 262 setNames, setValues, err := d.collectValues(mi, ind, true, false, tz)
249 if err != nil { 263 if err != nil {
250 return 0, err 264 return 0, err
251 } 265 }
...@@ -269,7 +283,7 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, e ...@@ -269,7 +283,7 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, e
269 return 0, nil 283 return 0, nil
270 } 284 }
271 285
272 func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, error) { 286 func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.Location) (int64, error) {
273 pkName, pkValue, ok := getExistPk(mi, ind) 287 pkName, pkValue, ok := getExistPk(mi, ind)
274 if ok == false { 288 if ok == false {
275 return 0, ErrMissPK 289 return 0, ErrMissPK
...@@ -293,7 +307,7 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, e ...@@ -293,7 +307,7 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, e
293 ind.Field(mi.fields.pk.fieldIndex).SetInt(0) 307 ind.Field(mi.fields.pk.fieldIndex).SetInt(0)
294 } 308 }
295 309
296 err := d.deleteRels(q, mi, []interface{}{pkValue}) 310 err := d.deleteRels(q, mi, []interface{}{pkValue}, tz)
297 if err != nil { 311 if err != nil {
298 return num, err 312 return num, err
299 } 313 }
...@@ -306,7 +320,7 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, e ...@@ -306,7 +320,7 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value) (int64, e
306 return 0, nil 320 return 0, nil
307 } 321 }
308 322
309 func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, params Params) (int64, error) { 323 func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, params Params, tz *time.Location) (int64, error) {
310 columns := make([]string, 0, len(params)) 324 columns := make([]string, 0, len(params))
311 values := make([]interface{}, 0, len(params)) 325 values := make([]interface{}, 0, len(params))
312 for col, val := range params { 326 for col, val := range params {
...@@ -327,7 +341,7 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con ...@@ -327,7 +341,7 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
327 tables.parseRelated(qs.related, qs.relDepth) 341 tables.parseRelated(qs.related, qs.relDepth)
328 } 342 }
329 343
330 where, args := tables.getCondSql(cond, false) 344 where, args := tables.getCondSql(cond, false, tz)
331 345
332 values = append(values, args...) 346 values = append(values, args...)
333 347
...@@ -356,13 +370,13 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con ...@@ -356,13 +370,13 @@ func (d *dbBase) UpdateBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
356 return 0, nil 370 return 0, nil
357 } 371 }
358 372
359 func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}) error { 373 func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}, tz *time.Location) error {
360 for _, fi := range mi.fields.fieldsReverse { 374 for _, fi := range mi.fields.fieldsReverse {
361 fi = fi.reverseFieldInfo 375 fi = fi.reverseFieldInfo
362 switch fi.onDelete { 376 switch fi.onDelete {
363 case od_CASCADE: 377 case od_CASCADE:
364 cond := NewCondition().And(fmt.Sprintf("%s__in", fi.name), args...) 378 cond := NewCondition().And(fmt.Sprintf("%s__in", fi.name), args...)
365 _, err := d.DeleteBatch(q, nil, fi.mi, cond) 379 _, err := d.DeleteBatch(q, nil, fi.mi, cond, tz)
366 if err != nil { 380 if err != nil {
367 return err 381 return err
368 } 382 }
...@@ -372,7 +386,7 @@ func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}) erro ...@@ -372,7 +386,7 @@ func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}) erro
372 if fi.onDelete == od_SET_DEFAULT { 386 if fi.onDelete == od_SET_DEFAULT {
373 params[fi.column] = fi.initial.String() 387 params[fi.column] = fi.initial.String()
374 } 388 }
375 _, err := d.UpdateBatch(q, nil, fi.mi, cond, params) 389 _, err := d.UpdateBatch(q, nil, fi.mi, cond, params, tz)
376 if err != nil { 390 if err != nil {
377 return err 391 return err
378 } 392 }
...@@ -382,7 +396,7 @@ func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}) erro ...@@ -382,7 +396,7 @@ func (d *dbBase) deleteRels(q dbQuerier, mi *modelInfo, args []interface{}) erro
382 return nil 396 return nil
383 } 397 }
384 398
385 func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition) (int64, error) { 399 func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (int64, error) {
386 tables := newDbTables(mi, d.ins) 400 tables := newDbTables(mi, d.ins)
387 if qs != nil { 401 if qs != nil {
388 tables.parseRelated(qs.related, qs.relDepth) 402 tables.parseRelated(qs.related, qs.relDepth)
...@@ -394,7 +408,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con ...@@ -394,7 +408,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
394 408
395 Q := d.ins.TableQuote() 409 Q := d.ins.TableQuote()
396 410
397 where, args := tables.getCondSql(cond, false) 411 where, args := tables.getCondSql(cond, false, tz)
398 join := tables.getJoinSql() 412 join := tables.getJoinSql()
399 413
400 cols := fmt.Sprintf("T0.%s%s%s", Q, mi.fields.pk.column, Q) 414 cols := fmt.Sprintf("T0.%s%s%s", Q, mi.fields.pk.column, Q)
...@@ -425,7 +439,11 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con ...@@ -425,7 +439,11 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
425 return 0, nil 439 return 0, nil
426 } 440 }
427 441
428 sql, args := d.ins.GenerateOperatorSql(mi, mi.fields.pk, "in", args) 442 marks := make([]string, len(args))
443 for i, _ := range marks {
444 marks[i] = "?"
445 }
446 sql := fmt.Sprintf("IN (%s)", strings.Join(marks, ", "))
429 query = fmt.Sprintf("DELETE FROM %s%s%s WHERE %s%s%s %s", Q, mi.table, Q, Q, mi.fields.pk.column, Q, sql) 447 query = fmt.Sprintf("DELETE FROM %s%s%s WHERE %s%s%s %s", Q, mi.table, Q, Q, mi.fields.pk.column, Q, sql)
430 448
431 d.ins.ReplaceMarks(&query) 449 d.ins.ReplaceMarks(&query)
...@@ -437,7 +455,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con ...@@ -437,7 +455,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
437 } 455 }
438 456
439 if num > 0 { 457 if num > 0 {
440 err := d.deleteRels(q, mi, args) 458 err := d.deleteRels(q, mi, args, tz)
441 if err != nil { 459 if err != nil {
442 return num, err 460 return num, err
443 } 461 }
...@@ -451,7 +469,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con ...@@ -451,7 +469,7 @@ func (d *dbBase) DeleteBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Con
451 return 0, nil 469 return 0, nil
452 } 470 }
453 471
454 func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, container interface{}) (int64, error) { 472 func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, container interface{}, tz *time.Location) (int64, error) {
455 473
456 val := reflect.ValueOf(container) 474 val := reflect.ValueOf(container)
457 ind := reflect.Indirect(val) 475 ind := reflect.Indirect(val)
...@@ -490,7 +508,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi ...@@ -490,7 +508,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
490 tables := newDbTables(mi, d.ins) 508 tables := newDbTables(mi, d.ins)
491 tables.parseRelated(qs.related, qs.relDepth) 509 tables.parseRelated(qs.related, qs.relDepth)
492 510
493 where, args := tables.getCondSql(cond, false) 511 where, args := tables.getCondSql(cond, false, tz)
494 orderBy := tables.getOrderSql(qs.orders) 512 orderBy := tables.getOrderSql(qs.orders)
495 limit := tables.getLimitSql(mi, offset, rlimit) 513 limit := tables.getLimitSql(mi, offset, rlimit)
496 join := tables.getJoinSql() 514 join := tables.getJoinSql()
...@@ -539,7 +557,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi ...@@ -539,7 +557,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
539 cacheM := make(map[string]*modelInfo) 557 cacheM := make(map[string]*modelInfo)
540 trefs := refs 558 trefs := refs
541 559
542 d.setColsValues(mi, &mind, mi.fields.dbcols, refs[:len(mi.fields.dbcols)]) 560 d.setColsValues(mi, &mind, mi.fields.dbcols, refs[:len(mi.fields.dbcols)], tz)
543 trefs = refs[len(mi.fields.dbcols):] 561 trefs = refs[len(mi.fields.dbcols):]
544 562
545 for _, tbl := range tables.tables { 563 for _, tbl := range tables.tables {
...@@ -558,7 +576,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi ...@@ -558,7 +576,7 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
558 mmi := fi.relModelInfo 576 mmi := fi.relModelInfo
559 field := reflect.Indirect(last.Field(fi.fieldIndex)) 577 field := reflect.Indirect(last.Field(fi.fieldIndex))
560 if field.IsValid() { 578 if field.IsValid() {
561 d.setColsValues(mmi, &field, mmi.fields.dbcols, trefs[:len(mmi.fields.dbcols)]) 579 d.setColsValues(mmi, &field, mmi.fields.dbcols, trefs[:len(mmi.fields.dbcols)], tz)
562 for _, fi := range mmi.fields.fieldsReverse { 580 for _, fi := range mmi.fields.fieldsReverse {
563 if fi.reverseFieldInfo.mi == lastm { 581 if fi.reverseFieldInfo.mi == lastm {
564 if fi.reverseFieldInfo != nil { 582 if fi.reverseFieldInfo != nil {
...@@ -592,11 +610,11 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi ...@@ -592,11 +610,11 @@ func (d *dbBase) ReadBatch(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condi
592 return cnt, nil 610 return cnt, nil
593 } 611 }
594 612
595 func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition) (cnt int64, err error) { 613 func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, tz *time.Location) (cnt int64, err error) {
596 tables := newDbTables(mi, d.ins) 614 tables := newDbTables(mi, d.ins)
597 tables.parseRelated(qs.related, qs.relDepth) 615 tables.parseRelated(qs.related, qs.relDepth)
598 616
599 where, args := tables.getCondSql(cond, false) 617 where, args := tables.getCondSql(cond, false, tz)
600 tables.getOrderSql(qs.orders) 618 tables.getOrderSql(qs.orders)
601 join := tables.getJoinSql() 619 join := tables.getJoinSql()
602 620
...@@ -612,9 +630,9 @@ func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition ...@@ -612,9 +630,9 @@ func (d *dbBase) Count(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition
612 return 630 return
613 } 631 }
614 632
615 func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator string, args []interface{}) (string, []interface{}) { 633 func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator string, args []interface{}, tz *time.Location) (string, []interface{}) {
616 sql := "" 634 sql := ""
617 params := getFlatParams(fi, args) 635 params := getFlatParams(fi, args, tz)
618 636
619 if len(params) == 0 { 637 if len(params) == 0 {
620 panic(fmt.Sprintf("operator `%s` need at least one args", operator)) 638 panic(fmt.Sprintf("operator `%s` need at least one args", operator))
...@@ -665,11 +683,11 @@ func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator stri ...@@ -665,11 +683,11 @@ func (d *dbBase) GenerateOperatorSql(mi *modelInfo, fi *fieldInfo, operator stri
665 return sql, params 683 return sql, params
666 } 684 }
667 685
668 func (d *dbBase) GenerateOperatorLeftCol(string, *string) { 686 func (d *dbBase) GenerateOperatorLeftCol(*fieldInfo, string, *string) {
669 687 // default not use
670 } 688 }
671 689
672 func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, values []interface{}) { 690 func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, values []interface{}, tz *time.Location) {
673 for i, column := range cols { 691 for i, column := range cols {
674 val := reflect.Indirect(reflect.ValueOf(values[i])).Interface() 692 val := reflect.Indirect(reflect.ValueOf(values[i])).Interface()
675 693
...@@ -677,12 +695,12 @@ func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, ...@@ -677,12 +695,12 @@ func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string,
677 695
678 field := ind.Field(fi.fieldIndex) 696 field := ind.Field(fi.fieldIndex)
679 697
680 value, err := d.getValue(fi, val) 698 value, err := d.convertValueFromDB(fi, val, tz)
681 if err != nil { 699 if err != nil {
682 panic(fmt.Sprintf("Raw value: `%v` %s", val, err.Error())) 700 panic(fmt.Sprintf("Raw value: `%v` %s", val, err.Error()))
683 } 701 }
684 702
685 _, err = d.setValue(fi, value, &field) 703 _, err = d.setFieldValue(fi, value, &field)
686 704
687 if err != nil { 705 if err != nil {
688 panic(fmt.Sprintf("Raw value: `%v` %s", val, err.Error())) 706 panic(fmt.Sprintf("Raw value: `%v` %s", val, err.Error()))
...@@ -690,7 +708,7 @@ func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string, ...@@ -690,7 +708,7 @@ func (d *dbBase) setColsValues(mi *modelInfo, ind *reflect.Value, cols []string,
690 } 708 }
691 } 709 }
692 710
693 func (d *dbBase) getValue(fi *fieldInfo, val interface{}) (interface{}, error) { 711 func (d *dbBase) convertValueFromDB(fi *fieldInfo, val interface{}, tz *time.Location) (interface{}, error) {
694 if val == nil { 712 if val == nil {
695 return nil, nil 713 return nil, nil
696 } 714 }
...@@ -739,29 +757,32 @@ setValue: ...@@ -739,29 +757,32 @@ setValue:
739 } 757 }
740 case fieldType == TypeDateField || fieldType == TypeDateTimeField: 758 case fieldType == TypeDateField || fieldType == TypeDateTimeField:
741 if str == nil { 759 if str == nil {
742 switch v := val.(type) { 760 switch t := val.(type) {
743 case time.Time: 761 case time.Time:
744 value = v 762 d.ins.TimeFromDB(&t, tz)
763 value = t
745 default: 764 default:
746 s := StrTo(ToStr(v)) 765 s := StrTo(ToStr(t))
747 str = &s 766 str = &s
748 } 767 }
749 } 768 }
750 if str != nil { 769 if str != nil {
751 s := str.String() 770 s := str.String()
752 var format string 771 var (
772 t time.Time
773 err error
774 )
753 if fi.fieldType == TypeDateField { 775 if fi.fieldType == TypeDateField {
754 format = format_Date
755 if len(s) > 10 { 776 if len(s) > 10 {
756 s = s[:10] 777 s = s[:10]
757 } 778 }
779 t, err = time.ParseInLocation(format_Date, s, DefaultTimeLoc)
758 } else { 780 } else {
759 format = format_DateTime
760 if len(s) > 19 { 781 if len(s) > 19 {
761 s = s[:19] 782 s = s[:19]
762 } 783 }
784 t, err = time.ParseInLocation(format_DateTime, s, tz)
763 } 785 }
764 t, err := timeParse(s, format)
765 if err != nil && s != "0000-00-00" && s != "0000-00-00 00:00:00" { 786 if err != nil && s != "0000-00-00" && s != "0000-00-00 00:00:00" {
766 tErr = err 787 tErr = err
767 goto end 788 goto end
...@@ -776,12 +797,16 @@ setValue: ...@@ -776,12 +797,16 @@ setValue:
776 if str != nil { 797 if str != nil {
777 var err error 798 var err error
778 switch fieldType { 799 switch fieldType {
800 case TypeBitField:
801 _, err = str.Int8()
779 case TypeSmallIntegerField: 802 case TypeSmallIntegerField:
780 _, err = str.Int16() 803 _, err = str.Int16()
781 case TypeIntegerField: 804 case TypeIntegerField:
782 _, err = str.Int32() 805 _, err = str.Int32()
783 case TypeBigIntegerField: 806 case TypeBigIntegerField:
784 _, err = str.Int64() 807 _, err = str.Int64()
808 case TypePostiveBitField:
809 _, err = str.Uint8()
785 case TypePositiveSmallIntegerField: 810 case TypePositiveSmallIntegerField:
786 _, err = str.Uint16() 811 _, err = str.Uint16()
787 case TypePositiveIntegerField: 812 case TypePositiveIntegerField:
...@@ -835,7 +860,7 @@ end: ...@@ -835,7 +860,7 @@ end:
835 860
836 } 861 }
837 862
838 func (d *dbBase) setValue(fi *fieldInfo, value interface{}, field *reflect.Value) (interface{}, error) { 863 func (d *dbBase) setFieldValue(fi *fieldInfo, value interface{}, field *reflect.Value) (interface{}, error) {
839 864
840 fieldType := fi.fieldType 865 fieldType := fi.fieldType
841 isNative := fi.isFielder == false 866 isNative := fi.isFielder == false
...@@ -909,7 +934,7 @@ setValue: ...@@ -909,7 +934,7 @@ setValue:
909 return value, nil 934 return value, nil
910 } 935 }
911 936
912 func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, exprs []string, container interface{}) (int64, error) { 937 func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Condition, exprs []string, container interface{}, tz *time.Location) (int64, error) {
913 938
914 var ( 939 var (
915 maps []Params 940 maps []Params
...@@ -960,7 +985,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond ...@@ -960,7 +985,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
960 } 985 }
961 } 986 }
962 987
963 where, args := tables.getCondSql(cond, false) 988 where, args := tables.getCondSql(cond, false, tz)
964 orderBy := tables.getOrderSql(qs.orders) 989 orderBy := tables.getOrderSql(qs.orders)
965 limit := tables.getLimitSql(mi, qs.offset, qs.limit) 990 limit := tables.getLimitSql(mi, qs.offset, qs.limit)
966 join := tables.getJoinSql() 991 join := tables.getJoinSql()
...@@ -1007,7 +1032,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond ...@@ -1007,7 +1032,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
1007 1032
1008 val := reflect.Indirect(reflect.ValueOf(ref)).Interface() 1033 val := reflect.Indirect(reflect.ValueOf(ref)).Interface()
1009 1034
1010 value, err := d.getValue(fi, val) 1035 value, err := d.convertValueFromDB(fi, val, tz)
1011 if err != nil { 1036 if err != nil {
1012 panic(fmt.Sprintf("db value convert failed `%v` %s", val, err.Error())) 1037 panic(fmt.Sprintf("db value convert failed `%v` %s", val, err.Error()))
1013 } 1038 }
...@@ -1022,7 +1047,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond ...@@ -1022,7 +1047,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
1022 1047
1023 val := reflect.Indirect(reflect.ValueOf(ref)).Interface() 1048 val := reflect.Indirect(reflect.ValueOf(ref)).Interface()
1024 1049
1025 value, err := d.getValue(fi, val) 1050 value, err := d.convertValueFromDB(fi, val, tz)
1026 if err != nil { 1051 if err != nil {
1027 panic(fmt.Sprintf("db value convert failed `%v` %s", val, err.Error())) 1052 panic(fmt.Sprintf("db value convert failed `%v` %s", val, err.Error()))
1028 } 1053 }
...@@ -1036,7 +1061,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond ...@@ -1036,7 +1061,7 @@ func (d *dbBase) ReadValues(q dbQuerier, qs *querySet, mi *modelInfo, cond *Cond
1036 1061
1037 val := reflect.Indirect(reflect.ValueOf(ref)).Interface() 1062 val := reflect.Indirect(reflect.ValueOf(ref)).Interface()
1038 1063
1039 value, err := d.getValue(fi, val) 1064 value, err := d.convertValueFromDB(fi, val, tz)
1040 if err != nil { 1065 if err != nil {
1041 panic(fmt.Sprintf("db value convert failed `%v` %s", val, err.Error())) 1066 panic(fmt.Sprintf("db value convert failed `%v` %s", val, err.Error()))
1042 } 1067 }
...@@ -1079,3 +1104,11 @@ func (d *dbBase) ReplaceMarks(query *string) { ...@@ -1079,3 +1104,11 @@ func (d *dbBase) ReplaceMarks(query *string) {
1079 func (d *dbBase) HasReturningID(*modelInfo, *string) bool { 1104 func (d *dbBase) HasReturningID(*modelInfo, *string) bool {
1080 return false 1105 return false
1081 } 1106 }
1107
1108 func (d *dbBase) TimeFromDB(t *time.Time, tz *time.Location) {
1109 *t = t.In(tz)
1110 }
1111
1112 func (d *dbBase) TimeToDB(t *time.Time, tz *time.Location) {
1113 *t = t.In(tz)
1114 }
......
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
5 "fmt" 5 "fmt"
6 "os" 6 "os"
7 "sync" 7 "sync"
8 "time"
8 ) 9 )
9 10
10 const defaultMaxIdle = 30 11 const defaultMaxIdle = 30
...@@ -82,6 +83,7 @@ type alias struct { ...@@ -82,6 +83,7 @@ type alias struct {
82 MaxIdle int 83 MaxIdle int
83 DB *sql.DB 84 DB *sql.DB
84 DbBaser dbBaser 85 DbBaser dbBaser
86 TZ *time.Location
85 } 87 }
86 88
87 func RegisterDataBase(name, driverName, dataSource string, maxIdle int) { 89 func RegisterDataBase(name, driverName, dataSource string, maxIdle int) {
...@@ -120,6 +122,33 @@ func RegisterDataBase(name, driverName, dataSource string, maxIdle int) { ...@@ -120,6 +122,33 @@ func RegisterDataBase(name, driverName, dataSource string, maxIdle int) {
120 122
121 al.DB.SetMaxIdleConns(al.MaxIdle) 123 al.DB.SetMaxIdleConns(al.MaxIdle)
122 124
125 // orm timezone system match database
126 // default use Local
127 al.TZ = time.Local
128
129 switch al.Driver {
130 case DR_MySQL:
131 row := al.DB.QueryRow("SELECT @@session.time_zone")
132 var tz string
133 row.Scan(&tz)
134 if tz != "SYSTEM" {
135 t, err := time.Parse("-07:00", tz)
136 if err == nil {
137 al.TZ = t.Location()
138 }
139 }
140 case DR_Sqlite:
141 al.TZ = time.UTC
142 case DR_Postgres:
143 row := al.DB.QueryRow("SELECT current_setting('TIMEZONE')")
144 var tz string
145 row.Scan(&tz)
146 loc, err := time.LoadLocation(tz)
147 if err == nil {
148 al.TZ = loc
149 }
150 }
151
123 err = al.DB.Ping() 152 err = al.DB.Ping()
124 if err != nil { 153 if err != nil {
125 err = fmt.Errorf("register db `%s`, %s", name, err.Error()) 154 err = fmt.Errorf("register db `%s`, %s", name, err.Error())
...@@ -133,13 +162,22 @@ end: ...@@ -133,13 +162,22 @@ end:
133 } 162 }
134 } 163 }
135 164
136 func RegisterDriver(name string, typ DriverType) { 165 func RegisterDriver(driverName string, typ DriverType) {
137 if t, ok := drivers[name]; ok == false { 166 if t, ok := drivers[driverName]; ok == false {
138 drivers[name] = typ 167 drivers[driverName] = typ
139 } else { 168 } else {
140 if t != typ { 169 if t != typ {
141 fmt.Println("name `%s` db driver already registered and is other type") 170 fmt.Sprintf("driverName `%s` db driver already registered and is other type\n", driverName)
142 os.Exit(2) 171 os.Exit(2)
143 } 172 }
144 } 173 }
145 } 174 }
175
176 func SetDataBaseTZ(name string, tz *time.Location) {
177 if al, ok := dataBaseCache.get(name); ok {
178 al.TZ = tz
179 } else {
180 fmt.Sprintf("DataBase name `%s` not registered\n", name)
181 os.Exit(2)
182 }
183 }
......
...@@ -30,7 +30,7 @@ func (d *dbBasePostgres) OperatorSql(operator string) string { ...@@ -30,7 +30,7 @@ func (d *dbBasePostgres) OperatorSql(operator string) string {
30 return postgresOperators[operator] 30 return postgresOperators[operator]
31 } 31 }
32 32
33 func (d *dbBasePostgres) GenerateOperatorLeftCol(operator string, leftCol *string) { 33 func (d *dbBasePostgres) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) {
34 switch operator { 34 switch operator {
35 case "contains", "startswith", "endswith": 35 case "contains", "startswith", "endswith":
36 *leftCol = fmt.Sprintf("%s::text", *leftCol) 36 *leftCol = fmt.Sprintf("%s::text", *leftCol)
......
1 package orm 1 package orm
2 2
3 import (
4 "fmt"
5 )
6
3 var sqliteOperators = map[string]string{ 7 var sqliteOperators = map[string]string{
4 "exact": "= ?", 8 "exact": "= ?",
5 "iexact": "LIKE ? ESCAPE '\\'", 9 "iexact": "LIKE ? ESCAPE '\\'",
...@@ -25,6 +29,12 @@ func (d *dbBaseSqlite) OperatorSql(operator string) string { ...@@ -25,6 +29,12 @@ func (d *dbBaseSqlite) OperatorSql(operator string) string {
25 return sqliteOperators[operator] 29 return sqliteOperators[operator]
26 } 30 }
27 31
32 func (d *dbBaseSqlite) GenerateOperatorLeftCol(fi *fieldInfo, operator string, leftCol *string) {
33 if fi.fieldType == TypeDateField {
34 *leftCol = fmt.Sprintf("DATE(%s)", *leftCol)
35 }
36 }
37
28 func (d *dbBaseSqlite) SupportUpdateJoin() bool { 38 func (d *dbBaseSqlite) SupportUpdateJoin() bool {
29 return false 39 return false
30 } 40 }
......
...@@ -3,6 +3,7 @@ package orm ...@@ -3,6 +3,7 @@ package orm
3 import ( 3 import (
4 "fmt" 4 "fmt"
5 "strings" 5 "strings"
6 "time"
6 ) 7 )
7 8
8 type dbTable struct { 9 type dbTable struct {
...@@ -266,7 +267,7 @@ func (d *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string ...@@ -266,7 +267,7 @@ func (d *dbTables) parseExprs(mi *modelInfo, exprs []string) (index, name string
266 return 267 return
267 } 268 }
268 269
269 func (d *dbTables) getCondSql(cond *Condition, sub bool) (where string, params []interface{}) { 270 func (d *dbTables) getCondSql(cond *Condition, sub bool, tz *time.Location) (where string, params []interface{}) {
270 if cond == nil || cond.IsEmpty() { 271 if cond == nil || cond.IsEmpty() {
271 return 272 return
272 } 273 }
...@@ -288,7 +289,7 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool) (where string, params [ ...@@ -288,7 +289,7 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool) (where string, params [
288 where += "NOT " 289 where += "NOT "
289 } 290 }
290 if p.isCond { 291 if p.isCond {
291 w, ps := d.getCondSql(p.cond, true) 292 w, ps := d.getCondSql(p.cond, true, tz)
292 if w != "" { 293 if w != "" {
293 w = fmt.Sprintf("( %s) ", w) 294 w = fmt.Sprintf("( %s) ", w)
294 } 295 }
...@@ -313,10 +314,10 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool) (where string, params [ ...@@ -313,10 +314,10 @@ func (d *dbTables) getCondSql(cond *Condition, sub bool) (where string, params [
313 operator = "exact" 314 operator = "exact"
314 } 315 }
315 316
316 operSql, args := d.base.GenerateOperatorSql(mi, fi, operator, p.args) 317 operSql, args := d.base.GenerateOperatorSql(mi, fi, operator, p.args, tz)
317 318
318 leftCol := fmt.Sprintf("%s.%s%s%s", index, Q, fi.column, Q) 319 leftCol := fmt.Sprintf("%s.%s%s%s", index, Q, fi.column, Q)
319 d.base.GenerateOperatorLeftCol(operator, &leftCol) 320 d.base.GenerateOperatorLeftCol(fi, operator, &leftCol)
320 321
321 where += fmt.Sprintf("%s %s ", leftCol, operSql) 322 where += fmt.Sprintf("%s %s ", leftCol, operSql)
322 params = append(params, args...) 323 params = append(params, args...)
......
...@@ -24,7 +24,7 @@ func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interfac ...@@ -24,7 +24,7 @@ func getExistPk(mi *modelInfo, ind reflect.Value) (column string, value interfac
24 return 24 return
25 } 25 }
26 26
27 func getFlatParams(fi *fieldInfo, args []interface{}) (params []interface{}) { 27 func getFlatParams(fi *fieldInfo, args []interface{}, tz *time.Location) (params []interface{}) {
28 28
29 outFor: 29 outFor:
30 for _, arg := range args { 30 for _, arg := range args {
...@@ -39,9 +39,9 @@ outFor: ...@@ -39,9 +39,9 @@ outFor:
39 case []byte: 39 case []byte:
40 case time.Time: 40 case time.Time:
41 if fi != nil && fi.fieldType == TypeDateField { 41 if fi != nil && fi.fieldType == TypeDateField {
42 arg = v.Format(format_Date) 42 arg = v.In(DefaultTimeLoc).Format(format_Date)
43 } else { 43 } else {
44 arg = v.Format(format_DateTime) 44 arg = v.In(tz).Format(format_DateTime)
45 } 45 }
46 default: 46 default:
47 kind := val.Kind() 47 kind := val.Kind()
...@@ -65,7 +65,7 @@ outFor: ...@@ -65,7 +65,7 @@ outFor:
65 } 65 }
66 66
67 if len(args) > 0 { 67 if len(args) > 0 {
68 p := getFlatParams(fi, args) 68 p := getFlatParams(fi, args, tz)
69 params = append(params, p...) 69 params = append(params, p...)
70 } 70 }
71 continue outFor 71 continue outFor
......
...@@ -164,27 +164,91 @@ type Profile struct { ...@@ -164,27 +164,91 @@ type Profile struct {
164 ``` 164 ```
165 165
166 166
167 ## Struct Field 类型与数据库的对应 167 ## 模型字段与数据库类型的对应
168 168
169 现在 orm 支持下面的字段形式 169 在此列出 orm 推荐的对应数据库类型,自动建表功能也会以此为标准。
170 170
171 | go type | field type | mysql type 171 默认所有的字段都是 **NOT NULL**
172 | :--- | :--- | :--- 172
173 | bool | TypeBooleanField | tinyint 173 #### MySQL
174 | string | TypeCharField | varchar 174
175 | string | TypeTextField | longtext 175 | go |mysql
176 | time.Time | TypeDateField | date 176 | :--- | :---
177 | time.TIme | TypeDateTimeField | datetime 177 | bool | bool
178 | int16 |TypeSmallIntegerField | int(4) 178 | string - 设置 size 时 | varchar(size)
179 | int, int32 |TypeIntegerField | int(11) 179 | string | longtext
180 | int64 |TypeBigIntegerField | bigint(20) 180 | time.Time - 设置 type 为 date 时 | date
181 | uint, uint16 |TypePositiveSmallIntegerField | int(4) unsigned 181 | time.TIme | datetime
182 | uint32 |TypePositiveIntegerField | int(11) unsigned 182 | byte | tinyint unsigned
183 | uint64 |TypePositiveBigIntegerField | bigint(20) unsigned 183 | rune | integer
184 | float32, float64 | TypeFloatField | double 184 | int | integer
185 | float32, float64 | TypeDecimalField | double(digits, decimals) 185 | int8 | tinyint
186 186 | int16 | smallint
187 关系型的字段,其字段类型取决于对应的主键。 187 | int32 | integer
188 | int64 | bigint
189 | uint | integer unsigned
190 | uint8 | tinyint unsigned
191 | uint16 | smallint unsigned
192 | uint32 | integer unsigned
193 | uint64 | bigint unsigned
194 | float32 | double precision
195 | float64 | double precision
196 | float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
197
198 #### Sqlite3
199
200 | go | sqlite3
201 | :--- | :---
202 | bool | bool
203 | string - 设置 size 时 | varchar(size)
204 | string | text
205 | time.Time - 设置 type 为 date 时 | date
206 | time.TIme | datetime
207 | byte | tinyint unsigned
208 | rune | integer
209 | int | integer
210 | int8 | tinyint
211 | int16 | smallint
212 | int32 | integer
213 | int64 | bigint
214 | uint | integer unsigned
215 | uint8 | tinyint unsigned
216 | uint16 | smallint unsigned
217 | uint32 | integer unsigned
218 | uint64 | bigint unsigned
219 | float32 | real
220 | float64 | real
221 | float64 - 设置 digits, decimals 时 | decimal
222
223 #### PostgreSQL
224
225 | go | postgres
226 | :--- | :---
227 | bool | bool
228 | string - 设置 size 时 | varchar(size)
229 | string | text
230 | time.Time - 设置 type 为 date 时 | date
231 | time.TIme | timestamp with time zone
232 | byte | smallint CHECK("column" >= 0 AND "column" <= 255)
233 | rune | integer
234 | int | integer
235 | int8 | smallint CHECK("column" >= -127 AND "column" <= 128)
236 | int16 | smallint
237 | int32 | integer
238 | int64 | bigint
239 | uint | bigint CHECK("column" >= 0)
240 | uint8 | smallint CHECK("column" >= 0 AND "column" <= 255)
241 | uint16 | integer CHECK("column" >= 0)
242 | uint32 | bigint CHECK("column" >= 0)
243 | uint64 | bigint CHECK("column" >= 0)
244 | float32 | double precision
245 | float64 | double precision
246 | float64 - 设置 digits, decimals 时 | numeric(digits, decimals)
247
248
249 ## 关系型字段
250
251 其字段类型取决于对应的主键。
188 252
189 * RelForeignKey 253 * RelForeignKey
190 * RelOneToOne 254 * RelOneToOne
......
...@@ -80,7 +80,7 @@ import ( ...@@ -80,7 +80,7 @@ import (
80 80
81 #### RegisterDriver 81 #### RegisterDriver
82 82
83 三种数据库类型 83 三种默认数据库类型
84 84
85 ```go 85 ```go
86 orm.DR_MySQL 86 orm.DR_MySQL
...@@ -93,7 +93,7 @@ orm.DR_Postgres ...@@ -93,7 +93,7 @@ orm.DR_Postgres
93 // 参数2 数据库类型 93 // 参数2 数据库类型
94 // 这个用来设置 driverName 对应的数据库类型 94 // 这个用来设置 driverName 对应的数据库类型
95 // mysql / sqlite3 / postgres 这三种是默认已经注册过的,所以可以无需设置 95 // mysql / sqlite3 / postgres 这三种是默认已经注册过的,所以可以无需设置
96 orm.RegisterDriver("mysql", orm.DR_MySQL) 96 orm.RegisterDriver("mymysql", orm.DR_MySQL)
97 ``` 97 ```
98 98
99 #### RegisterDataBase 99 #### RegisterDataBase
...@@ -108,6 +108,56 @@ orm 必须注册一个名称为 `default` 的数据库,用以作为默认使 ...@@ -108,6 +108,56 @@ orm 必须注册一个名称为 `default` 的数据库,用以作为默认使
108 orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", 30) 108 orm.RegisterDataBase("default", "mysql", "root:root@/orm_test?charset=utf8", 30)
109 ``` 109 ```
110 110
111 #### 时区设置
112
113 orm 默认使用 time.Local 本地时区
114
115 * 作用于 orm 自动创建的时间
116 * 从数据库中取回的时间转换成 orm 本地时间
117
118 如果需要的话,你也可以进行更改
119
120 ```go
121 // 设置为 UTC 时间
122 orm.DefaultTimeLoc = time.UTC
123 ```
124
125 orm 在进行 RegisterDataBase 的同时,会获取数据库使用的时区,然后在 time.Time 类型存取的时做相应转换,以匹配时间系统,从而保证时间不会出错。
126
127 **注意:** 鉴于 Sqlite3 的设计,存取默认都为 UTC 时间
128
129 ## RegisterModel
130
131 如果使用 orm.QuerySeter 进行高级查询的话,这个是必须的。
132
133 反之,如果只使用 Raw 查询和 map struct,是无需这一步的。您可以去查看 [Raw SQL 查询](Raw.md)
134
135 将你定义的 Model 进行注册,最佳设计是有单独的 models.go 文件,在他的 init 函数中进行注册。
136
137
138 迷你版 models.go
139 ```go
140 package main
141
142 import "github.com/astaxie/beego/orm"
143
144 type User struct {
145 Id int `orm:"auto"`
146 name string
147 }
148
149 func init(){
150 orm.RegisterModel(new(User))
151 }
152 ```
153
154 RegisterModel 也可以同时注册多个 model
155
156 ```go
157 orm.RegisterModel(new(User), new(Profile), new(Post))
158 ```
159
160
111 ## ORM 接口使用 161 ## ORM 接口使用
112 162
113 使用 orm 必然接触的 Ormer 接口,我们来熟悉一下 163 使用 orm 必然接触的 Ormer 接口,我们来熟悉一下
......
...@@ -15,7 +15,7 @@ qs = o.QueryTable(user) // 返回 QuerySeter ...@@ -15,7 +15,7 @@ qs = o.QueryTable(user) // 返回 QuerySeter
15 ``` 15 ```
16 ## expr 16 ## expr
17 17
18 QuerySeter 中用于描述字段和 sql 操作符使用简单的 expr 查询方法 18 QuerySeter 中用于描述字段和 sql 操作符使用简单的 expr 查询方法
19 19
20 字段组合的前后顺序依照表的关系,比如 User 表拥有 Profile 的外键,那么对 User 表查询对应的 Profile.Age 为条件,则使用 `Profile__Age` 注意,字段的分隔符号使用双下划线 `__`,除了描述字段, expr 的尾部可以增加操作符以执行对应的 sql 操作。比如 `Profile__Age__gt` 代表 Profile.Age > 18 的条件查询。 20 字段组合的前后顺序依照表的关系,比如 User 表拥有 Profile 的外键,那么对 User 表查询对应的 Profile.Age 为条件,则使用 `Profile__Age` 注意,字段的分隔符号使用双下划线 `__`,除了描述字段, expr 的尾部可以增加操作符以执行对应的 sql 操作。比如 `Profile__Age__gt` 代表 Profile.Age > 18 的条件查询。
21 21
......
1 ## 文档目录 1 ## 文档目录
2 2
3
4 1. [Orm 使用方法](Orm.md) 3 1. [Orm 使用方法](Orm.md)
5 - [数据库的设置](Orm.md#数据库的设置) 4 - [数据库的设置](Orm.md#数据库的设置)
5 * [驱动类型设置](Orm.md#registerdriver)
6 * [参数设置](Orm.md#registerdataBase)
7 * [时区设置](Orm.md#时区设置)
8 - [注册 ORM 使用的模型](Orm.md#registermodel)
6 - [ORM 接口使用](Orm.md#orm-接口使用) 9 - [ORM 接口使用](Orm.md#orm-接口使用)
7 - [调试模式打印查询语句](Orm.md#调试模式打印查询语句) 10 - [调试模式打印查询语句](Orm.md#调试模式打印查询语句)
8 2. [对象的CRUD操作](Object.md) 11 2. [对象的CRUD操作](Object.md)
...@@ -15,6 +18,12 @@ ...@@ -15,6 +18,12 @@
15 6. [模型定义](Models.md) 18 6. [模型定义](Models.md)
16 - [Struct Tag 设置参数](Models.md#struct-tag-设置参数) 19 - [Struct Tag 设置参数](Models.md#struct-tag-设置参数)
17 - [表关系设置](Models.md#表关系设置) 20 - [表关系设置](Models.md#表关系设置)
18 - [Struct Field 类型与数据库的对应](Models.md#struct-field-类型与数据库的对应) 21 - [模型字段与数据库类型的对应](Models.md#模型字段与数据库类型的对应)
19 7. Custom Fields 22 7. Custom Fields
20 8. Faq 23 8. Faq
24
25
26 ### 文档更新记录
27
28 * 2013-08-13: ORM 的 [时区设置](Orm.md#时区设置)
29 * 2013-08-13: [模型字段与数据库类型的对应](Models.md#模型字段与数据库类型的对应) 推荐的数据库对应使用的类型
......
...@@ -22,12 +22,16 @@ const ( ...@@ -22,12 +22,16 @@ const (
22 // time.Time 22 // time.Time
23 TypeDateTimeField 23 TypeDateTimeField
24 24
25 // int8
26 TypeBitField
25 // int16 27 // int16
26 TypeSmallIntegerField 28 TypeSmallIntegerField
27 // int32 29 // int32
28 TypeIntegerField 30 TypeIntegerField
29 // int64 31 // int64
30 TypeBigIntegerField 32 TypeBigIntegerField
33 // uint8
34 TypePostiveBitField
31 // uint16 35 // uint16
32 TypePositiveSmallIntegerField 36 TypePositiveSmallIntegerField
33 // uint32 37 // uint32
...@@ -49,8 +53,8 @@ const ( ...@@ -49,8 +53,8 @@ const (
49 53
50 const ( 54 const (
51 IsIntegerField = ^-TypePositiveBigIntegerField >> 4 << 5 55 IsIntegerField = ^-TypePositiveBigIntegerField >> 4 << 5
52 IsPostiveIntegerField = ^-TypePositiveBigIntegerField >> 7 << 8 56 IsPostiveIntegerField = ^-TypePositiveBigIntegerField >> 8 << 9
53 IsRelField = ^-RelReverseMany >> 12 << 13 57 IsRelField = ^-RelReverseMany >> 14 << 15
54 IsFieldType = ^-RelReverseMany<<1 + 1 58 IsFieldType = ^-RelReverseMany<<1 + 1
55 ) 59 )
56 60
......
...@@ -327,8 +327,8 @@ checkType: ...@@ -327,8 +327,8 @@ checkType:
327 case TypeDecimalField: 327 case TypeDecimalField:
328 d1 := digits 328 d1 := digits
329 d2 := decimals 329 d2 := decimals
330 v1, er1 := StrTo(d1).Int16() 330 v1, er1 := StrTo(d1).Int8()
331 v2, er2 := StrTo(d2).Int16() 331 v2, er2 := StrTo(d2).Int8()
332 if er1 != nil || er2 != nil { 332 if er1 != nil || er2 != nil {
333 err = fmt.Errorf("wrong digits/decimals value %s/%s", d2, d1) 333 err = fmt.Errorf("wrong digits/decimals value %s/%s", d2, d1)
334 goto end 334 goto end
...@@ -383,12 +383,16 @@ checkType: ...@@ -383,12 +383,16 @@ checkType:
383 _, err = v.Bool() 383 _, err = v.Bool()
384 case TypeFloatField, TypeDecimalField: 384 case TypeFloatField, TypeDecimalField:
385 _, err = v.Float64() 385 _, err = v.Float64()
386 case TypeBitField:
387 _, err = v.Int8()
386 case TypeSmallIntegerField: 388 case TypeSmallIntegerField:
387 _, err = v.Int16() 389 _, err = v.Int16()
388 case TypeIntegerField: 390 case TypeIntegerField:
389 _, err = v.Int32() 391 _, err = v.Int32()
390 case TypeBigIntegerField: 392 case TypeBigIntegerField:
391 _, err = v.Int64() 393 _, err = v.Int64()
394 case TypePostiveBitField:
395 _, err = v.Uint8()
392 case TypePositiveSmallIntegerField: 396 case TypePositiveSmallIntegerField:
393 _, err = v.Uint16() 397 _, err = v.Uint16()
394 case TypePositiveIntegerField: 398 case TypePositiveIntegerField:
......
...@@ -6,11 +6,60 @@ import ( ...@@ -6,11 +6,60 @@ import (
6 "strings" 6 "strings"
7 "time" 7 "time"
8 8
9 // _ "github.com/bylevel/pq"
9 _ "github.com/go-sql-driver/mysql" 10 _ "github.com/go-sql-driver/mysql"
10 _ "github.com/lib/pq" 11 _ "github.com/lib/pq"
11 _ "github.com/mattn/go-sqlite3" 12 _ "github.com/mattn/go-sqlite3"
12 ) 13 )
13 14
15 type Data struct {
16 Id int `orm:"auto"`
17 Boolean bool
18 Char string `orm:"size(50)"`
19 Text string
20 Date time.Time `orm:"type(date)"`
21 DateTime time.Time
22 Byte byte
23 Rune rune
24 Int int
25 Int8 int8
26 Int16 int16
27 Int32 int32
28 Int64 int64
29 Uint uint
30 Uint8 uint8
31 Uint16 uint16
32 Uint32 uint32
33 Uint64 uint64
34 Float32 float32
35 Float64 float64
36 Decimal float64 `orm:"digits(8);decimals(4)"`
37 }
38
39 type DataNull struct {
40 Id int `orm:"auto"`
41 Boolean bool `orm:"null"`
42 Char string `orm:"size(50);null"`
43 Text string `orm:"null"`
44 Date time.Time `orm:"type(date);null"`
45 DateTime time.Time `orm:"null"`
46 Byte byte `orm:"null"`
47 Rune rune `orm:"null"`
48 Int int `orm:"null"`
49 Int8 int8 `orm:"null"`
50 Int16 int16 `orm:"null"`
51 Int32 int32 `orm:"null"`
52 Int64 int64 `orm:"null"`
53 Uint uint `orm:"null"`
54 Uint8 uint8 `orm:"null"`
55 Uint16 uint16 `orm:"null"`
56 Uint32 uint32 `orm:"null"`
57 Uint64 uint64 `orm:"null"`
58 Float32 float32 `orm:"null"`
59 Float64 float64 `orm:"null"`
60 Decimal float64 `orm:"digits(8);decimals(4);null"`
61 }
62
14 type User struct { 63 type User struct {
15 Id int `orm:"auto"` 64 Id int `orm:"auto"`
16 UserName string `orm:"size(30);unique"` 65 UserName string `orm:"size(30);unique"`
...@@ -111,6 +160,8 @@ var initSQLs = map[string]string{ ...@@ -111,6 +160,8 @@ var initSQLs = map[string]string{
111 "DROP TABLE IF EXISTS `tag`;\n" + 160 "DROP TABLE IF EXISTS `tag`;\n" +
112 "DROP TABLE IF EXISTS `post_tags`;\n" + 161 "DROP TABLE IF EXISTS `post_tags`;\n" +
113 "DROP TABLE IF EXISTS `comment`;\n" + 162 "DROP TABLE IF EXISTS `comment`;\n" +
163 "DROP TABLE IF EXISTS `data`;\n" +
164 "DROP TABLE IF EXISTS `data_null`;\n" +
114 "CREATE TABLE `user_profile` (\n" + 165 "CREATE TABLE `user_profile` (\n" +
115 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" + 166 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" +
116 " `age` smallint NOT NULL,\n" + 167 " `age` smallint NOT NULL,\n" +
...@@ -153,6 +204,52 @@ var initSQLs = map[string]string{ ...@@ -153,6 +204,52 @@ var initSQLs = map[string]string{
153 " `parent_id` integer,\n" + 204 " `parent_id` integer,\n" +
154 " `created` datetime NOT NULL\n" + 205 " `created` datetime NOT NULL\n" +
155 ") ENGINE=INNODB;\n" + 206 ") ENGINE=INNODB;\n" +
207 "CREATE TABLE `data` (\n" +
208 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" +
209 " `boolean` bool NOT NULL,\n" +
210 " `char` varchar(50) NOT NULL,\n" +
211 " `text` longtext NOT NULL,\n" +
212 " `date` date NOT NULL,\n" +
213 " `date_time` datetime NOT NULL,\n" +
214 " `byte` tinyint unsigned NOT NULL,\n" +
215 " `rune` integer NOT NULL,\n" +
216 " `int` integer NOT NULL,\n" +
217 " `int8` tinyint NOT NULL,\n" +
218 " `int16` smallint NOT NULL,\n" +
219 " `int32` integer NOT NULL,\n" +
220 " `int64` bigint NOT NULL,\n" +
221 " `uint` integer unsigned NOT NULL,\n" +
222 " `uint8` tinyint unsigned NULL,\n" +
223 " `uint16` smallint unsigned NOT NULL,\n" +
224 " `uint32` integer unsigned NOT NULL,\n" +
225 " `uint64` bigint unsigned NOT NULL,\n" +
226 " `float32` double precision NOT NULL,\n" +
227 " `float64` double precision NOT NULL,\n" +
228 " `decimal` numeric(8,4) NOT NULL\n" +
229 ") ENGINE=INNODB;\n" +
230 "CREATE TABLE `data_null` (\n" +
231 " `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n" +
232 " `boolean` bool,\n" +
233 " `char` varchar(50),\n" +
234 " `text` longtext,\n" +
235 " `date` date,\n" +
236 " `date_time` datetime,\n" +
237 " `byte` tinyint unsigned,\n" +
238 " `rune` integer,\n" +
239 " `int` integer,\n" +
240 " `int8` tinyint,\n" +
241 " `int16` smallint,\n" +
242 " `int32` integer,\n" +
243 " `int64` bigint,\n" +
244 " `uint` integer unsigned,\n" +
245 " `uint8` tinyint unsigned,\n" +
246 " `uint16` smallint unsigned,\n" +
247 " `uint32` integer unsigned,\n" +
248 " `uint64` bigint unsigned,\n" +
249 " `float32` double precision,\n" +
250 " `float64` double precision,\n" +
251 " `decimal` numeric(8,4)\n" +
252 ") ENGINE=INNODB;\n" +
156 "CREATE INDEX `user_141c6eec` ON `user` (`profile_id`);\n" + 253 "CREATE INDEX `user_141c6eec` ON `user` (`profile_id`);\n" +
157 "CREATE INDEX `post_fbfc09f1` ON `post` (`user_id`);\n" + 254 "CREATE INDEX `post_fbfc09f1` ON `post` (`user_id`);\n" +
158 "CREATE INDEX `comment_699ae8ca` ON `comment` (`post_id`);\n" + 255 "CREATE INDEX `comment_699ae8ca` ON `comment` (`post_id`);\n" +
...@@ -165,6 +262,8 @@ DROP TABLE IF EXISTS "post"; ...@@ -165,6 +262,8 @@ DROP TABLE IF EXISTS "post";
165 DROP TABLE IF EXISTS "tag"; 262 DROP TABLE IF EXISTS "tag";
166 DROP TABLE IF EXISTS "post_tags"; 263 DROP TABLE IF EXISTS "post_tags";
167 DROP TABLE IF EXISTS "comment"; 264 DROP TABLE IF EXISTS "comment";
265 DROP TABLE IF EXISTS "data";
266 DROP TABLE IF EXISTS "data_null";
168 CREATE TABLE "user_profile" ( 267 CREATE TABLE "user_profile" (
169 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 268 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
170 "age" smallint NOT NULL, 269 "age" smallint NOT NULL,
...@@ -207,6 +306,52 @@ CREATE TABLE "comment" ( ...@@ -207,6 +306,52 @@ CREATE TABLE "comment" (
207 "parent_id" integer, 306 "parent_id" integer,
208 "created" datetime NOT NULL 307 "created" datetime NOT NULL
209 ); 308 );
309 CREATE TABLE "data" (
310 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
311 "boolean" bool NOT NULL,
312 "char" varchar(50) NOT NULL,
313 "text" text NOT NULL,
314 "date" date NOT NULL,
315 "date_time" datetime NOT NULL,
316 "byte" tinyint unsigned NOT NULL,
317 "rune" integer NOT NULL,
318 "int" integer NOT NULL,
319 "int8" tinyint NOT NULL,
320 "int16" smallint NOT NULL,
321 "int32" integer NOT NULL,
322 "int64" bigint NOT NULL,
323 "uint" integer unsigned NOT NULL,
324 "uint8" tinyint unsigned NOT NULL,
325 "uint16" smallint unsigned NOT NULL,
326 "uint32" integer unsigned NOT NULL,
327 "uint64" bigint unsigned NOT NULL,
328 "float32" real NOT NULL,
329 "float64" real NOT NULL,
330 "decimal" decimal
331 );
332 CREATE TABLE "data_null" (
333 "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
334 "boolean" bool,
335 "char" varchar(50),
336 "text" text,
337 "date" date,
338 "date_time" datetime,
339 "byte" tinyint unsigned,
340 "rune" integer,
341 "int" integer,
342 "int8" tinyint,
343 "int16" smallint,
344 "int32" integer,
345 "int64" bigint,
346 "uint" integer unsigned,
347 "uint8" tinyint unsigned,
348 "uint16" smallint unsigned,
349 "uint32" integer unsigned,
350 "uint64" bigint unsigned,
351 "float32" real,
352 "float64" real,
353 "decimal" decimal
354 );
210 CREATE INDEX "user_141c6eec" ON "user" ("profile_id"); 355 CREATE INDEX "user_141c6eec" ON "user" ("profile_id");
211 CREATE INDEX "post_fbfc09f1" ON "post" ("user_id"); 356 CREATE INDEX "post_fbfc09f1" ON "post" ("user_id");
212 CREATE INDEX "comment_699ae8ca" ON "comment" ("post_id"); 357 CREATE INDEX "comment_699ae8ca" ON "comment" ("post_id");
...@@ -220,6 +365,8 @@ DROP TABLE IF EXISTS "post"; ...@@ -220,6 +365,8 @@ DROP TABLE IF EXISTS "post";
220 DROP TABLE IF EXISTS "tag"; 365 DROP TABLE IF EXISTS "tag";
221 DROP TABLE IF EXISTS "post_tags"; 366 DROP TABLE IF EXISTS "post_tags";
222 DROP TABLE IF EXISTS "comment"; 367 DROP TABLE IF EXISTS "comment";
368 DROP TABLE IF EXISTS "data";
369 DROP TABLE IF EXISTS "data_null";
223 CREATE TABLE "user_profile" ( 370 CREATE TABLE "user_profile" (
224 "id" serial NOT NULL PRIMARY KEY, 371 "id" serial NOT NULL PRIMARY KEY,
225 "age" smallint NOT NULL, 372 "age" smallint NOT NULL,
...@@ -262,6 +409,52 @@ CREATE TABLE "comment" ( ...@@ -262,6 +409,52 @@ CREATE TABLE "comment" (
262 "parent_id" integer, 409 "parent_id" integer,
263 "created" timestamp with time zone NOT NULL 410 "created" timestamp with time zone NOT NULL
264 ); 411 );
412 CREATE TABLE "data" (
413 "id" serial NOT NULL PRIMARY KEY,
414 "boolean" bool NOT NULL,
415 "char" varchar(50) NOT NULL,
416 "text" text NOT NULL,
417 "date" date NOT NULL,
418 "date_time" timestamp with time zone NOT NULL,
419 "byte" smallint CHECK("byte" >= 0 AND "byte" <= 255) NOT NULL,
420 "rune" integer NOT NULL,
421 "int" integer NOT NULL,
422 "int8" smallint CHECK("int8" >= -127 AND "int8" <= 128) NOT NULL,
423 "int16" smallint NOT NULL,
424 "int32" integer NOT NULL,
425 "int64" bigint NOT NULL,
426 "uint" bigint CHECK("uint" >= 0) NOT NULL,
427 "uint8" smallint CHECK("uint8" >= 0 AND "uint8" <= 255) NOT NULL,
428 "uint16" integer CHECK("uint16" >= 0) NOT NULL,
429 "uint32" bigint CHECK("uint32" >= 0) NOT NULL,
430 "uint64" bigint CHECK("uint64" >= 0) NOT NULL,
431 "float32" double precision NOT NULL,
432 "float64" double precision NOT NULL,
433 "decimal" numeric(8, 4)
434 );
435 CREATE TABLE "data_null" (
436 "id" serial NOT NULL PRIMARY KEY,
437 "boolean" bool,
438 "char" varchar(50),
439 "text" text,
440 "date" date,
441 "date_time" timestamp with time zone,
442 "byte" smallint CHECK("byte" >= 0 AND "byte" <= 255),
443 "rune" integer,
444 "int" integer,
445 "int8" smallint CHECK("int8" >= -127 AND "int8" <= 128),
446 "int16" smallint,
447 "int32" integer,
448 "int64" bigint,
449 "uint" bigint CHECK("uint" >= 0),
450 "uint8" smallint CHECK("uint8" >= 0 AND "uint8" <= 255),
451 "uint16" integer CHECK("uint16" >= 0),
452 "uint32" bigint CHECK("uint32" >= 0),
453 "uint64" bigint CHECK("uint64" >= 0),
454 "float32" double precision,
455 "float64" double precision,
456 "decimal" numeric(8, 4)
457 );
265 CREATE INDEX "user_profile_id" ON "user" ("profile_id"); 458 CREATE INDEX "user_profile_id" ON "user" ("profile_id");
266 CREATE INDEX "post_user_id" ON "post" ("user_id"); 459 CREATE INDEX "post_user_id" ON "post" ("user_id");
267 CREATE INDEX "comment_post_id" ON "comment" ("post_id"); 460 CREATE INDEX "comment_post_id" ON "comment" ("post_id");
...@@ -269,6 +462,10 @@ CREATE INDEX "comment_parent_id" ON "comment" ("parent_id"); ...@@ -269,6 +462,10 @@ CREATE INDEX "comment_parent_id" ON "comment" ("parent_id");
269 `} 462 `}
270 463
271 func init() { 464 func init() {
465 // err := os.Setenv("TZ", "+00:00")
466 // fmt.Println(err)
467
468 RegisterModel(new(Data), new(DataNull))
272 RegisterModel(new(User)) 469 RegisterModel(new(User))
273 RegisterModel(new(Profile)) 470 RegisterModel(new(Profile))
274 RegisterModel(new(Post)) 471 RegisterModel(new(Post))
......
...@@ -43,15 +43,19 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col ...@@ -43,15 +43,19 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col
43 func getFieldType(val reflect.Value) (ft int, err error) { 43 func getFieldType(val reflect.Value) (ft int, err error) {
44 elm := reflect.Indirect(val) 44 elm := reflect.Indirect(val)
45 switch elm.Kind() { 45 switch elm.Kind() {
46 case reflect.Int8:
47 ft = TypeBitField
46 case reflect.Int16: 48 case reflect.Int16:
47 ft = TypeSmallIntegerField 49 ft = TypeSmallIntegerField
48 case reflect.Int32, reflect.Int: 50 case reflect.Int32, reflect.Int:
49 ft = TypeIntegerField 51 ft = TypeIntegerField
50 case reflect.Int64: 52 case reflect.Int64:
51 ft = TypeBigIntegerField 53 ft = TypeBigIntegerField
54 case reflect.Uint8:
55 ft = TypePostiveBitField
52 case reflect.Uint16: 56 case reflect.Uint16:
53 ft = TypePositiveSmallIntegerField 57 ft = TypePositiveSmallIntegerField
54 case reflect.Uint32: 58 case reflect.Uint32, reflect.Uint:
55 ft = TypePositiveIntegerField 59 ft = TypePositiveIntegerField
56 case reflect.Uint64: 60 case reflect.Uint64:
57 ft = TypePositiveBigIntegerField 61 ft = TypePositiveBigIntegerField
......
...@@ -55,7 +55,7 @@ func (o *orm) getMiInd(md interface{}) (mi *modelInfo, ind reflect.Value) { ...@@ -55,7 +55,7 @@ func (o *orm) getMiInd(md interface{}) (mi *modelInfo, ind reflect.Value) {
55 55
56 func (o *orm) Read(md interface{}) error { 56 func (o *orm) Read(md interface{}) error {
57 mi, ind := o.getMiInd(md) 57 mi, ind := o.getMiInd(md)
58 err := o.alias.DbBaser.Read(o.db, mi, ind) 58 err := o.alias.DbBaser.Read(o.db, mi, ind, o.alias.TZ)
59 if err != nil { 59 if err != nil {
60 return err 60 return err
61 } 61 }
...@@ -64,7 +64,7 @@ func (o *orm) Read(md interface{}) error { ...@@ -64,7 +64,7 @@ func (o *orm) Read(md interface{}) error {
64 64
65 func (o *orm) Insert(md interface{}) (int64, error) { 65 func (o *orm) Insert(md interface{}) (int64, error) {
66 mi, ind := o.getMiInd(md) 66 mi, ind := o.getMiInd(md)
67 id, err := o.alias.DbBaser.Insert(o.db, mi, ind) 67 id, err := o.alias.DbBaser.Insert(o.db, mi, ind, o.alias.TZ)
68 if err != nil { 68 if err != nil {
69 return id, err 69 return id, err
70 } 70 }
...@@ -78,7 +78,7 @@ func (o *orm) Insert(md interface{}) (int64, error) { ...@@ -78,7 +78,7 @@ func (o *orm) Insert(md interface{}) (int64, error) {
78 78
79 func (o *orm) Update(md interface{}) (int64, error) { 79 func (o *orm) Update(md interface{}) (int64, error) {
80 mi, ind := o.getMiInd(md) 80 mi, ind := o.getMiInd(md)
81 num, err := o.alias.DbBaser.Update(o.db, mi, ind) 81 num, err := o.alias.DbBaser.Update(o.db, mi, ind, o.alias.TZ)
82 if err != nil { 82 if err != nil {
83 return num, err 83 return num, err
84 } 84 }
...@@ -87,7 +87,7 @@ func (o *orm) Update(md interface{}) (int64, error) { ...@@ -87,7 +87,7 @@ func (o *orm) Update(md interface{}) (int64, error) {
87 87
88 func (o *orm) Delete(md interface{}) (int64, error) { 88 func (o *orm) Delete(md interface{}) (int64, error) {
89 mi, ind := o.getMiInd(md) 89 mi, ind := o.getMiInd(md)
90 num, err := o.alias.DbBaser.Delete(o.db, mi, ind) 90 num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ)
91 if err != nil { 91 if err != nil {
92 return num, err 92 return num, err
93 } 93 }
......
...@@ -28,7 +28,7 @@ func (o *insertSet) Insert(md interface{}) (int64, error) { ...@@ -28,7 +28,7 @@ func (o *insertSet) Insert(md interface{}) (int64, error) {
28 if name != o.mi.fullName { 28 if name != o.mi.fullName {
29 panic(fmt.Sprintf("<Inserter.Insert> need model `%s` but found `%s`", o.mi.fullName, name)) 29 panic(fmt.Sprintf("<Inserter.Insert> need model `%s` but found `%s`", o.mi.fullName, name))
30 } 30 }
31 id, err := o.orm.alias.DbBaser.InsertStmt(o.stmt, o.mi, ind) 31 id, err := o.orm.alias.DbBaser.InsertStmt(o.stmt, o.mi, ind, o.orm.alias.TZ)
32 if err != nil { 32 if err != nil {
33 return id, err 33 return id, err
34 } 34 }
......
...@@ -77,15 +77,15 @@ func (o querySet) SetCond(cond *Condition) QuerySeter { ...@@ -77,15 +77,15 @@ func (o querySet) SetCond(cond *Condition) QuerySeter {
77 } 77 }
78 78
79 func (o *querySet) Count() (int64, error) { 79 func (o *querySet) Count() (int64, error) {
80 return o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond) 80 return o.orm.alias.DbBaser.Count(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ)
81 } 81 }
82 82
83 func (o *querySet) Update(values Params) (int64, error) { 83 func (o *querySet) Update(values Params) (int64, error) {
84 return o.orm.alias.DbBaser.UpdateBatch(o.orm.db, o, o.mi, o.cond, values) 84 return o.orm.alias.DbBaser.UpdateBatch(o.orm.db, o, o.mi, o.cond, values, o.orm.alias.TZ)
85 } 85 }
86 86
87 func (o *querySet) Delete() (int64, error) { 87 func (o *querySet) Delete() (int64, error) {
88 return o.orm.alias.DbBaser.DeleteBatch(o.orm.db, o, o.mi, o.cond) 88 return o.orm.alias.DbBaser.DeleteBatch(o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ)
89 } 89 }
90 90
91 func (o *querySet) PrepareInsert() (Inserter, error) { 91 func (o *querySet) PrepareInsert() (Inserter, error) {
...@@ -93,11 +93,11 @@ func (o *querySet) PrepareInsert() (Inserter, error) { ...@@ -93,11 +93,11 @@ func (o *querySet) PrepareInsert() (Inserter, error) {
93 } 93 }
94 94
95 func (o *querySet) All(container interface{}) (int64, error) { 95 func (o *querySet) All(container interface{}) (int64, error) {
96 return o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container) 96 return o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ)
97 } 97 }
98 98
99 func (o *querySet) One(container interface{}) error { 99 func (o *querySet) One(container interface{}) error {
100 num, err := o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container) 100 num, err := o.orm.alias.DbBaser.ReadBatch(o.orm.db, o, o.mi, o.cond, container, o.orm.alias.TZ)
101 if err != nil { 101 if err != nil {
102 return err 102 return err
103 } 103 }
...@@ -111,15 +111,15 @@ func (o *querySet) One(container interface{}) error { ...@@ -111,15 +111,15 @@ func (o *querySet) One(container interface{}) error {
111 } 111 }
112 112
113 func (o *querySet) Values(results *[]Params, exprs ...string) (int64, error) { 113 func (o *querySet) Values(results *[]Params, exprs ...string) (int64, error) {
114 return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results) 114 return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ)
115 } 115 }
116 116
117 func (o *querySet) ValuesList(results *[]ParamsList, exprs ...string) (int64, error) { 117 func (o *querySet) ValuesList(results *[]ParamsList, exprs ...string) (int64, error) {
118 return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results) 118 return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, exprs, results, o.orm.alias.TZ)
119 } 119 }
120 120
121 func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) { 121 func (o *querySet) ValuesFlat(result *ParamsList, expr string) (int64, error) {
122 return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, []string{expr}, result) 122 return o.orm.alias.DbBaser.ReadValues(o.orm.db, o, o.mi, o.cond, []string{expr}, result, o.orm.alias.TZ)
123 } 123 }
124 124
125 func newQuerySet(orm *orm, mi *modelInfo) QuerySeter { 125 func newQuerySet(orm *orm, mi *modelInfo) QuerySeter {
......
...@@ -60,7 +60,7 @@ func (o *rawSet) Exec() (sql.Result, error) { ...@@ -60,7 +60,7 @@ func (o *rawSet) Exec() (sql.Result, error) {
60 query := o.query 60 query := o.query
61 o.orm.alias.DbBaser.ReplaceMarks(&query) 61 o.orm.alias.DbBaser.ReplaceMarks(&query)
62 62
63 args := getFlatParams(nil, o.args) 63 args := getFlatParams(nil, o.args, o.orm.alias.TZ)
64 return o.orm.db.Exec(query, args...) 64 return o.orm.db.Exec(query, args...)
65 } 65 }
66 66
...@@ -96,7 +96,7 @@ func (o *rawSet) readValues(container interface{}) (int64, error) { ...@@ -96,7 +96,7 @@ func (o *rawSet) readValues(container interface{}) (int64, error) {
96 query := o.query 96 query := o.query
97 o.orm.alias.DbBaser.ReplaceMarks(&query) 97 o.orm.alias.DbBaser.ReplaceMarks(&query)
98 98
99 args := getFlatParams(nil, o.args) 99 args := getFlatParams(nil, o.args, o.orm.alias.TZ)
100 100
101 var rs *sql.Rows 101 var rs *sql.Rows
102 if r, err := o.orm.db.Query(query, args...); err != nil { 102 if r, err := o.orm.db.Query(query, args...); err != nil {
......
...@@ -15,6 +15,11 @@ import ( ...@@ -15,6 +15,11 @@ import (
15 15
16 var _ = os.PathSeparator 16 var _ = os.PathSeparator
17 17
18 var (
19 test_Date = format_Date + " -0700"
20 test_DateTime = format_DateTime + " -0700"
21 )
22
18 type T_Code int 23 type T_Code int
19 24
20 const ( 25 const (
...@@ -141,7 +146,7 @@ func getCaller(skip int) string { ...@@ -141,7 +146,7 @@ func getCaller(skip int) string {
141 if cur == line { 146 if cur == line {
142 flag = ">>" 147 flag = ">>"
143 } 148 }
144 code := fmt.Sprintf(" %s %5d: %s", flag, cur, strings.TrimSpace(string(lines[o+i]))) 149 code := fmt.Sprintf(" %s %5d: %s", flag, cur, strings.Replace(string(lines[o+i]), "\t", " ", -1))
145 if code != "" { 150 if code != "" {
146 codes = append(codes, code) 151 codes = append(codes, code)
147 } 152 }
...@@ -158,7 +163,11 @@ func throwFail(t *testing.T, err error, args ...interface{}) { ...@@ -158,7 +163,11 @@ func throwFail(t *testing.T, err error, args ...interface{}) {
158 if err != nil { 163 if err != nil {
159 con := fmt.Sprintf("\t\nError: %s\n%s\n", err.Error(), getCaller(2)) 164 con := fmt.Sprintf("\t\nError: %s\n%s\n", err.Error(), getCaller(2))
160 if len(args) > 0 { 165 if len(args) > 0 {
161 con += fmt.Sprint(args...) 166 parts := make([]string, 0, len(args))
167 for _, arg := range args {
168 parts = append(parts, fmt.Sprintf("%v", arg))
169 }
170 con += " " + strings.Join(parts, ", ")
162 } 171 }
163 t.Error(con) 172 t.Error(con)
164 t.Fail() 173 t.Fail()
...@@ -169,7 +178,11 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) { ...@@ -169,7 +178,11 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) {
169 if err != nil { 178 if err != nil {
170 con := fmt.Sprintf("\t\nError: %s\n%s\n", err.Error(), getCaller(2)) 179 con := fmt.Sprintf("\t\nError: %s\n%s\n", err.Error(), getCaller(2))
171 if len(args) > 0 { 180 if len(args) > 0 {
172 con += fmt.Sprint(args...) 181 parts := make([]string, 0, len(args))
182 for _, arg := range args {
183 parts = append(parts, fmt.Sprintf("%v", arg))
184 }
185 con += " " + strings.Join(parts, ", ")
173 } 186 }
174 t.Error(con) 187 t.Error(con)
175 t.FailNow() 188 t.FailNow()
...@@ -177,13 +190,100 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) { ...@@ -177,13 +190,100 @@ func throwFailNow(t *testing.T, err error, args ...interface{}) {
177 } 190 }
178 191
179 func TestModelSyntax(t *testing.T) { 192 func TestModelSyntax(t *testing.T) {
180 mi, ok := modelCache.get("user") 193 user := &User{}
194 ind := reflect.ValueOf(user).Elem()
195 fn := getFullName(ind.Type())
196 mi, ok := modelCache.getByFN(fn)
197 throwFail(t, AssertIs(ok, T_Equal, true))
198
199 mi, ok = modelCache.get("user")
181 throwFail(t, AssertIs(ok, T_Equal, true)) 200 throwFail(t, AssertIs(ok, T_Equal, true))
182 if ok { 201 if ok {
183 throwFail(t, AssertIs(mi.fields.GetByName("ShouldSkip") == nil, T_Equal, true)) 202 throwFail(t, AssertIs(mi.fields.GetByName("ShouldSkip") == nil, T_Equal, true))
184 } 203 }
185 } 204 }
186 205
206 func TestDataTypes(t *testing.T) {
207 values := map[string]interface{}{
208 "Boolean": true,
209 "Char": "char",
210 "Text": "text",
211 "Date": time.Now(),
212 "DateTime": time.Now(),
213 "Byte": byte(1<<8 - 1),
214 "Rune": rune(1<<31 - 1),
215 "Int": int(1<<31 - 1),
216 "Int8": int8(1<<7 - 1),
217 "Int16": int16(1<<15 - 1),
218 "Int32": int32(1<<31 - 1),
219 "Int64": int64(1<<63 - 1),
220 "Uint": uint(1<<32 - 1),
221 "Uint8": uint8(1<<8 - 1),
222 "Uint16": uint16(1<<16 - 1),
223 "Uint32": uint32(1<<32 - 1),
224 "Uint64": uint64(1<<63 - 1), // uint64 values with high bit set are not supported
225 "Float32": float32(100.1234),
226 "Float64": float64(100.1234),
227 "Decimal": float64(100.1234),
228 }
229 d := Data{}
230 ind := reflect.Indirect(reflect.ValueOf(&d))
231
232 for name, value := range values {
233 e := ind.FieldByName(name)
234 e.Set(reflect.ValueOf(value))
235 }
236
237 id, err := dORM.Insert(&d)
238 throwFail(t, err)
239 throwFail(t, AssertIs(id, T_Equal, 1))
240
241 d = Data{Id: 1}
242 err = dORM.Read(&d)
243 throwFail(t, err)
244
245 ind = reflect.Indirect(reflect.ValueOf(&d))
246
247 for name, value := range values {
248 e := ind.FieldByName(name)
249 vu := e.Interface()
250 switch name {
251 case "Date":
252 vu = vu.(time.Time).In(DefaultTimeLoc).Format(test_Date)
253 value = value.(time.Time).In(DefaultTimeLoc).Format(test_Date)
254 case "DateTime":
255 vu = vu.(time.Time).In(DefaultTimeLoc).Format(test_DateTime)
256 value = value.(time.Time).In(DefaultTimeLoc).Format(test_DateTime)
257 }
258 throwFail(t, AssertIs(vu == value, T_Equal, true), value, vu)
259 }
260 }
261
262 func TestNullDataTypes(t *testing.T) {
263 d := DataNull{}
264
265 if IsPostgres {
266 // can removed when this fixed
267 // https://github.com/lib/pq/pull/125
268 d.DateTime = time.Now()
269 }
270
271 id, err := dORM.Insert(&d)
272 throwFail(t, err)
273 throwFail(t, AssertIs(id, T_Equal, 1))
274
275 d = DataNull{Id: 1}
276 err = dORM.Read(&d)
277 throwFail(t, err)
278
279 _, err = dORM.Raw(`INSERT INTO data_null (boolean) VALUES (?)`, nil).Exec()
280 throwFail(t, err)
281
282 d = DataNull{Id: 2}
283 err = dORM.Read(&d)
284 throwFail(t, err)
285 }
286
187 func TestCRUD(t *testing.T) { 287 func TestCRUD(t *testing.T) {
188 profile := NewProfile() 288 profile := NewProfile()
189 profile.Age = 30 289 profile.Age = 30
...@@ -214,8 +314,8 @@ func TestCRUD(t *testing.T) { ...@@ -214,8 +314,8 @@ func TestCRUD(t *testing.T) {
214 throwFail(t, AssertIs(u.Status, T_Equal, 3)) 314 throwFail(t, AssertIs(u.Status, T_Equal, 3))
215 throwFail(t, AssertIs(u.IsStaff, T_Equal, true)) 315 throwFail(t, AssertIs(u.IsStaff, T_Equal, true))
216 throwFail(t, AssertIs(u.IsActive, T_Equal, true)) 316 throwFail(t, AssertIs(u.IsActive, T_Equal, true))
217 throwFail(t, AssertIs(u.Created, T_Equal, user.Created, format_Date)) 317 throwFail(t, AssertIs(u.Created.In(DefaultTimeLoc), T_Equal, user.Created.In(DefaultTimeLoc), test_Date))
218 throwFail(t, AssertIs(u.Updated, T_Equal, user.Updated, format_DateTime)) 318 throwFail(t, AssertIs(u.Updated.In(DefaultTimeLoc), T_Equal, user.Updated.In(DefaultTimeLoc), test_DateTime))
219 319
220 user.UserName = "astaxie" 320 user.UserName = "astaxie"
221 user.Profile = profile 321 user.Profile = profile
...@@ -360,7 +460,9 @@ The program—and web server—godoc processes Go source files to extract docume ...@@ -360,7 +460,9 @@ The program—and web server—godoc processes Go source files to extract docume
360 } 460 }
361 461
362 func TestExpr(t *testing.T) { 462 func TestExpr(t *testing.T) {
363 qs := dORM.QueryTable("User") 463 user := &User{}
464 qs := dORM.QueryTable(user)
465 qs = dORM.QueryTable("User")
364 qs = dORM.QueryTable("user") 466 qs = dORM.QueryTable("user")
365 num, err := qs.Filter("UserName", "slene").Filter("user_name", "slene").Filter("profile__Age", 28).Count() 467 num, err := qs.Filter("UserName", "slene").Filter("user_name", "slene").Filter("profile__Age", 28).Count()
366 throwFail(t, err) 468 throwFail(t, err)
...@@ -369,6 +471,10 @@ func TestExpr(t *testing.T) { ...@@ -369,6 +471,10 @@ func TestExpr(t *testing.T) {
369 num, err = qs.Filter("created", time.Now()).Count() 471 num, err = qs.Filter("created", time.Now()).Count()
370 throwFail(t, err) 472 throwFail(t, err)
371 throwFail(t, AssertIs(num, T_Equal, 3)) 473 throwFail(t, AssertIs(num, T_Equal, 3))
474
475 num, err = qs.Filter("created", time.Now().Format(format_Date)).Count()
476 throwFail(t, err)
477 throwFail(t, AssertIs(num, T_Equal, 3))
372 } 478 }
373 479
374 func TestOperators(t *testing.T) { 480 func TestOperators(t *testing.T) {
...@@ -820,9 +926,11 @@ func TestRaw(t *testing.T) { ...@@ -820,9 +926,11 @@ func TestRaw(t *testing.T) {
820 res, err := dORM.Raw(`DELETE FROM "tag" WHERE "name" IN (?, ?, ?)`, []string{"name1", "name2", "name3"}).Exec() 926 res, err := dORM.Raw(`DELETE FROM "tag" WHERE "name" IN (?, ?, ?)`, []string{"name1", "name2", "name3"}).Exec()
821 throwFail(t, err) 927 throwFail(t, err)
822 928
823 num, err := res.RowsAffected() 929 if err == nil {
824 throwFail(t, err) 930 num, err := res.RowsAffected()
825 throwFail(t, AssertIs(num, T_Equal, 3)) 931 throwFail(t, err)
932 throwFail(t, AssertIs(num, T_Equal, 3))
933 }
826 } 934 }
827 } 935 }
828 } 936 }
......
...@@ -3,6 +3,7 @@ package orm ...@@ -3,6 +3,7 @@ package orm
3 import ( 3 import (
4 "database/sql" 4 "database/sql"
5 "reflect" 5 "reflect"
6 "time"
6 ) 7 )
7 8
8 type Driver interface { 9 type Driver interface {
...@@ -110,23 +111,25 @@ type txEnder interface { ...@@ -110,23 +111,25 @@ type txEnder interface {
110 } 111 }
111 112
112 type dbBaser interface { 113 type dbBaser interface {
113 Read(dbQuerier, *modelInfo, reflect.Value) error 114 Read(dbQuerier, *modelInfo, reflect.Value, *time.Location) error
114 Insert(dbQuerier, *modelInfo, reflect.Value) (int64, error) 115 Insert(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
115 InsertStmt(stmtQuerier, *modelInfo, reflect.Value) (int64, error) 116 InsertStmt(stmtQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
116 Update(dbQuerier, *modelInfo, reflect.Value) (int64, error) 117 Update(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
117 Delete(dbQuerier, *modelInfo, reflect.Value) (int64, error) 118 Delete(dbQuerier, *modelInfo, reflect.Value, *time.Location) (int64, error)
118 ReadBatch(dbQuerier, *querySet, *modelInfo, *Condition, interface{}) (int64, error) 119 ReadBatch(dbQuerier, *querySet, *modelInfo, *Condition, interface{}, *time.Location) (int64, error)
119 SupportUpdateJoin() bool 120 SupportUpdateJoin() bool
120 UpdateBatch(dbQuerier, *querySet, *modelInfo, *Condition, Params) (int64, error) 121 UpdateBatch(dbQuerier, *querySet, *modelInfo, *Condition, Params, *time.Location) (int64, error)
121 DeleteBatch(dbQuerier, *querySet, *modelInfo, *Condition) (int64, error) 122 DeleteBatch(dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
122 Count(dbQuerier, *querySet, *modelInfo, *Condition) (int64, error) 123 Count(dbQuerier, *querySet, *modelInfo, *Condition, *time.Location) (int64, error)
123 OperatorSql(string) string 124 OperatorSql(string) string
124 GenerateOperatorSql(*modelInfo, *fieldInfo, string, []interface{}) (string, []interface{}) 125 GenerateOperatorSql(*modelInfo, *fieldInfo, string, []interface{}, *time.Location) (string, []interface{})
125 GenerateOperatorLeftCol(string, *string) 126 GenerateOperatorLeftCol(*fieldInfo, string, *string)
126 PrepareInsert(dbQuerier, *modelInfo) (stmtQuerier, string, error) 127 PrepareInsert(dbQuerier, *modelInfo) (stmtQuerier, string, error)
127 ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}) (int64, error) 128 ReadValues(dbQuerier, *querySet, *modelInfo, *Condition, []string, interface{}, *time.Location) (int64, error)
128 MaxLimit() uint64 129 MaxLimit() uint64
129 TableQuote() string 130 TableQuote() string
130 ReplaceMarks(*string) 131 ReplaceMarks(*string)
131 HasReturningID(*modelInfo, *string) bool 132 HasReturningID(*modelInfo, *string) bool
133 TimeFromDB(*time.Time, *time.Location)
134 TimeToDB(*time.Time, *time.Location)
132 } 135 }
......
...@@ -38,6 +38,11 @@ func (f StrTo) Float64() (float64, error) { ...@@ -38,6 +38,11 @@ func (f StrTo) Float64() (float64, error) {
38 return strconv.ParseFloat(f.String(), 64) 38 return strconv.ParseFloat(f.String(), 64)
39 } 39 }
40 40
41 func (f StrTo) Int8() (int8, error) {
42 v, err := strconv.ParseInt(f.String(), 10, 8)
43 return int8(v), err
44 }
45
41 func (f StrTo) Int16() (int16, error) { 46 func (f StrTo) Int16() (int16, error) {
42 v, err := strconv.ParseInt(f.String(), 10, 16) 47 v, err := strconv.ParseInt(f.String(), 10, 16)
43 return int16(v), err 48 return int16(v), err
...@@ -53,6 +58,11 @@ func (f StrTo) Int64() (int64, error) { ...@@ -53,6 +58,11 @@ func (f StrTo) Int64() (int64, error) {
53 return int64(v), err 58 return int64(v), err
54 } 59 }
55 60
61 func (f StrTo) Uint8() (uint8, error) {
62 v, err := strconv.ParseUint(f.String(), 10, 8)
63 return uint8(v), err
64 }
65
56 func (f StrTo) Uint16() (uint16, error) { 66 func (f StrTo) Uint16() (uint16, error) {
57 v, err := strconv.ParseUint(f.String(), 10, 16) 67 v, err := strconv.ParseUint(f.String(), 10, 16)
58 return uint16(v), err 68 return uint16(v), err
...@@ -85,6 +95,8 @@ func ToStr(value interface{}, args ...int) (s string) { ...@@ -85,6 +95,8 @@ func ToStr(value interface{}, args ...int) (s string) {
85 s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64)) 95 s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
86 case int: 96 case int:
87 s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) 97 s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
98 case int8:
99 s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
88 case int16: 100 case int16:
89 s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) 101 s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
90 case int32: 102 case int32:
...@@ -93,6 +105,8 @@ func ToStr(value interface{}, args ...int) (s string) { ...@@ -93,6 +105,8 @@ func ToStr(value interface{}, args ...int) (s string) {
93 s = strconv.FormatInt(v, argInt(args).Get(0, 10)) 105 s = strconv.FormatInt(v, argInt(args).Get(0, 10))
94 case uint: 106 case uint:
95 s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) 107 s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
108 case uint8:
109 s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
96 case uint16: 110 case uint16:
97 s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) 111 s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
98 case uint32: 112 case uint32:
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!