Skip to content

Commit 2402d7d

Browse files
authored
Realize column factory (#355)
1 parent dee9f17 commit 2402d7d

File tree

7 files changed

+303
-152
lines changed

7 files changed

+303
-152
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- Enh #353: Update `bit` type according to main PR yiisoft/db#860 (@Tigrov)
1212
- Enh #354: Refactor PHP type of `ColumnSchemaInterface` instances (@Tigrov)
1313
- Enh #356: Raise minimum PHP version to `^8.1` with minor refactoring (@Tigrov)
14+
- Enh #355: Implement `ColumnFactory` class (@Tigrov)
1415

1516
## 1.3.0 March 21, 2024
1617

src/Column/ArrayColumnSchema.php

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@
1212
use Yiisoft\Db\Pgsql\Schema;
1313
use Yiisoft\Db\Schema\Column\AbstractColumnSchema;
1414
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
15-
use Yiisoft\Db\Schema\Column\DoubleColumnSchema;
16-
use Yiisoft\Db\Schema\Column\JsonColumnSchema;
17-
use Yiisoft\Db\Schema\Column\StringColumnSchema;
1815
use Yiisoft\Db\Schema\SchemaInterface;
1916

2017
use function array_map;
@@ -57,26 +54,7 @@ public function column(ColumnSchemaInterface|null $column): static
5754
public function getColumn(): ColumnSchemaInterface
5855
{
5956
if ($this->column === null) {
60-
$type = $this->getType();
61-
62-
$this->column = match ($type) {
63-
SchemaInterface::TYPE_BOOLEAN => new BooleanColumnSchema($type),
64-
SchemaInterface::TYPE_BIT => new BitColumnSchema($type),
65-
SchemaInterface::TYPE_TINYINT => new IntegerColumnSchema($type),
66-
SchemaInterface::TYPE_SMALLINT => new IntegerColumnSchema($type),
67-
SchemaInterface::TYPE_INTEGER => new IntegerColumnSchema($type),
68-
SchemaInterface::TYPE_BIGINT => PHP_INT_SIZE !== 8
69-
? new BigIntColumnSchema($type)
70-
: new IntegerColumnSchema($type),
71-
SchemaInterface::TYPE_DECIMAL => new DoubleColumnSchema($type),
72-
SchemaInterface::TYPE_FLOAT => new DoubleColumnSchema($type),
73-
SchemaInterface::TYPE_DOUBLE => new DoubleColumnSchema($type),
74-
SchemaInterface::TYPE_BINARY => new BinaryColumnSchema($type),
75-
SchemaInterface::TYPE_JSON => new JsonColumnSchema($type),
76-
Schema::TYPE_STRUCTURED => new StructuredColumnSchema($type),
77-
default => new StringColumnSchema($type),
78-
};
79-
57+
$this->column = (new ColumnFactory())->fromType($this->getType());
8058
$this->column->dbType($this->getDbType());
8159
$this->column->enumValues($this->getEnumValues());
8260
$this->column->precision($this->getPrecision());

src/Column/ColumnFactory.php

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yiisoft\Db\Pgsql\Column;
6+
7+
use Yiisoft\Db\Pgsql\Schema;
8+
use Yiisoft\Db\Schema\Column\AbstractColumnFactory;
9+
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
10+
use Yiisoft\Db\Schema\SchemaInterface;
11+
12+
use const PHP_INT_SIZE;
13+
14+
/**
15+
* @psalm-type ColumnInfo = array{
16+
* allow_null?: bool|string|null,
17+
* auto_increment?: bool|string,
18+
* columns?: array<string, ColumnSchemaInterface>,
19+
* comment?: string|null,
20+
* computed?: bool|string,
21+
* db_type?: string|null,
22+
* default_value?: mixed,
23+
* dimension?: int|string,
24+
* enum_values?: array|null,
25+
* extra?: string|null,
26+
* primary_key?: bool|string,
27+
* name?: string,
28+
* precision?: int|string|null,
29+
* sequence_name?: string|null,
30+
* scale?: int|string|null,
31+
* schema?: string|null,
32+
* size?: int|string|null,
33+
* table?: string|null,
34+
* type?: string,
35+
* }
36+
*/
37+
final class ColumnFactory extends AbstractColumnFactory
38+
{
39+
/**
40+
* The mapping from physical column types (keys) to abstract column types (values).
41+
*
42+
* @link https://www.postgresql.org/docs/current/datatype.html#DATATYPE-TABLE
43+
*
44+
* @var string[]
45+
*
46+
* @psalm-suppress MissingClassConstType
47+
*/
48+
private const TYPE_MAP = [
49+
'bool' => SchemaInterface::TYPE_BOOLEAN,
50+
'boolean' => SchemaInterface::TYPE_BOOLEAN,
51+
'bit' => SchemaInterface::TYPE_BIT,
52+
'bit varying' => SchemaInterface::TYPE_BIT,
53+
'varbit' => SchemaInterface::TYPE_BIT,
54+
'smallint' => SchemaInterface::TYPE_SMALLINT,
55+
'int2' => SchemaInterface::TYPE_SMALLINT,
56+
'smallserial' => SchemaInterface::TYPE_SMALLINT,
57+
'serial2' => SchemaInterface::TYPE_SMALLINT,
58+
'int4' => SchemaInterface::TYPE_INTEGER,
59+
'int' => SchemaInterface::TYPE_INTEGER,
60+
'integer' => SchemaInterface::TYPE_INTEGER,
61+
'serial' => SchemaInterface::TYPE_INTEGER,
62+
'serial4' => SchemaInterface::TYPE_INTEGER,
63+
'bigint' => SchemaInterface::TYPE_BIGINT,
64+
'int8' => SchemaInterface::TYPE_BIGINT,
65+
'bigserial' => SchemaInterface::TYPE_BIGINT,
66+
'serial8' => SchemaInterface::TYPE_BIGINT,
67+
'oid' => SchemaInterface::TYPE_BIGINT, // shouldn't be used. it's pg internal!
68+
'pg_lsn' => SchemaInterface::TYPE_BIGINT,
69+
'real' => SchemaInterface::TYPE_FLOAT,
70+
'float4' => SchemaInterface::TYPE_FLOAT,
71+
'float8' => SchemaInterface::TYPE_DOUBLE,
72+
'double precision' => SchemaInterface::TYPE_DOUBLE,
73+
'decimal' => SchemaInterface::TYPE_DECIMAL,
74+
'numeric' => SchemaInterface::TYPE_DECIMAL,
75+
'money' => SchemaInterface::TYPE_MONEY,
76+
'char' => SchemaInterface::TYPE_CHAR,
77+
'character' => SchemaInterface::TYPE_CHAR,
78+
'bpchar' => SchemaInterface::TYPE_CHAR,
79+
'character varying' => SchemaInterface::TYPE_STRING,
80+
'varchar' => SchemaInterface::TYPE_STRING,
81+
'text' => SchemaInterface::TYPE_TEXT,
82+
'bytea' => SchemaInterface::TYPE_BINARY,
83+
'date' => SchemaInterface::TYPE_DATE,
84+
'time' => SchemaInterface::TYPE_TIME,
85+
'time without time zone' => SchemaInterface::TYPE_TIME,
86+
'time with time zone' => SchemaInterface::TYPE_TIME,
87+
'timetz' => SchemaInterface::TYPE_TIME,
88+
'timestamp' => SchemaInterface::TYPE_TIMESTAMP,
89+
'timestamp without time zone' => SchemaInterface::TYPE_TIMESTAMP,
90+
'timestamp with time zone' => SchemaInterface::TYPE_TIMESTAMP,
91+
'timestamptz' => SchemaInterface::TYPE_TIMESTAMP,
92+
'abstime' => SchemaInterface::TYPE_TIMESTAMP,
93+
'interval' => SchemaInterface::TYPE_STRING,
94+
'box' => SchemaInterface::TYPE_STRING,
95+
'circle' => SchemaInterface::TYPE_STRING,
96+
'point' => SchemaInterface::TYPE_STRING,
97+
'line' => SchemaInterface::TYPE_STRING,
98+
'lseg' => SchemaInterface::TYPE_STRING,
99+
'polygon' => SchemaInterface::TYPE_STRING,
100+
'path' => SchemaInterface::TYPE_STRING,
101+
'cidr' => SchemaInterface::TYPE_STRING,
102+
'inet' => SchemaInterface::TYPE_STRING,
103+
'macaddr' => SchemaInterface::TYPE_STRING,
104+
'tsquery' => SchemaInterface::TYPE_STRING,
105+
'tsvector' => SchemaInterface::TYPE_STRING,
106+
'txid_snapshot' => SchemaInterface::TYPE_STRING,
107+
'unknown' => SchemaInterface::TYPE_STRING,
108+
'uuid' => SchemaInterface::TYPE_STRING,
109+
'xml' => SchemaInterface::TYPE_STRING,
110+
'json' => SchemaInterface::TYPE_JSON,
111+
'jsonb' => SchemaInterface::TYPE_JSON,
112+
];
113+
114+
/**
115+
* @psalm-param ColumnInfo $info
116+
* @psalm-suppress MoreSpecificImplementedParamType
117+
*/
118+
public function fromType(string $type, array $info = []): ColumnSchemaInterface
119+
{
120+
$dimension = (int)($info['dimension'] ?? 0);
121+
122+
if ($dimension > 0) {
123+
unset($info['dimension']);
124+
$column = (new ArrayColumnSchema())
125+
->dimension($dimension)
126+
->column($this->fromType($type, $info));
127+
} else {
128+
$column = match ($type) {
129+
SchemaInterface::TYPE_BOOLEAN => new BooleanColumnSchema($type),
130+
SchemaInterface::TYPE_BIT => new BitColumnSchema($type),
131+
SchemaInterface::TYPE_TINYINT => new IntegerColumnSchema($type),
132+
SchemaInterface::TYPE_SMALLINT => new IntegerColumnSchema($type),
133+
SchemaInterface::TYPE_INTEGER => new IntegerColumnSchema($type),
134+
SchemaInterface::TYPE_BIGINT => PHP_INT_SIZE !== 8
135+
? new BigIntColumnSchema($type)
136+
: new IntegerColumnSchema($type),
137+
SchemaInterface::TYPE_BINARY => new BinaryColumnSchema($type),
138+
Schema::TYPE_STRUCTURED => (new StructuredColumnSchema($type))->columns($info['columns'] ?? []),
139+
default => parent::fromType($type, $info),
140+
};
141+
}
142+
143+
return $column;
144+
}
145+
146+
protected function getType(string $dbType, array $info = []): string
147+
{
148+
return self::TYPE_MAP[$dbType] ?? SchemaInterface::TYPE_STRING;
149+
}
150+
}

0 commit comments

Comments
 (0)