github.com/wangyougui/gf/v2@v2.6.5/database/gdb/gdb_model_update.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/wangyougui/gf. 6 7 package gdb 8 9 import ( 10 "database/sql" 11 "fmt" 12 "reflect" 13 14 "github.com/wangyougui/gf/v2/internal/intlog" 15 16 "github.com/wangyougui/gf/v2/errors/gcode" 17 "github.com/wangyougui/gf/v2/errors/gerror" 18 "github.com/wangyougui/gf/v2/internal/reflection" 19 "github.com/wangyougui/gf/v2/text/gstr" 20 "github.com/wangyougui/gf/v2/util/gconv" 21 ) 22 23 // Update does "UPDATE ... " statement for the model. 24 // 25 // If the optional parameter `dataAndWhere` is given, the dataAndWhere[0] is the updated data field, 26 // and dataAndWhere[1:] is treated as where condition fields. 27 // Also see Model.Data and Model.Where functions. 28 func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err error) { 29 var ctx = m.GetCtx() 30 if len(dataAndWhere) > 0 { 31 if len(dataAndWhere) > 2 { 32 return m.Data(dataAndWhere[0]).Where(dataAndWhere[1], dataAndWhere[2:]...).Update() 33 } else if len(dataAndWhere) == 2 { 34 return m.Data(dataAndWhere[0]).Where(dataAndWhere[1]).Update() 35 } else { 36 return m.Data(dataAndWhere[0]).Update() 37 } 38 } 39 defer func() { 40 if err == nil { 41 m.checkAndRemoveSelectCache(ctx) 42 } 43 }() 44 if m.data == nil { 45 return nil, gerror.NewCode(gcode.CodeMissingParameter, "updating table with empty data") 46 } 47 var ( 48 stm = m.softTimeMaintainer() 49 updateData = m.data 50 reflectInfo = reflection.OriginTypeAndKind(updateData) 51 conditionWhere, conditionExtra, conditionArgs = m.formatCondition(ctx, false, false) 52 conditionStr = conditionWhere + conditionExtra 53 fieldNameUpdate, fieldTypeUpdate = stm.GetFieldNameAndTypeForUpdate( 54 ctx, "", m.tablesInit, 55 ) 56 ) 57 if m.unscoped { 58 fieldNameUpdate = "" 59 } 60 61 switch reflectInfo.OriginKind { 62 case reflect.Map, reflect.Struct: 63 var dataMap = anyValueToMapBeforeToRecord(m.data) 64 // Automatically update the record updating time. 65 if fieldNameUpdate != "" { 66 dataValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeUpdate, false) 67 dataMap[fieldNameUpdate] = dataValue 68 } 69 updateData = dataMap 70 71 default: 72 updates := gconv.String(m.data) 73 // Automatically update the record updating time. 74 if fieldNameUpdate != "" { 75 dataValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeUpdate, false) 76 if fieldNameUpdate != "" && !gstr.Contains(updates, fieldNameUpdate) { 77 updates += fmt.Sprintf(`,%s=?`, fieldNameUpdate) 78 conditionArgs = append([]interface{}{dataValue}, conditionArgs...) 79 } 80 } 81 updateData = updates 82 } 83 newData, err := m.filterDataForInsertOrUpdate(updateData) 84 if err != nil { 85 return nil, err 86 } 87 88 if !gstr.ContainsI(conditionStr, " WHERE ") { 89 intlog.Printf( 90 ctx, 91 `sql condition string "%s" has no WHERE for UPDATE operation, fieldNameUpdate: %s`, 92 conditionStr, fieldNameUpdate, 93 ) 94 return nil, gerror.NewCode( 95 gcode.CodeMissingParameter, 96 "there should be WHERE condition statement for UPDATE operation", 97 ) 98 } 99 100 in := &HookUpdateInput{ 101 internalParamHookUpdate: internalParamHookUpdate{ 102 internalParamHook: internalParamHook{ 103 link: m.getLink(true), 104 }, 105 handler: m.hookHandler.Update, 106 }, 107 Model: m, 108 Table: m.tables, 109 Data: newData, 110 Condition: conditionStr, 111 Args: m.mergeArguments(conditionArgs), 112 } 113 return in.Next(ctx) 114 } 115 116 // UpdateAndGetAffected performs update statement and returns the affected rows number. 117 func (m *Model) UpdateAndGetAffected(dataAndWhere ...interface{}) (affected int64, err error) { 118 result, err := m.Update(dataAndWhere...) 119 if err != nil { 120 return 0, err 121 } 122 return result.RowsAffected() 123 } 124 125 // Increment increments a column's value by a given amount. 126 // The parameter `amount` can be type of float or integer. 127 func (m *Model) Increment(column string, amount interface{}) (sql.Result, error) { 128 return m.getModel().Data(column, &Counter{ 129 Field: column, 130 Value: gconv.Float64(amount), 131 }).Update() 132 } 133 134 // Decrement decrements a column's value by a given amount. 135 // The parameter `amount` can be type of float or integer. 136 func (m *Model) Decrement(column string, amount interface{}) (sql.Result, error) { 137 return m.getModel().Data(column, &Counter{ 138 Field: column, 139 Value: -gconv.Float64(amount), 140 }).Update() 141 }