Add support for UPDATE ... LIMIT ... (#1991)
Some checks are pending
license / Release Audit Tool (RAT) (push) Waiting to run
Rust / codestyle (push) Waiting to run
Rust / lint (push) Waiting to run
Rust / benchmark-lint (push) Waiting to run
Rust / compile (push) Waiting to run
Rust / docs (push) Waiting to run
Rust / compile-no-std (push) Waiting to run
Rust / test (beta) (push) Waiting to run
Rust / test (nightly) (push) Waiting to run
Rust / test (stable) (push) Waiting to run

This commit is contained in:
Sven Sauleau 2025-08-08 12:19:35 +02:00 committed by GitHub
parent 67fca82495
commit 27544f9343
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 36 additions and 1 deletions

View file

@ -3238,6 +3238,8 @@ pub enum Statement {
returning: Option<Vec<SelectItem>>, returning: Option<Vec<SelectItem>>,
/// SQLite-specific conflict resolution clause /// SQLite-specific conflict resolution clause
or: Option<SqliteOnConflict>, or: Option<SqliteOnConflict>,
/// LIMIT
limit: Option<Expr>,
}, },
/// ```sql /// ```sql
/// DELETE /// DELETE
@ -4810,6 +4812,7 @@ impl fmt::Display for Statement {
selection, selection,
returning, returning,
or, or,
limit,
} => { } => {
f.write_str("UPDATE ")?; f.write_str("UPDATE ")?;
if let Some(or) = or { if let Some(or) = or {
@ -4843,6 +4846,10 @@ impl fmt::Display for Statement {
f.write_str("RETURNING")?; f.write_str("RETURNING")?;
indented_list(f, returning)?; indented_list(f, returning)?;
} }
if let Some(limit) = limit {
SpaceOrNewline.fmt(f)?;
write!(f, "LIMIT {limit}")?;
}
Ok(()) Ok(())
} }
Statement::Delete(delete) => delete.fmt(f), Statement::Delete(delete) => delete.fmt(f),

View file

@ -378,6 +378,7 @@ impl Spanned for Statement {
selection, selection,
returning, returning,
or: _, or: _,
limit: _,
} => union_spans( } => union_spans(
core::iter::once(table.span()) core::iter::once(table.span())
.chain(assignments.iter().map(|i| i.span())) .chain(assignments.iter().map(|i| i.span()))

View file

@ -15152,6 +15152,11 @@ impl<'a> Parser<'a> {
} else { } else {
None None
}; };
let limit = if self.parse_keyword(Keyword::LIMIT) {
Some(self.parse_expr()?)
} else {
None
};
Ok(Statement::Update { Ok(Statement::Update {
table, table,
assignments, assignments,
@ -15159,6 +15164,7 @@ impl<'a> Parser<'a> {
selection, selection,
returning, returning,
or, or,
limit,
}) })
} }

View file

@ -515,6 +515,7 @@ fn parse_update_set_from() {
}), }),
returning: None, returning: None,
or: None, or: None,
limit: None
} }
); );
@ -533,6 +534,7 @@ fn parse_update_with_table_alias() {
selection, selection,
returning, returning,
or: None, or: None,
limit: None,
} => { } => {
assert_eq!( assert_eq!(
TableWithJoins { TableWithJoins {

View file

@ -2516,6 +2516,7 @@ fn parse_update_with_joins() {
selection, selection,
returning, returning,
or: None, or: None,
limit: None,
} => { } => {
assert_eq!( assert_eq!(
TableWithJoins { TableWithJoins {

View file

@ -485,7 +485,8 @@ fn parse_update_tuple_row_values() {
joins: vec![], joins: vec![],
}, },
from: None, from: None,
returning: None returning: None,
limit: None
} }
); );
} }
@ -592,6 +593,23 @@ fn test_regexp_operator() {
sqlite().verified_only_select(r#"SELECT count(*) FROM messages WHERE msg_text REGEXP '\d+'"#); sqlite().verified_only_select(r#"SELECT count(*) FROM messages WHERE msg_text REGEXP '\d+'"#);
} }
#[test]
fn test_update_delete_limit() {
match sqlite().verified_stmt("UPDATE foo SET bar = 1 LIMIT 99") {
Statement::Update { limit, .. } => {
assert_eq!(limit, Some(Expr::value(number("99"))));
}
_ => unreachable!(),
}
match sqlite().verified_stmt("DELETE FROM foo LIMIT 99") {
Statement::Delete(Delete { limit, .. }) => {
assert_eq!(limit, Some(Expr::value(number("99"))));
}
_ => unreachable!(),
}
}
fn sqlite() -> TestedDialects { fn sqlite() -> TestedDialects {
TestedDialects::new(vec![Box::new(SQLiteDialect {})]) TestedDialects::new(vec![Box::new(SQLiteDialect {})])
} }