Skip to content

GenericDialect should support multi-table DELETE and DELETE without FROM clause #1846

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
takaebato opened this issue May 9, 2025 · 1 comment

Comments

@takaebato
Copy link
Contributor

takaebato commented May 9, 2025

According to the design policy, GenericDialect is intended to parse any SQL that other dialects can handle, but it currently fails to parse multi-table DELETE statements and DELETE statements without a FROM clause.

I think the expected behavior is that the following tests should also pass with GenericDialect.

#[test]
fn parse_delete_without_from_error() {
let sql = "DELETE \"table\" WHERE 1";
let dialects = all_dialects_except(|d| d.is::<BigQueryDialect>() || d.is::<GenericDialect>());
let res = dialects.parse_sql_statements(sql);
assert_eq!(
ParserError::ParserError("Expected: FROM, found: WHERE".to_string()),
res.unwrap_err()
);
}
#[test]
fn parse_delete_statement_for_multi_tables() {
let sql = "DELETE schema1.table1, schema2.table2 FROM schema1.table1 JOIN schema2.table2 ON schema2.table2.col1 = schema1.table1.col1 WHERE schema2.table2.col2 = 1";
let dialects = all_dialects_except(|d| d.is::<BigQueryDialect>() || d.is::<GenericDialect>());
match dialects.verified_stmt(sql) {
Statement::Delete(Delete {
tables,
from: FromTable::WithFromKeyword(from),
..
}) => {
assert_eq!(
ObjectName::from(vec![Ident::new("schema1"), Ident::new("table1")]),
tables[0]
);
assert_eq!(
ObjectName::from(vec![Ident::new("schema2"), Ident::new("table2")]),
tables[1]
);
assert_eq!(
table_from_name(ObjectName::from(vec![
Ident::new("schema1"),
Ident::new("table1")
])),
from[0].relation
);
assert_eq!(
table_from_name(ObjectName::from(vec![
Ident::new("schema2"),
Ident::new("table2")
])),
from[0].joins[0].relation
);
}
_ => unreachable!(),
}
}

@piki
Copy link

piki commented May 11, 2025

It looks like #1120 is where this changed. BigQueryDialect got the ability to parse DELETE statements without the FROM keyword. GenericDialect got treated the same way as BigQueryDialect, but that broke its ability to parse some statements from dialects other than BigQueryDialect.

The most permissive thing would be for GenericDialect to be able to support both of these DELETE formats:

  • DELETE [FROM] table [alias] WHERE condition (like BigQuery)
  • DELETE tables FROM table WHERE condition (like all the other dialects)

The challenge is that just making FROM optional doesn't work, because these two statements become a reduce-reduce conflict:

  • DELETE table_list [FROM] table WHERE condition
  • DELETE [FROM] table alias WHERE condition

So I think the best approach is to split parse_delete into two functions: one in the BigQueryDialect style and one in the all-others style, and let GenericDialect try both.

Supporting the union of many grammars is hard and sometimes undefined, but I think that 👆 is what makes the most sense for DELETE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants