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 7dbf31b5 Add support for DROP EXTENSION (#1610)
7dbf31b5 is described below
commit 7dbf31b5875c4643dee493367203d4f29e7f1033
Author: Ramnivas Laddad <[email protected]>
AuthorDate: Fri Dec 27 04:19:42 2024 -0800
Add support for DROP EXTENSION (#1610)
---
src/ast/mod.rs | 27 +++++++++++++
src/ast/spans.rs | 1 +
src/parser/mod.rs | 23 ++++++++++-
tests/sqlparser_postgres.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 144 insertions(+), 1 deletion(-)
diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index 5bdce21e..d99f6888 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -2755,6 +2755,18 @@ pub enum Statement {
version: Option<Ident>,
},
/// ```sql
+ /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
+ ///
+ /// Note: this is a PostgreSQL-specific statement.
+ /// https://www.postgresql.org/docs/current/sql-dropextension.html
+ /// ```
+ DropExtension {
+ names: Vec<Ident>,
+ if_exists: bool,
+ /// `CASCADE` or `RESTRICT`
+ cascade_or_restrict: Option<ReferentialAction>,
+ },
+ /// ```sql
/// FETCH
/// ```
/// Retrieve rows from a query using a cursor
@@ -4029,6 +4041,21 @@ impl fmt::Display for Statement {
Ok(())
}
+ Statement::DropExtension {
+ names,
+ if_exists,
+ cascade_or_restrict,
+ } => {
+ write!(f, "DROP EXTENSION")?;
+ if *if_exists {
+ write!(f, " IF EXISTS")?;
+ }
+ write!(f, " {}", display_comma_separated(names))?;
+ if let Some(cascade_or_restrict) = cascade_or_restrict {
+ write!(f, " {cascade_or_restrict}")?;
+ }
+ Ok(())
+ }
Statement::CreateRole {
names,
if_not_exists,
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index 521b5399..574830ef 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -430,6 +430,7 @@ impl Spanned for Statement {
Statement::DropSecret { .. } => Span::empty(),
Statement::Declare { .. } => Span::empty(),
Statement::CreateExtension { .. } => Span::empty(),
+ Statement::DropExtension { .. } => Span::empty(),
Statement::Fetch { .. } => Span::empty(),
Statement::Flush { .. } => Span::empty(),
Statement::Discard { .. } => Span::empty(),
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 3b582701..2756ed6c 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -5414,9 +5414,11 @@ impl<'a> Parser<'a> {
return self.parse_drop_secret(temporary, persistent);
} else if self.parse_keyword(Keyword::TRIGGER) {
return self.parse_drop_trigger();
+ } else if self.parse_keyword(Keyword::EXTENSION) {
+ return self.parse_drop_extension();
} else {
return self.expected(
- "TABLE, VIEW, INDEX, ROLE, SCHEMA, DATABASE, FUNCTION,
PROCEDURE, STAGE, TRIGGER, SECRET, SEQUENCE, or TYPE after DROP",
+ "TABLE, VIEW, INDEX, ROLE, SCHEMA, DATABASE, FUNCTION,
PROCEDURE, STAGE, TRIGGER, SECRET, SEQUENCE, TYPE, or EXTENSION after DROP",
self.peek_token(),
);
};
@@ -6079,6 +6081,25 @@ impl<'a> Parser<'a> {
})
}
+ /// Parse a PostgreSQL-specific [Statement::DropExtension] statement.
+ pub fn parse_drop_extension(&mut self) -> Result<Statement, ParserError> {
+ let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
+ let names = self.parse_comma_separated(|p| p.parse_identifier(false))?;
+ let cascade_or_restrict =
+ self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]);
+ Ok(Statement::DropExtension {
+ names,
+ if_exists,
+ cascade_or_restrict: cascade_or_restrict
+ .map(|k| match k {
+ Keyword::CASCADE => Ok(ReferentialAction::Cascade),
+ Keyword::RESTRICT => Ok(ReferentialAction::Restrict),
+ _ => self.expected("CASCADE or RESTRICT",
self.peek_token()),
+ })
+ .transpose()?,
+ })
+ }
+
//TODO: Implement parsing for Skewed
pub fn parse_hive_distribution(&mut self) -> Result<HiveDistributionStyle,
ParserError> {
if self.parse_keywords(&[Keyword::PARTITIONED, Keyword::BY]) {
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index 557e70bf..fd520d50 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -662,6 +662,100 @@ fn parse_create_extension() {
.verified_stmt("CREATE EXTENSION extension_name WITH SCHEMA
schema_name VERSION version");
}
+#[test]
+fn parse_drop_extension() {
+ assert_eq!(
+ pg_and_generic().verified_stmt("DROP EXTENSION extension_name"),
+ Statement::DropExtension {
+ names: vec!["extension_name".into()],
+ if_exists: false,
+ cascade_or_restrict: None,
+ }
+ );
+ assert_eq!(
+ pg_and_generic().verified_stmt("DROP EXTENSION extension_name
CASCADE"),
+ Statement::DropExtension {
+ names: vec!["extension_name".into()],
+ if_exists: false,
+ cascade_or_restrict: Some(ReferentialAction::Cascade),
+ }
+ );
+
+ assert_eq!(
+ pg_and_generic().verified_stmt("DROP EXTENSION extension_name
RESTRICT"),
+ Statement::DropExtension {
+ names: vec!["extension_name".into()],
+ if_exists: false,
+ cascade_or_restrict: Some(ReferentialAction::Restrict),
+ }
+ );
+
+ assert_eq!(
+ pg_and_generic().verified_stmt("DROP EXTENSION extension_name,
extension_name2 CASCADE"),
+ Statement::DropExtension {
+ names: vec!["extension_name".into(), "extension_name2".into()],
+ if_exists: false,
+ cascade_or_restrict: Some(ReferentialAction::Cascade),
+ }
+ );
+
+ assert_eq!(
+ pg_and_generic().verified_stmt("DROP EXTENSION extension_name,
extension_name2 RESTRICT"),
+ Statement::DropExtension {
+ names: vec!["extension_name".into(), "extension_name2".into()],
+ if_exists: false,
+ cascade_or_restrict: Some(ReferentialAction::Restrict),
+ }
+ );
+
+ assert_eq!(
+ pg_and_generic().verified_stmt("DROP EXTENSION IF EXISTS
extension_name"),
+ Statement::DropExtension {
+ names: vec!["extension_name".into()],
+ if_exists: true,
+ cascade_or_restrict: None,
+ }
+ );
+
+ assert_eq!(
+ pg_and_generic().verified_stmt("DROP EXTENSION IF EXISTS
extension_name CASCADE"),
+ Statement::DropExtension {
+ names: vec!["extension_name".into()],
+ if_exists: true,
+ cascade_or_restrict: Some(ReferentialAction::Cascade),
+ }
+ );
+
+ assert_eq!(
+ pg_and_generic().verified_stmt("DROP EXTENSION IF EXISTS
extension_name RESTRICT"),
+ Statement::DropExtension {
+ names: vec!["extension_name".into()],
+ if_exists: true,
+ cascade_or_restrict: Some(ReferentialAction::Restrict),
+ }
+ );
+
+ assert_eq!(
+ pg_and_generic()
+ .verified_stmt("DROP EXTENSION IF EXISTS extension_name1,
extension_name2 CASCADE"),
+ Statement::DropExtension {
+ names: vec!["extension_name1".into(), "extension_name2".into()],
+ if_exists: true,
+ cascade_or_restrict: Some(ReferentialAction::Cascade),
+ }
+ );
+
+ assert_eq!(
+ pg_and_generic()
+ .verified_stmt("DROP EXTENSION IF EXISTS extension_name1,
extension_name2 RESTRICT"),
+ Statement::DropExtension {
+ names: vec!["extension_name1".into(), "extension_name2".into()],
+ if_exists: true,
+ cascade_or_restrict: Some(ReferentialAction::Restrict),
+ }
+ );
+}
+
#[test]
fn parse_alter_table_alter_column() {
pg().one_statement_parses_to(
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]