fix(transfer): ClickHouse ORDER BY must cover PRIMARY KEY columns

This commit is contained in:
t8y2 2026-06-18 10:50:53 +08:00
parent 03e5e27c79
commit 8de8a85d66
1 changed files with 49 additions and 2 deletions

View File

@ -1098,7 +1098,9 @@ pub fn generate_create_table_ddl(
ddl.push_str(&format!("{create_prefix} {full_table} (\n"));
ddl.push_str(&col_lines.join(",\n"));
if !pks.is_empty() {
// ClickHouse: PRIMARY KEY must be a prefix of ORDER BY; skip inline PK
// and encode it in the ENGINE clause below instead.
if !pks.is_empty() && !matches!(target_db, DatabaseType::ClickHouse) {
ddl.push_str(&format!(",\n PRIMARY KEY ({})", pks.join(", ")));
}
@ -1114,7 +1116,11 @@ pub fn generate_create_table_ddl(
}
if matches!(target_db, DatabaseType::ClickHouse) {
ddl.push_str(" ENGINE = MergeTree() ORDER BY tuple()");
if pks.is_empty() {
ddl.push_str(" ENGINE = MergeTree() ORDER BY tuple()");
} else {
ddl.push_str(&format!(" ENGINE = MergeTree() ORDER BY ({})", pks.join(", ")));
}
}
ddl
@ -3655,6 +3661,47 @@ mod tests {
assert!(!ddl.contains("COMMENT"));
}
#[test]
fn clickhouse_create_table_with_pk_uses_order_by_pk() {
let cols = vec![
db::ColumnInfo { is_primary_key: true, is_nullable: false, ..test_column("id", "UInt64") },
db::ColumnInfo { ..test_column("name", "String") },
];
let ddl = generate_create_table_ddl(
&cols,
"logs",
"",
"",
&DatabaseType::ClickHouse,
&DatabaseType::ClickHouse,
None,
);
// Must include ENGINE with ORDER BY using the PK columns
assert!(ddl.contains("ENGINE = MergeTree() ORDER BY (`id`)"));
// Must NOT have a separate PRIMARY KEY clause (ORDER BY serves that role)
assert!(!ddl.contains("PRIMARY KEY"));
}
#[test]
fn clickhouse_create_table_without_pk_uses_order_by_tuple() {
let cols = vec![db::ColumnInfo { ..test_column("message", "String") }];
let ddl = generate_create_table_ddl(
&cols,
"logs",
"",
"",
&DatabaseType::ClickHouse,
&DatabaseType::ClickHouse,
None,
);
assert!(ddl.contains("ENGINE = MergeTree() ORDER BY tuple()"));
assert!(!ddl.contains("PRIMARY KEY"));
}
#[test]
fn hive_create_table_uses_hive_friendly_columns() {
let cols = vec![