Skip to content

Commit 0ffa242

Browse files
Merge pull request #14 from utopia-php/fix/clickhouse-lowcardinality-nullable-order
Fix ClickHouse LowCardinality + Nullable wrapping order
2 parents 84d3182 + f53941c commit 0ffa242

4 files changed

Lines changed: 29 additions & 14 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,10 +2217,10 @@ $schema->table('events')
22172217
->create();
22182218

22192219
// CREATE TABLE `events` (`id` Int64, `status` LowCardinality(String),
2220-
// `country` Nullable(LowCardinality(String))) ENGINE = MergeTree() ORDER BY (`id`)
2220+
// `country` LowCardinality(Nullable(String))) ENGINE = MergeTree() ORDER BY (`id`)
22212221
```
22222222

2223-
`Nullable` is applied outside `LowCardinality` to match ClickHouse's required wrapping order. The `lowCardinality()` method is only available on the ClickHouse builder — callers on other dialects (`MySQL`, `PostgreSQL`, `SQLite`, `MongoDB`) cannot reach this method at all.
2223+
`Nullable` is applied inside `LowCardinality` to match ClickHouse's required wrapping order. The `lowCardinality()` method is only available on the ClickHouse builder — callers on other dialects (`MySQL`, `PostgreSQL`, `SQLite`, `MongoDB`) cannot reach this method at all.
22242224

22252225
**FixedString(N)** — fixed-length string column. Use for ISO codes, hash digests, and other values whose byte length is known and constant:
22262226

src/Query/Schema/ClickHouse.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ protected function compileColumnType(Column $column): string
3737
if ($column instanceof Column\ClickHouse && $column->isFixedString()) {
3838
$type = 'FixedString(' . $column->fixedStringLength . ')';
3939

40-
if ($column->isLowCardinality) {
41-
$type = 'LowCardinality(' . $type . ')';
42-
}
43-
4440
if ($column->isNullable) {
4541
$type = 'Nullable(' . $type . ')';
4642
}
4743

44+
if ($column->isLowCardinality) {
45+
$type = 'LowCardinality(' . $type . ')';
46+
}
47+
4848
return $type;
4949
}
5050

@@ -112,14 +112,14 @@ protected function compileColumnType(Column $column): string
112112
),
113113
};
114114

115-
if ($column instanceof Column\ClickHouse && $column->isLowCardinality) {
116-
$type = 'LowCardinality(' . $type . ')';
117-
}
118-
119115
if ($column->isNullable) {
120116
$type = 'Nullable(' . $type . ')';
121117
}
122118

119+
if ($column instanceof Column\ClickHouse && $column->isLowCardinality) {
120+
$type = 'LowCardinality(' . $type . ')';
121+
}
122+
123123
return $type;
124124
}
125125

src/Query/Schema/Column/ClickHouse.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ public function primary(array $columns = []): static|Table
114114
*
115115
* Suitable for string columns with a small number of distinct values
116116
* (status enums, type discriminators, country codes). `Nullable` is
117-
* applied outside `LowCardinality` to match ClickHouse's required
118-
* wrapping order: `Nullable(LowCardinality(String))`.
117+
* applied inside `LowCardinality` to match ClickHouse's required
118+
* wrapping order: `LowCardinality(Nullable(String))`.
119119
*/
120120
public function lowCardinality(): static
121121
{

tests/Query/Schema/ClickHouseTest.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ public function testCreateTableLowCardinalityColumn(): void
999999
);
10001000
}
10011001

1002-
public function testCreateTableLowCardinalityNullableWrapsInBothOrder(): void
1002+
public function testCreateTableLowCardinalityNullableWrapsLowCardinalityOutermost(): void
10031003
{
10041004
$schema = new Schema();
10051005
$result = $schema->table('events')
@@ -1009,7 +1009,22 @@ public function testCreateTableLowCardinalityNullableWrapsInBothOrder(): void
10091009
$this->assertBindingCount($result);
10101010

10111011
$this->assertSame(
1012-
'CREATE TABLE `events` (`id` Int64, `status` Nullable(LowCardinality(String))) ENGINE = MergeTree() ORDER BY (`id`)',
1012+
'CREATE TABLE `events` (`id` Int64, `status` LowCardinality(Nullable(String))) ENGINE = MergeTree() ORDER BY (`id`)',
1013+
$result->query,
1014+
);
1015+
}
1016+
1017+
public function testCreateTableLowCardinalityNullableFixedStringWrapsLowCardinalityOutermost(): void
1018+
{
1019+
$schema = new Schema();
1020+
$result = $schema->table('events')
1021+
->bigInteger('id')->primary()
1022+
->fixedString('code', 2)->lowCardinality()->nullable()
1023+
->create();
1024+
$this->assertBindingCount($result);
1025+
1026+
$this->assertSame(
1027+
'CREATE TABLE `events` (`id` Int64, `code` LowCardinality(Nullable(FixedString(2)))) ENGINE = MergeTree() ORDER BY (`id`)',
10131028
$result->query,
10141029
);
10151030
}

0 commit comments

Comments
 (0)