Skip to content

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

Open
@takaebato

Description

@takaebato

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!(),
}
}

Activity

piki

piki commented on May 11, 2025

@piki

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      `GenericDialect` should support multi-table DELETE and DELETE without FROM clause · Issue #1846 · apache/datafusion-sqlparser-rs