mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-10-08 13:10:20 +00:00
Add support of DROP|CLEAR|MATERIALIZE PROJECTION
syntax for ClickHouse (#1417)
This commit is contained in:
parent
4875dadbf5
commit
a7b49b5072
4 changed files with 198 additions and 0 deletions
|
@ -57,6 +57,33 @@ pub enum AlterTableOperation {
|
|||
name: Ident,
|
||||
select: ProjectionSelect,
|
||||
},
|
||||
|
||||
/// `DROP PROJECTION [IF EXISTS] name`
|
||||
///
|
||||
/// Note: this is a ClickHouse-specific operation.
|
||||
/// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#drop-projection)
|
||||
DropProjection { if_exists: bool, name: Ident },
|
||||
|
||||
/// `MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
|
||||
///
|
||||
/// Note: this is a ClickHouse-specific operation.
|
||||
/// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#materialize-projection)
|
||||
MaterializeProjection {
|
||||
if_exists: bool,
|
||||
name: Ident,
|
||||
partition: Option<Ident>,
|
||||
},
|
||||
|
||||
/// `CLEAR PROJECTION [IF EXISTS] name [IN PARTITION partition_name]`
|
||||
///
|
||||
/// Note: this is a ClickHouse-specific operation.
|
||||
/// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#clear-projection)
|
||||
ClearProjection {
|
||||
if_exists: bool,
|
||||
name: Ident,
|
||||
partition: Option<Ident>,
|
||||
},
|
||||
|
||||
/// `DISABLE ROW LEVEL SECURITY`
|
||||
///
|
||||
/// Note: this is a PostgreSQL-specific operation.
|
||||
|
@ -275,6 +302,43 @@ impl fmt::Display for AlterTableOperation {
|
|||
}
|
||||
write!(f, " {} ({})", name, query)
|
||||
}
|
||||
AlterTableOperation::DropProjection { if_exists, name } => {
|
||||
write!(f, "DROP PROJECTION")?;
|
||||
if *if_exists {
|
||||
write!(f, " IF EXISTS")?;
|
||||
}
|
||||
write!(f, " {}", name)
|
||||
}
|
||||
AlterTableOperation::MaterializeProjection {
|
||||
if_exists,
|
||||
name,
|
||||
partition,
|
||||
} => {
|
||||
write!(f, "MATERIALIZE PROJECTION")?;
|
||||
if *if_exists {
|
||||
write!(f, " IF EXISTS")?;
|
||||
}
|
||||
write!(f, " {}", name)?;
|
||||
if let Some(partition) = partition {
|
||||
write!(f, " IN PARTITION {}", partition)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
AlterTableOperation::ClearProjection {
|
||||
if_exists,
|
||||
name,
|
||||
partition,
|
||||
} => {
|
||||
write!(f, "CLEAR PROJECTION")?;
|
||||
if *if_exists {
|
||||
write!(f, " IF EXISTS")?;
|
||||
}
|
||||
write!(f, " {}", name)?;
|
||||
if let Some(partition) = partition {
|
||||
write!(f, " IN PARTITION {}", partition)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
AlterTableOperation::AlterColumn { column_name, op } => {
|
||||
write!(f, "ALTER COLUMN {column_name} {op}")
|
||||
}
|
||||
|
|
|
@ -153,6 +153,7 @@ define_keywords!(
|
|||
CHARSET,
|
||||
CHAR_LENGTH,
|
||||
CHECK,
|
||||
CLEAR,
|
||||
CLOB,
|
||||
CLONE,
|
||||
CLOSE,
|
||||
|
@ -450,6 +451,7 @@ define_keywords!(
|
|||
MATCHES,
|
||||
MATCH_CONDITION,
|
||||
MATCH_RECOGNIZE,
|
||||
MATERIALIZE,
|
||||
MATERIALIZED,
|
||||
MAX,
|
||||
MAXVALUE,
|
||||
|
|
|
@ -6615,6 +6615,36 @@ impl<'a> Parser<'a> {
|
|||
self.peek_token(),
|
||||
);
|
||||
}
|
||||
} else if self.parse_keywords(&[Keyword::CLEAR, Keyword::PROJECTION])
|
||||
&& dialect_of!(self is ClickHouseDialect|GenericDialect)
|
||||
{
|
||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||
let name = self.parse_identifier(false)?;
|
||||
let partition = if self.parse_keywords(&[Keyword::IN, Keyword::PARTITION]) {
|
||||
Some(self.parse_identifier(false)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
AlterTableOperation::ClearProjection {
|
||||
if_exists,
|
||||
name,
|
||||
partition,
|
||||
}
|
||||
} else if self.parse_keywords(&[Keyword::MATERIALIZE, Keyword::PROJECTION])
|
||||
&& dialect_of!(self is ClickHouseDialect|GenericDialect)
|
||||
{
|
||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||
let name = self.parse_identifier(false)?;
|
||||
let partition = if self.parse_keywords(&[Keyword::IN, Keyword::PARTITION]) {
|
||||
Some(self.parse_identifier(false)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
AlterTableOperation::MaterializeProjection {
|
||||
if_exists,
|
||||
name,
|
||||
partition,
|
||||
}
|
||||
} else if self.parse_keyword(Keyword::DROP) {
|
||||
if self.parse_keywords(&[Keyword::IF, Keyword::EXISTS, Keyword::PARTITION]) {
|
||||
self.expect_token(&Token::LParen)?;
|
||||
|
@ -6645,6 +6675,12 @@ impl<'a> Parser<'a> {
|
|||
&& dialect_of!(self is MySqlDialect | GenericDialect)
|
||||
{
|
||||
AlterTableOperation::DropPrimaryKey
|
||||
} else if self.parse_keyword(Keyword::PROJECTION)
|
||||
&& dialect_of!(self is ClickHouseDialect|GenericDialect)
|
||||
{
|
||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||
let name = self.parse_identifier(false)?;
|
||||
AlterTableOperation::DropProjection { if_exists, name }
|
||||
} else {
|
||||
let _ = self.parse_keyword(Keyword::COLUMN); // [ COLUMN ]
|
||||
let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
|
||||
|
|
|
@ -359,6 +359,102 @@ fn parse_alter_table_add_projection() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_alter_table_drop_projection() {
|
||||
match clickhouse_and_generic().verified_stmt("ALTER TABLE t0 DROP PROJECTION IF EXISTS my_name")
|
||||
{
|
||||
Statement::AlterTable {
|
||||
name, operations, ..
|
||||
} => {
|
||||
assert_eq!(name, ObjectName(vec!["t0".into()]));
|
||||
assert_eq!(1, operations.len());
|
||||
assert_eq!(
|
||||
operations[0],
|
||||
AlterTableOperation::DropProjection {
|
||||
if_exists: true,
|
||||
name: "my_name".into(),
|
||||
}
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
// allow to skip `IF EXISTS`
|
||||
clickhouse_and_generic().verified_stmt("ALTER TABLE t0 DROP PROJECTION my_name");
|
||||
|
||||
assert_eq!(
|
||||
clickhouse_and_generic()
|
||||
.parse_sql_statements("ALTER TABLE t0 DROP PROJECTION")
|
||||
.unwrap_err(),
|
||||
ParserError("Expected: identifier, found: EOF".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_alter_table_clear_and_materialize_projection() {
|
||||
for keyword in ["CLEAR", "MATERIALIZE"] {
|
||||
match clickhouse_and_generic().verified_stmt(
|
||||
format!("ALTER TABLE t0 {keyword} PROJECTION IF EXISTS my_name IN PARTITION p0",)
|
||||
.as_str(),
|
||||
) {
|
||||
Statement::AlterTable {
|
||||
name, operations, ..
|
||||
} => {
|
||||
assert_eq!(name, ObjectName(vec!["t0".into()]));
|
||||
assert_eq!(1, operations.len());
|
||||
assert_eq!(
|
||||
operations[0],
|
||||
if keyword == "CLEAR" {
|
||||
AlterTableOperation::ClearProjection {
|
||||
if_exists: true,
|
||||
name: "my_name".into(),
|
||||
partition: Some(Ident::new("p0")),
|
||||
}
|
||||
} else {
|
||||
AlterTableOperation::MaterializeProjection {
|
||||
if_exists: true,
|
||||
name: "my_name".into(),
|
||||
partition: Some(Ident::new("p0")),
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
// allow to skip `IF EXISTS`
|
||||
clickhouse_and_generic().verified_stmt(
|
||||
format!("ALTER TABLE t0 {keyword} PROJECTION my_name IN PARTITION p0",).as_str(),
|
||||
);
|
||||
// allow to skip `IN PARTITION partition_name`
|
||||
clickhouse_and_generic()
|
||||
.verified_stmt(format!("ALTER TABLE t0 {keyword} PROJECTION my_name",).as_str());
|
||||
|
||||
assert_eq!(
|
||||
clickhouse_and_generic()
|
||||
.parse_sql_statements(format!("ALTER TABLE t0 {keyword} PROJECTION",).as_str())
|
||||
.unwrap_err(),
|
||||
ParserError("Expected: identifier, found: EOF".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
clickhouse_and_generic()
|
||||
.parse_sql_statements(
|
||||
format!("ALTER TABLE t0 {keyword} PROJECTION my_name IN PARTITION",).as_str()
|
||||
)
|
||||
.unwrap_err(),
|
||||
ParserError("Expected: identifier, found: EOF".to_string())
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
clickhouse_and_generic()
|
||||
.parse_sql_statements(
|
||||
format!("ALTER TABLE t0 {keyword} PROJECTION my_name IN",).as_str()
|
||||
)
|
||||
.unwrap_err(),
|
||||
ParserError("Expected: end of statement, found: IN".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_optimize_table() {
|
||||
clickhouse_and_generic().verified_stmt("OPTIMIZE TABLE t0");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue