github.com/gogf/gf/v2@v2.7.4/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/gogf/gf. 6 7 package gdb 8 9 import ( 10 "database/sql" 11 "fmt" 12 "reflect" 13 14 "github.com/gogf/gf/v2/errors/gcode" 15 "github.com/gogf/gf/v2/errors/gerror" 16 "github.com/gogf/gf/v2/internal/empty" 17 "github.com/gogf/gf/v2/internal/intlog" 18 "github.com/gogf/gf/v2/internal/reflection" 19 "github.com/gogf/gf/v2/text/gstr" 20 "github.com/gogf/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 newData interface{} 49 stm = m.softTimeMaintainer() 50 reflectInfo = reflection.OriginTypeAndKind(m.data) 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 fieldNameUpdate != "" && (m.unscoped || m.isFieldInFieldsEx(fieldNameUpdate)) { 58 fieldNameUpdate = "" 59 } 60 61 newData, err = m.filterDataForInsertOrUpdate(m.data) 62 if err != nil { 63 return nil, err 64 } 65 66 switch reflectInfo.OriginKind { 67 case reflect.Map, reflect.Struct: 68 var dataMap = anyValueToMapBeforeToRecord(newData) 69 // Automatically update the record updating time. 70 if fieldNameUpdate != "" && empty.IsNil(dataMap[fieldNameUpdate]) { 71 dataValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeUpdate, false) 72 dataMap[fieldNameUpdate] = dataValue 73 } 74 newData = dataMap 75 76 default: 77 var updateStr = gconv.String(newData) 78 // Automatically update the record updating time. 79 if fieldNameUpdate != "" && !gstr.Contains(updateStr, fieldNameUpdate) { 80 dataValue := stm.GetValueByFieldTypeForCreateOrUpdate(ctx, fieldTypeUpdate, false) 81 updateStr += fmt.Sprintf(`,%s=?`, fieldNameUpdate) 82 conditionArgs = append([]interface{}{dataValue}, conditionArgs...) 83 } 84 newData = updateStr 85 } 86 87 if !gstr.ContainsI(conditionStr, " WHERE ") { 88 intlog.Printf( 89 ctx, 90 `sql condition string "%s" has no WHERE for UPDATE operation, fieldNameUpdate: %s`, 91 conditionStr, fieldNameUpdate, 92 ) 93 return nil, gerror.NewCode( 94 gcode.CodeMissingParameter, 95 "there should be WHERE condition statement for UPDATE operation", 96 ) 97 } 98 99 in := &HookUpdateInput{ 100 internalParamHookUpdate: internalParamHookUpdate{ 101 internalParamHook: internalParamHook{ 102 link: m.getLink(true), 103 }, 104 handler: m.hookHandler.Update, 105 }, 106 Model: m, 107 Table: m.tables, 108 Data: newData, 109 Condition: conditionStr, 110 Args: m.mergeArguments(conditionArgs), 111 } 112 return in.Next(ctx) 113 } 114 115 // UpdateAndGetAffected performs update statement and returns the affected rows number. 116 func (m *Model) UpdateAndGetAffected(dataAndWhere ...interface{}) (affected int64, err error) { 117 result, err := m.Update(dataAndWhere...) 118 if err != nil { 119 return 0, err 120 } 121 return result.RowsAffected() 122 } 123 124 // Increment increments a column's value by a given amount. 125 // The parameter `amount` can be type of float or integer. 126 func (m *Model) Increment(column string, amount interface{}) (sql.Result, error) { 127 return m.getModel().Data(column, &Counter{ 128 Field: column, 129 Value: gconv.Float64(amount), 130 }).Update() 131 } 132 133 // Decrement decrements a column's value by a given amount. 134 // The parameter `amount` can be type of float or integer. 135 func (m *Model) Decrement(column string, amount interface{}) (sql.Result, error) { 136 return m.getModel().Data(column, &Counter{ 137 Field: column, 138 Value: -gconv.Float64(amount), 139 }).Update() 140 }