mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-26 23:49:10 +00:00
Add support of FREEZE|UNFREEZE PARTITION
syntax for ClickHouse (#1380)
This commit is contained in:
parent
c2f46ae07b
commit
6a11a67fcd
4 changed files with 146 additions and 0 deletions
|
@ -87,6 +87,20 @@ pub enum AlterTableOperation {
|
||||||
// See `AttachPartition` for more details
|
// See `AttachPartition` for more details
|
||||||
partition: Partition,
|
partition: Partition,
|
||||||
},
|
},
|
||||||
|
/// `FREEZE PARTITION <partition_expr>`
|
||||||
|
/// Note: this is a ClickHouse-specific operation, please refer to
|
||||||
|
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#freeze-partition)
|
||||||
|
FreezePartition {
|
||||||
|
partition: Partition,
|
||||||
|
with_name: Option<Ident>,
|
||||||
|
},
|
||||||
|
/// `UNFREEZE PARTITION <partition_expr>`
|
||||||
|
/// Note: this is a ClickHouse-specific operation, please refer to
|
||||||
|
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#unfreeze-partition)
|
||||||
|
UnfreezePartition {
|
||||||
|
partition: Partition,
|
||||||
|
with_name: Option<Ident>,
|
||||||
|
},
|
||||||
/// `DROP PRIMARY KEY`
|
/// `DROP PRIMARY KEY`
|
||||||
///
|
///
|
||||||
/// Note: this is a MySQL-specific operation.
|
/// Note: this is a MySQL-specific operation.
|
||||||
|
@ -379,6 +393,26 @@ impl fmt::Display for AlterTableOperation {
|
||||||
display_comma_separated(table_properties)
|
display_comma_separated(table_properties)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
AlterTableOperation::FreezePartition {
|
||||||
|
partition,
|
||||||
|
with_name,
|
||||||
|
} => {
|
||||||
|
write!(f, "FREEZE {partition}")?;
|
||||||
|
if let Some(name) = with_name {
|
||||||
|
write!(f, " WITH NAME {name}")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
AlterTableOperation::UnfreezePartition {
|
||||||
|
partition,
|
||||||
|
with_name,
|
||||||
|
} => {
|
||||||
|
write!(f, "UNFREEZE {partition}")?;
|
||||||
|
if let Some(name) = with_name {
|
||||||
|
write!(f, " WITH NAME {name}")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -763,6 +763,7 @@ define_keywords!(
|
||||||
UNBOUNDED,
|
UNBOUNDED,
|
||||||
UNCACHE,
|
UNCACHE,
|
||||||
UNCOMMITTED,
|
UNCOMMITTED,
|
||||||
|
UNFREEZE,
|
||||||
UNION,
|
UNION,
|
||||||
UNIQUE,
|
UNIQUE,
|
||||||
UNKNOWN,
|
UNKNOWN,
|
||||||
|
|
|
@ -6684,6 +6684,34 @@ impl<'a> Parser<'a> {
|
||||||
AlterTableOperation::DetachPartition {
|
AlterTableOperation::DetachPartition {
|
||||||
partition: self.parse_part_or_partition()?,
|
partition: self.parse_part_or_partition()?,
|
||||||
}
|
}
|
||||||
|
} else if dialect_of!(self is ClickHouseDialect|GenericDialect)
|
||||||
|
&& self.parse_keyword(Keyword::FREEZE)
|
||||||
|
{
|
||||||
|
let partition = self.parse_part_or_partition()?;
|
||||||
|
let with_name = if self.parse_keyword(Keyword::WITH) {
|
||||||
|
self.expect_keyword(Keyword::NAME)?;
|
||||||
|
Some(self.parse_identifier(false)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
AlterTableOperation::FreezePartition {
|
||||||
|
partition,
|
||||||
|
with_name,
|
||||||
|
}
|
||||||
|
} else if dialect_of!(self is ClickHouseDialect|GenericDialect)
|
||||||
|
&& self.parse_keyword(Keyword::UNFREEZE)
|
||||||
|
{
|
||||||
|
let partition = self.parse_part_or_partition()?;
|
||||||
|
let with_name = if self.parse_keyword(Keyword::WITH) {
|
||||||
|
self.expect_keyword(Keyword::NAME)?;
|
||||||
|
Some(self.parse_identifier(false)?)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
AlterTableOperation::UnfreezePartition {
|
||||||
|
partition,
|
||||||
|
with_name,
|
||||||
|
}
|
||||||
} 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])?;
|
||||||
|
|
|
@ -1216,6 +1216,89 @@ fn parse_create_table_on_commit_and_as_query() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_freeze_and_unfreeze_partition() {
|
||||||
|
// test cases without `WITH NAME`
|
||||||
|
for operation_name in &["FREEZE", "UNFREEZE"] {
|
||||||
|
let sql = format!("ALTER TABLE t {operation_name} PARTITION '2024-08-14'");
|
||||||
|
|
||||||
|
let expected_partition = Partition::Expr(Expr::Value(Value::SingleQuotedString(
|
||||||
|
"2024-08-14".to_string(),
|
||||||
|
)));
|
||||||
|
match clickhouse_and_generic().verified_stmt(&sql) {
|
||||||
|
Statement::AlterTable { operations, .. } => {
|
||||||
|
assert_eq!(operations.len(), 1);
|
||||||
|
let expected_operation = if operation_name == &"FREEZE" {
|
||||||
|
AlterTableOperation::FreezePartition {
|
||||||
|
partition: expected_partition,
|
||||||
|
with_name: None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AlterTableOperation::UnfreezePartition {
|
||||||
|
partition: expected_partition,
|
||||||
|
with_name: None,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assert_eq!(operations[0], expected_operation);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test case with `WITH NAME`
|
||||||
|
for operation_name in &["FREEZE", "UNFREEZE"] {
|
||||||
|
let sql =
|
||||||
|
format!("ALTER TABLE t {operation_name} PARTITION '2024-08-14' WITH NAME 'hello'");
|
||||||
|
match clickhouse_and_generic().verified_stmt(&sql) {
|
||||||
|
Statement::AlterTable { operations, .. } => {
|
||||||
|
assert_eq!(operations.len(), 1);
|
||||||
|
let expected_partition = Partition::Expr(Expr::Value(Value::SingleQuotedString(
|
||||||
|
"2024-08-14".to_string(),
|
||||||
|
)));
|
||||||
|
let expected_operation = if operation_name == &"FREEZE" {
|
||||||
|
AlterTableOperation::FreezePartition {
|
||||||
|
partition: expected_partition,
|
||||||
|
with_name: Some(Ident::with_quote('\'', "hello")),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AlterTableOperation::UnfreezePartition {
|
||||||
|
partition: expected_partition,
|
||||||
|
with_name: Some(Ident::with_quote('\'', "hello")),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assert_eq!(operations[0], expected_operation);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// negative cases
|
||||||
|
for operation_name in &["FREEZE", "UNFREEZE"] {
|
||||||
|
assert_eq!(
|
||||||
|
clickhouse_and_generic()
|
||||||
|
.parse_sql_statements(format!("ALTER TABLE t0 {operation_name} PARTITION").as_str())
|
||||||
|
.unwrap_err(),
|
||||||
|
ParserError("Expected: an expression:, found: EOF".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
clickhouse_and_generic()
|
||||||
|
.parse_sql_statements(
|
||||||
|
format!("ALTER TABLE t0 {operation_name} PARTITION p0 WITH").as_str()
|
||||||
|
)
|
||||||
|
.unwrap_err(),
|
||||||
|
ParserError("Expected: NAME, found: EOF".to_string())
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
clickhouse_and_generic()
|
||||||
|
.parse_sql_statements(
|
||||||
|
format!("ALTER TABLE t0 {operation_name} PARTITION p0 WITH NAME").as_str()
|
||||||
|
)
|
||||||
|
.unwrap_err(),
|
||||||
|
ParserError("Expected: identifier, found: EOF".to_string())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_select_table_function_settings() {
|
fn parse_select_table_function_settings() {
|
||||||
fn check_settings(sql: &str, expected: &TableFunctionArgs) {
|
fn check_settings(sql: &str, expected: &TableFunctionArgs) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue