From 4ca150898717f759b6cff781742ebe94156422db Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Sun, 27 Apr 2025 17:44:43 +0200 Subject: [PATCH 1/2] Added support for `DROP DOMAIN` --- src/ast/mod.rs | 27 +++++++++++++++++ src/ast/spans.rs | 1 + src/keywords.rs | 1 + src/parser/mod.rs | 16 ++++++++++ tests/sqlparser_postgres.rs | 60 +++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 45924579b..362976a5b 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3319,6 +3319,18 @@ pub enum Statement { drop_behavior: Option, }, /// ```sql + /// DROP DOMAIN + /// ``` + /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-dropdomain.html) + /// + /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] + /// + DropDomain { + if_exists: bool, + name: ObjectName, + drop_behavior: Option, + }, + /// ```sql /// DROP PROCEDURE /// ``` DropProcedure { @@ -5092,6 +5104,21 @@ impl fmt::Display for Statement { } Ok(()) } + Statement::DropDomain { + if_exists, + name, + drop_behavior, + } => { + write!( + f, + "DROP DOMAIN{} {name}", + if *if_exists { " IF EXISTS" } else { "" }, + )?; + if let Some(op) = drop_behavior { + write!(f, " {op}")?; + } + Ok(()) + } Statement::DropProcedure { if_exists, proc_desc, diff --git a/src/ast/spans.rs b/src/ast/spans.rs index 93de5fff2..623c93370 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -454,6 +454,7 @@ impl Spanned for Statement { Statement::DetachDuckDBDatabase { .. } => Span::empty(), Statement::Drop { .. } => Span::empty(), Statement::DropFunction { .. } => Span::empty(), + Statement::DropDomain { .. } => Span::empty(), Statement::DropProcedure { .. } => Span::empty(), Statement::DropSecret { .. } => Span::empty(), Statement::Declare { .. } => Span::empty(), diff --git a/src/keywords.rs b/src/keywords.rs index 4eaad7ed2..a872911b3 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -286,6 +286,7 @@ define_keywords!( DISTRIBUTE, DIV, DO, + DOMAIN, DOUBLE, DOW, DOY, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0546548af..c0e7fa490 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6051,6 +6051,8 @@ impl<'a> Parser<'a> { return self.parse_drop_policy(); } else if self.parse_keyword(Keyword::CONNECTOR) { return self.parse_drop_connector(); + } else if self.parse_keyword(Keyword::DOMAIN) { + return self.parse_drop_domain(); } else if self.parse_keyword(Keyword::PROCEDURE) { return self.parse_drop_procedure(); } else if self.parse_keyword(Keyword::SECRET) { @@ -6146,6 +6148,20 @@ impl<'a> Parser<'a> { Ok(Statement::DropConnector { if_exists, name }) } + /// ```sql + /// DROP DOMAIN [ IF EXISTS ] name [ CASCADE | RESTRICT ] + /// ``` + fn parse_drop_domain(&mut self) -> Result { + let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); + let name = self.parse_object_name(false)?; + let drop_behavior = self.parse_optional_drop_behavior(); + Ok(Statement::DropDomain { + if_exists, + name, + drop_behavior, + }) + } + /// ```sql /// DROP PROCEDURE [ IF EXISTS ] name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] [, ...] /// [ CASCADE | RESTRICT ] diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 27fc7fa17..6ad3716a2 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -4239,6 +4239,66 @@ fn parse_drop_function() { ); } +#[test] +fn parse_drop_domain() { + let sql = "DROP DOMAIN IF EXISTS jpeg_domain"; + assert_eq!( + pg().verified_stmt(sql), + Statement::DropDomain { + if_exists: true, + name: ObjectName::from(vec![Ident { + value: "jpeg_domain".to_string(), + quote_style: None, + span: Span::empty(), + }]), + drop_behavior: None + } + ); + + let sql = "DROP DOMAIN jpeg_domain"; + assert_eq!( + pg().verified_stmt(sql), + Statement::DropDomain { + if_exists: false, + name: ObjectName::from(vec![Ident { + value: "jpeg_domain".to_string(), + quote_style: None, + span: Span::empty(), + }]), + drop_behavior: None + } + ); + + let sql = "DROP DOMAIN IF EXISTS jpeg_domain CASCADE"; + assert_eq!( + pg().verified_stmt(sql), + Statement::DropDomain { + if_exists: true, + name: ObjectName::from(vec![Ident { + value: "jpeg_domain".to_string(), + quote_style: None, + span: Span::empty(), + }]), + drop_behavior: Some(DropBehavior::Cascade) + } + ); + + let sql = "DROP DOMAIN IF EXISTS jpeg_domain RESTRICT"; + + assert_eq!( + pg().verified_stmt(sql), + Statement::DropDomain { + if_exists: true, + name: ObjectName::from(vec![Ident { + value: "jpeg_domain".to_string(), + quote_style: None, + span: Span::empty(), + }]), + drop_behavior: Some(DropBehavior::Restrict) + } + ); +} + #[test] fn parse_drop_procedure() { let sql = "DROP PROCEDURE IF EXISTS test_proc"; From 10dab5142da31e0fd0768318cc57b389ed6b1de2 Mon Sep 17 00:00:00 2001 From: LucaCappelletti94 Date: Wed, 30 Apr 2025 09:49:11 +0200 Subject: [PATCH 2/2] Refactored into struct `DropDomain` --- src/ast/mod.rs | 23 ++++++++++++++++------- src/parser/mod.rs | 4 ++-- tests/sqlparser_postgres.rs | 16 ++++++++-------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 362976a5b..dc4e0715e 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3325,11 +3325,7 @@ pub enum Statement { /// /// DROP DOMAIN [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ] /// - DropDomain { - if_exists: bool, - name: ObjectName, - drop_behavior: Option, - }, + DropDomain(DropDomain), /// ```sql /// DROP PROCEDURE /// ``` @@ -5104,11 +5100,11 @@ impl fmt::Display for Statement { } Ok(()) } - Statement::DropDomain { + Statement::DropDomain(DropDomain { if_exists, name, drop_behavior, - } => { + }) => { write!( f, "DROP DOMAIN{} {name}", @@ -6854,6 +6850,19 @@ impl fmt::Display for CloseCursor { } } +/// A Drop Domain statement +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub struct DropDomain { + /// Whether to drop the domain if it exists + pub if_exists: bool, + /// The name of the domain to drop + pub name: ObjectName, + /// The behavior to apply when dropping the domain + pub drop_behavior: Option, +} + /// A function call #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] diff --git a/src/parser/mod.rs b/src/parser/mod.rs index c0e7fa490..8f8fb748a 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -6155,11 +6155,11 @@ impl<'a> Parser<'a> { let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); let name = self.parse_object_name(false)?; let drop_behavior = self.parse_optional_drop_behavior(); - Ok(Statement::DropDomain { + Ok(Statement::DropDomain(DropDomain { if_exists, name, drop_behavior, - }) + })) } /// ```sql diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 6ad3716a2..e7b7fc15f 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -4244,7 +4244,7 @@ fn parse_drop_domain() { let sql = "DROP DOMAIN IF EXISTS jpeg_domain"; assert_eq!( pg().verified_stmt(sql), - Statement::DropDomain { + Statement::DropDomain(DropDomain { if_exists: true, name: ObjectName::from(vec![Ident { value: "jpeg_domain".to_string(), @@ -4252,13 +4252,13 @@ fn parse_drop_domain() { span: Span::empty(), }]), drop_behavior: None - } + }) ); let sql = "DROP DOMAIN jpeg_domain"; assert_eq!( pg().verified_stmt(sql), - Statement::DropDomain { + Statement::DropDomain(DropDomain { if_exists: false, name: ObjectName::from(vec![Ident { value: "jpeg_domain".to_string(), @@ -4266,13 +4266,13 @@ fn parse_drop_domain() { span: Span::empty(), }]), drop_behavior: None - } + }) ); let sql = "DROP DOMAIN IF EXISTS jpeg_domain CASCADE"; assert_eq!( pg().verified_stmt(sql), - Statement::DropDomain { + Statement::DropDomain(DropDomain { if_exists: true, name: ObjectName::from(vec![Ident { value: "jpeg_domain".to_string(), @@ -4280,14 +4280,14 @@ fn parse_drop_domain() { span: Span::empty(), }]), drop_behavior: Some(DropBehavior::Cascade) - } + }) ); let sql = "DROP DOMAIN IF EXISTS jpeg_domain RESTRICT"; assert_eq!( pg().verified_stmt(sql), - Statement::DropDomain { + Statement::DropDomain(DropDomain { if_exists: true, name: ObjectName::from(vec![Ident { value: "jpeg_domain".to_string(), @@ -4295,7 +4295,7 @@ fn parse_drop_domain() { span: Span::empty(), }]), drop_behavior: Some(DropBehavior::Restrict) - } + }) ); }