This is an automated email from the ASF dual-hosted git repository.
iffyio pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 3392623b add support for `with` clauses (CTEs) in `delete` statements
(#1764)
3392623b is described below
commit 3392623b00718be68268fa65298ae98f74d2eda5
Author: Ophir LOJKINE <[email protected]>
AuthorDate: Wed Mar 12 11:42:51 2025 +0100
add support for `with` clauses (CTEs) in `delete` statements (#1764)
---
src/ast/query.rs | 2 ++
src/ast/spans.rs | 1 +
src/parser/mod.rs | 22 ++++++++++++++++++++++
tests/sqlparser_common.rs | 27 +++++++++++++++++++++++++++
4 files changed, 52 insertions(+)
diff --git a/src/ast/query.rs b/src/ast/query.rs
index bed99111..12f72932 100644
--- a/src/ast/query.rs
+++ b/src/ast/query.rs
@@ -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,
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index 62ca9dc0..8c3eff3c 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -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(),
}
}
}
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 2b95d674..400a9480 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -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())?;
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index a8ccd70a..8225d367 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -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";
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]