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,
|
name: Ident,
|
||||||
select: ProjectionSelect,
|
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`
|
/// `DISABLE ROW LEVEL SECURITY`
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific operation.
|
/// Note: this is a PostgreSQL-specific operation.
|
||||||
|
@ -275,6 +302,43 @@ impl fmt::Display for AlterTableOperation {
|
||||||
}
|
}
|
||||||
write!(f, " {} ({})", name, query)
|
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 } => {
|
AlterTableOperation::AlterColumn { column_name, op } => {
|
||||||
write!(f, "ALTER COLUMN {column_name} {op}")
|
write!(f, "ALTER COLUMN {column_name} {op}")
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,6 +153,7 @@ define_keywords!(
|
||||||
CHARSET,
|
CHARSET,
|
||||||
CHAR_LENGTH,
|
CHAR_LENGTH,
|
||||||
CHECK,
|
CHECK,
|
||||||
|
CLEAR,
|
||||||
CLOB,
|
CLOB,
|
||||||
CLONE,
|
CLONE,
|
||||||
CLOSE,
|
CLOSE,
|
||||||
|
@ -450,6 +451,7 @@ define_keywords!(
|
||||||
MATCHES,
|
MATCHES,
|
||||||
MATCH_CONDITION,
|
MATCH_CONDITION,
|
||||||
MATCH_RECOGNIZE,
|
MATCH_RECOGNIZE,
|
||||||
|
MATERIALIZE,
|
||||||
MATERIALIZED,
|
MATERIALIZED,
|
||||||
MAX,
|
MAX,
|
||||||
MAXVALUE,
|
MAXVALUE,
|
||||||
|
|
|
@ -6615,6 +6615,36 @@ impl<'a> Parser<'a> {
|
||||||
self.peek_token(),
|
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) {
|
} else if self.parse_keyword(Keyword::DROP) {
|
||||||
if self.parse_keywords(&[Keyword::IF, Keyword::EXISTS, Keyword::PARTITION]) {
|
if self.parse_keywords(&[Keyword::IF, Keyword::EXISTS, Keyword::PARTITION]) {
|
||||||
self.expect_token(&Token::LParen)?;
|
self.expect_token(&Token::LParen)?;
|
||||||
|
@ -6645,6 +6675,12 @@ impl<'a> Parser<'a> {
|
||||||
&& dialect_of!(self is MySqlDialect | GenericDialect)
|
&& dialect_of!(self is MySqlDialect | GenericDialect)
|
||||||
{
|
{
|
||||||
AlterTableOperation::DropPrimaryKey
|
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 {
|
} 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]);
|
||||||
|
|
|
@ -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]
|
#[test]
|
||||||
fn parse_optimize_table() {
|
fn parse_optimize_table() {
|
||||||
clickhouse_and_generic().verified_stmt("OPTIMIZE TABLE t0");
|
clickhouse_and_generic().verified_stmt("OPTIMIZE TABLE t0");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue