Skip to content

Commit f3cf96d

Browse files
committed
support for SQLite UPDATE ... LIMIT ...
1 parent c1648e7 commit f3cf96d

File tree

6 files changed

+36
-1
lines changed

6 files changed

+36
-1
lines changed

src/ast/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,6 +3238,8 @@ pub enum Statement {
32383238
returning: Option<Vec<SelectItem>>,
32393239
/// SQLite-specific conflict resolution clause
32403240
or: Option<SqliteOnConflict>,
3241+
/// LIMIT
3242+
limit: Option<Expr>,
32413243
},
32423244
/// ```sql
32433245
/// DELETE
@@ -4799,6 +4801,7 @@ impl fmt::Display for Statement {
47994801
selection,
48004802
returning,
48014803
or,
4804+
limit,
48024805
} => {
48034806
f.write_str("UPDATE ")?;
48044807
if let Some(or) = or {
@@ -4832,6 +4835,10 @@ impl fmt::Display for Statement {
48324835
f.write_str("RETURNING")?;
48334836
indented_list(f, returning)?;
48344837
}
4838+
if let Some(limit) = limit {
4839+
SpaceOrNewline.fmt(f)?;
4840+
write!(f, "LIMIT {limit}")?;
4841+
}
48354842
Ok(())
48364843
}
48374844
Statement::Delete(delete) => delete.fmt(f),

src/ast/spans.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ impl Spanned for Statement {
378378
selection,
379379
returning,
380380
or: _,
381+
limit: _,
381382
} => union_spans(
382383
core::iter::once(table.span())
383384
.chain(assignments.iter().map(|i| i.span()))

src/parser/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15116,13 +15116,19 @@ impl<'a> Parser<'a> {
1511615116
} else {
1511715117
None
1511815118
};
15119+
let limit = if self.parse_keyword(Keyword::LIMIT) {
15120+
Some(self.parse_expr()?)
15121+
} else {
15122+
None
15123+
};
1511915124
Ok(Statement::Update {
1512015125
table,
1512115126
assignments,
1512215127
from,
1512315128
selection,
1512415129
returning,
1512515130
or,
15131+
limit,
1512615132
})
1512715133
}
1512815134

tests/sqlparser_common.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ fn parse_update_set_from() {
515515
}),
516516
returning: None,
517517
or: None,
518+
limit: None
518519
}
519520
);
520521

@@ -533,6 +534,7 @@ fn parse_update_with_table_alias() {
533534
selection,
534535
returning,
535536
or: None,
537+
limit: None,
536538
} => {
537539
assert_eq!(
538540
TableWithJoins {

tests/sqlparser_mysql.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2509,6 +2509,7 @@ fn parse_update_with_joins() {
25092509
selection,
25102510
returning,
25112511
or: None,
2512+
limit: None,
25122513
} => {
25132514
assert_eq!(
25142515
TableWithJoins {

tests/sqlparser_sqlite.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,8 @@ fn parse_update_tuple_row_values() {
485485
joins: vec![],
486486
},
487487
from: None,
488-
returning: None
488+
returning: None,
489+
limit: None
489490
}
490491
);
491492
}
@@ -592,6 +593,23 @@ fn test_regexp_operator() {
592593
sqlite().verified_only_select(r#"SELECT count(*) FROM messages WHERE msg_text REGEXP '\d+'"#);
593594
}
594595

596+
#[test]
597+
fn test_update_delete_limit() {
598+
match sqlite().verified_stmt("UPDATE foo SET bar = 1 LIMIT 99") {
599+
Statement::Update { limit, .. } => {
600+
assert_eq!(limit, Some(Expr::value(number("99"))));
601+
}
602+
_ => unreachable!(),
603+
}
604+
605+
match sqlite().verified_stmt("DELETE FROM foo LIMIT 99") {
606+
Statement::Delete(Delete { limit, .. }) => {
607+
assert_eq!(limit, Some(Expr::value(number("99"))));
608+
}
609+
_ => unreachable!(),
610+
}
611+
}
612+
595613
fn sqlite() -> TestedDialects {
596614
TestedDialects::new(vec![Box::new(SQLiteDialect {})])
597615
}

0 commit comments

Comments
 (0)