Skip to content

Commit 951783c

Browse files
committed
refactor(clickhouse): scope FixedString to ClickHouse dialect, drop from global ColumnType
Removes `ColumnType::FixedString` from the cross-dialect enum. FixedString state now lives on `Column\ClickHouse` (via `asFixedString()` / `isFixedString()` / `$fixedStringLength`), and `Schema\ClickHouse::compileColumnType()` reads that state to emit `FixedString(N)` DDL. `Table\ClickHouse::fixedString()` now registers a `ColumnType::String` column and tags it with the FixedString state, so the global enum carries no ClickHouse-only cases and the other dialects (`MySQL`, `PostgreSQL`, `SQLite`, `MongoDB`) no longer need `UnsupportedException` match branches — their `compileColumnType()` methods are byte-identical to `main`. `Feature\OLAP` remains a marker interface matching the dialect-shape pattern (OLAP modifiers live on the column/table builder, not on `Schema`, so they cannot be expressed as a Schema-level method contract); docblock updated to explain why and to confirm the non-OLAP dialects are unchanged by construction. Compiled DDL bytes for ClickHouse are unchanged; all 5175 tests pass; lint and PHPStan max are clean.
1 parent 825c507 commit 951783c

9 files changed

Lines changed: 60 additions & 13 deletions

File tree

src/Query/Schema/ClickHouse.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,22 @@ protected function compileColumnType(Column $column): string
3333
throw new UnsupportedException('User-defined types are not supported in ClickHouse.');
3434
}
3535

36+
if ($column instanceof Column\ClickHouse && $column->isFixedString()) {
37+
$type = 'FixedString(' . $column->fixedStringLength . ')';
38+
39+
if ($column->isLowCardinality) {
40+
$type = 'LowCardinality(' . $type . ')';
41+
}
42+
43+
if ($column->isNullable) {
44+
$type = 'Nullable(' . $type . ')';
45+
}
46+
47+
return $type;
48+
}
49+
3650
$type = match ($column->type) {
3751
ColumnType::String, ColumnType::Varchar, ColumnType::Relationship => 'String',
38-
ColumnType::FixedString => 'FixedString(' . ($column->length ?? throw new ValidationException('FixedString requires a length.')) . ')',
3952
ColumnType::Text => 'String',
4053
ColumnType::MediumText, ColumnType::LongText => 'String',
4154
ColumnType::Integer => $column->isUnsigned ? 'UInt32' : 'Int32',

src/Query/Schema/Column/ClickHouse.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,38 @@ class ClickHouse extends Column
1616

1717
public protected(set) bool $isLowCardinality = false;
1818

19+
/** Length when the column should be emitted as `FixedString(N)`; null otherwise. */
20+
public protected(set) ?int $fixedStringLength = null;
21+
1922
/** @var list<string> Column-level CODEC clauses, e.g. ['Delta(4)', 'LZ4'] */
2023
public protected(set) array $codecs = [];
2124

25+
/**
26+
* Mark the column as `FixedString(N)`.
27+
*
28+
* Used by {@see Table\ClickHouse::fixedString()} to attach the
29+
* ClickHouse-specific FixedString width to a column whose generic
30+
* {@see \Utopia\Query\Schema\ColumnType} is `String`. The compiler reads
31+
* this state when emitting DDL.
32+
*
33+
* @throws ValidationException if $length is less than 1.
34+
*/
35+
public function asFixedString(int $length): static
36+
{
37+
if ($length < 1) {
38+
throw new ValidationException('FixedString length must be at least 1.');
39+
}
40+
41+
$this->fixedStringLength = $length;
42+
43+
return $this;
44+
}
45+
46+
public function isFixedString(): bool
47+
{
48+
return $this->fixedStringLength !== null;
49+
}
50+
2251
/**
2352
* @param list<string> $columns
2453
*

src/Query/Schema/ColumnType.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
enum ColumnType: string
66
{
77
case String = 'string';
8-
case FixedString = 'fixedstring';
98
case Varchar = 'varchar';
109
case Text = 'text';
1110
case MediumText = 'mediumtext';

src/Query/Schema/Feature/OLAP.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,20 @@
66
* Marker for dialects that expose OLAP-shaped column and table modifiers
77
* (`LowCardinality`, `FixedString`, column-level `CODEC`, `SAMPLE BY`).
88
*
9-
* The modifier methods live on the dialect's `Table` / `Column` subclasses
10-
* (e.g. {@see \Utopia\Query\Schema\Table\ClickHouse},
9+
* Unlike sibling `Feature/*` interfaces — which declare schema-level method
10+
* signatures because their operations are emitted as standalone statements —
11+
* OLAP modifiers are intrinsic to a dialect's column/table builder shape and
12+
* cannot be expressed as `Schema` methods. They live on the dialect's
13+
* `Table` / `Column` subclasses (e.g. {@see \Utopia\Query\Schema\Table\ClickHouse},
1114
* {@see \Utopia\Query\Schema\Column\ClickHouse}) and the corresponding
1215
* `Forwarder` trait, so callers can only chain them when the underlying
1316
* dialect supports them — the methods aren't reachable from non-OLAP
1417
* dialects at the type level.
18+
*
19+
* Non-OLAP dialects therefore have nothing to handle or throw from: the
20+
* cross-dialect `ColumnType` enum carries no OLAP-only cases, and the
21+
* `compileColumnType()` implementations on `MySQL` / `PostgreSQL` / `SQLite` /
22+
* `MongoDB` are byte-identical to their pre-OLAP form.
1523
*/
1624
interface OLAP
1725
{

src/Query/Schema/MongoDB.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ protected function compileColumnType(Column $column): string
4545
ColumnType::Linestring, ColumnType::Polygon => 'object',
4646
ColumnType::Uuid7 => 'string',
4747
ColumnType::Vector => 'array',
48-
ColumnType::FixedString => throw new UnsupportedException('FixedString type is not supported in MongoDB.'),
4948
};
5049
}
5150

