-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathupdate.go
More file actions
147 lines (130 loc) · 4.38 KB
/
update.go
File metadata and controls
147 lines (130 loc) · 4.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// A quickly mysql access component.
//
// Copyright 2023 The daog Authors. All rights reserved.
package daog
import (
txrequest "github.com/rolandhe/daog/tx"
"time"
)
type fieldExtractor[T any] struct {
ins *T
meta *TableMeta[T]
}
func (fe * fieldExtractor[T]) Extract(fieldName string) any{
return fe.meta.LookupFieldFunc(fieldName,fe.ins,true)
}
// Update 更新一条数据,把 *T类型的 ins 更新到数据,ins中的主键必须被设置
// meta 表的元数据,由compile编译生成,比如 GroupInfo.GroupInfoMeta
// 返回值是 更新的数据的条数,是0或者1
func Update[T any](tc *TransContext, ins *T, meta *TableMeta[T]) (int64, error) {
if BeforeUpdateCallback != nil{
tableName := GetTableName(tc.ctx, meta)
if err := BeforeUpdateCallback(tableName,ins);err != nil{
return 0, err
}
}
idValue := meta.LookupFieldFunc(TableIdColumnName, ins, false)
m := NewMatcher()
fieldId := TableIdColumnName
if meta.AutoColumn != "" {
fieldId = meta.AutoColumn
}
m.Eq(fieldId, idValue)
if err := auoFillField(tc,ins,meta);err != nil{
return 0, err
}
sql, args, err := updateExec(meta, ins, tc.ctx, m)
if err != nil {
return 0, err
}
return execSQLCore(tc, sql, args)
}
// UpdateList 更新多条数据,把多个 *T类型的 ins 更新到数据,每个ins中的主键必须被设置
// meta 表的元数据,由compile编译生成,比如 GroupInfo.GroupInfoMeta
// 返回值是 更新的数据的条数,是0或者1
// 注意: 当 tc 的事务类型是 txrequest.RequestNone 时,如果某一个 ins 更新失败,会立即返回错误,但该 ins之前的更新都会成功,此时的两个返回值都不是0值
func UpdateList[T any](tc *TransContext, insList []*T, meta *TableMeta[T]) (int64, error) {
var affectRow int64
for _, ins := range insList {
n, err := Update(tc, ins, meta)
if err != nil {
if tc.txRequest == txrequest.RequestNone {
return affectRow, err
}
return 0, err
}
affectRow += n
}
return affectRow, nil
}
// UpdateById 根据主键修改一条记录,需要修改的字段值通过 Modifier 指定
func UpdateById[T any](tc *TransContext, modifier Modifier, id int64, meta *TableMeta[T]) (int64, error) {
m := NewMatcher()
fieldId := TableIdColumnName
if meta.AutoColumn != "" {
fieldId = meta.AutoColumn
}
m.Eq(fieldId, id)
return UpdateByModifier(tc, modifier, m, meta)
}
// UpdateByIds 根据多个主键修改多条记录,需要修改的字段值通过 Modifier 指定,表达 update table set a=?,b=? where id in(xx,xx)的语义
func UpdateByIds[T any](tc *TransContext, modifier Modifier, ids []int64, meta *TableMeta[T]) (int64, error) {
if len(ids) == 0 {
return 0, nil
}
m := NewMatcher()
fieldId := TableIdColumnName
if meta.AutoColumn != "" {
fieldId = meta.AutoColumn
}
m.In(fieldId, ConvertToAnySlice(ids))
return UpdateByModifier(tc, modifier, m, meta)
}
// UpdateByModifier 根据Matcher条件修改多条记录,需要修改的字段值通过 Modifier 指定,表达 update table set a=?,b=? where uid=? and status=0 的类似语义
func UpdateByModifier[T any](tc *TransContext, modifier Modifier, matcher Matcher, meta *TableMeta[T]) (int64, error) {
if AddNewModifyFieldBeforeUpdate != nil{
if err := AddNewModifyFieldBeforeUpdate(tc.ExtInfo,modifier, func(fieldName string) bool {
for _,name := range meta.Columns {
if name == fieldName {
return true
}
}
return false
});err !=nil{
return 0, err
}
}
sql, args, err := buildModifierExec(meta, tc.ctx, modifier, matcher)
if err != nil {
return 0, err
}
if sql == "" {
return 0, nil
}
return execSQLCore(tc, sql, args)
}
// ExecRawSQL 执行原生的sql
func ExecRawSQL(tc *TransContext, sql string, args ...any) (int64, error) {
return execSQLCore(tc, sql, args)
}
// ExecInsertWithAutoId 执行原生的insert sql,并返回自增id
func ExecInsertWithAutoId(tc *TransContext, sql string, args ...any) (int64, error) {
_, lastId, err := execInsert(tc, sql, args, true)
return lastId, err
}
func execSQLCore(tc *TransContext, sql string, args []any) (int64, error) {
err := tc.check()
if err != nil {
return 0, err
}
if tc.LogSQL {
sqlMd5 := traceLogSQLBefore(tc.ctx, sql, args)
defer traceLogSQLAfter(tc.ctx, sqlMd5, time.Now().UnixMilli())
}
result, err := tc.conn.ExecContext(tc.ctx, sql, args...)
if err != nil {
return 0, err
}
affectRow, err := result.RowsAffected()
return affectRow, err
}