-
Notifications
You must be signed in to change notification settings - Fork 0
/
update.go
133 lines (112 loc) · 3.3 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
package statement
import (
"sort"
"strings"
)
// UpdateStatement statement.
type UpdateStatement struct {
table string
with Statement
values map[string]interface{}
where []Statement
comment []Statement
returning []string
}
// Update creates a new update statement
func Update() (s *UpdateStatement) {
return &UpdateStatement{values: make(map[string]interface{})}
}
// Comment adds a SQL comment to the generated query.
// Each call to comment creates a new `-- <comment>` line.
func (s *UpdateStatement) Comment(c string, values ...interface{}) *UpdateStatement {
p := &part{}
p.query = "-- " + c
p.values = values
s.comment = append(s.comment, p)
return s
}
// Table specifies the table for update.
func (s *UpdateStatement) Table(table string) *UpdateStatement {
s.table = table
return s
}
// Set adds a `SET column = value` clause, multiple calls to set append
// additional updates `SET column = value, column = value`
func (s *UpdateStatement) Set(column string, value interface{}) *UpdateStatement {
s.values[column] = value
return s
}
// SetMap specifies a map of column-value pairs to be updated.
func (s *UpdateStatement) SetMap(m map[string]interface{}) *UpdateStatement {
for col, val := range m {
s.values[col] = val
}
return s
}
// With adds a `WITH alias AS (stmt)` clause.
func (s *UpdateStatement) With(alias string, stmt Statement) *UpdateStatement {
s.with = &with{alias: alias, stmt: stmt}
return s
}
// Where adds a `WHERE` clause, multiple calls to Where are `ANDed` together.
func (s *UpdateStatement) Where(q string, values ...interface{}) *UpdateStatement {
s.where = append(s.where, &part{query: q, values: values})
return s
}
// WhereIn adds a `WHERE IN (values)` clause, multiple calls to WhereIn are `ANDed` together.
func (s *UpdateStatement) WhereIn(column string, values ...interface{}) *UpdateStatement {
s.where = append(s.where, buildWhereIn(column, values...))
return s
}
// Returning adds a `RETURNING columns` clause.
func (s *UpdateStatement) Returning(columns ...string) *UpdateStatement {
s.returning = columns
return s
}
// Build builds the statement into the given buffer.
func (s *UpdateStatement) Build(buf Buffer) (err error) {
for x := 0; x < len(s.comment); x++ {
if err = s.comment[x].Build(buf); err != nil {
return err
}
_, _ = buf.WriteString("\n")
}
if s.with != nil {
if err = s.with.Build(buf); err != nil {
return err
}
_, _ = buf.WriteString(" ")
}
_, _ = buf.WriteString("UPDATE " + s.table)
_, _ = buf.WriteString(" SET")
sorted := make([]string, 0, len(s.values))
for k := range s.values {
sorted = append(sorted, k)
}
sort.Strings(sorted)
for x := 0; x < len(sorted); x++ {
if x > 0 {
_, _ = buf.WriteString(", " + sorted[x] + " = ")
} else {
_, _ = buf.WriteString(" " + sorted[x] + " = ")
}
if err = writeValue(buf, s.values[sorted[x]], false); err != nil {
return err
}
}
if err = buildWhere(buf, s.where); err != nil {
return err
}
if len(s.returning) > 0 {
_, _ = buf.WriteString(" RETURNING " + strings.Join(s.returning, ","))
}
return nil
}
// String builds the statement and returns the resulting query string.
func (s *UpdateStatement) String() (q string, err error) {
var buf strings.Builder
if err = s.Build(&buf); err != nil {
return "", err
}
return buf.String(), nil
}