mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-07 17:04:59 +00:00
add support for with
clauses (CTEs) in delete
statements (#1764)
This commit is contained in:
parent
1e54a34acd
commit
3392623b00
4 changed files with 52 additions and 0 deletions
|
@ -156,6 +156,7 @@ pub enum SetExpr {
|
|||
Values(Values),
|
||||
Insert(Statement),
|
||||
Update(Statement),
|
||||
Delete(Statement),
|
||||
Table(Box<Table>),
|
||||
}
|
||||
|
||||
|
@ -178,6 +179,7 @@ impl fmt::Display for SetExpr {
|
|||
SetExpr::Values(v) => write!(f, "{v}"),
|
||||
SetExpr::Insert(v) => write!(f, "{v}"),
|
||||
SetExpr::Update(v) => write!(f, "{v}"),
|
||||
SetExpr::Delete(v) => write!(f, "{v}"),
|
||||
SetExpr::Table(t) => write!(f, "{t}"),
|
||||
SetExpr::SetOperation {
|
||||
left,
|
||||
|
|
|
@ -191,6 +191,7 @@ impl Spanned for SetExpr {
|
|||
SetExpr::Insert(statement) => statement.span(),
|
||||
SetExpr::Table(_) => Span::empty(),
|
||||
SetExpr::Update(statement) => statement.span(),
|
||||
SetExpr::Delete(statement) => statement.span(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10050,6 +10050,13 @@ impl<'a> Parser<'a> {
|
|||
Ok(parent_type(inside_type.into()))
|
||||
}
|
||||
|
||||
/// Parse a DELETE statement, returning a `Box`ed SetExpr
|
||||
///
|
||||
/// This is used to reduce the size of the stack frames in debug builds
|
||||
fn parse_delete_setexpr_boxed(&mut self) -> Result<Box<SetExpr>, ParserError> {
|
||||
Ok(Box::new(SetExpr::Delete(self.parse_delete()?)))
|
||||
}
|
||||
|
||||
pub fn parse_delete(&mut self) -> Result<Statement, ParserError> {
|
||||
let (tables, with_from_keyword) = if !self.parse_keyword(Keyword::FROM) {
|
||||
// `FROM` keyword is optional in BigQuery SQL.
|
||||
|
@ -10249,6 +10256,21 @@ impl<'a> Parser<'a> {
|
|||
format_clause: None,
|
||||
}
|
||||
.into())
|
||||
} else if self.parse_keyword(Keyword::DELETE) {
|
||||
Ok(Query {
|
||||
with,
|
||||
body: self.parse_delete_setexpr_boxed()?,
|
||||
limit: None,
|
||||
limit_by: vec![],
|
||||
order_by: None,
|
||||
offset: None,
|
||||
fetch: None,
|
||||
locks: vec![],
|
||||
for_clause: None,
|
||||
settings: None,
|
||||
format_clause: None,
|
||||
}
|
||||
.into())
|
||||
} else {
|
||||
let body = self.parse_query_body(self.dialect.prec_unknown())?;
|
||||
|
||||
|
|
|
@ -7383,6 +7383,33 @@ fn parse_recursive_cte() {
|
|||
assert_eq!(with.cte_tables.first().unwrap(), &expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_cte_in_data_modification_statements() {
|
||||
match verified_stmt("WITH x AS (SELECT 1) UPDATE t SET bar = (SELECT * FROM x)") {
|
||||
Statement::Query(query) => {
|
||||
assert_eq!(query.with.unwrap().to_string(), "WITH x AS (SELECT 1)");
|
||||
assert!(matches!(*query.body, SetExpr::Update(_)));
|
||||
}
|
||||
other => panic!("Expected: UPDATE, got: {:?}", other),
|
||||
}
|
||||
|
||||
match verified_stmt("WITH t (x) AS (SELECT 9) DELETE FROM q WHERE id IN (SELECT x FROM t)") {
|
||||
Statement::Query(query) => {
|
||||
assert_eq!(query.with.unwrap().to_string(), "WITH t (x) AS (SELECT 9)");
|
||||
assert!(matches!(*query.body, SetExpr::Delete(_)));
|
||||
}
|
||||
other => panic!("Expected: DELETE, got: {:?}", other),
|
||||
}
|
||||
|
||||
match verified_stmt("WITH x AS (SELECT 42) INSERT INTO t SELECT foo FROM x") {
|
||||
Statement::Query(query) => {
|
||||
assert_eq!(query.with.unwrap().to_string(), "WITH x AS (SELECT 42)");
|
||||
assert!(matches!(*query.body, SetExpr::Insert(_)));
|
||||
}
|
||||
other => panic!("Expected: INSERT, got: {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_derived_tables() {
|
||||
let sql = "SELECT a.x, b.y FROM (SELECT x FROM foo) AS a CROSS JOIN (SELECT y FROM bar) AS b";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue