Skip to content

Commit 9902d02

Browse files
Cristhian Lopez VidalCopilot
authored 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 9550e93 commit 9902d02

2 files changed

Lines changed: 34 additions & 1 deletion

File tree

src/parser/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8564,6 +8564,17 @@ impl<'a> Parser<'a> {
85648564
None
85658565
};
85668566

8567+
// ClickHouse allows PARTITION BY after ORDER BY
8568+
// https://clickhouse.com/docs/en/sql-reference/statements/create/table#partition-by
8569+
let partition_by = if create_table_config.partition_by.is_none()
8570+
&& dialect_of!(self is ClickHouseDialect | GenericDialect)
8571+
&& self.parse_keywords(&[Keyword::PARTITION, Keyword::BY])
8572+
{
8573+
Some(Box::new(self.parse_expr()?))
8574+
} else {
8575+
create_table_config.partition_by
8576+
};
8577+
85678578
let on_commit = if self.parse_keywords(&[Keyword::ON, Keyword::COMMIT]) {
85688579
Some(self.parse_create_table_on_commit()?)
85698580
} else {
@@ -8634,7 +8645,7 @@ impl<'a> Parser<'a> {
86348645
.on_commit(on_commit)
86358646
.on_cluster(on_cluster)
86368647
.clustered_by(clustered_by)
8637-
.partition_by(create_table_config.partition_by)
8648+
.partition_by(partition_by)
86388649
.cluster_by(create_table_config.cluster_by)
86398650
.inherits(create_table_config.inherits)
86408651
.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)