mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-10-08 13:10:20 +00:00
Snowflake ALTER TABLE clustering options (#1579)
This commit is contained in:
parent
7b50ac31c3
commit
d0fcc06652
5 changed files with 123 additions and 15 deletions
|
@ -70,7 +70,10 @@ pub enum AlterTableOperation {
|
||||||
///
|
///
|
||||||
/// Note: this is a ClickHouse-specific operation.
|
/// Note: this is a ClickHouse-specific operation.
|
||||||
/// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#drop-projection)
|
/// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#drop-projection)
|
||||||
DropProjection { if_exists: bool, name: Ident },
|
DropProjection {
|
||||||
|
if_exists: bool,
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
|
|
||||||
/// `MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
|
/// `MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
|
||||||
///
|
///
|
||||||
|
@ -99,11 +102,15 @@ pub enum AlterTableOperation {
|
||||||
/// `DISABLE RULE rewrite_rule_name`
|
/// `DISABLE RULE rewrite_rule_name`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
DisableRule { name: Ident },
|
DisableRule {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// `DISABLE TRIGGER [ trigger_name | ALL | USER ]`
|
/// `DISABLE TRIGGER [ trigger_name | ALL | USER ]`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
DisableTrigger { name: Ident },
|
DisableTrigger {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// `DROP CONSTRAINT [ IF EXISTS ] <name>`
|
/// `DROP CONSTRAINT [ IF EXISTS ] <name>`
|
||||||
DropConstraint {
|
DropConstraint {
|
||||||
if_exists: bool,
|
if_exists: bool,
|
||||||
|
@ -152,19 +159,27 @@ pub enum AlterTableOperation {
|
||||||
/// `ENABLE ALWAYS RULE rewrite_rule_name`
|
/// `ENABLE ALWAYS RULE rewrite_rule_name`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
EnableAlwaysRule { name: Ident },
|
EnableAlwaysRule {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// `ENABLE ALWAYS TRIGGER trigger_name`
|
/// `ENABLE ALWAYS TRIGGER trigger_name`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
EnableAlwaysTrigger { name: Ident },
|
EnableAlwaysTrigger {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// `ENABLE REPLICA RULE rewrite_rule_name`
|
/// `ENABLE REPLICA RULE rewrite_rule_name`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
EnableReplicaRule { name: Ident },
|
EnableReplicaRule {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// `ENABLE REPLICA TRIGGER trigger_name`
|
/// `ENABLE REPLICA TRIGGER trigger_name`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
EnableReplicaTrigger { name: Ident },
|
EnableReplicaTrigger {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// `ENABLE ROW LEVEL SECURITY`
|
/// `ENABLE ROW LEVEL SECURITY`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
|
@ -172,11 +187,15 @@ pub enum AlterTableOperation {
|
||||||
/// `ENABLE RULE rewrite_rule_name`
|
/// `ENABLE RULE rewrite_rule_name`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
EnableRule { name: Ident },
|
EnableRule {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// `ENABLE TRIGGER [ trigger_name | ALL | USER ]`
|
/// `ENABLE TRIGGER [ trigger_name | ALL | USER ]`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
EnableTrigger { name: Ident },
|
EnableTrigger {
|
||||||
|
name: Ident,
|
||||||
|
},
|
||||||
/// `RENAME TO PARTITION (partition=val)`
|
/// `RENAME TO PARTITION (partition=val)`
|
||||||
RenamePartitions {
|
RenamePartitions {
|
||||||
old_partitions: Vec<Expr>,
|
old_partitions: Vec<Expr>,
|
||||||
|
@ -197,7 +216,9 @@ pub enum AlterTableOperation {
|
||||||
new_column_name: Ident,
|
new_column_name: Ident,
|
||||||
},
|
},
|
||||||
/// `RENAME TO <table_name>`
|
/// `RENAME TO <table_name>`
|
||||||
RenameTable { table_name: ObjectName },
|
RenameTable {
|
||||||
|
table_name: ObjectName,
|
||||||
|
},
|
||||||
// CHANGE [ COLUMN ] <old_name> <new_name> <data_type> [ <options> ]
|
// CHANGE [ COLUMN ] <old_name> <new_name> <data_type> [ <options> ]
|
||||||
ChangeColumn {
|
ChangeColumn {
|
||||||
old_name: Ident,
|
old_name: Ident,
|
||||||
|
@ -218,7 +239,10 @@ pub enum AlterTableOperation {
|
||||||
/// `RENAME CONSTRAINT <old_constraint_name> TO <new_constraint_name>`
|
/// `RENAME CONSTRAINT <old_constraint_name> TO <new_constraint_name>`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
RenameConstraint { old_name: Ident, new_name: Ident },
|
RenameConstraint {
|
||||||
|
old_name: Ident,
|
||||||
|
new_name: Ident,
|
||||||
|
},
|
||||||
/// `ALTER [ COLUMN ]`
|
/// `ALTER [ COLUMN ]`
|
||||||
AlterColumn {
|
AlterColumn {
|
||||||
column_name: Ident,
|
column_name: Ident,
|
||||||
|
@ -227,14 +251,27 @@ pub enum AlterTableOperation {
|
||||||
/// 'SWAP WITH <table_name>'
|
/// 'SWAP WITH <table_name>'
|
||||||
///
|
///
|
||||||
/// Note: this is Snowflake specific <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
|
/// Note: this is Snowflake specific <https://docs.snowflake.com/en/sql-reference/sql/alter-table>
|
||||||
SwapWith { table_name: ObjectName },
|
SwapWith {
|
||||||
|
table_name: ObjectName,
|
||||||
|
},
|
||||||
/// 'SET TBLPROPERTIES ( { property_key [ = ] property_val } [, ...] )'
|
/// 'SET TBLPROPERTIES ( { property_key [ = ] property_val } [, ...] )'
|
||||||
SetTblProperties { table_properties: Vec<SqlOption> },
|
SetTblProperties {
|
||||||
|
table_properties: Vec<SqlOption>,
|
||||||
|
},
|
||||||
/// `OWNER TO { <new_owner> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }`
|
/// `OWNER TO { <new_owner> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }`
|
||||||
///
|
///
|
||||||
/// Note: this is PostgreSQL-specific <https://www.postgresql.org/docs/current/sql-altertable.html>
|
/// Note: this is PostgreSQL-specific <https://www.postgresql.org/docs/current/sql-altertable.html>
|
||||||
OwnerTo { new_owner: Owner },
|
OwnerTo {
|
||||||
|
new_owner: Owner,
|
||||||
|
},
|
||||||
|
/// Snowflake table clustering options
|
||||||
|
/// <https://docs.snowflake.com/en/sql-reference/sql/alter-table#clustering-actions-clusteringaction>
|
||||||
|
ClusterBy {
|
||||||
|
exprs: Vec<Expr>,
|
||||||
|
},
|
||||||
|
DropClusteringKey,
|
||||||
|
SuspendRecluster,
|
||||||
|
ResumeRecluster,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An `ALTER Policy` (`Statement::AlterPolicy`) operation
|
/// An `ALTER Policy` (`Statement::AlterPolicy`) operation
|
||||||
|
@ -548,6 +585,22 @@ impl fmt::Display for AlterTableOperation {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
AlterTableOperation::ClusterBy { exprs } => {
|
||||||
|
write!(f, "CLUSTER BY ({})", display_comma_separated(exprs))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
AlterTableOperation::DropClusteringKey => {
|
||||||
|
write!(f, "DROP CLUSTERING KEY")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
AlterTableOperation::SuspendRecluster => {
|
||||||
|
write!(f, "SUSPEND RECLUSTER")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
AlterTableOperation::ResumeRecluster => {
|
||||||
|
write!(f, "RESUME RECLUSTER")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1020,6 +1020,10 @@ impl Spanned for AlterTableOperation {
|
||||||
union_spans(table_properties.iter().map(|i| i.span()))
|
union_spans(table_properties.iter().map(|i| i.span()))
|
||||||
}
|
}
|
||||||
AlterTableOperation::OwnerTo { .. } => Span::empty(),
|
AlterTableOperation::OwnerTo { .. } => Span::empty(),
|
||||||
|
AlterTableOperation::ClusterBy { exprs } => union_spans(exprs.iter().map(|e| e.span())),
|
||||||
|
AlterTableOperation::DropClusteringKey => Span::empty(),
|
||||||
|
AlterTableOperation::SuspendRecluster => Span::empty(),
|
||||||
|
AlterTableOperation::ResumeRecluster => Span::empty(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,6 +168,7 @@ define_keywords!(
|
||||||
CLOSE,
|
CLOSE,
|
||||||
CLUSTER,
|
CLUSTER,
|
||||||
CLUSTERED,
|
CLUSTERED,
|
||||||
|
CLUSTERING,
|
||||||
COALESCE,
|
COALESCE,
|
||||||
COLLATE,
|
COLLATE,
|
||||||
COLLATION,
|
COLLATION,
|
||||||
|
@ -622,6 +623,7 @@ define_keywords!(
|
||||||
READS,
|
READS,
|
||||||
READ_ONLY,
|
READ_ONLY,
|
||||||
REAL,
|
REAL,
|
||||||
|
RECLUSTER,
|
||||||
RECURSIVE,
|
RECURSIVE,
|
||||||
REF,
|
REF,
|
||||||
REFERENCES,
|
REFERENCES,
|
||||||
|
@ -656,6 +658,7 @@ define_keywords!(
|
||||||
RESTRICTIVE,
|
RESTRICTIVE,
|
||||||
RESULT,
|
RESULT,
|
||||||
RESULTSET,
|
RESULTSET,
|
||||||
|
RESUME,
|
||||||
RETAIN,
|
RETAIN,
|
||||||
RETURN,
|
RETURN,
|
||||||
RETURNING,
|
RETURNING,
|
||||||
|
@ -745,6 +748,7 @@ define_keywords!(
|
||||||
SUM,
|
SUM,
|
||||||
SUPER,
|
SUPER,
|
||||||
SUPERUSER,
|
SUPERUSER,
|
||||||
|
SUSPEND,
|
||||||
SWAP,
|
SWAP,
|
||||||
SYMMETRIC,
|
SYMMETRIC,
|
||||||
SYNC,
|
SYNC,
|
||||||
|
|
|
@ -7273,6 +7273,8 @@ impl<'a> Parser<'a> {
|
||||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
let name = self.parse_identifier(false)?;
|
let name = self.parse_identifier(false)?;
|
||||||
AlterTableOperation::DropProjection { if_exists, name }
|
AlterTableOperation::DropProjection { if_exists, name }
|
||||||
|
} else if self.parse_keywords(&[Keyword::CLUSTERING, Keyword::KEY]) {
|
||||||
|
AlterTableOperation::DropClusteringKey
|
||||||
} else {
|
} else {
|
||||||
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
||||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||||
|
@ -7444,6 +7446,15 @@ impl<'a> Parser<'a> {
|
||||||
partition,
|
partition,
|
||||||
with_name,
|
with_name,
|
||||||
}
|
}
|
||||||
|
} else if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) {
|
||||||
|
self.expect_token(&Token::LParen)?;
|
||||||
|
let exprs = self.parse_comma_separated(|parser| parser.parse_expr())?;
|
||||||
|
self.expect_token(&Token::RParen)?;
|
||||||
|
AlterTableOperation::ClusterBy { exprs }
|
||||||
|
} else if self.parse_keywords(&[Keyword::SUSPEND, Keyword::RECLUSTER]) {
|
||||||
|
AlterTableOperation::SuspendRecluster
|
||||||
|
} else if self.parse_keywords(&[Keyword::RESUME, Keyword::RECLUSTER]) {
|
||||||
|
AlterTableOperation::ResumeRecluster
|
||||||
} else {
|
} else {
|
||||||
let options: Vec<SqlOption> =
|
let options: Vec<SqlOption> =
|
||||||
self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?;
|
self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?;
|
||||||
|
|
|
@ -1411,6 +1411,42 @@ fn test_alter_table_swap_with() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_alter_table_clustering() {
|
||||||
|
let sql = r#"ALTER TABLE tab CLUSTER BY (c1, "c2", TO_DATE(c3))"#;
|
||||||
|
match alter_table_op(snowflake_and_generic().verified_stmt(sql)) {
|
||||||
|
AlterTableOperation::ClusterBy { exprs } => {
|
||||||
|
assert_eq!(
|
||||||
|
exprs,
|
||||||
|
[
|
||||||
|
Expr::Identifier(Ident::new("c1")),
|
||||||
|
Expr::Identifier(Ident::with_quote('"', "c2")),
|
||||||
|
Expr::Function(Function {
|
||||||
|
name: ObjectName(vec![Ident::new("TO_DATE")]),
|
||||||
|
parameters: FunctionArguments::None,
|
||||||
|
args: FunctionArguments::List(FunctionArgumentList {
|
||||||
|
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
|
||||||
|
Expr::Identifier(Ident::new("c3"))
|
||||||
|
))],
|
||||||
|
duplicate_treatment: None,
|
||||||
|
clauses: vec![],
|
||||||
|
}),
|
||||||
|
filter: None,
|
||||||
|
null_treatment: None,
|
||||||
|
over: None,
|
||||||
|
within_group: vec![]
|
||||||
|
})
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
snowflake_and_generic().verified_stmt("ALTER TABLE tbl DROP CLUSTERING KEY");
|
||||||
|
snowflake_and_generic().verified_stmt("ALTER TABLE tbl SUSPEND RECLUSTER");
|
||||||
|
snowflake_and_generic().verified_stmt("ALTER TABLE tbl RESUME RECLUSTER");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_drop_stage() {
|
fn test_drop_stage() {
|
||||||
match snowflake_and_generic().verified_stmt("DROP STAGE s1") {
|
match snowflake_and_generic().verified_stmt("DROP STAGE s1") {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue