Skip to content

Commit

Permalink
Realize column factory (#355)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov authored Sep 1, 2024
1 parent dee9f17 commit 2402d7d
Show file tree
Hide file tree
Showing 7 changed files with 303 additions and 152 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Enh #353: Update `bit` type according to main PR yiisoft/db#860 (@Tigrov)
- Enh #354: Refactor PHP type of `ColumnSchemaInterface` instances (@Tigrov)
- Enh #356: Raise minimum PHP version to `^8.1` with minor refactoring (@Tigrov)
- Enh #355: Implement `ColumnFactory` class (@Tigrov)

## 1.3.0 March 21, 2024

Expand Down
24 changes: 1 addition & 23 deletions src/Column/ArrayColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
use Yiisoft\Db\Pgsql\Schema;
use Yiisoft\Db\Schema\Column\AbstractColumnSchema;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
use Yiisoft\Db\Schema\Column\DoubleColumnSchema;
use Yiisoft\Db\Schema\Column\JsonColumnSchema;
use Yiisoft\Db\Schema\Column\StringColumnSchema;
use Yiisoft\Db\Schema\SchemaInterface;

use function array_map;
Expand Down Expand Up @@ -57,26 +54,7 @@ public function column(ColumnSchemaInterface|null $column): static
public function getColumn(): ColumnSchemaInterface
{
if ($this->column === null) {
$type = $this->getType();

$this->column = match ($type) {
SchemaInterface::TYPE_BOOLEAN => new BooleanColumnSchema($type),
SchemaInterface::TYPE_BIT => new BitColumnSchema($type),
SchemaInterface::TYPE_TINYINT => new IntegerColumnSchema($type),
SchemaInterface::TYPE_SMALLINT => new IntegerColumnSchema($type),
SchemaInterface::TYPE_INTEGER => new IntegerColumnSchema($type),
SchemaInterface::TYPE_BIGINT => PHP_INT_SIZE !== 8
? new BigIntColumnSchema($type)
: new IntegerColumnSchema($type),
SchemaInterface::TYPE_DECIMAL => new DoubleColumnSchema($type),
SchemaInterface::TYPE_FLOAT => new DoubleColumnSchema($type),
SchemaInterface::TYPE_DOUBLE => new DoubleColumnSchema($type),
SchemaInterface::TYPE_BINARY => new BinaryColumnSchema($type),
SchemaInterface::TYPE_JSON => new JsonColumnSchema($type),
Schema::TYPE_STRUCTURED => new StructuredColumnSchema($type),
default => new StringColumnSchema($type),
};

$this->column = (new ColumnFactory())->fromType($this->getType());
$this->column->dbType($this->getDbType());
$this->column->enumValues($this->getEnumValues());
$this->column->precision($this->getPrecision());
Expand Down
150 changes: 150 additions & 0 deletions src/Column/ColumnFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Db\Pgsql\Column;

use Yiisoft\Db\Pgsql\Schema;
use Yiisoft\Db\Schema\Column\AbstractColumnFactory;
use Yiisoft\Db\Schema\Column\ColumnSchemaInterface;
use Yiisoft\Db\Schema\SchemaInterface;

use const PHP_INT_SIZE;

/**
* @psalm-type ColumnInfo = array{
* allow_null?: bool|string|null,
* auto_increment?: bool|string,
* columns?: array<string, ColumnSchemaInterface>,
* comment?: string|null,
* computed?: bool|string,
* db_type?: string|null,
* default_value?: mixed,
* dimension?: int|string,
* enum_values?: array|null,
* extra?: string|null,
* primary_key?: bool|string,
* name?: string,
* precision?: int|string|null,
* sequence_name?: string|null,
* scale?: int|string|null,
* schema?: string|null,
* size?: int|string|null,
* table?: string|null,
* type?: string,
* }
*/
final class ColumnFactory extends AbstractColumnFactory
{
/**
* The mapping from physical column types (keys) to abstract column types (values).
*
* @link https://www.postgresql.org/docs/current/datatype.html#DATATYPE-TABLE
*
* @var string[]
*
* @psalm-suppress MissingClassConstType
*/
private const TYPE_MAP = [
'bool' => SchemaInterface::TYPE_BOOLEAN,
'boolean' => SchemaInterface::TYPE_BOOLEAN,
'bit' => SchemaInterface::TYPE_BIT,
'bit varying' => SchemaInterface::TYPE_BIT,
'varbit' => SchemaInterface::TYPE_BIT,
'smallint' => SchemaInterface::TYPE_SMALLINT,
'int2' => SchemaInterface::TYPE_SMALLINT,
'smallserial' => SchemaInterface::TYPE_SMALLINT,
'serial2' => SchemaInterface::TYPE_SMALLINT,
'int4' => SchemaInterface::TYPE_INTEGER,
'int' => SchemaInterface::TYPE_INTEGER,
'integer' => SchemaInterface::TYPE_INTEGER,
'serial' => SchemaInterface::TYPE_INTEGER,
'serial4' => SchemaInterface::TYPE_INTEGER,
'bigint' => SchemaInterface::TYPE_BIGINT,
'int8' => SchemaInterface::TYPE_BIGINT,
'bigserial' => SchemaInterface::TYPE_BIGINT,
'serial8' => SchemaInterface::TYPE_BIGINT,
'oid' => SchemaInterface::TYPE_BIGINT, // shouldn't be used. it's pg internal!
'pg_lsn' => SchemaInterface::TYPE_BIGINT,
'real' => SchemaInterface::TYPE_FLOAT,
'float4' => SchemaInterface::TYPE_FLOAT,
'float8' => SchemaInterface::TYPE_DOUBLE,
'double precision' => SchemaInterface::TYPE_DOUBLE,
'decimal' => SchemaInterface::TYPE_DECIMAL,
'numeric' => SchemaInterface::TYPE_DECIMAL,
'money' => SchemaInterface::TYPE_MONEY,
'char' => SchemaInterface::TYPE_CHAR,
'character' => SchemaInterface::TYPE_CHAR,
'bpchar' => SchemaInterface::TYPE_CHAR,
'character varying' => SchemaInterface::TYPE_STRING,
'varchar' => SchemaInterface::TYPE_STRING,
'text' => SchemaInterface::TYPE_TEXT,
'bytea' => SchemaInterface::TYPE_BINARY,
'date' => SchemaInterface::TYPE_DATE,
'time' => SchemaInterface::TYPE_TIME,
'time without time zone' => SchemaInterface::TYPE_TIME,
'time with time zone' => SchemaInterface::TYPE_TIME,
'timetz' => SchemaInterface::TYPE_TIME,
'timestamp' => SchemaInterface::TYPE_TIMESTAMP,
'timestamp without time zone' => SchemaInterface::TYPE_TIMESTAMP,
'timestamp with time zone' => SchemaInterface::TYPE_TIMESTAMP,
'timestamptz' => SchemaInterface::TYPE_TIMESTAMP,
'abstime' => SchemaInterface::TYPE_TIMESTAMP,
'interval' => SchemaInterface::TYPE_STRING,
'box' => SchemaInterface::TYPE_STRING,
'circle' => SchemaInterface::TYPE_STRING,
'point' => SchemaInterface::TYPE_STRING,
'line' => SchemaInterface::TYPE_STRING,
'lseg' => SchemaInterface::TYPE_STRING,
'polygon' => SchemaInterface::TYPE_STRING,
'path' => SchemaInterface::TYPE_STRING,
'cidr' => SchemaInterface::TYPE_STRING,
'inet' => SchemaInterface::TYPE_STRING,
'macaddr' => SchemaInterface::TYPE_STRING,
'tsquery' => SchemaInterface::TYPE_STRING,
'tsvector' => SchemaInterface::TYPE_STRING,
'txid_snapshot' => SchemaInterface::TYPE_STRING,
'unknown' => SchemaInterface::TYPE_STRING,
'uuid' => SchemaInterface::TYPE_STRING,
'xml' => SchemaInterface::TYPE_STRING,
'json' => SchemaInterface::TYPE_JSON,
'jsonb' => SchemaInterface::TYPE_JSON,
];

/**
* @psalm-param ColumnInfo $info
* @psalm-suppress MoreSpecificImplementedParamType
*/
public function fromType(string $type, array $info = []): ColumnSchemaInterface
{
$dimension = (int)($info['dimension'] ?? 0);

if ($dimension > 0) {
unset($info['dimension']);
$column = (new ArrayColumnSchema())
->dimension($dimension)
->column($this->fromType($type, $info));
} else {
$column = match ($type) {
SchemaInterface::TYPE_BOOLEAN => new BooleanColumnSchema($type),
SchemaInterface::TYPE_BIT => new BitColumnSchema($type),
SchemaInterface::TYPE_TINYINT => new IntegerColumnSchema($type),
SchemaInterface::TYPE_SMALLINT => new IntegerColumnSchema($type),
SchemaInterface::TYPE_INTEGER => new IntegerColumnSchema($type),
SchemaInterface::TYPE_BIGINT => PHP_INT_SIZE !== 8
? new BigIntColumnSchema($type)
: new IntegerColumnSchema($type),
SchemaInterface::TYPE_BINARY => new BinaryColumnSchema($type),
Schema::TYPE_STRUCTURED => (new StructuredColumnSchema($type))->columns($info['columns'] ?? []),
default => parent::fromType($type, $info),
};
}

return $column;
}

protected function getType(string $dbType, array $info = []): string
{
return self::TYPE_MAP[$dbType] ?? SchemaInterface::TYPE_STRING;
}
}
Loading

0 comments on commit 2402d7d

Please sign in to comment.