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]

Reply via email to