Skip to content

Commit c4f20db

Browse files
author
fangxu.hu
committed
ClickHouse: support alter table update ...
1 parent 7c20d4a commit c4f20db

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

src/ast/ddl.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ use crate::ast::{
3636
use crate::keywords::Keyword;
3737
use crate::tokenizer::Token;
3838

39+
use super::Assignment;
40+
3941
/// An `ALTER TABLE` (`Statement::AlterTable`) operation
4042
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4143
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@@ -143,6 +145,17 @@ pub enum AlterTableOperation {
143145
partition: Partition,
144146
with_name: Option<Ident>,
145147
},
148+
/// `UPDATE <column> = <expression> [, ...] [IN PARTITION partition_id] WHERE <filter_expr>`
149+
/// Note: this is a ClickHouse-specific operation, please refer to
150+
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
151+
UpdateData {
152+
/// Column assignments
153+
assignments: Vec<Assignment>,
154+
/// PARTITION
155+
partition_id: Option<Ident>,
156+
/// WHERE
157+
selection: Option<Expr>,
158+
},
146159
/// `DROP PRIMARY KEY`
147160
///
148161
/// Note: this is a MySQL-specific operation.
@@ -546,6 +559,16 @@ impl fmt::Display for AlterTableOperation {
546559
}
547560
Ok(())
548561
}
562+
AlterTableOperation::UpdateData { assignments, partition_id, selection } => {
563+
write!(f, "UPDATE {}", display_comma_separated(assignments))?;
564+
if let Some(partition_id) = partition_id {
565+
write!(f, " IN PARTITION {}", partition_id)?;
566+
}
567+
if let Some(selection) = selection {
568+
write!(f, " WHERE {}", selection)?;
569+
}
570+
Ok(())
571+
}
549572
}
550573
}
551574
}

src/parser/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7156,6 +7156,25 @@ impl<'a> Parser<'a> {
71567156
partition,
71577157
with_name,
71587158
}
7159+
} else if dialect_of!(self is ClickHouseDialect|GenericDialect)
7160+
&& self.parse_keyword(Keyword::UPDATE)
7161+
{
7162+
let assignments = self.parse_comma_separated(Parser::parse_assignment)?;
7163+
let partition_id = if self.parse_keywords(&[Keyword::IN, Keyword::PARTITION]) {
7164+
Some(self.parse_identifier(false)?)
7165+
} else {
7166+
None
7167+
};
7168+
let selection = if self.parse_keyword(Keyword::WHERE) {
7169+
Some(self.parse_expr()?)
7170+
} else {
7171+
None
7172+
};
7173+
AlterTableOperation::UpdateData {
7174+
assignments,
7175+
partition_id,
7176+
selection,
7177+
}
71597178
} else {
71607179
let options: Vec<SqlOption> =
71617180
self.parse_options_with_keywords(&[Keyword::SET, Keyword::TBLPROPERTIES])?;

tests/sqlparser_clickhouse.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,6 +1422,38 @@ fn parse_create_table_on_commit_and_as_query() {
14221422
}
14231423
}
14241424

1425+
#[test]
1426+
fn parse_update_data() {
1427+
let sql = "ALTER TABLE t UPDATE col1 = 1, col2 = col3 + col4 WHERE cod4 = 1";
1428+
match clickhouse_and_generic().verified_stmt(sql) {
1429+
Statement::AlterTable { operations, .. } => {
1430+
assert_eq!(operations.len(), 1);
1431+
if let AlterTableOperation::UpdateData {
1432+
assignments,
1433+
partition_id,
1434+
selection,
1435+
} = &operations[0]
1436+
{
1437+
assert_eq!(assignments.len(), 2);
1438+
assert!(partition_id.is_none());
1439+
if let Some(Expr::BinaryOp { op, .. }) = selection {
1440+
assert_eq!(*op, BinaryOperator::Eq);
1441+
} else {
1442+
unreachable!()
1443+
}
1444+
} else {
1445+
unreachable!();
1446+
}
1447+
}
1448+
_ => unreachable!(),
1449+
}
1450+
1451+
let fails = ["ALTER TABLE t UPDATE", "ALTER TABLE t UPDATE c WHERE 1 = 1"];
1452+
for f in fails {
1453+
assert!(clickhouse_and_generic().parse_sql_statements(f).is_err());
1454+
}
1455+
}
1456+
14251457
#[test]
14261458
fn parse_freeze_and_unfreeze_partition() {
14271459
// test cases without `WITH NAME`

0 commit comments

Comments
 (0)