diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 425e1fb60..02832408c 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3996,6 +3996,7 @@ pub enum Statement { with_grant_option: bool, as_grantor: Option, granted_by: Option, + current_grants: Option, }, /// ```sql /// DENY privileges ON object TO grantees @@ -4312,6 +4313,28 @@ pub enum Statement { Return(ReturnStatement), } +/// ```sql +/// {COPY | REVOKE} CURRENT GRANTS +/// ``` +/// +/// - [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/grant-ownership#optional-parameters) +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub enum CurrentGrantsKind { + CopyCurrentGrants, + RevokeCurrentGrants, +} + +impl fmt::Display for CurrentGrantsKind { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + CurrentGrantsKind::CopyCurrentGrants => write!(f, "COPY CURRENT GRANTS"), + CurrentGrantsKind::RevokeCurrentGrants => write!(f, "REVOKE CURRENT GRANTS"), + } + } +} + #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] @@ -5715,6 +5738,7 @@ impl fmt::Display for Statement { with_grant_option, as_grantor, granted_by, + current_grants, } => { write!(f, "GRANT {privileges} ")?; if let Some(objects) = objects { @@ -5724,6 +5748,9 @@ impl fmt::Display for Statement { if *with_grant_option { write!(f, " WITH GRANT OPTION")?; } + if let Some(current_grants) = current_grants { + write!(f, " {current_grants}")?; + } if let Some(grantor) = as_grantor { write!(f, " AS {grantor}")?; } diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 839d36459..1c9c55d07 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -13794,6 +13794,15 @@ impl<'a> Parser<'a> { let with_grant_option = self.parse_keywords(&[Keyword::WITH, Keyword::GRANT, Keyword::OPTION]); + let current_grants = + if self.parse_keywords(&[Keyword::COPY, Keyword::CURRENT, Keyword::GRANTS]) { + Some(CurrentGrantsKind::CopyCurrentGrants) + } else if self.parse_keywords(&[Keyword::REVOKE, Keyword::CURRENT, Keyword::GRANTS]) { + Some(CurrentGrantsKind::RevokeCurrentGrants) + } else { + None + }; + let as_grantor = if self.parse_keywords(&[Keyword::AS]) { Some(self.parse_identifier()?) } else { @@ -13813,6 +13822,7 @@ impl<'a> Parser<'a> { with_grant_option, as_grantor, granted_by, + current_grants, }) } diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index ed9bb704d..aecee6682 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -9437,6 +9437,8 @@ fn parse_grant() { verified_stmt("GRANT USAGE ON SCHEMA sc1 TO a:b"); verified_stmt("GRANT USAGE ON SCHEMA sc1 TO GROUP group1"); verified_stmt("GRANT OWNERSHIP ON ALL TABLES IN SCHEMA DEV_STAS_ROGOZHIN TO ROLE ANALYST"); + verified_stmt("GRANT OWNERSHIP ON ALL TABLES IN SCHEMA DEV_STAS_ROGOZHIN TO ROLE ANALYST COPY CURRENT GRANTS"); + verified_stmt("GRANT OWNERSHIP ON ALL TABLES IN SCHEMA DEV_STAS_ROGOZHIN TO ROLE ANALYST REVOKE CURRENT GRANTS"); verified_stmt("GRANT USAGE ON DATABASE db1 TO ROLE role1"); verified_stmt("GRANT USAGE ON WAREHOUSE wh1 TO ROLE role1"); verified_stmt("GRANT OWNERSHIP ON INTEGRATION int1 TO ROLE role1"); diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs index 79e2259b2..44f365844 100644 --- a/tests/sqlparser_mysql.rs +++ b/tests/sqlparser_mysql.rs @@ -3616,6 +3616,7 @@ fn parse_grant() { with_grant_option, as_grantor: _, granted_by, + current_grants: _, } = stmt { assert_eq!(