Add support of DROP|CLEAR|MATERIALIZE PROJECTION syntax for ClickHouse (#1417)

This commit is contained in:
hulk 2024-09-11 03:26:07 +08:00 committed by GitHub
parent 4875dadbf5
commit a7b49b5072
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 198 additions and 0 deletions

View file

@ -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}")
}

View file

@ -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,

View file

@ -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]);