代码拉取完成,页面将自动刷新
package db
import (
"database/sql"
"database/sql/driver"
"encoding/json"
"fmt"
"gorm.io/gorm"
"gorm.io/gorm/callbacks"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
"reflect"
)
type Version sql.NullInt64
func (n *Version) Scan(value interface{}) error {
return (*sql.NullInt64)(n).Scan(value)
}
func (n Version) Value() (driver.Value, error) {
if !n.Valid {
return 0, nil
}
return n.Int64, nil
}
func (n Version) MarshalJSON() ([]byte, error) {
if n.Valid {
return json.Marshal(n.Int64)
}
return json.Marshal(0)
}
func (n *Version) UnmarshalJSON(b []byte) error {
if string(b) == "null" {
n.Valid = false
return nil
}
err := json.Unmarshal(b, &n.Int64)
if err == nil {
n.Valid = true
}
return err
}
func (Version) UpdateClauses(f *schema.Field) []clause.Interface {
return []clause.Interface{OptimisticLockUpdateClause{Field: f}}
}
type OptimisticLockUpdateClause struct {
Field *schema.Field
}
func (sd OptimisticLockUpdateClause) Name() string {
return ""
}
func (sd OptimisticLockUpdateClause) Build(clause.Builder) {
}
func (sd OptimisticLockUpdateClause) MergeClause(*clause.Clause) {
}
func (sd OptimisticLockUpdateClause) ModifyStatement(stmt *gorm.Statement) {
versionValue := clause.Expr{SQL: fmt.Sprintf("%s+1", sd.Field.DBName)}
if stmt.SQL.String() == "" {
if set := callbacks.ConvertToAssignments(stmt); len(set) > 0 {
exists := false
for i, c := range set {
if c.Column.Name == sd.Field.DBName {
c.Value = versionValue
set[i] = c
exists = true
break
}
}
if !exists {
set = append(set, clause.Assignment{Column: clause.Column{Name: sd.Field.DBName}, Value: versionValue})
}
stmt.AddClause(set)
} else {
stmt.AddClause(clause.Set{{Column: clause.Column{Name: sd.Field.DBName}, Value: versionValue}})
}
stmt.SetColumn(sd.Field.DBName, versionValue, true)
if stmt.Schema != nil {
_, queryValues := schema.GetIdentityFieldValuesMap(stmt.ReflectValue, stmt.Schema.PrimaryFields)
column, values := schema.ToQueryValues(stmt.Table, stmt.Schema.PrimaryFieldDBNames, queryValues)
if len(values) > 0 {
stmt.AddClause(clause.Where{Exprs: []clause.Expression{clause.IN{Column: column, Values: values}}})
}
if stmt.ReflectValue.CanAddr() && stmt.Dest != stmt.Model && stmt.Model != nil {
_, queryValues = schema.GetIdentityFieldValuesMap(reflect.ValueOf(stmt.Model), stmt.Schema.PrimaryFields)
column, values = schema.ToQueryValues(stmt.Table, stmt.Schema.PrimaryFieldDBNames, queryValues)
if len(values) > 0 {
stmt.AddClause(clause.Where{Exprs: []clause.Expression{clause.IN{Column: column, Values: values}}})
}
}
}
if _, ok := stmt.Clauses["WHERE"]; !stmt.DB.AllowGlobalUpdate && !ok {
stmt.DB.AddError(gorm.ErrMissingWhereClause)
} else {
oldVersion := sd.getVersionValue(stmt)
if _, ok := stmt.Clauses["optimistic_lock_enabled"]; !ok && oldVersion > 0 {
if c, ok := stmt.Clauses["WHERE"]; ok {
if where, ok := c.Expression.(clause.Where); ok && len(where.Exprs) > 1 {
for _, expr := range where.Exprs {
if orCond, ok := expr.(clause.OrConditions); ok && len(orCond.Exprs) == 1 {
where.Exprs = []clause.Expression{clause.And(where.Exprs...)}
c.Expression = where
stmt.Clauses["WHERE"] = c
break
}
}
}
}
stmt.AddClause(clause.Where{Exprs: []clause.Expression{
clause.Eq{Column: clause.Column{Table: clause.CurrentTable, Name: sd.Field.DBName}, Value: oldVersion},
}})
stmt.Clauses["optimistic_lock_enabled"] = clause.Clause{}
}
}
stmt.AddClauseIfNotExists(clause.Update{})
stmt.Build("UPDATE", "SET", "WHERE")
}
}
func (sd OptimisticLockUpdateClause) getVersionValue(stmt *gorm.Statement) int64 {
if stmt.Dest != nil {
v := reflect.ValueOf(stmt.Dest)
k := reflect.ValueOf(stmt.Dest).Kind()
if k == reflect.Ptr {
v = v.Elem()
k = v.Kind()
}
if k == reflect.Struct {
fv := v.FieldByName(sd.Field.Name)
if fv.Kind() == reflect.Ptr {
fv = fv.Elem()
}
iv := fv.FieldByName("Int64")
return iv.Int()
}
}
return 0
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。