From 129f77f43c86c4da81646d45bcb6592b530fd471 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 23 Apr 2014 14:01:53 +0800 Subject: [PATCH 01/10] bug fixed --- session.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/session.go b/session.go index feeda785..c1074601 100644 --- a/session.go +++ b/session.go @@ -3314,7 +3314,7 @@ func genCols(table *core.Table, session *Session, bean interface{}, useCol bool, } if (col.IsCreated || col.IsUpdated) && session.Statement.UseAutoTime { - args = append(args, time.Now()) + args = append(args, session.Engine.NowTime(col.SQLType.Name)) } else if col.IsVersion && session.Statement.checkVersion { args = append(args, 1) } else { From edbdf1e6122fe30667953e198ce428a997053ae0 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 23 Apr 2014 14:57:40 +0800 Subject: [PATCH 02/10] docs small improved --- README.md | 5 +---- README_CN.md | 5 +---- docs/QuickStart.md | 2 +- docs/QuickStartCn.md | 2 +- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 9c9ecfa7..dc8e4b2a 100644 --- a/README.md +++ b/README.md @@ -123,13 +123,10 @@ Or Please visit [Xorm on Google Groups](https://groups.google.com/forum/#!forum/xorm) -# Contributors +# Contributing If you want to pull request, please see [CONTRIBUTING](https://github.com/go-xorm/xorm/blob/master/CONTRIBUTING.md) -* [Lunny](https://github.com/lunny) -* [Nashtsai](https://github.com/nashtsai) - # LICENSE BSD License diff --git a/README_CN.md b/README_CN.md index c8f3f180..ce9b3f3c 100644 --- a/README_CN.md +++ b/README_CN.md @@ -124,13 +124,10 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作 请加入QQ群:280360085 进行讨论。 -# 贡献者 +## 贡献 如果您也想为Xorm贡献您的力量,请查看 [CONTRIBUTING](https://github.com/go-xorm/xorm/blob/master/CONTRIBUTING.md) -* [Lunny](https://github.com/lunny) -* [Nashtsai](https://github.com/nashtsai) - ## LICENSE BSD License diff --git a/docs/QuickStart.md b/docs/QuickStart.md index f240806d..5ea49bdc 100644 --- a/docs/QuickStart.md +++ b/docs/QuickStart.md @@ -385,7 +385,7 @@ engine.Cols("age", "name").Update(&user) * Omit(...string) 和cols相反,此函数指定排除某些指定的字段。注意:此方法和Cols方法不可同时使用 ```Go -engine.Cols("age").Update(&user) +engine.Omit("age").Update(&user) // UPDATE user SET name = ? AND department = ? ``` diff --git a/docs/QuickStartCn.md b/docs/QuickStartCn.md index 2b76ca8e..11ea03e2 100644 --- a/docs/QuickStartCn.md +++ b/docs/QuickStartCn.md @@ -419,7 +419,7 @@ engine.Cols("age", "name").Update(&user) * Omit(...string) 和cols相反,此函数指定排除某些指定的字段。注意:此方法和Cols方法不可同时使用 ```Go -engine.Cols("age").Update(&user) +engine.Omit("age").Update(&user) // UPDATE user SET name = ? AND department = ? ``` From f419c31da18a782ad89c235f4640ce8ac5e17be0 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 23 Apr 2014 15:25:27 +0800 Subject: [PATCH 03/10] bug fixs #105 --- statement.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/statement.go b/statement.go index 2de1f84a..b591f189 100644 --- a/statement.go +++ b/statement.go @@ -762,11 +762,12 @@ func (statement *Statement) genCountSql(bean interface{}) (string, []interface{} statement.ConditionStr = strings.Join(colNames, " AND ") statement.BeanArgs = args // count(index fieldname) > count(0) > count(*) - var id string = "0" + // for compitable on kinds of database, just use * + /*var id string = "0" if len(table.PrimaryKeys) == 1 { - id = statement.Engine.Quote(table.PrimaryKeys[0]) - } - return statement.genSelectSql(fmt.Sprintf("COUNT(%v) AS %v", id, statement.Engine.Quote("total"))), append(statement.Params, statement.BeanArgs...) + id = statement.Engine.Quote(statement.TableName()) + "." + statement.Engine.Quote(table.PrimaryKeys[0]) + }*/ + return statement.genSelectSql(fmt.Sprintf("COUNT(*) AS %v", statement.Engine.Quote("total"))), append(statement.Params, statement.BeanArgs...) } func (statement *Statement) genSelectSql(columnStr string) (a string) { From 96d483e8457c554362342cd2a1c75a44c3f63088 Mon Sep 17 00:00:00 2001 From: Holo Date: Wed, 23 Apr 2014 16:47:52 +0800 Subject: [PATCH 04/10] Format Format directory 6.1 --- docs/QuickStartCn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/QuickStartCn.md b/docs/QuickStartCn.md index 11ea03e2..e5734824 100644 --- a/docs/QuickStartCn.md +++ b/docs/QuickStartCn.md @@ -23,7 +23,7 @@ xorm 快速入门 * [5.6.Count方法](#66) * [5.7.Rows方法](#67) * [6.更新数据](#70) -* [6.1.乐观锁](#71) + * [6.1.乐观锁](#71) * [7.删除数据](#80) * [8.执行SQL查询](#90) * [9.执行SQL命令](#100) From 62e08a781bb31392bd131e8215efd8be39141369 Mon Sep 17 00:00:00 2001 From: Chris Dillon Date: Fri, 25 Apr 2014 11:18:46 -0400 Subject: [PATCH 05/10] Update QuickStart.md "go routines" typo. --- docs/QuickStart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/QuickStart.md b/docs/QuickStart.md index 5ea49bdc..2b1f5829 100644 --- a/docs/QuickStart.md +++ b/docs/QuickStart.md @@ -58,7 +58,7 @@ engine, err = xorm.NewEngine("sqlite3", "./test.db") defer engine.Close() ``` -Generally, you can only create one engine. Engine supports run on go rutines. +Generally, you can only create one engine. Engine supports run on go routines. xorm supports four drivers now: From f3fc0b9976337ffa0af7fc06688a7b8cd6556e9a Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 30 Apr 2014 10:19:24 +0800 Subject: [PATCH 06/10] remove trace string --- statement.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/statement.go b/statement.go index b591f189..5c08a7f9 100644 --- a/statement.go +++ b/statement.go @@ -353,7 +353,7 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{}, continue } val = engine.FormatTime(col.SQLType.Name, t) - fmt.Println("-------", t, val, col.Name) + //fmt.Println("-------", t, val, col.Name) } else { engine.autoMapType(fieldValue) if table, ok := engine.Tables[fieldValue.Type()]; ok { From 685a4a63fd438a3e2eb30dbd3090fede51a3dfad Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 2 May 2014 08:48:51 +0800 Subject: [PATCH 07/10] bug fixed and docs improved --- docs/QuickStart.md | 2 +- docs/QuickStartCn.md | 2 +- engine.go | 34 ++++----- session.go | 2 +- statement.go | 168 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 184 insertions(+), 24 deletions(-) diff --git a/docs/QuickStart.md b/docs/QuickStart.md index 2b1f5829..a53673e1 100644 --- a/docs/QuickStart.md +++ b/docs/QuickStart.md @@ -58,7 +58,7 @@ engine, err = xorm.NewEngine("sqlite3", "./test.db") defer engine.Close() ``` -Generally, you can only create one engine. Engine supports run on go routines. +You can create many engines for different databases.Generally, you just need create only one engine. Engine supports run on go routines. xorm supports four drivers now: diff --git a/docs/QuickStartCn.md b/docs/QuickStartCn.md index e5734824..607bdda6 100644 --- a/docs/QuickStartCn.md +++ b/docs/QuickStartCn.md @@ -62,7 +62,7 @@ engine, err = xorm.NewEngine("sqlite3", "./test.db") defer engine.Close() ``` -一般如果只针对一个数据库进行操作,只需要创建一个Engine即可。Engine支持在多GoRutine下使用。 +你可以创建一个或多个engine, 不过一般如果操作一个数据库,只需要创建一个Engine即可。Engine支持在多GoRutine下使用。 xorm当前支持五种驱动四个数据库如下: diff --git a/engine.go b/engine.go index 671c1b87..50b45a78 100644 --- a/engine.go +++ b/engine.go @@ -34,8 +34,7 @@ type Engine struct { ShowErr bool ShowDebug bool ShowWarn bool - //Pool IConnectPool - //Filters []core.Filter + Logger ILogger // io.Writer TZLocation *time.Location } @@ -456,15 +455,6 @@ func (engine *Engine) autoMap(bean interface{}) *core.Table { return engine.autoMapType(v) } -/*func (engine *Engine) mapType(t reflect.Type) *core.Table { - return mappingTable(t, engine.TableMapper, engine.ColumnMapper, engine.dialect, engine.TagIdentifier) -}*/ - -/* -func mappingTable(t reflect.Type, tableMapper core.IMapper, colMapper core.IMapper, dialect core.Dialect, tagId string) *core.Table { - table := core.NewEmptyTable() - table.Name = tableMapper.Obj2Table(t.Name()) -*/ func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) { if index, ok := table.Indexes[indexName]; ok { index.AddColumn(col.Name) @@ -524,17 +514,19 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table { if tags[0] == "-" { continue } - if (strings.ToUpper(tags[0]) == "EXTENDS") && - (fieldType.Kind() == reflect.Struct) { + if strings.ToUpper(tags[0]) == "EXTENDS" { + fieldValue = reflect.Indirect(fieldValue) + if fieldValue.Kind() == reflect.Struct { + //parentTable := mappingTable(fieldType, tableMapper, colMapper, dialect, tagId) + parentTable := engine.mapType(fieldValue) + for _, col := range parentTable.Columns() { + col.FieldName = fmt.Sprintf("%v.%v", fieldValue.Type().Name(), col.FieldName) + table.AddColumn(col) + } - //parentTable := mappingTable(fieldType, tableMapper, colMapper, dialect, tagId) - parentTable := engine.mapType(fieldValue) - for _, col := range parentTable.Columns() { - col.FieldName = fmt.Sprintf("%v.%v", fieldType.Name(), col.FieldName) - table.AddColumn(col) + continue } - - continue + //TODO: warning } indexNames := make(map[string]int) @@ -701,7 +693,7 @@ func (engine *Engine) IsTableEmpty(bean interface{}) (bool, error) { session := engine.NewSession() defer session.Close() rows, err := session.Count(bean) - return rows > 0, err + return rows == 0, err } // If a table is exist diff --git a/session.go b/session.go index c1074601..921849eb 100644 --- a/session.go +++ b/session.go @@ -2947,7 +2947,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 session.Statement.RefTable = table if session.Statement.ColumnStr == "" { - colNames, args = buildConditions(session.Engine, table, bean, false, false, + colNames, args = buildUpdates(session.Engine, table, bean, false, false, false, false, session.Statement.allUseBool, session.Statement.useAllCols, session.Statement.mustColumnMap) } else { diff --git a/statement.go b/statement.go index 5c08a7f9..1ae46f3d 100644 --- a/statement.go +++ b/statement.go @@ -253,6 +253,174 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement { return results }*/ +// Auto generating conditions according a struct +func buildUpdates(engine *Engine, table *core.Table, bean interface{}, + includeVersion bool, includeUpdated bool, includeNil bool, + includeAutoIncr bool, allUseBool bool, useAllCols bool, + mustColumnMap map[string]bool) ([]string, []interface{}) { + + colNames := make([]string, 0) + var args = make([]interface{}, 0) + for _, col := range table.Columns() { + if !includeVersion && col.IsVersion { + continue + } + if col.IsCreated { + continue + } + if !includeUpdated && col.IsUpdated { + continue + } + if !includeAutoIncr && col.IsAutoIncrement { + continue + } + // + //fmt.Println(engine.dialect.DBType(), Text) + if engine.dialect.DBType() == core.MSSQL && col.SQLType.Name == core.Text { + continue + } + fieldValuePtr, err := col.ValueOf(bean) + if err != nil { + engine.LogError(err) + continue + } + + fieldValue := *fieldValuePtr + fieldType := reflect.TypeOf(fieldValue.Interface()) + + requiredField := useAllCols + if b, ok := mustColumnMap[strings.ToLower(col.Name)]; ok { + if b { + requiredField = true + } else { + continue + } + } + + if fieldType.Kind() == reflect.Ptr { + if fieldValue.IsNil() { + if includeNil { + args = append(args, nil) + colNames = append(colNames, fmt.Sprintf("%v=?", engine.Quote(col.Name))) + } + continue + } else if !fieldValue.IsValid() { + continue + } else { + // dereference ptr type to instance type + fieldValue = fieldValue.Elem() + fieldType = reflect.TypeOf(fieldValue.Interface()) + requiredField = true + } + } + + var val interface{} + switch fieldType.Kind() { + case reflect.Bool: + if allUseBool || requiredField { + val = fieldValue.Interface() + } else { + // if a bool in a struct, it will not be as a condition because it default is false, + // please use Where() instead + continue + } + case reflect.String: + if !requiredField && fieldValue.String() == "" { + continue + } + // for MyString, should convert to string or panic + if fieldType.String() != reflect.String.String() { + val = fieldValue.String() + } else { + val = fieldValue.Interface() + } + case reflect.Int8, reflect.Int16, reflect.Int, reflect.Int32, reflect.Int64: + if !requiredField && fieldValue.Int() == 0 { + continue + } + val = fieldValue.Interface() + case reflect.Float32, reflect.Float64: + if !requiredField && fieldValue.Float() == 0.0 { + continue + } + val = fieldValue.Interface() + case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64: + if !requiredField && fieldValue.Uint() == 0 { + continue + } + val = fieldValue.Interface() + case reflect.Struct: + if fieldType == reflect.TypeOf(time.Now()) { + t := fieldValue.Interface().(time.Time) + if !requiredField && (t.IsZero() || !fieldValue.IsValid()) { + continue + } + val = engine.FormatTime(col.SQLType.Name, t) + //fmt.Println("-------", t, val, col.Name) + } else { + engine.autoMapType(fieldValue) + if table, ok := engine.Tables[fieldValue.Type()]; ok { + if len(table.PrimaryKeys) == 1 { + pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName) + if pkField.Int() != 0 { + val = pkField.Interface() + } else { + continue + } + } else { + //TODO: how to handler? + } + } else { + val = fieldValue.Interface() + } + } + case reflect.Array, reflect.Slice, reflect.Map: + if fieldValue == reflect.Zero(fieldType) { + continue + } + if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 { + continue + } + + if col.SQLType.IsText() { + bytes, err := json.Marshal(fieldValue.Interface()) + if err != nil { + engine.LogError(err) + continue + } + val = string(bytes) + } else if col.SQLType.IsBlob() { + var bytes []byte + var err error + if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) && + fieldType.Elem().Kind() == reflect.Uint8 { + if fieldValue.Len() > 0 { + val = fieldValue.Bytes() + } else { + continue + } + } else { + bytes, err = json.Marshal(fieldValue.Interface()) + if err != nil { + engine.LogError(err) + continue + } + val = bytes + } + } else { + continue + } + default: + val = fieldValue.Interface() + } + + args = append(args, val) + colNames = append(colNames, fmt.Sprintf("%v=?", engine.Quote(col.Name))) + } + + return colNames, args +} + // Auto generating conditions according a struct func buildConditions(engine *Engine, table *core.Table, bean interface{}, includeVersion bool, includeUpdated bool, includeNil bool, From 93209fa5b2be4c1e77b90f1bddfa1f07b6dcd2c3 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 2 May 2014 11:11:19 +0800 Subject: [PATCH 08/10] fixed reference of README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dc8e4b2a..f001357f 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Xorm is a simple and powerful ORM for Go. * Query Cache speed up -* Database Reverse support, See [Xorm Tool README](https://github.com/go-xorm/xorm/blob/master/xorm/README.md) +* Database Reverse support, See [Xorm Tool README](https://github.com/go-xorm/cmd/blob/master/README.md) * Simple cascade loading support From 9e147d2fde1acb426b0463c53180512cd652232e Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sun, 4 May 2014 13:53:38 +0800 Subject: [PATCH 09/10] add BeforeSet processor and Dump function --- engine.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++ examples/tables.go | 34 ++++++++++++++++++++++ processors.go | 4 +++ session.go | 65 ++++++++++++++++++++++------------------- sqlite3_dialect.go | 5 ++++ statement.go | 5 +++- 6 files changed, 154 insertions(+), 31 deletions(-) create mode 100644 examples/tables.go diff --git a/engine.go b/engine.go index 50b45a78..d9d49b09 100644 --- a/engine.go +++ b/engine.go @@ -6,6 +6,7 @@ import ( "database/sql" "errors" "fmt" + "io" "os" "reflect" "strconv" @@ -265,6 +266,77 @@ func (engine *Engine) DBMetas() ([]*core.Table, error) { return tables, nil } +func (engine *Engine) DumpAllToFile(fp string) error { + f, err := os.Create(fp) + if err != nil { + return err + } + defer f.Close() + return engine.DumpAll(f) +} + +func (engine *Engine) DumpAll(w io.Writer) error { + tables, err := engine.DBMetas() + if err != nil { + return err + } + + for _, table := range tables { + _, err = io.WriteString(w, engine.dialect.CreateTableSql(table, "", "", "")+"\n\n") + if err != nil { + return err + } + for _, index := range table.Indexes { + _, err = io.WriteString(w, engine.dialect.CreateIndexSql(table.Name, index)+"\n\n") + if err != nil { + return err + } + } + + rows, err := engine.DB().Query("SELECT * FROM " + engine.Quote(table.Name)) + if err != nil { + return err + } + cols, err := rows.Columns() + if err != nil { + return err + } + if len(cols) == 0 { + continue + } + for rows.Next() { + dest := make([]interface{}, len(cols)) + err = rows.ScanSlice(&dest) + if err != nil { + return err + } + + _, err = io.WriteString(w, "INSERT INTO "+engine.Quote(table.Name)+" ("+engine.Quote(strings.Join(cols, engine.Quote(", ")))+") VALUES (") + if err != nil { + return err + } + + var temp string + for _, d := range dest { + if d == nil { + temp += ", NULL" + } else if reflect.TypeOf(d).Kind() == reflect.String { + temp += ", '" + strings.Replace(d.(string), "'", "''", -1) + "'" + } else if reflect.TypeOf(d).Kind() == reflect.Slice { + temp += fmt.Sprintf(", %s", engine.dialect.FormatBytes(d.([]byte))) + } else { + temp += fmt.Sprintf(", %v", d) + } + } + _, err = io.WriteString(w, temp[2:]+");\n\n") + if err != nil { + return err + } + } + } + return nil +} + // use cascade or not func (engine *Engine) Cascade(trueOrFalse ...bool) *Session { session := engine.NewSession() diff --git a/examples/tables.go b/examples/tables.go new file mode 100644 index 00000000..97c842be --- /dev/null +++ b/examples/tables.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "os" + + "github.com/go-xorm/xorm" + _ "github.com/mattn/go-sqlite3" +) + +func main() { + if len(os.Args) < 2 { + fmt.Println("need db path") + return + } + + orm, err := xorm.NewEngine("sqlite3", os.Args[1]) + if err != nil { + fmt.Println(err) + return + } + defer orm.Close() + orm.ShowSQL = true + + tables, err := orm.DBMetas() + if err != nil { + fmt.Println(err) + return + } + + for _, table := range tables { + fmt.Println(table.Name) + } +} diff --git a/processors.go b/processors.go index 770515e6..03ae8e0f 100644 --- a/processors.go +++ b/processors.go @@ -15,6 +15,10 @@ type BeforeDeleteProcessor interface { BeforeDelete() } +type BeforeSetProcessor interface { + BeforeSet(string, Cell) +} + // !nashtsai! TODO enable BeforeValidateProcessor when xorm start to support validations //// Executed before an object is validated //type BeforeValidateProcessor interface { diff --git a/session.go b/session.go index 921849eb..f312e41b 100644 --- a/session.go +++ b/session.go @@ -883,7 +883,6 @@ func (session *Session) Rows(bean interface{}) (*Rows, error) { // are conditions. beans could be []Struct, []*Struct, map[int64]Struct // map[int64]*Struct func (session *Session) Iterate(bean interface{}, fun IterFunc) error { - rows, err := session.Rows(bean) if err != nil { return err @@ -982,24 +981,6 @@ func (session *Session) Get(bean interface{}) (bool, error) { } else { return false, nil } - - // resultsSlice, err := session.query(sqlStr, args...) - // if err != nil { - // return false, err - // } - // if len(resultsSlice) < 1 { - // return false, nil - // } - - // err = session.scanMapIntoStruct(bean, resultsSlice[0]) - // if err != nil { - // return true, err - // } - // if len(resultsSlice) == 1 { - // return true, nil - // } else { - // return true, errors.New("More than one record") - // } } // Count counts the records. bean's non-empty fields @@ -1441,6 +1422,8 @@ func (session *Session) getField(dataStruct *reflect.Value, key string, table *c return fieldValue } +type Cell *interface{} + func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}) error { dataStruct := rValue(bean) if dataStruct.Kind() != reflect.Struct { @@ -1449,18 +1432,24 @@ func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount i table := session.Engine.autoMapType(dataStruct) - scanResultContainers := make([]interface{}, len(fields)) + scanResults := make([]interface{}, len(fields)) for i := 0; i < len(fields); i++ { - var scanResultContainer interface{} - scanResultContainers[i] = &scanResultContainer + var cell interface{} + scanResults[i] = &cell } - if err := rows.Scan(scanResultContainers...); err != nil { + if err := rows.Scan(scanResults...); err != nil { return err } + b, hasBeforeSet := bean.(BeforeSetProcessor) + for ii, key := range fields { + if hasBeforeSet { + b.BeforeSet(fields[ii], Cell(scanResults[ii].(*interface{}))) + } + if fieldValue := session.getField(&dataStruct, key, table); fieldValue != nil { - rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])) + rawValue := reflect.Indirect(reflect.ValueOf(scanResults[ii])) //if row is null then ignore if rawValue.Interface() == nil { @@ -1468,7 +1457,18 @@ func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount i continue } - if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok { + if fieldValue.CanAddr() { + if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok { + if data, err := value2Bytes(&rawValue); err == nil { + structConvert.FromDB(data) + } else { + session.Engine.LogError(err) + } + continue + } + } + + if structConvert, ok := fieldValue.Interface().(core.Conversion); ok { if data, err := value2Bytes(&rawValue); err == nil { structConvert.FromDB(data) } else { @@ -2451,6 +2451,16 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val } } } + + if fieldConvert, ok := fieldValue.Interface().(core.Conversion); ok { + data, err := fieldConvert.ToDB() + if err != nil { + return 0, err + } else { + return string(data), nil + } + } + fieldType := fieldValue.Type() k := fieldType.Kind() if k == reflect.Ptr { @@ -2470,11 +2480,6 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val switch k { case reflect.Bool: return fieldValue.Bool(), nil - /*if fieldValue.Bool() { - return 1, nil - } else { - return 0, nil - }*/ case reflect.String: return fieldValue.String(), nil case reflect.Struct: diff --git a/sqlite3_dialect.go b/sqlite3_dialect.go index 0e19f96c..a889a0ab 100644 --- a/sqlite3_dialect.go +++ b/sqlite3_dialect.go @@ -1,6 +1,7 @@ package xorm import ( + "fmt" "strings" "github.com/go-xorm/core" @@ -44,6 +45,10 @@ func (db *sqlite3) SqlType(c *core.Column) string { } } +func (db *sqlite3) FormatBytes(bs []byte) string { + return fmt.Sprintf("X'%x'", bs) +} + func (db *sqlite3) SupportInsertMany() bool { return true } diff --git a/statement.go b/statement.go index 1ae46f3d..0c2207d8 100644 --- a/statement.go +++ b/statement.go @@ -451,8 +451,11 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{}, } fieldValue := *fieldValuePtr - fieldType := reflect.TypeOf(fieldValue.Interface()) + if fieldValue.Interface() == nil { + continue + } + fieldType := reflect.TypeOf(fieldValue.Interface()) requiredField := useAllCols if b, ok := mustColumnMap[strings.ToLower(col.Name)]; ok { if b { From 53dfe7747a924776657a94d9c5dd4fad2250c3e8 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 5 May 2014 14:45:42 +0800 Subject: [PATCH 10/10] bug fixed for Conversion --- statement.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/statement.go b/statement.go index 0c2207d8..02078cb9 100644 --- a/statement.go +++ b/statement.go @@ -297,6 +297,30 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{}, } } + var val interface{} + + if fieldValue.CanAddr() { + if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok { + data, err := structConvert.ToDB() + if err != nil { + engine.LogError(err) + } else { + val = data + } + continue + } + } + + if structConvert, ok := fieldValue.Interface().(core.Conversion); ok { + data, err := structConvert.ToDB() + if err != nil { + engine.LogError(err) + } else { + val = data + } + continue + } + if fieldType.Kind() == reflect.Ptr { if fieldValue.IsNil() { if includeNil { @@ -314,7 +338,6 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{}, } } - var val interface{} switch fieldType.Kind() { case reflect.Bool: if allUseBool || requiredField {