Skip to content

Commit 1c0bae3

Browse files
committed
Adding From to Update builder.
1 parent 7759e1a commit 1c0bae3

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

update.go

+29
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type UpdateBuilder struct {
1212
prefixes []SQLizer
1313
table string
1414
setClauses []setClause
15+
fromParts []SQLizer
1516
whereParts []SQLizer
1617
orderBys []string
1718
returning []SQLizer
@@ -70,6 +71,14 @@ func (b UpdateBuilder) SQL() (sqlStr string, args []any, err error) {
7071
}
7172
sql.WriteString(strings.Join(setSQLs, ", "))
7273

74+
if len(b.fromParts) > 0 {
75+
sql.WriteString(" FROM ")
76+
args, err = appendSQL(b.fromParts, sql, ", ", args)
77+
if err != nil {
78+
return
79+
}
80+
}
81+
7382
if len(b.whereParts) > 0 {
7483
sql.WriteString(" WHERE ")
7584
args, err = appendSQL(b.whereParts, sql, " AND ", args)
@@ -153,6 +162,26 @@ func (b UpdateBuilder) SetMap(clauses map[string]any) UpdateBuilder {
153162
return b
154163
}
155164

165+
// From adds FROM expressions to the query.
166+
//
167+
// A table expression allowing columns from other tables to appear in the WHERE condition and update expressions.
168+
// This uses the same syntax as the FROM clause of a SELECT statement.
169+
// Do not repeat the target table unless you intend a self-join (in which case, you must use an alias).
170+
func (b UpdateBuilder) From(items ...string) UpdateBuilder {
171+
parts := make([]SQLizer, 0, len(items))
172+
for _, str := range items {
173+
parts = append(parts, newPart(str))
174+
}
175+
b.fromParts = append(b.fromParts, parts...)
176+
return b
177+
}
178+
179+
// FromSelect adds FROM expressions to the query similar to From, but takes a Select statement.
180+
func (b UpdateBuilder) FromSelect(from SelectBuilder, alias string) UpdateBuilder {
181+
b.fromParts = append(b.fromParts, Alias{Expr: from, As: alias})
182+
return b
183+
}
184+
156185
// Where adds WHERE expressions to the query.
157186
//
158187
// See SelectBuilder.Where for more information.

update_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,28 @@ func TestUpdateBuilderSQL(t *testing.T) {
103103
"RETURNING (SELECT abc FROM atable) AS something",
104104
wantArgs: []any{0, 1, 2, "foo", "bar", 3},
105105
},
106+
{
107+
name: "from",
108+
b: Update("employees").Set("sales_count", Expr("sales_count + 1")).From("accounts").
109+
Where("accounts.name = ?", "Acme Corporation").
110+
Where("employees.id = accounts.sales_person"),
111+
wantSQL: "UPDATE employees SET sales_count = sales_count + 1 FROM accounts " +
112+
"WHERE accounts.name = $1 " +
113+
"AND employees.id = accounts.sales_person",
114+
wantArgs: []any{"Acme Corporation"},
115+
},
116+
{
117+
name: "from_select",
118+
b: Update("employees").Set("sales_count", Expr("sales_count + 1")).FromSelect(
119+
Select("name").From("accounts"), "acc",
120+
).
121+
Where("acc.name = ?", "Acme Corporation").
122+
Where("employees.id = acc.sales_person"),
123+
wantSQL: "UPDATE employees SET sales_count = sales_count + 1 " +
124+
"FROM (SELECT name FROM accounts) " +
125+
"AS acc WHERE acc.name = $1 AND employees.id = acc.sales_person",
126+
wantArgs: []any{"Acme Corporation"},
127+
},
106128
}
107129

108130
for _, tc := range testCases {

0 commit comments

Comments
 (0)