Skip to content

Commit 7047de4

Browse files
authored
Merge pull request #452 from Hasaber8/feature/448
feature: Add support for LIMIT query in UPDATE for sql/sqlite
2 parents 262d866 + d733f96 commit 7047de4

File tree

3 files changed

+101
-5
lines changed

3 files changed

+101
-5
lines changed

mysql/update_statement.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type UpdateStatement interface {
1212
MODEL(data interface{}) UpdateStatement
1313

1414
WHERE(expression BoolExpression) UpdateStatement
15+
LIMIT(limit int64) UpdateStatement
1516
}
1617

1718
type updateStatementImpl struct {
@@ -21,6 +22,7 @@ type updateStatementImpl struct {
2122
Set jet.SetClause
2223
SetNew jet.SetClauseNew
2324
Where jet.ClauseWhere
25+
Limit jet.ClauseLimit
2426
}
2527

2628
func newUpdateStatement(table Table, columns []jet.Column) UpdateStatement {
@@ -29,11 +31,13 @@ func newUpdateStatement(table Table, columns []jet.Column) UpdateStatement {
2931
&update.Update,
3032
&update.Set,
3133
&update.SetNew,
32-
&update.Where)
34+
&update.Where,
35+
&update.Limit)
3336

3437
update.Update.Table = table
3538
update.Set.Columns = columns
3639
update.Where.Mandatory = true
40+
update.Limit.Count = -1 // Initialize to -1 to indicate no LIMIT
3741

3842
return update
3943
}
@@ -67,3 +71,11 @@ func (u *updateStatementImpl) WHERE(expression BoolExpression) UpdateStatement {
6771
u.Where.Condition = expression
6872
return u
6973
}
74+
75+
func (u *updateStatementImpl) LIMIT(limit int64) UpdateStatement {
76+
if _, isJoinTable := u.Update.Table.(*joinTable); isJoinTable {
77+
panic("jet: MySQL does not support LIMIT with multi-table UPDATE statements")
78+
}
79+
u.Limit.Count = limit
80+
return u
81+
}

mysql/update_statement_test.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ import (
66
"testing"
77
)
88

9+
func TestUpdateWithLimit(t *testing.T) {
10+
expectedSQL := `
11+
UPDATE db.table1
12+
SET col_int = ?
13+
WHERE table1.col_int >= ?
14+
LIMIT ?;
15+
`
16+
stmt := table1.UPDATE(table1ColInt).
17+
SET(1).
18+
WHERE(table1ColInt.GT_EQ(Int(33))).
19+
LIMIT(5)
20+
21+
assertStatementSql(t, stmt, expectedSQL, 1, int64(33), int64(5))
22+
}
23+
924
func TestUpdateWithOneValue(t *testing.T) {
1025
expectedSQL := `
1126
UPDATE db.table1
@@ -69,11 +84,26 @@ func TestUpdateReservedWorldColumn(t *testing.T) {
6984
Load: "foo",
7085
},
7186
).
72-
WHERE(loadColumn.EQ(String("bar"))), strings.Replace(`
87+
WHERE(loadColumn.EQ(String("bar"))).
88+
LIMIT(0),
89+
strings.Replace(`
7390
UPDATE db.table1
7491
SET ''Load'' = ?
75-
WHERE ''Load'' = ?;
76-
`, "''", "`", -1), "foo", "bar")
92+
WHERE ''Load'' = ?
93+
LIMIT ?;
94+
`, "''", "`", -1), "foo", "bar", int64(0))
95+
}
96+
97+
func LimitPanicStatement() {
98+
joinedTable := table1.INNER_JOIN(table2, table1Col1.EQ(table2Col3))
99+
joinedTable.UPDATE(table1ColInt).
100+
SET(1).
101+
WHERE(table1ColInt.GT_EQ(Int(33))).
102+
LIMIT(5)
103+
}
104+
105+
func TestUpdateWithMultiTableAndLimit(t *testing.T) {
106+
assertPanicErr(t, func() { LimitPanicStatement() }, "jet: MySQL does not support LIMIT with multi-table UPDATE statements")
77107
}
78108

79109
func TestInvalidInputs(t *testing.T) {

tests/mysql/update_test.go

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package mysql
22

33
import (
44
"context"
5-
"github.com/go-jet/jet/v2/qrm"
65
"testing"
76
"time"
87

8+
"github.com/go-jet/jet/v2/qrm"
9+
910
"github.com/stretchr/testify/require"
1011

1112
"github.com/go-jet/jet/v2/internal/testutils"
@@ -285,3 +286,56 @@ WHERE link.name = 'Bing';
285286
require.NoError(t, err)
286287
})
287288
}
289+
290+
func TestUpdateWithLimit(t *testing.T) {
291+
t.Run("single table update with limit", func(t *testing.T) {
292+
stmt := Link.
293+
UPDATE(Link.Name).
294+
SET(String("Updated Link")).
295+
WHERE(Link.Name.NOT_EQ(String(""))).
296+
LIMIT(2)
297+
298+
testutils.AssertDebugStatementSql(t, stmt, `
299+
UPDATE test_sample.link
300+
SET name = 'Updated Link'
301+
WHERE link.name != ''
302+
LIMIT 2;
303+
`)
304+
305+
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
306+
// Execute update
307+
testutils.AssertExec(t, stmt, tx)
308+
requireLogged(t, stmt)
309+
310+
// Verify only 2 rows were updated
311+
var updatedLinks []model.Link
312+
err := Link.
313+
SELECT(Link.AllColumns).
314+
WHERE(Link.Name.EQ(String("Updated Link"))).
315+
Query(tx, &updatedLinks)
316+
317+
require.NoError(t, err)
318+
require.Equal(t, 2, len(updatedLinks))
319+
})
320+
})
321+
322+
t.Run("multi-table update with limit should panic", func(t *testing.T) {
323+
defer func() {
324+
r := recover()
325+
require.NotNil(t, r)
326+
require.Equal(t, "jet: MySQL does not support LIMIT with multi-table UPDATE statements", r)
327+
}()
328+
329+
joinedTable := Link.
330+
INNER_JOIN(Link2, Link.Name.EQ(Link2.Name))
331+
332+
stmt := joinedTable.
333+
UPDATE(Link.Name).
334+
SET(String("Updated Link")).
335+
WHERE(Link.Name.NOT_EQ(String(""))).
336+
LIMIT(2)
337+
338+
// Statement construction itself should panic
339+
_ = stmt
340+
})
341+
}

0 commit comments

Comments
 (0)