diff --git a/README.md b/README.md index 6e82d7a..060dbff 100644 --- a/README.md +++ b/README.md @@ -2217,10 +2217,10 @@ $schema->table('events') ->create(); // CREATE TABLE `events` (`id` Int64, `status` LowCardinality(String), -// `country` Nullable(LowCardinality(String))) ENGINE = MergeTree() ORDER BY (`id`) +// `country` LowCardinality(Nullable(String))) ENGINE = MergeTree() ORDER BY (`id`) ``` -`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. +`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. **FixedString(N)** — fixed-length string column. Use for ISO codes, hash digests, and other values whose byte length is known and constant: diff --git a/src/Query/Schema/ClickHouse.php b/src/Query/Schema/ClickHouse.php index adacd7e..34cee36 100644 --- a/src/Query/Schema/ClickHouse.php +++ b/src/Query/Schema/ClickHouse.php @@ -37,14 +37,14 @@ protected function compileColumnType(Column $column): string if ($column instanceof Column\ClickHouse && $column->isFixedString()) { $type = 'FixedString(' . $column->fixedStringLength . ')'; - if ($column->isLowCardinality) { - $type = 'LowCardinality(' . $type . ')'; - } - if ($column->isNullable) { $type = 'Nullable(' . $type . ')'; } + if ($column->isLowCardinality) { + $type = 'LowCardinality(' . $type . ')'; + } + return $type; } @@ -112,14 +112,14 @@ protected function compileColumnType(Column $column): string ), }; - if ($column instanceof Column\ClickHouse && $column->isLowCardinality) { - $type = 'LowCardinality(' . $type . ')'; - } - if ($column->isNullable) { $type = 'Nullable(' . $type . ')'; } + if ($column instanceof Column\ClickHouse && $column->isLowCardinality) { + $type = 'LowCardinality(' . $type . ')'; + } + return $type; } diff --git a/src/Query/Schema/Column/ClickHouse.php b/src/Query/Schema/Column/ClickHouse.php index 73068cf..eee41ec 100644 --- a/src/Query/Schema/Column/ClickHouse.php +++ b/src/Query/Schema/Column/ClickHouse.php @@ -114,8 +114,8 @@ public function primary(array $columns = []): static|Table * * Suitable for string columns with a small number of distinct values * (status enums, type discriminators, country codes). `Nullable` is - * applied outside `LowCardinality` to match ClickHouse's required - * wrapping order: `Nullable(LowCardinality(String))`. + * applied inside `LowCardinality` to match ClickHouse's required + * wrapping order: `LowCardinality(Nullable(String))`. */ public function lowCardinality(): static { diff --git a/tests/Query/Schema/ClickHouseTest.php b/tests/Query/Schema/ClickHouseTest.php index 1c9803b..0a3b923 100644 --- a/tests/Query/Schema/ClickHouseTest.php +++ b/tests/Query/Schema/ClickHouseTest.php @@ -999,7 +999,7 @@ public function testCreateTableLowCardinalityColumn(): void ); } - public function testCreateTableLowCardinalityNullableWrapsInBothOrder(): void + public function testCreateTableLowCardinalityNullableWrapsLowCardinalityOutermost(): void { $schema = new Schema(); $result = $schema->table('events') @@ -1009,7 +1009,22 @@ public function testCreateTableLowCardinalityNullableWrapsInBothOrder(): void $this->assertBindingCount($result); $this->assertSame( - 'CREATE TABLE `events` (`id` Int64, `status` Nullable(LowCardinality(String))) ENGINE = MergeTree() ORDER BY (`id`)', + 'CREATE TABLE `events` (`id` Int64, `status` LowCardinality(Nullable(String))) ENGINE = MergeTree() ORDER BY (`id`)', + $result->query, + ); + } + + public function testCreateTableLowCardinalityNullableFixedStringWrapsLowCardinalityOutermost(): void + { + $schema = new Schema(); + $result = $schema->table('events') + ->bigInteger('id')->primary() + ->fixedString('code', 2)->lowCardinality()->nullable() + ->create(); + $this->assertBindingCount($result); + + $this->assertSame( + 'CREATE TABLE `events` (`id` Int64, `code` LowCardinality(Nullable(FixedString(2)))) ENGINE = MergeTree() ORDER BY (`id`)', $result->query, ); }