diff --git a/fuzz/fuzz_seeds/mysql_2615_delete_limit.sql b/fuzz/fuzz_seeds/mysql_2615_delete_limit.sql new file mode 100644 index 0000000000..20517468d7 --- /dev/null +++ b/fuzz/fuzz_seeds/mysql_2615_delete_limit.sql @@ -0,0 +1 @@ +DELETE FROM customers LIMIT 100 diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs index 8fc72eec34..87177cdca5 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -713,6 +713,17 @@ pub trait Dialect: Debug + Any { false } + /// Returns true if the dialect supports `LIMIT` in `DELETE` statements. + /// + /// ```sql + /// DELETE FROM foo LIMIT 10; + /// ``` + /// See + /// and + fn supports_delete_limit(&self) -> bool { + false + } + /// Returns true if the dialect supports an `EXCEPT` clause following a /// wildcard in a select list. /// diff --git a/src/dialect/mysql.rs b/src/dialect/mysql.rs index 95bd27168e..6bc722f3e7 100644 --- a/src/dialect/mysql.rs +++ b/src/dialect/mysql.rs @@ -195,6 +195,11 @@ impl Dialect for MySqlDialect { true } + /// See: + fn supports_delete_limit(&self) -> bool { + true + } + fn supports_data_type_signed_suffix(&self) -> bool { true } diff --git a/src/dialect/sqlite.rs b/src/dialect/sqlite.rs index 0124f1f645..004b5077cc 100644 --- a/src/dialect/sqlite.rs +++ b/src/dialect/sqlite.rs @@ -151,6 +151,11 @@ impl Dialect for SQLiteDialect { true } + /// See: + fn supports_delete_limit(&self) -> bool { + true + } + fn supports_asc_desc_in_column_definition(&self) -> bool { true } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index d523b48cb5..9d47171c71 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -15233,7 +15233,7 @@ impl<'a> Parser<'a> { } else { vec![] }; - let limit = if self.parse_keyword(Keyword::LIMIT) { + let limit = if self.dialect.supports_delete_limit() && self.parse_keyword(Keyword::LIMIT) { self.parse_limit()? } else { None diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index bd1d7606af..7bdcc5a306 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -23106,3 +23106,16 @@ fn parse_alter_table_reset_options() { ); } } + +#[test] +fn parse_delete_limit_dialect_gated() { + let sql = "DELETE FROM customers LIMIT 100"; + all_dialects_where(|d| d.supports_delete_limit()).verified_stmt(sql); + + assert_eq!( + all_dialects_where(|d| !d.supports_delete_limit()).parse_sql_statements(sql), + Err(ParserError::ParserError( + "Expected: end of statement, found: LIMIT".to_string() + )) + ); +}