diff --git a/session.go b/session.go index 9e56bfc5..0c52e917 100644 --- a/session.go +++ b/session.go @@ -1254,6 +1254,9 @@ func row2map(rows *sql.Rows, fields []string) (resultsMap map[string][]byte, err if err := rows.Scan(scanResultContainers...); err != nil { return nil, err } + + // !nashtsai! TODO optimization for query performance, where current process has gone from + // sql driver converted type back to []bytes then to ORM's fields for ii, key := range fields { rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])) @@ -1288,7 +1291,7 @@ func row2map(rows *sql.Rows, fields []string) (resultsMap map[string][]byte, err } //时间类型 case reflect.Struct: - if aa.String() == "time.Time" { + if aa == reflect.TypeOf(c_TIME_DEFAULT) { str = rawValue.Interface().(time.Time).Format(time.RFC3339Nano) result[key] = []byte(str) } else { @@ -1585,6 +1588,46 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) { return session.innerInsertMulti(rowsSlicePtr) } +func (session *Session) byte2Time(col *Column, data []byte) (outTime time.Time, outErr error) { + sdata := strings.TrimSpace(string(data)) + var x time.Time + var err error + + if sdata == "0000-00-00 00:00:00" || + sdata == "0001-01-01 00:00:00" { + } else if !strings.ContainsAny(sdata, "- :") { + // time stamp + sd, err := strconv.ParseInt(sdata, 10, 64) + if err == nil { + x = time.Unix(0, sd) + } + } else if len(sdata) > 19 { + x, err = time.Parse(time.RFC3339Nano, sdata) + if err != nil { + x, err = time.Parse("2006-01-02 15:04:05.999999999", sdata) + } + } else if len(sdata) == 19 { + x, err = time.Parse("2006-01-02 15:04:05", sdata) + } else if len(sdata) == 10 && sdata[4] == '-' && sdata[7] == '-' { + x, err = time.Parse("2006-01-02", sdata) + } else if col.SQLType.Name == Time { + if len(sdata) > 8 { + sdata = sdata[len(sdata)-8:] + } + st := fmt.Sprintf("2006-01-02 %v", sdata) + x, err = time.Parse("2006-01-02 15:04:05", st) + } else { + outErr = errors.New(fmt.Sprintf("unsupported time format %v", sdata)) + return + } + if err != nil { + outErr = errors.New(fmt.Sprintf("unsupported time format %v: %v", sdata, err)) + return + } + outTime = x + return +} + // convert a db data([]byte) to a field value func (session *Session) bytes2Value(col *Column, fieldValue *reflect.Value, data []byte) error { if structConvert, ok := fieldValue.Addr().Interface().(Conversion); ok { @@ -1680,41 +1723,11 @@ func (session *Session) bytes2Value(col *Column, fieldValue *reflect.Value, data fieldValue.SetUint(x) //Now only support Time type case reflect.Struct: - if fieldType.String() == "time.Time" { - sdata := strings.TrimSpace(string(data)) - var x time.Time - var err error - - if sdata == "0000-00-00 00:00:00" || - sdata == "0001-01-01 00:00:00" { - } else if !strings.ContainsAny(sdata, "- :") { - // time stamp - sd, err := strconv.ParseInt(sdata, 10, 64) - if err == nil { - x = time.Unix(0, sd) - } - } else if len(sdata) > 19 { - x, err = time.Parse(time.RFC3339Nano, sdata) - if err != nil { - x, err = time.Parse("2006-01-02 15:04:05.999999999", sdata) - } - } else if len(sdata) == 19 { - x, err = time.Parse("2006-01-02 15:04:05", sdata) - } else if len(sdata) == 10 && sdata[4] == '-' && sdata[7] == '-' { - x, err = time.Parse("2006-01-02", sdata) - } else if col.SQLType.Name == Time { - if len(sdata) > 8 { - sdata = sdata[len(sdata)-8:] - } - st := fmt.Sprintf("2006-01-02 %v", sdata) - x, err = time.Parse("2006-01-02 15:04:05", st) - } else { - return errors.New(fmt.Sprintf("unsupported time format %v", string(data))) - } + if fieldType == reflect.TypeOf(c_TIME_DEFAULT) { + x, err := session.byte2Time(col, data) if err != nil { - return errors.New(fmt.Sprintf("unsupported time format %v: %v", string(data), err)) + return err } - v = x fieldValue.Set(reflect.ValueOf(v)) } else if session.Statement.UseCascade { @@ -1795,40 +1808,10 @@ func (session *Session) bytes2Value(col *Column, fieldValue *reflect.Value, data fieldValue.Set(reflect.ValueOf(&x)) // case "*time.Time": case reflect.TypeOf(&c_TIME_DEFAULT): - sdata := strings.TrimSpace(string(data)) - var x time.Time - var err error - - if sdata == "0000-00-00 00:00:00" || - sdata == "0001-01-01 00:00:00" { - } else if !strings.ContainsAny(sdata, "- :") { - // time stamp - sd, err := strconv.ParseInt(sdata, 10, 64) - if err == nil { - x = time.Unix(0, sd) - } - } else if len(sdata) > 19 { - x, err = time.Parse(time.RFC3339Nano, sdata) - if err != nil { - x, err = time.Parse("2006-01-02 15:04:05.999999999", sdata) - } - } else if len(sdata) == 19 { - x, err = time.Parse("2006-01-02 15:04:05", sdata) - } else if len(sdata) == 10 && sdata[4] == '-' && sdata[7] == '-' { - x, err = time.Parse("2006-01-02", sdata) - } else if col.SQLType.Name == Time { - if len(sdata) > 8 { - sdata = sdata[len(sdata)-8:] - } - st := fmt.Sprintf("2006-01-02 %v", sdata) - x, err = time.Parse("2006-01-02 15:04:05", st) - } else { - return errors.New(fmt.Sprintf("unsupported time format %v", string(data))) - } + x, err := session.byte2Time(col, data) if err != nil { - return errors.New(fmt.Sprintf("unsupported time format %v: %v", string(data), err)) + return err } - v = x fieldValue.Set(reflect.ValueOf(&x)) // case "*uint64": @@ -2064,7 +2047,7 @@ func (session *Session) value2Interface(col *Column, fieldValue reflect.Value) ( case reflect.String: return fieldValue.String(), nil case reflect.Struct: - if fieldType.String() == "time.Time" { + if fieldType == reflect.TypeOf(c_TIME_DEFAULT) { if col.SQLType.Name == Time { //s := fieldValue.Interface().(time.Time).Format("2006-01-02 15:04:05 -0700") s := fieldValue.Interface().(time.Time).Format(time.RFC3339) diff --git a/statement.go b/statement.go index 31718f18..fc5187aa 100644 --- a/statement.go +++ b/statement.go @@ -1,6 +1,7 @@ package xorm import ( + //"bytes" "fmt" "reflect" //"strconv" @@ -9,27 +10,6 @@ import ( "time" ) -// !nashtsai! treat following var as interal const values -var ( - c_EMPTY_STRING = "" - c_BOOL_DEFAULT = false - c_COMPLEX64_DEFAULT = complex64(0) - c_COMPLEX128_DEFAULT = complex128(0) - c_FLOAT32_DEFAULT = float32(0) - c_FLOAT64_DEFAULT = float64(0) - c_INT64_DEFAULT = int64(0) - c_UINT64_DEFAULT = uint64(0) - c_INT32_DEFAULT = int32(0) - c_UINT32_DEFAULT = uint32(0) - c_INT16_DEFAULT = int16(0) - c_UINT16_DEFAULT = uint16(0) - c_INT8_DEFAULT = int8(0) - c_UINT8_DEFAULT = uint8(0) - c_INT_DEFAULT = int(0) - c_UINT_DEFAULT = uint(0) - c_TIME_DEFAULT time.Time = time.Unix(0, 0) -) - // statement save all the sql info for executing SQL type Statement struct { RefTable *Table @@ -706,7 +686,6 @@ func (s *Statement) genDropSQL() string { return sql } -// !nashtsai! REVIEW, Statement is a huge struct why is this method not passing *Statement? func (statement *Statement) genGetSql(bean interface{}) (string, []interface{}) { table := statement.Engine.autoMap(bean) statement.RefTable = table diff --git a/table.go b/table.go index 976e30f9..aac87528 100644 --- a/table.go +++ b/table.go @@ -115,8 +115,27 @@ var ( uintTypes = sort.StringSlice{"*uint", "*uint16", "*uint32", "*uint8"} ) -var b byte -var tm time.Time +// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparision +var ( + c_EMPTY_STRING string + c_BOOL_DEFAULT bool + c_BYTE_DEFAULT byte + c_COMPLEX64_DEFAULT complex64 + c_COMPLEX128_DEFAULT complex128 + c_FLOAT32_DEFAULT float32 + c_FLOAT64_DEFAULT float64 + c_INT64_DEFAULT int64 + c_UINT64_DEFAULT uint64 + c_INT32_DEFAULT int32 + c_UINT32_DEFAULT uint32 + c_INT16_DEFAULT int16 + c_UINT16_DEFAULT uint16 + c_INT8_DEFAULT int8 + c_UINT8_DEFAULT uint8 + c_INT_DEFAULT int + c_UINT_DEFAULT uint + c_TIME_DEFAULT time.Time +) func Type2SQLType(t reflect.Type) (st SQLType) { switch k := t.Kind(); k { @@ -131,7 +150,7 @@ func Type2SQLType(t reflect.Type) (st SQLType) { case reflect.Complex64, reflect.Complex128: st = SQLType{Varchar, 64, 0} case reflect.Array, reflect.Slice, reflect.Map: - if t.Elem() == reflect.TypeOf(b) { + if t.Elem() == reflect.TypeOf(c_BYTE_DEFAULT) { st = SQLType{Blob, 0, 0} } else { st = SQLType{Text, 0, 0} @@ -141,7 +160,7 @@ func Type2SQLType(t reflect.Type) (st SQLType) { case reflect.String: st = SQLType{Varchar, 255, 0} case reflect.Struct: - if t == reflect.TypeOf(tm) { + if t == reflect.TypeOf(c_TIME_DEFAULT) { st = SQLType{DateTime, 0, 0} } else { st = SQLType{Text, 0, 0} @@ -200,7 +219,7 @@ func SQLType2Type(st SQLType) reflect.Type { case Bool: return reflect.TypeOf(true) case DateTime, Date, Time, TimeStamp, TimeStampz: - return reflect.TypeOf(tm) + return reflect.TypeOf(c_TIME_DEFAULT) case Decimal, Numeric: return reflect.TypeOf("") default: