Skip to content

Commit 9f13026

Browse files
Snowflake: parse ALTER TAG SET/UNSET MASKING POLICY
1 parent b5e11f2 commit 9f13026

4 files changed

Lines changed: 174 additions & 10 deletions

File tree

src/ast/ddl.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,61 @@ impl fmt::Display for AlterMaskingPolicyOperation {
14131413
}
14141414
}
14151415

1416+
/// An operation in an `ALTER TAG` statement.
1417+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1418+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1419+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1420+
pub enum AlterTagOperation {
1421+
/// `RENAME TO <new_name>`
1422+
RenameTo {
1423+
/// The new tag name.
1424+
new_name: ObjectName,
1425+
},
1426+
/// `SET MASKING POLICY <p> [, MASKING POLICY <p> ...] [FORCE]`
1427+
SetMaskingPolicy {
1428+
/// The masking policies to attach.
1429+
policies: Vec<ObjectName>,
1430+
/// `FORCE` flag.
1431+
force: bool,
1432+
},
1433+
/// `UNSET MASKING POLICY <p> [, MASKING POLICY <p> ...]`
1434+
UnsetMaskingPolicy {
1435+
/// The masking policies to detach.
1436+
policies: Vec<ObjectName>,
1437+
},
1438+
}
1439+
1440+
impl fmt::Display for AlterTagOperation {
1441+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1442+
match self {
1443+
AlterTagOperation::RenameTo { new_name } => write!(f, "RENAME TO {new_name}"),
1444+
AlterTagOperation::SetMaskingPolicy { policies, force } => {
1445+
write!(f, "SET ")?;
1446+
for (i, p) in policies.iter().enumerate() {
1447+
if i > 0 {
1448+
write!(f, ", ")?;
1449+
}
1450+
write!(f, "MASKING POLICY {p}")?;
1451+
}
1452+
if *force {
1453+
write!(f, " FORCE")?;
1454+
}
1455+
Ok(())
1456+
}
1457+
AlterTagOperation::UnsetMaskingPolicy { policies } => {
1458+
write!(f, "UNSET ")?;
1459+
for (i, p) in policies.iter().enumerate() {
1460+
if i > 0 {
1461+
write!(f, ", ")?;
1462+
}
1463+
write!(f, "MASKING POLICY {p}")?;
1464+
}
1465+
Ok(())
1466+
}
1467+
}
1468+
}
1469+
}
1470+
14161471
impl fmt::Display for AlterColumnOperation {
14171472
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
14181473
match self {

src/ast/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub use self::dcl::{
6464
pub use self::ddl::{
6565
Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation, AlterConnectorOwner,
6666
AlterFunction, AlterFunctionAction, AlterFunctionKind, AlterFunctionOperation,
67-
AlterMaskingPolicyOperation,
67+
AlterMaskingPolicyOperation, AlterTagOperation,
6868
AlterIndexOperation, AlterProcedure, AlterProcedureOperation,
6969
AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
7070
AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
@@ -5276,14 +5276,16 @@ pub enum Statement {
52765276
},
52775277
/// ```sql
52785278
/// ALTER TAG [IF EXISTS] <name> RENAME TO <new_name>
5279+
/// ALTER TAG [IF EXISTS] <name> SET MASKING POLICY <p> [, MASKING POLICY <p> ...] [FORCE]
5280+
/// ALTER TAG [IF EXISTS] <name> UNSET MASKING POLICY <p> [, MASKING POLICY <p> ...]
52795281
/// ```
52805282
AlterTag {
52815283
/// `IF EXISTS` flag.
52825284
if_exists: bool,
52835285
/// Tag name.
52845286
name: ObjectName,
5285-
/// New tag name.
5286-
new_name: ObjectName,
5287+
/// The operation to apply to the tag.
5288+
operation: AlterTagOperation,
52875289
},
52885290
/// ```sql
52895291
/// DROP TAG [IF EXISTS] <name>
@@ -7810,11 +7812,11 @@ impl fmt::Display for Statement {
78107812
Statement::AlterTag {
78117813
if_exists,
78127814
name,
7813-
new_name,
7815+
operation,
78147816
} => {
78157817
write!(
78167818
f,
7817-
"ALTER TAG {if_exists}{name} RENAME TO {new_name}",
7819+
"ALTER TAG {if_exists}{name} {operation}",
78187820
if_exists = if *if_exists { "IF EXISTS " } else { "" },
78197821
)
78207822
}

src/dialect/snowflake.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::ast::helpers::stmt_data_loading::{
2828
};
2929
use crate::ast::{
3030
AlterExternalVolumeOperation, AlterFileFormatOperation, AlterMaskingPolicyOperation,
31-
AlterProcedure, AlterProcedureOperation, AlterStageOperation, AlterTable,
31+
AlterProcedure, AlterProcedureOperation, AlterStageOperation, AlterTable, AlterTagOperation,
3232
AlterTableOperation, AlterTableType, CatalogRestAuthentication, CatalogRestConfig,
3333
CatalogSource, CatalogSyncNamespaceMode, CatalogTableFormat, ColumnOption, ColumnPolicy,
3434
ColumnPolicyProperty, ContactEntry, CopyIntoSnowflakeKind, CreateTable, CreateTableLikeKind,
@@ -3252,16 +3252,42 @@ fn parse_create_tag(or_replace: bool, parser: &mut Parser) -> Result<Statement,
32523252
})
32533253
}
32543254

3255-
/// Parse `ALTER TAG [IF EXISTS] <name> RENAME TO <new_name>`
3255+
/// Parse a comma-separated list of `MASKING POLICY <name>` items, where the
3256+
/// `MASKING POLICY` keywords are repeated before each policy name.
3257+
fn parse_masking_policy_list(parser: &mut Parser) -> Result<Vec<ObjectName>, ParserError> {
3258+
let mut policies = Vec::new();
3259+
loop {
3260+
parser.expect_keywords(&[Keyword::MASKING, Keyword::POLICY])?;
3261+
policies.push(parser.parse_object_name(false)?);
3262+
if !parser.consume_token(&Token::Comma) {
3263+
break;
3264+
}
3265+
}
3266+
Ok(policies)
3267+
}
3268+
3269+
/// Parse `ALTER TAG [IF EXISTS] <name> { RENAME TO <new_name>
3270+
/// | SET MASKING POLICY <p> [, MASKING POLICY <p> ...] [FORCE]
3271+
/// | UNSET MASKING POLICY <p> [, MASKING POLICY <p> ...] }`
32563272
fn parse_alter_tag(parser: &mut Parser) -> Result<Statement, ParserError> {
32573273
let if_exists = parser.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
32583274
let name = parser.parse_object_name(false)?;
3259-
parser.expect_keywords(&[Keyword::RENAME, Keyword::TO])?;
3260-
let new_name = parser.parse_object_name(false)?;
3275+
let operation = if parser.parse_keyword(Keyword::SET) {
3276+
let policies = parse_masking_policy_list(parser)?;
3277+
let force = parser.parse_keyword(Keyword::FORCE);
3278+
AlterTagOperation::SetMaskingPolicy { policies, force }
3279+
} else if parser.parse_keyword(Keyword::UNSET) {
3280+
let policies = parse_masking_policy_list(parser)?;
3281+
AlterTagOperation::UnsetMaskingPolicy { policies }
3282+
} else {
3283+
parser.expect_keywords(&[Keyword::RENAME, Keyword::TO])?;
3284+
let new_name = parser.parse_object_name(false)?;
3285+
AlterTagOperation::RenameTo { new_name }
3286+
};
32613287
Ok(Statement::AlterTag {
32623288
if_exists,
32633289
name,
3264-
new_name,
3290+
operation,
32653291
})
32663292
}
32673293

tests/sqlparser_snowflake.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9164,3 +9164,84 @@ fn parse_snowflake_create_view_column_masking_policy() {
91649164
other => panic!("expected CreateView, got {other:?}"),
91659165
}
91669166
}
9167+
9168+
#[test]
9169+
fn parse_snowflake_alter_tag_rename() {
9170+
match snowflake().verified_stmt("ALTER TAG IF EXISTS t RENAME TO u") {
9171+
Statement::AlterTag {
9172+
if_exists,
9173+
name,
9174+
operation,
9175+
} => {
9176+
assert!(if_exists);
9177+
assert_eq!("t", name.to_string());
9178+
assert_eq!(
9179+
AlterTagOperation::RenameTo {
9180+
new_name: ObjectName::from(vec![Ident::new("u")]),
9181+
},
9182+
operation
9183+
);
9184+
}
9185+
other => panic!("expected AlterTag, got {other:?}"),
9186+
}
9187+
}
9188+
9189+
#[test]
9190+
fn parse_snowflake_alter_tag_set_masking_policy() {
9191+
match snowflake().verified_stmt("ALTER TAG t SET MASKING POLICY p") {
9192+
Statement::AlterTag {
9193+
if_exists,
9194+
operation,
9195+
..
9196+
} => {
9197+
assert!(!if_exists);
9198+
assert_eq!(
9199+
AlterTagOperation::SetMaskingPolicy {
9200+
policies: vec![ObjectName::from(vec![Ident::new("p")])],
9201+
force: false,
9202+
},
9203+
operation
9204+
);
9205+
}
9206+
other => panic!("expected AlterTag, got {other:?}"),
9207+
}
9208+
9209+
match snowflake()
9210+
.verified_stmt("ALTER TAG IF EXISTS t SET MASKING POLICY p, MASKING POLICY q FORCE")
9211+
{
9212+
Statement::AlterTag {
9213+
if_exists,
9214+
operation,
9215+
..
9216+
} => {
9217+
assert!(if_exists);
9218+
assert_eq!(
9219+
AlterTagOperation::SetMaskingPolicy {
9220+
policies: vec![
9221+
ObjectName::from(vec![Ident::new("p")]),
9222+
ObjectName::from(vec![Ident::new("q")]),
9223+
],
9224+
force: true,
9225+
},
9226+
operation
9227+
);
9228+
}
9229+
other => panic!("expected AlterTag, got {other:?}"),
9230+
}
9231+
}
9232+
9233+
#[test]
9234+
fn parse_snowflake_alter_tag_unset_masking_policy() {
9235+
match snowflake().verified_stmt("ALTER TAG t UNSET MASKING POLICY p, MASKING POLICY q") {
9236+
Statement::AlterTag { operation, .. } => assert_eq!(
9237+
AlterTagOperation::UnsetMaskingPolicy {
9238+
policies: vec![
9239+
ObjectName::from(vec![Ident::new("p")]),
9240+
ObjectName::from(vec![Ident::new("q")]),
9241+
],
9242+
},
9243+
operation
9244+
),
9245+
other => panic!("expected AlterTag, got {other:?}"),
9246+
}
9247+
}

0 commit comments

Comments
 (0)