Skip to content

Commit d8eb51b

Browse files
authored
[#82] Added FROM clause to update builder (#256)
1 parent e1c3903 commit d8eb51b

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

update.go

+22
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type updateData struct {
1616
Prefixes []Sqlizer
1717
Table string
1818
SetClauses []setClause
19+
From Sqlizer
1920
WhereParts []Sqlizer
2021
OrderBys []string
2122
Limit string
@@ -100,6 +101,14 @@ func (d *updateData) ToSql() (sqlStr string, args []interface{}, err error) {
100101
}
101102
sql.WriteString(strings.Join(setSqls, ", "))
102103

104+
if d.From != nil {
105+
sql.WriteString(" FROM ")
106+
args, err = appendToSql([]Sqlizer{d.From}, sql, "", args)
107+
if err != nil {
108+
return
109+
}
110+
}
111+
103112
if len(d.WhereParts) > 0 {
104113
sql.WriteString(" WHERE ")
105114
args, err = appendToSql(d.WhereParts, sql, " AND ", args)
@@ -233,6 +242,19 @@ func (b UpdateBuilder) SetMap(clauses map[string]interface{}) UpdateBuilder {
233242
return b
234243
}
235244

245+
// From adds FROM clause to the query
246+
// FROM is valid construct in postgresql only.
247+
func (b UpdateBuilder) From(from string) UpdateBuilder {
248+
return builder.Set(b, "From", newPart(from)).(UpdateBuilder)
249+
}
250+
251+
// FromSelect sets a subquery into the FROM clause of the query.
252+
func (b UpdateBuilder) FromSelect(from SelectBuilder, alias string) UpdateBuilder {
253+
// Prevent misnumbered parameters in nested selects (#183).
254+
from = from.PlaceholderFormat(Question)
255+
return builder.Set(b, "From", Alias(from, alias)).(UpdateBuilder)
256+
}
257+
236258
// Where adds WHERE expressions to the query.
237259
//
238260
// See SelectBuilder.Where for more information.

update_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,26 @@ func TestUpdateBuilderNoRunner(t *testing.T) {
8282
_, err := b.Exec()
8383
assert.Equal(t, RunnerNotSet, err)
8484
}
85+
86+
func TestUpdateBuilderFrom(t *testing.T) {
87+
sql, _, err := Update("employees").Set("sales_count", 100).From("accounts").Where("accounts.name = ?", "ACME").ToSql()
88+
assert.NoError(t, err)
89+
assert.Equal(t, "UPDATE employees SET sales_count = ? FROM accounts WHERE accounts.name = ?", sql)
90+
}
91+
92+
func TestUpdateBuilderFromSelect(t *testing.T) {
93+
sql, _, err := Update("employees").
94+
Set("sales_count", 100).
95+
FromSelect(Select("id").
96+
From("accounts").
97+
Where("accounts.name = ?", "ACME"), "subquery").
98+
Where("employees.account_id = subquery.id").ToSql()
99+
assert.NoError(t, err)
100+
101+
expectedSql :=
102+
"UPDATE employees " +
103+
"SET sales_count = ? " +
104+
"FROM (SELECT id FROM accounts WHERE accounts.name = ?) AS subquery " +
105+
"WHERE employees.account_id = subquery.id"
106+
assert.Equal(t, expectedSql, sql)
107+
}

0 commit comments

Comments
 (0)