Skip to content

Commit 1970fc9

Browse files
Cristhian Lopez VidalCopilot
andcommitted
feat(clickhouse): support PARTITION BY after ORDER BY in CREATE TABLE
ClickHouse DDL allows PARTITION BY to appear after ORDER BY, which differs from standard SQL ordering. This change makes the parser accept both orderings when using the ClickHouseDialect or GenericDialect. Fixes a parse failure for production ClickHouse CREATE TABLE statements like: CREATE TABLE t (...) ENGINE = MergeTree() ORDER BY (...) PARTITION BY expr Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 1097a0d commit 1970fc9

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

src/parser/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8435,6 +8435,17 @@ impl<'a> Parser<'a> {
84358435
None
84368436
};
84378437

8438+
// ClickHouse allows PARTITION BY after ORDER BY
8439+
// https://clickhouse.com/docs/en/sql-reference/statements/create/table#partition-by
8440+
let partition_by = if create_table_config.partition_by.is_none()
8441+
&& dialect_of!(self is ClickHouseDialect | GenericDialect)
8442+
&& self.parse_keywords(&[Keyword::PARTITION, Keyword::BY])
8443+
{
8444+
Some(Box::new(self.parse_expr()?))
8445+
} else {
8446+
create_table_config.partition_by
8447+
};
8448+
84388449
let on_commit = if self.parse_keywords(&[Keyword::ON, Keyword::COMMIT]) {
84398450
Some(self.parse_create_table_on_commit()?)
84408451
} else {
@@ -8505,7 +8516,7 @@ impl<'a> Parser<'a> {
85058516
.on_commit(on_commit)
85068517
.on_cluster(on_cluster)
85078518
.clustered_by(clustered_by)
8508-
.partition_by(create_table_config.partition_by)
8519+
.partition_by(partition_by)
85098520
.cluster_by(create_table_config.cluster_by)
85108521
.inherits(create_table_config.inherits)
85118522
.partition_of(partition_of)

tests/sqlparser_clickhouse.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,28 @@ fn parse_create_table() {
233233
);
234234
}
235235

236+
#[test]
237+
fn parse_create_table_partition_by_after_order_by() {
238+
// ClickHouse DDL places PARTITION BY after ORDER BY.
239+
// MergeTree() is canonicalized to MergeTree and type names are uppercased.
240+
clickhouse().one_statement_parses_to(
241+
concat!(
242+
"CREATE TABLE IF NOT EXISTS \"MyTable\" (`col1` Int64, `col2` Int32) ",
243+
"ENGINE = MergeTree() ",
244+
"PRIMARY KEY (toDate(toDateTime(`col2`)), `col1`, `col2`) ",
245+
"ORDER BY (toDate(toDateTime(`col2`)), `col1`, `col2`) ",
246+
"PARTITION BY col1 % 64"
247+
),
248+
concat!(
249+
"CREATE TABLE IF NOT EXISTS \"MyTable\" (`col1` INT64, `col2` Int32) ",
250+
"ENGINE = MergeTree ",
251+
"PRIMARY KEY (toDate(toDateTime(`col2`)), `col1`, `col2`) ",
252+
"ORDER BY (toDate(toDateTime(`col2`)), `col1`, `col2`) ",
253+
"PARTITION BY col1 % 64"
254+
),
255+
);
256+
}
257+
236258
#[test]
237259
fn parse_insert_into_function() {
238260
clickhouse().verified_stmt(r#"INSERT INTO TABLE FUNCTION remote('localhost', default.simple_table) VALUES (100, 'inserted via remote()')"#);

0 commit comments

Comments
 (0)