Skip to content

MySQL: Gate DELETE LIMIT behind supports_delete_limit() - #2757

Open
ump45nose wants to merge 2 commits into
apache:mainfrom
ump45nose:fix/2615-delete-limit-dialect-gate
Open

ump45nose wants to merge 2 commits into
apache:mainfrom
ump45nose:fix/2615-delete-limit-dialect-gate

Conversation

@ump45nose

Copy link
Copy Markdown

Dialects: MySQL, SQLite, Generic, PostgreSQL, DuckDB

Summary

DELETE ... LIMIT n was accepted by every dialect, including GenericDialect.
Engines that use Generic (e.g. DataFusion) therefore parsed the LIMIT and then
silently ignored it.

Fix

  • Add Dialect::supports_delete_limit() (default false)
  • Enable for MySQL and SQLite (real engine support)
  • Parse LIMIT in DELETE only when the dialect opts in

Closes #2615.

Docs:

Test plan

  • cargo test --all-features
  • cargo fmt --all
  • cargo clippy --all-targets --all-features -- -D warnings
  • New: parse_delete_limit_dialect_gated (positive for supporting dialects, reject others)
  • Existing MySQL/SQLite DELETE LIMIT tests still pass
  • Fuzz seed: fuzz/fuzz_seeds/mysql_2615_delete_limit.sql

AI assistance

This change was developed with AI assistance (Cursor / Grok Bot). I reviewed
every line of the diff and the test output before opening this PR.

GenericDialect (and other dialects that do not support DELETE+LIMIT)
previously accepted `DELETE ... LIMIT n`, so engines like DataFusion
that use GenericDialect silently ignored the LIMIT.

Add Dialect::supports_delete_limit() (default false), enable it for
MySQL and SQLite, and only parse LIMIT in DELETE when the dialect
opts in. Closes apache#2615.

Signed-off-by: Vincent <ump45nose@users.noreply.github.com>
@ump45nose

Copy link
Copy Markdown
Author

Rebased onto latest main.

(AI-assisted reply.)

@zvonimir-dd zvonimir-dd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up. I'm not sure gating Generic off is the right fix, though, and it might be worth a maintainer weighing in on #2615 first:

  • GenericDialect usually opts in to permissive syntax. The closest precedent, supports_update_order_by(), returns true for Generic as well as MySQL. With this PR, Generic users parsing MySQL-flavoured SQL get a new parse error, which makes this a breaking change.
  • The DataFusion bug behind #2615 is already fixed on the DataFusion side: apache/datafusion#25005 (merged 2026-10-08) rejects DELETE ... LIMIT during planning, and describes that as temporary until bounded DELETE is implemented. Keeping limit in Generic's AST lets DataFusion add that support later without a parser change.

If the flag stays, I'd enable it for GenericDialect as supports_update_order_by does, and call out the behavior change for the remaining dialects in the description/changelog.

Comment thread src/parser/mod.rs
vec![]
};
let limit = if self.parse_keyword(Keyword::LIMIT) {
let limit = if self.dialect.supports_delete_limit() && self.parse_keyword(Keyword::LIMIT) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DELETE ... ORDER BY, parsed a few lines above, is also MySQL/SQLite-only but stays ungated, so DELETE FROM t ORDER BY a still parses in every dialect. Same for UPDATE ... LIMIT. If we gate on dialect, it would be more consistent to gate these together.

…it-dialect-gate

Signed-off-by: Vincent <1729065730@qq.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Should DELETE + LIMIT be supported by the generic dialect ?

2 participants