github.com/gogf/gf@v1.16.9/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  	"github.com/gogf/gf/errors/gcode"
    13  	"reflect"
    14  
    15  	"github.com/gogf/gf/errors/gerror"
    16  	"github.com/gogf/gf/os/gtime"
    17  	"github.com/gogf/gf/text/gstr"
    18  	"github.com/gogf/gf/util/gconv"
    19  )
    20  
    21  // Update does "UPDATE ... " statement for the model.
    22  //
    23  // If the optional parameter `dataAndWhere` is given, the dataAndWhere[0] is the updated data field,
    24  // and dataAndWhere[1:] is treated as where condition fields.
    25  // Also see Model.Data and Model.Where functions.
    26  func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err error) {
    27  	if len(dataAndWhere) > 0 {
    28  		if len(dataAndWhere) > 2 {
    29  			return m.Data(dataAndWhere[0]).Where(dataAndWhere[1], dataAndWhere[2:]...).Update()
    30  		} else if len(dataAndWhere) == 2 {
    31  			return m.Data(dataAndWhere[0]).Where(dataAndWhere[1]).Update()
    32  		} else {
    33  			return m.Data(dataAndWhere[0]).Update()
    34  		}
    35  	}
    36  	defer func() {
    37  		if err == nil {
    38  			m.checkAndRemoveCache()
    39  		}
    40  	}()
    41  	if m.data == nil {
    42  		return nil, gerror.NewCode(gcode.CodeMissingParameter, "updating table with empty data")
    43  	}
    44  	var (
    45  		updateData                                    = m.data
    46  		fieldNameUpdate                               = m.getSoftFieldNameUpdated()
    47  		conditionWhere, conditionExtra, conditionArgs = m.formatCondition(false, false)
    48  	)
    49  	// Automatically update the record updating time.
    50  	if !m.unscoped && fieldNameUpdate != "" {
    51  		var (
    52  			refValue = reflect.ValueOf(m.data)
    53  			refKind  = refValue.Kind()
    54  		)
    55  		if refKind == reflect.Ptr {
    56  			refValue = refValue.Elem()
    57  			refKind = refValue.Kind()
    58  		}
    59  		switch refKind {
    60  		case reflect.Map, reflect.Struct:
    61  			dataMap := ConvertDataForTableRecord(m.data)
    62  			if fieldNameUpdate != "" {
    63  				dataMap[fieldNameUpdate] = gtime.Now().String()
    64  			}
    65  			updateData = dataMap
    66  		default:
    67  			updates := gconv.String(m.data)
    68  			if fieldNameUpdate != "" && !gstr.Contains(updates, fieldNameUpdate) {
    69  				updates += fmt.Sprintf(`,%s='%s'`, fieldNameUpdate, gtime.Now().String())
    70  			}
    71  			updateData = updates
    72  		}
    73  	}
    74  	newData, err := m.filterDataForInsertOrUpdate(updateData)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	conditionStr := conditionWhere + conditionExtra
    79  	if !gstr.ContainsI(conditionStr, " WHERE ") {
    80  		return nil, gerror.NewCode(gcode.CodeMissingParameter, "there should be WHERE condition statement for UPDATE operation")
    81  	}
    82  	return m.db.DoUpdate(
    83  		m.GetCtx(),
    84  		m.getLink(true),
    85  		m.tables,
    86  		newData,
    87  		conditionStr,
    88  		m.mergeArguments(conditionArgs)...,
    89  	)
    90  }
    91  
    92  // Increment increments a column's value by a given amount.
    93  // The parameter `amount` can be type of float or integer.
    94  func (m *Model) Increment(column string, amount interface{}) (sql.Result, error) {
    95  	return m.getModel().Data(column, &Counter{
    96  		Field: column,
    97  		Value: gconv.Float64(amount),
    98  	}).Update()
    99  }
   100  
   101  // Decrement decrements a column's value by a given amount.
   102  // The parameter `amount` can be type of float or integer.
   103  func (m *Model) Decrement(column string, amount interface{}) (sql.Result, error) {
   104  	return m.getModel().Data(column, &Counter{
   105  		Field: column,
   106  		Value: -gconv.Float64(amount),
   107  	}).Update()
   108  }