From 1ebd50ead514a50c90505df88667bcf77f8520e4 Mon Sep 17 00:00:00 2001 From: evalphobia Date: Wed, 10 Jun 2015 23:04:14 +0900 Subject: [PATCH 1/4] Added feature to update with null for non pointer value --- engine.go | 7 +++++++ helpers.go | 10 ++++++++++ session.go | 9 ++++++++- statement.go | 26 ++++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/engine.go b/engine.go index bbe8eb47..4081ec14 100644 --- a/engine.go +++ b/engine.go @@ -553,6 +553,13 @@ func (engine *Engine) Omit(columns ...string) *Session { return session.Omit(columns...) } +// Set null when column is zero-value and nullable for update +func (engine *Engine) Nullable(columns ...string) *Session { + session := engine.NewSession() + session.IsAutoClose = true + return session.Nullable(columns...) +} + // This method will generate "column IN (?, ?)" func (engine *Engine) In(column string, args ...interface{}) *Session { session := engine.NewSession() diff --git a/helpers.go b/helpers.go index 979a67a1..4f3be860 100644 --- a/helpers.go +++ b/helpers.go @@ -39,6 +39,8 @@ func isZero(k interface{}) bool { return k.(uint64) == 0 case string: return k.(string) == "" + case time.Time: + return k.(time.Time).IsZero() } return false } @@ -356,6 +358,14 @@ func genCols(table *core.Table, session *Session, bean interface{}, useCol bool, } } + // !evalphobia! set fieldValue as nil when column is nullable and zero-value + if _, ok := session.Statement.nullableMap[lColName]; ok { + if col.Nullable && isZero(fieldValue.Interface()) { + var nilValue *int + fieldValue = reflect.ValueOf(nilValue) + } + } + if (col.IsCreated || col.IsUpdated) && session.Statement.UseAutoTime { val, t := session.Engine.NowTime2(col.SQLType.Name) args = append(args, val) diff --git a/session.go b/session.go index b47d2780..a1984805 100644 --- a/session.go +++ b/session.go @@ -223,6 +223,12 @@ func (session *Session) Omit(columns ...string) *Session { return session } +// Set null when column is zero-value and nullable for update +func (session *Session) Nullable(columns ...string) *Session { + session.Statement.Nullable(columns...) + return session +} + // Method NoAutoTime means do not automatically give created field and updated field // the current time on the current session temporarily func (session *Session) NoAutoTime() *Session { @@ -3408,7 +3414,8 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 if session.Statement.ColumnStr == "" { colNames, args = buildUpdates(session.Engine, table, bean, false, false, false, false, session.Statement.allUseBool, session.Statement.useAllCols, - session.Statement.mustColumnMap, session.Statement.columnMap, true) + session.Statement.mustColumnMap, session.Statement.nullableMap, + session.Statement.columnMap, true) } else { colNames, args, err = genCols(table, session, bean, true, true) if err != nil { diff --git a/statement.go b/statement.go index dcd7fefa..0a8de1ee 100644 --- a/statement.go +++ b/statement.go @@ -70,6 +70,7 @@ type Statement struct { checkVersion bool unscoped bool mustColumnMap map[string]bool + nullableMap map[string]bool inColumns map[string]*inParam incrColumns map[string]incrParam decrColumns map[string]decrParam @@ -105,6 +106,7 @@ func (statement *Statement) Init() { statement.allUseBool = false statement.useAllCols = false statement.mustColumnMap = make(map[string]bool) + statement.nullableMap = make(map[string]bool) statement.checkVersion = true statement.unscoped = false statement.inColumns = make(map[string]*inParam) @@ -176,7 +178,8 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement { 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, columnMap map[string]bool, update bool) ([]string, []interface{}) { + mustColumnMap map[string]bool, nullableMap map[string]bool, + columnMap map[string]bool, update bool) ([]string, []interface{}) { colNames := make([]string, 0) var args = make([]interface{}, 0) @@ -215,7 +218,8 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{}, requiredField := useAllCols includeNil := useAllCols - if b, ok := mustColumnMap[strings.ToLower(col.Name)]; ok { + lColName := strings.ToLower(col.Name) + if b, ok := mustColumnMap[lColName]; ok { if b { requiredField = true } else { @@ -223,6 +227,16 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{}, } } + // !evalphobia! set fieldValue as nil when column is nullable and zero-value + if b, ok := nullableMap[lColName]; ok { + if b && col.Nullable && isZero(fieldValue.Interface()) { + var nilValue *int + fieldValue = reflect.ValueOf(nilValue) + fieldType = reflect.TypeOf(fieldValue.Interface()) + includeNil = true + } + } + var val interface{} if fieldValue.CanAddr() { @@ -818,6 +832,14 @@ func (statement *Statement) Omit(columns ...string) { statement.OmitStr = statement.Engine.Quote(strings.Join(newColumns, statement.Engine.Quote(", "))) } +// Update use only: update columns to null when value is nullable and zero-value +func (statement *Statement) Nullable(columns ...string) { + newColumns := col2NewCols(columns...) + for _, nc := range newColumns { + statement.nullableMap[strings.ToLower(nc)] = true + } +} + // Generate LIMIT limit statement func (statement *Statement) Top(limit int) *Statement { statement.Limit(limit) From f7a19aef975d1e5b3391f6eebceecb430ed060ad Mon Sep 17 00:00:00 2001 From: evalphobia Date: Fri, 12 Jun 2015 14:03:11 +0900 Subject: [PATCH 2/4] Support float and bool for nullable update --- helpers.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/helpers.go b/helpers.go index 4f3be860..7e8978f0 100644 --- a/helpers.go +++ b/helpers.go @@ -37,6 +37,12 @@ func isZero(k interface{}) bool { return k.(uint32) == 0 case uint64: return k.(uint64) == 0 + case float32: + return k.(float32) == 0 + case float64: + return k.(float64) == 0 + case bool: + return k.(bool) == false case string: return k.(string) == "" case time.Time: From 6b8d0973c7efad78170c7ee425431a11a7d5a554 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Jun 2015 21:21:12 +0800 Subject: [PATCH 3/4] bug fixed for #261 --- xorm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xorm.go b/xorm.go index 036d420f..f5f8f2a7 100644 --- a/xorm.go +++ b/xorm.go @@ -39,7 +39,7 @@ func regDrvsNDialects() bool { for driverName, v := range providedDrvsNDialects { if driver := core.QueryDriver(driverName); driver == nil { core.RegisterDriver(driverName, v.getDriver()) - core.RegisterDialect(v.dbType, v.getDialect()) + core.RegisterDialect(v.dbType, v.getDialect) } } return true From 2ee7de9fa5577a77ca28cef30af678aea50e91ba Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Sat, 27 Jun 2015 12:36:38 +0800 Subject: [PATCH 4/4] bug fixed for sync2 --- session.go | 33 +++++++++++++++++++-------------- xorm.go | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/session.go b/session.go index a1984805..79dbe3ae 100644 --- a/session.go +++ b/session.go @@ -3889,6 +3889,7 @@ func (s *Session) Sync2(beans ...interface{}) error { } var foundIndexNames = make(map[string]bool) + var addedNames = make(map[string]*core.Index) for name, index := range table.Indexes { var oriIndex *core.Index @@ -3912,20 +3913,7 @@ func (s *Session) Sync2(beans ...interface{}) error { } if oriIndex == nil { - if index.Type == core.UniqueType { - session := engine.NewSession() - session.Statement.RefTable = table - defer session.Close() - err = session.addUnique(table.Name, name) - } else if index.Type == core.IndexType { - session := engine.NewSession() - session.Statement.RefTable = table - defer session.Close() - err = session.addIndex(table.Name, name) - } - if err != nil { - return err - } + addedNames[name] = index } } @@ -3938,6 +3926,23 @@ func (s *Session) Sync2(beans ...interface{}) error { } } } + + for name, index := range addedNames { + if index.Type == core.UniqueType { + session := engine.NewSession() + session.Statement.RefTable = table + defer session.Close() + err = session.addUnique(table.Name, name) + } else if index.Type == core.IndexType { + session := engine.NewSession() + session.Statement.RefTable = table + defer session.Close() + err = session.addIndex(table.Name, name) + } + if err != nil { + return err + } + } } } diff --git a/xorm.go b/xorm.go index f5f8f2a7..8e630b9a 100644 --- a/xorm.go +++ b/xorm.go @@ -17,7 +17,7 @@ import ( ) const ( - Version string = "0.4.3.0526" + Version string = "0.4.3.0627" ) func regDrvsNDialects() bool {