src/Query/Schema/MySQL.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ protected function compileColumnType(Column $column): string
7373
ColumnType::Polygon => 'POLYGON' . ($column->srid !== null ? ' SRID ' . $column->srid : ''),
7474
ColumnType::Uuid7 => 'VARCHAR(36)',
7575
ColumnType::Vector => throw new UnsupportedException('Vector type is not supported in MySQL.'),
76-
ColumnType::FixedString => throw new UnsupportedException('FixedString type is not supported in MySQL.'),
7776
};
7877
}
7978

src/Query/Schema/PostgreSQL.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ protected function compileColumnType(Column $column): string
7979
ColumnType::Serial => 'SERIAL',
8080
ColumnType::BigSerial => 'BIGSERIAL',
8181
ColumnType::SmallSerial => 'SMALLSERIAL',
82-
ColumnType::FixedString => throw new UnsupportedException('FixedString type is not supported in PostgreSQL.'),
8382
};
8483
}
8584

src/Query/Schema/SQLite.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ protected function compileColumnType(Column $column): string
3636
ColumnType::Point, ColumnType::Linestring, ColumnType::Polygon => 'TEXT',
3737
ColumnType::Uuid7 => 'VARCHAR(36)',
3838
ColumnType::Vector => throw new UnsupportedException('Vector type is not supported in SQLite.'),
39-
ColumnType::FixedString => throw new UnsupportedException('FixedString type is not supported in SQLite.'),
4039
};
4140
}
4241

src/Query/Schema/Table/ClickHouse.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,17 @@ public function vector(string $name, int $dimensions): Column\ClickHouse
4242
* digests, and similar values that benefit from ClickHouse's columnar
4343
* storage of fixed-width data.
4444
*
45+
* The column is registered with the generic `ColumnType::String` type and
46+
* tagged with FixedString state on {@see Column\ClickHouse}; the compiler
47+
* reads that state when emitting DDL, so the global `ColumnType` enum
48+
* stays free of ClickHouse-only cases.
49+
*
4550
* @throws ValidationException if $length is less than 1.
4651
*/
4752
public function fixedString(string $name, int $length): Column\ClickHouse
4853
{
49-
if ($length < 1) {
50-
throw new ValidationException('FixedString length must be at least 1.');
51-
}
52-
53-
$col = $this->newColumn($name, ColumnType::FixedString, $length);
54+
$col = $this->newColumn($name, ColumnType::String, $length);
55+
$col->asFixedString($length);
5456
$this->columns[] = $col;
5557

5658
return $col;

0 commit comments

Comments
 (0)