From a6eb640d81ebf3f5b02779d2667038ae860e068c Mon Sep 17 00:00:00 2001 From: Nash Tsai Date: Wed, 18 Dec 2013 15:24:00 +0800 Subject: [PATCH 1/6] tidy up comments --- statement.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/statement.go b/statement.go index 6fdcd56a..feafe873 100644 --- a/statement.go +++ b/statement.go @@ -1,6 +1,7 @@ package xorm import ( + "bytes" "fmt" "reflect" //"strconv" @@ -9,14 +10,14 @@ import ( "time" ) -// !nashtsai! treat following var as interal const values +// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparision 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_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) @@ -707,7 +708,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 From 9f3a211ed9c30fe78282797c044ff08632fe4c55 Mon Sep 17 00:00:00 2001 From: Nash Tsai Date: Wed, 18 Dec 2013 22:55:39 +0800 Subject: [PATCH 2/6] code tidy up --- statement.go | 21 --------------------- table.go | 29 ++++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/statement.go b/statement.go index 2ceeee69..fc5187aa 100644 --- a/statement.go +++ b/statement.go @@ -10,27 +10,6 @@ import ( "time" ) -// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparision -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 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: From 31dbc146ee9d579f081dca72ea537ef8aebe5c26 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 19 Dec 2013 22:32:00 +0800 Subject: [PATCH 3/6] add nocascade method --- engine.go | 15 +++++++++++---- session.go | 21 +++++++++++++++++---- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/engine.go b/engine.go index 56a286cb..aac949b1 100644 --- a/engine.go +++ b/engine.go @@ -15,10 +15,11 @@ import ( ) const ( - POSTGRES = "postgres" - SQLITE = "sqlite3" - MYSQL = "mysql" - MYMYSQL = "mymysql" + POSTGRES = "postgres" + SQLITE = "sqlite3" + MYSQL = "mysql" + MYMYSQL = "mymysql" + ORACLE_OCI = "oci8" ) // a dialect is a driver's wrapper @@ -140,6 +141,12 @@ func (engine *Engine) NoCache() *Session { return session.NoCache() } +func (engine *Engine) NoCascade() *Session { + session := engine.NewSession() + session.IsAutoClose = true + return session.NoCascade() +} + // Set a table use a special cacher func (engine *Engine) MapCacher(bean interface{}, cacher Cacher) { t := rType(bean) diff --git a/session.go b/session.go index c8de127d..7f156a4a 100644 --- a/session.go +++ b/session.go @@ -129,6 +129,16 @@ func (session *Session) Cols(columns ...string) *Session { return session } +func (session *Session) NoCascade() *Session { + session.Statement.UseCascade = false + return session +} + +/* +func (session *Session) MustCols(columns ...string) *Session { + session.Statement.Must() +}*/ + // Xorm automatically retrieve condition according struct, but // if struct has bool field, it will ignore them. So use UseBool // to tell system to do not ignore them. @@ -635,11 +645,14 @@ func (session *Session) cacheGet(bean interface{}, sql string, args ...interface newSession := session.Engine.NewSession() defer newSession.Close() cacheBean = reflect.New(structValue.Type()).Interface() + newSession.Id(id).NoCache() if session.Statement.AltTableName != "" { - has, err = newSession.Id(id).NoCache().Table(session.Statement.AltTableName).Get(cacheBean) - } else { - has, err = newSession.Id(id).NoCache().Get(cacheBean) + newSession.Table(session.Statement.AltTableName) } + if !session.Statement.UseCascade { + newSession.NoCascade() + } + has, err = newSession.Get(cacheBean) if err != nil || !has { return has, err } @@ -2129,7 +2142,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { } // -- - colNames, args, err := table.genCols(session, bean, false, false) + colNames, args, err := table.genCols(session, bean, true, false) if err != nil { return 0, err } From 81af494cabd886e3e2b1ebe4bfd0a9047301bc3b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Thu, 19 Dec 2013 23:28:38 +0800 Subject: [PATCH 4/6] bug fixed --- base_test.go | 19 ++-- oracle.go | 258 +++++++++++++++++++++++++++++++++++++++++++++++++++ session.go | 2 +- xorm.go | 5 +- 4 files changed, 276 insertions(+), 8 deletions(-) create mode 100644 oracle.go diff --git a/base_test.go b/base_test.go index 6816fc70..81ff316a 100644 --- a/base_test.go +++ b/base_test.go @@ -189,6 +189,13 @@ func insertAutoIncr(engine *Engine, t *testing.T) { } } +type BigInsert struct { +} + +func insertDefault(engine *Engine, t *testing.T) { + +} + func insertMulti(engine *Engine, t *testing.T) { //engine.InsertMany = true users := []Userinfo{ @@ -1540,26 +1547,26 @@ func testStrangeName(engine *Engine, t *testing.T) { } } -type Version struct { +type VersionS struct { Id int64 Name string Ver int `xorm:"version"` } func testVersion(engine *Engine, t *testing.T) { - err := engine.DropTables(new(Version)) + err := engine.DropTables(new(VersionS)) if err != nil { t.Error(err) panic(err) } - err = engine.CreateTables(new(Version)) + err = engine.CreateTables(new(VersionS)) if err != nil { t.Error(err) panic(err) } - ver := &Version{Name: "sfsfdsfds"} + ver := &VersionS{Name: "sfsfdsfds"} _, err = engine.Insert(ver) if err != nil { t.Error(err) @@ -1572,7 +1579,7 @@ func testVersion(engine *Engine, t *testing.T) { panic(err) } - newVer := new(Version) + newVer := new(VersionS) has, err := engine.Id(ver.Id).Get(newVer) if err != nil { t.Error(err) @@ -1597,7 +1604,7 @@ func testVersion(engine *Engine, t *testing.T) { panic(err) } - newVer = new(Version) + newVer = new(VersionS) has, err = engine.Id(ver.Id).Get(newVer) if err != nil { t.Error(err) diff --git a/oracle.go b/oracle.go new file mode 100644 index 00000000..b863b6ab --- /dev/null +++ b/oracle.go @@ -0,0 +1,258 @@ +package xorm + +import ( + "database/sql" + "errors" + "fmt" + "regexp" + "strconv" + "strings" +) + +type oracle struct { + base +} + +type oracleParser struct { +} + +//dataSourceName=user/password@ipv4:port/dbname +//dataSourceName=user/password@[ipv6]:port/dbname +func (p *oracleParser) parse(driverName, dataSourceName string) (*uri, error) { + db := &uri{dbType: ORACLE_OCI} + dsnPattern := regexp.MustCompile( + `^(?P.*)\/(?P.*)@` + // user:password@ + `(?P.*)` + // ip:port + `\/(?P.*)`) // dbname + matches := dsnPattern.FindStringSubmatch(dataSourceName) + names := dsnPattern.SubexpNames() + for i, match := range matches { + switch names[i] { + case "dbname": + db.dbName = match + } + } + if db.dbName == "" { + return nil, errors.New("dbname is empty") + } + return db, nil +} + +func (db *oracle) Init(drivername, uri string) error { + return db.base.init(&oracleParser{}, drivername, uri) +} + +func (db *oracle) SqlType(c *Column) string { + var res string + switch t := c.SQLType.Name; t { + case Bit, TinyInt, SmallInt, MediumInt, Int, Integer, BigInt, Bool, Serial, BigSerial: + return "NUMBER" + case Binary, VarBinary, Blob, TinyBlob, MediumBlob, LongBlob, Bytea: + return Blob + case Time, DateTime, TimeStamp: + res = TimeStamp + case TimeStampz: + res = "TIMESTAMP WITH TIME ZONE" + case Float, Double, Numeric, Decimal: + res = "NUMBER" + case Text, MediumText, LongText: + res = "CLOB" + case Char, Varchar, TinyText: + return "VARCHAR2" + default: + res = t + } + + var hasLen1 bool = (c.Length > 0) + var hasLen2 bool = (c.Length2 > 0) + if hasLen1 { + res += "(" + strconv.Itoa(c.Length) + ")" + } else if hasLen2 { + res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")" + } + return res +} + +func (db *oracle) SupportInsertMany() bool { + return true +} + +func (db *oracle) QuoteStr() string { + return "\"" +} + +func (db *oracle) AutoIncrStr() string { + return "" +} + +func (db *oracle) SupportEngine() bool { + return false +} + +func (db *oracle) SupportCharset() bool { + return false +} + +func (db *oracle) IndexOnTable() bool { + return false +} + +func (db *oracle) IndexCheckSql(tableName, idxName string) (string, []interface{}) { + args := []interface{}{strings.ToUpper(tableName), strings.ToUpper(idxName)} + return `SELECT INDEX_NAME FROM USER_INDEXES ` + + `WHERE TABLE_NAME = ? AND INDEX_NAME = ?`, args +} + +func (db *oracle) TableCheckSql(tableName string) (string, []interface{}) { + args := []interface{}{strings.ToUpper(tableName)} + return `SELECT table_name FROM user_tables WHERE table_name = ?`, args +} + +func (db *oracle) ColumnCheckSql(tableName, colName string) (string, []interface{}) { + args := []interface{}{strings.ToUpper(tableName), strings.ToUpper(colName)} + return "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = ?" + + " AND column_name = ?", args +} + +func (db *oracle) GetColumns(tableName string) ([]string, map[string]*Column, error) { + args := []interface{}{strings.ToUpper(tableName)} + s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," + + "nullable FROM USER_TAB_COLUMNS WHERE table_name = :1" + + cnn, err := sql.Open(db.driverName, db.dataSourceName) + if err != nil { + return nil, nil, err + } + defer cnn.Close() + res, err := query(cnn, s, args...) + if err != nil { + return nil, nil, err + } + cols := make(map[string]*Column) + colSeq := make([]string, 0) + for _, record := range res { + col := new(Column) + col.Indexes = make(map[string]bool) + for name, content := range record { + switch name { + case "column_name": + col.Name = strings.Trim(string(content), `" `) + case "data_default": + col.Default = string(content) + case "nullable": + if string(content) == "Y" { + col.Nullable = true + } else { + col.Nullable = false + } + case "data_type": + ct := string(content) + switch ct { + case "VARCHAR2": + col.SQLType = SQLType{Varchar, 0, 0} + case "TIMESTAMP WITH TIME ZONE": + col.SQLType = SQLType{TimeStamp, 0, 0} + default: + col.SQLType = SQLType{strings.ToUpper(ct), 0, 0} + } + if _, ok := sqlTypes[col.SQLType.Name]; !ok { + return nil, nil, errors.New(fmt.Sprintf("unkonw colType %v", ct)) + } + case "data_length": + i, err := strconv.Atoi(string(content)) + if err != nil { + return nil, nil, errors.New("retrieve length error") + } + col.Length = i + case "data_precision": + case "data_scale": + } + } + if col.SQLType.IsText() { + if col.Default != "" { + col.Default = "'" + col.Default + "'" + } + } + cols[col.Name] = col + colSeq = append(colSeq, col.Name) + } + + return colSeq, cols, nil +} + +func (db *oracle) GetTables() ([]*Table, error) { + args := []interface{}{} + s := "SELECT table_name FROM user_tables" + cnn, err := sql.Open(db.driverName, db.dataSourceName) + if err != nil { + return nil, err + } + defer cnn.Close() + res, err := query(cnn, s, args...) + if err != nil { + return nil, err + } + + tables := make([]*Table, 0) + for _, record := range res { + table := new(Table) + for name, content := range record { + switch name { + case "table_name": + table.Name = string(content) + } + } + tables = append(tables, table) + } + return tables, nil +} + +func (db *oracle) GetIndexes(tableName string) (map[string]*Index, error) { + args := []interface{}{tableName} + s := "SELECT t.column_name,i.table_name,i.uniqueness,i.index_name FROM user_ind_columns t,user_indexes i " + + "WHERE t.index_name = i.index_name and t.table_name = i.table_name and t.table_name =:1" + + cnn, err := sql.Open(db.driverName, db.dataSourceName) + if err != nil { + return nil, err + } + defer cnn.Close() + res, err := query(cnn, s, args...) + if err != nil { + return nil, err + } + + indexes := make(map[string]*Index, 0) + for _, record := range res { + var indexType int + var indexName string + var colName string + + for name, content := range record { + switch name { + case "index_name": + indexName = strings.Trim(string(content), `" `) + case "uniqueness": + c := string(content) + if c == "UNIQUE" { + indexType = UniqueType + } else { + indexType = IndexType + } + case "column_name": + colName = string(content) + } + } + + var index *Index + var ok bool + if index, ok = indexes[indexName]; !ok { + index = new(Index) + index.Type = indexType + index.Name = indexName + indexes[indexName] = index + } + index.AddColumn(colName) + } + return indexes, nil +} diff --git a/session.go b/session.go index 7f156a4a..9e56bfc5 100644 --- a/session.go +++ b/session.go @@ -2142,7 +2142,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { } // -- - colNames, args, err := table.genCols(session, bean, true, false) + colNames, args, err := table.genCols(session, bean, false, false) if err != nil { return 0, err } diff --git a/xorm.go b/xorm.go index 23a4a69b..b05f7ac5 100644 --- a/xorm.go +++ b/xorm.go @@ -10,7 +10,7 @@ import ( ) const ( - version string = "0.2.3" + Version string = "0.2.3" ) func close(engine *Engine) { @@ -34,6 +34,9 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) { engine.Filters = append(engine.Filters, &QuoteFilter{}) } else if driverName == MYMYSQL { engine.dialect = &mymysql{} + } else if driverName == ORACLE_OCI { + engine.dialect = &oracle{} + engine.Filters = append(engine.Filters, &QuoteFilter{}) } else { return nil, errors.New(fmt.Sprintf("Unsupported driver name: %v", driverName)) } From 7ebbe91892e18dba9eae4775636725093ef40a77 Mon Sep 17 00:00:00 2001 From: Nash Tsai Date: Fri, 20 Dec 2013 02:25:27 +0800 Subject: [PATCH 5/6] code tidy up --- session.go | 117 +++++++++++++++++++++++------------------------------ 1 file changed, 50 insertions(+), 67 deletions(-) diff --git a/session.go b/session.go index c8de127d..8162ebf6 100644 --- a/session.go +++ b/session.go @@ -1241,6 +1241,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])) @@ -1275,7 +1278,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 { @@ -1572,6 +1575,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 { @@ -1637,7 +1680,7 @@ func (session *Session) bytes2Value(col *Column, fieldValue *reflect.Value, data if col.SQLType.Name == Bit && strings.Contains(session.Engine.DriverName, "mysql") { if len(data) == 1 { - x = int64(data[0]) + x = int64((data)[0]) } else { x = 0 } @@ -1667,41 +1710,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 { @@ -1782,40 +1795,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": From 40bea73d0b3aec081ad7fe0443aaa6a28b4f56ca Mon Sep 17 00:00:00 2001 From: Nash Tsai Date: Fri, 20 Dec 2013 02:32:11 +0800 Subject: [PATCH 6/6] code tidy up --- session.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/session.go b/session.go index f762a588..0c52e917 100644 --- a/session.go +++ b/session.go @@ -1693,7 +1693,7 @@ func (session *Session) bytes2Value(col *Column, fieldValue *reflect.Value, data if col.SQLType.Name == Bit && strings.Contains(session.Engine.DriverName, "mysql") { if len(data) == 1 { - x = int64((data)[0]) + x = int64(data[0]) } else { x = 0 } @@ -2047,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)