mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-07-08 01:15:00 +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),
|
Values(Values),
|
||||||
Insert(Statement),
|
Insert(Statement),
|
||||||
Update(Statement),
|
Update(Statement),
|
||||||
|
Delete(Statement),
|
||||||
Table(Box<Table>),
|
Table(Box<Table>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +179,7 @@ impl fmt::Display for SetExpr {
|
||||||
SetExpr::Values(v) => write!(f, "{v}"),
|
SetExpr::Values(v) => write!(f, "{v}"),
|
||||||
SetExpr::Insert(v) => write!(f, "{v}"),
|
SetExpr::Insert(v) => write!(f, "{v}"),
|
||||||
SetExpr::Update(v) => write!(f, "{v}"),
|
SetExpr::Update(v) => write!(f, "{v}"),
|
||||||
|
SetExpr::Delete(v) => write!(f, "{v}"),
|
||||||
SetExpr::Table(t) => write!(f, "{t}"),
|
SetExpr::Table(t) => write!(f, "{t}"),
|
||||||
SetExpr::SetOperation {
|
SetExpr::SetOperation {
|
||||||
left,
|
left,
|
||||||
|
|
|
@ -191,6 +191,7 @@ impl Spanned for SetExpr {
|
||||||
SetExpr::Insert(statement) => statement.span(),
|
SetExpr::Insert(statement) => statement.span(),
|
||||||
SetExpr::Table(_) => Span::empty(),
|
SetExpr::Table(_) => Span::empty(),
|
||||||
SetExpr::Update(statement) => statement.span(),
|
SetExpr::Update(statement) => statement.span(),
|
||||||
|
SetExpr::Delete(statement) => statement.span(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10050,6 +10050,13 @@ impl<'a> Parser<'a> {
|
||||||
Ok(parent_type(inside_type.into()))
|
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> {
|
pub fn parse_delete(&mut self) -> Result<Statement, ParserError> {
|
||||||
let (tables, with_from_keyword) = if !self.parse_keyword(Keyword::FROM) {
|
let (tables, with_from_keyword) = if !self.parse_keyword(Keyword::FROM) {
|
||||||
// `FROM` keyword is optional in BigQuery SQL.
|
// `FROM` keyword is optional in BigQuery SQL.
|
||||||
|
@ -10249,6 +10256,21 @@ impl<'a> Parser<'a> {
|
||||||
format_clause: None,
|
format_clause: None,
|
||||||
}
|
}
|
||||||
.into())
|
.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 {
|
} else {
|
||||||
let body = self.parse_query_body(self.dialect.prec_unknown())?;
|
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);
|
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]
|
#[test]
|
||||||
fn parse_derived_tables() {
|
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";
|
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