forked from deoxxa/go-sqlbuilder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate.go
155 lines (135 loc) · 3.06 KB
/
update.go
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
148
149
150
151
152
153
154
155
package sqlbuilder
// UpdateStatement represents a UPDATE statement.
type UpdateStatement struct {
table Table
set []serializable
where Condition
orderBy []serializable
limit int
offset int
err error
}
// Update returns new UPDATE statement. The table is Table object to update.
func Update(tbl Table) *UpdateStatement {
if tbl == nil {
return &UpdateStatement{
err: newError("table is nil."),
}
}
return &UpdateStatement{
table: tbl,
set: make([]serializable, 0),
}
}
// Set sets SETS clause like col=val. Call many time for update multi columns.
func (b *UpdateStatement) Set(col Column, val interface{}) *UpdateStatement {
if b.err != nil {
return b
}
if !b.table.hasColumn(col) {
b.err = newError("column not found in FROM.")
return b
}
b.set = append(b.set, newUpdateValue(col, val))
return b
}
// Where sets WHERE clause. The cond is filter condition.
func (b *UpdateStatement) Where(cond Condition) *UpdateStatement {
if b.err != nil {
return b
}
b.where = cond
return b
}
// Limit sets LIMIT clause.
func (b *UpdateStatement) Limit(limit int) *UpdateStatement {
if b.err != nil {
return b
}
b.limit = limit
return b
}
// Limit sets OFFSET clause.
func (b *UpdateStatement) Offset(offset int) *UpdateStatement {
if b.err != nil {
return b
}
b.offset = offset
return b
}
// OrderBy sets "ORDER BY" clause. Use descending order if the desc is true, by the columns.
func (b *UpdateStatement) OrderBy(desc bool, columns ...Column) *UpdateStatement {
if b.err != nil {
return b
}
if b.orderBy == nil {
b.orderBy = make([]serializable, 0)
}
for _, c := range columns {
b.orderBy = append(b.orderBy, newOrderBy(desc, c))
}
return b
}
// ToSql generates query string, placeholder arguments, and returns err on errors.
func (b *UpdateStatement) ToSql() (query string, args []interface{}, err error) {
bldr := newBuilder()
defer func() {
query, args, err = bldr.Query(), bldr.Args(), bldr.Err()
}()
if b.err != nil {
bldr.SetError(b.err)
return
}
// UPDATE TABLE SET (COLUMN=VALUE)
bldr.Append("UPDATE ")
bldr.AppendItem(b.table)
bldr.Append(" SET ")
if len(b.set) != 0 {
bldr.AppendItems(b.set, ", ")
} else {
bldr.SetError(newError("length of sets is 0."))
}
// WHERE
if b.where != nil {
bldr.Append(" WHERE ")
bldr.AppendItem(b.where)
}
// ORDER BY
if b.orderBy != nil {
bldr.Append(" ORDER BY ")
bldr.AppendItems(b.orderBy, ", ")
}
// LIMIT
if b.limit != 0 {
bldr.Append(" LIMIT ")
bldr.AppendValue(b.limit)
}
// Offset
if b.offset != 0 {
bldr.Append(" OFFSET ")
bldr.AppendValue(b.offset)
}
return
}
type updateValue struct {
col Column
val literal
}
func newUpdateValue(col Column, val interface{}) updateValue {
return updateValue{
col: col,
val: toLiteral(val),
}
}
func (m updateValue) serialize(bldr *builder) {
if !m.col.acceptType(m.val) {
bldr.SetError(newError("%s column not accept %T.",
m.col.config().Type().String(),
m.val.Raw(),
))
return
}
bldr.Append(dialect().QuoteField(m.col.column_name()))
bldr.Append("=")
bldr.AppendItem(m.val)
}