From 885b19b1d98440d7af3b970637b8de5ff0698e3e Mon Sep 17 00:00:00 2001 From: Tigrov Date: Fri, 18 Oct 2024 09:14:53 +0700 Subject: [PATCH 1/2] Remove `ColumnSchemaInterface::load()`, add properties to constructor --- UPGRADE.md | 3 +- src/Connection/AbstractDsn.php | 2 +- src/Schema/Column/AbstractColumnFactory.php | 89 ++++++++------ src/Schema/Column/AbstractColumnSchema.php | 116 +++++++++--------- src/Schema/Column/ArrayColumnSchema.php | 27 ++-- src/Schema/Column/BigIntColumnSchema.php | 12 +- src/Schema/Column/BinaryColumnSchema.php | 12 +- src/Schema/Column/BitColumnSchema.php | 12 +- src/Schema/Column/BooleanColumnSchema.php | 12 +- src/Schema/Column/ColumnBuilder.php | 61 +++------ src/Schema/Column/ColumnFactoryInterface.php | 40 ++++-- src/Schema/Column/ColumnSchemaInterface.php | 34 +---- src/Schema/Column/DoubleColumnSchema.php | 12 +- src/Schema/Column/IntegerColumnSchema.php | 12 +- src/Schema/Column/JsonColumnSchema.php | 12 +- src/Schema/Column/StringColumnSchema.php | 12 +- src/Schema/Column/StructuredColumnSchema.php | 17 ++- src/Syntax/ColumnDefinitionParser.php | 12 +- tests/Db/Schema/ColumnSchemaTest.php | 8 +- .../ColumnDefinitionParserProvider.php | 20 +-- tests/Provider/ColumnFactoryProvider.php | 2 +- tests/Provider/ColumnSchemaProvider.php | 44 ++----- tests/Support/Stub/ColumnSchema.php | 6 +- 23 files changed, 255 insertions(+), 322 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index 42496e1f1..849df852f 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -75,8 +75,7 @@ and the following changes were made: - `isNotNull()` method is added; - `unique(bool $unique = true)` method is added; - `isUnique()` method is added; -- `load(array $info)` method is added; -- constructor of `AbstractColumnSchema` class is changed to `__construct(string $type, string|null $phpType = null)`; +- all `AbstractColumnSchema` class properties moved to constructor; - added method chaining. ### New classes with constants diff --git a/src/Connection/AbstractDsn.php b/src/Connection/AbstractDsn.php index 8689a04f2..42814f405 100644 --- a/src/Connection/AbstractDsn.php +++ b/src/Connection/AbstractDsn.php @@ -25,7 +25,7 @@ abstract class AbstractDsn implements DsnInterface, Stringable */ public function __construct( private readonly string $driver, - private readonly string $host, + private readonly string $host = '127.0.0.1', private readonly string|null $databaseName = null, private readonly string|null $port = null, private readonly array $options = [] diff --git a/src/Schema/Column/AbstractColumnFactory.php b/src/Schema/Column/AbstractColumnFactory.php index cbc659d8f..a58789c1c 100644 --- a/src/Schema/Column/AbstractColumnFactory.php +++ b/src/Schema/Column/AbstractColumnFactory.php @@ -13,8 +13,7 @@ /** * The default implementation of the {@see ColumnFactoryInterface}. * - * @psalm-import-type ColumnInfo from ColumnSchemaInterface - * @psalm-suppress MixedArgumentTypeCoercion + * @psalm-import-type ColumnInfo from ColumnFactoryInterface */ abstract class AbstractColumnFactory implements ColumnFactoryInterface { @@ -38,8 +37,10 @@ abstract protected function isDbType(string $dbType): bool; public function fromDbType(string $dbType, array $info = []): ColumnSchemaInterface { - $info['db_type'] = $dbType; + unset($info['dbType']); $type = $info['type'] ?? $this->getType($dbType, $info); + unset($info['type']); + $info['dbType'] = $dbType; return $this->fromType($type, $info); } @@ -52,62 +53,76 @@ public function fromDefinition(string $definition, array $info = []): ColumnSche $info['extra'] = $definitionInfo['extra'] . ' ' . $info['extra']; } - /** @var string $dbType */ - $dbType = $definitionInfo['db_type'] ?? ''; - unset($definitionInfo['db_type']); + /** @var string $type */ + $type = $definitionInfo['type'] ?? ''; + unset($definitionInfo['type']); $info += $definitionInfo; - if ($this->isDbType($dbType)) { - return $this->fromDbType($dbType, $info); + if ($this->isDbType($type)) { + unset($info['dbType']); + return $this->fromDbType($type, $info); } - if ($this->isType($dbType)) { - return $this->fromType($dbType, $info); + if ($this->isType($type)) { + unset($info['type']); + return $this->fromType($type, $info); } - if ($this->isPseudoType($dbType)) { - return $this->fromPseudoType($dbType, $info); + if ($this->isPseudoType($type)) { + return $this->fromPseudoType($type, $info); } - return $this->fromDbType($dbType, $info); + unset($info['dbType']); + return $this->fromDbType($type, $info); } + /** + * @psalm-suppress MixedArgument + * @psalm-suppress InvalidArgument + * @psalm-suppress InvalidNamedArgument + */ public function fromPseudoType(string $pseudoType, array $info = []): ColumnSchemaInterface { + $info['primaryKey'] = true; + $info['autoIncrement'] = true; + return match ($pseudoType) { - PseudoType::PK => ColumnBuilder::primaryKey()->load($info), - PseudoType::UPK => ColumnBuilder::primaryKey()->unsigned()->load($info), - PseudoType::BIGPK => ColumnBuilder::bigPrimaryKey()->load($info), - PseudoType::UBIGPK => ColumnBuilder::bigPrimaryKey()->unsigned()->load($info), - PseudoType::UUID_PK => ColumnBuilder::uuidPrimaryKey()->load($info), - PseudoType::UUID_PK_SEQ => ColumnBuilder::uuidPrimaryKey()->load($info), + PseudoType::PK => new IntegerColumnSchema(ColumnType::INTEGER, ...$info), + PseudoType::UPK => new IntegerColumnSchema(ColumnType::INTEGER, ...[...$info, 'unsigned' => true]), + PseudoType::BIGPK => PHP_INT_SIZE !== 8 + ? new BigIntColumnSchema(ColumnType::BIGINT, ...$info) + : new IntegerColumnSchema(ColumnType::BIGINT, ...$info), + PseudoType::UBIGPK => new BigIntColumnSchema(ColumnType::BIGINT, ...[...$info, 'unsigned' => true]), + PseudoType::UUID_PK => new StringColumnSchema(ColumnType::UUID, ...$info), + PseudoType::UUID_PK_SEQ => new StringColumnSchema(ColumnType::UUID, ...$info), }; } + /** + * @psalm-suppress InvalidNamedArgument + */ public function fromType(string $type, array $info = []): ColumnSchemaInterface { - $column = match ($type) { - ColumnType::BOOLEAN => new BooleanColumnSchema($type), - ColumnType::BIT => new BitColumnSchema($type), - ColumnType::TINYINT => new IntegerColumnSchema($type), - ColumnType::SMALLINT => new IntegerColumnSchema($type), + return match ($type) { + ColumnType::BOOLEAN => new BooleanColumnSchema($type, ...$info), + ColumnType::BIT => new BitColumnSchema($type, ...$info), + ColumnType::TINYINT => new IntegerColumnSchema($type, ...$info), + ColumnType::SMALLINT => new IntegerColumnSchema($type, ...$info), ColumnType::INTEGER => PHP_INT_SIZE !== 8 && !empty($info['unsigned']) - ? new BigIntColumnSchema($type) - : new IntegerColumnSchema($type), + ? new BigIntColumnSchema($type, ...$info) + : new IntegerColumnSchema($type, ...$info), ColumnType::BIGINT => PHP_INT_SIZE !== 8 || !empty($info['unsigned']) - ? new BigIntColumnSchema($type) - : new IntegerColumnSchema($type), - ColumnType::DECIMAL => new DoubleColumnSchema($type), - ColumnType::FLOAT => new DoubleColumnSchema($type), - ColumnType::DOUBLE => new DoubleColumnSchema($type), - ColumnType::BINARY => new BinaryColumnSchema($type), - ColumnType::STRUCTURED => new StructuredColumnSchema($type), - ColumnType::JSON => new JsonColumnSchema($type), - default => new StringColumnSchema($type), + ? new BigIntColumnSchema($type, ...$info) + : new IntegerColumnSchema($type, ...$info), + ColumnType::DECIMAL => new DoubleColumnSchema($type, ...$info), + ColumnType::FLOAT => new DoubleColumnSchema($type, ...$info), + ColumnType::DOUBLE => new DoubleColumnSchema($type, ...$info), + ColumnType::BINARY => new BinaryColumnSchema($type, ...$info), + ColumnType::STRUCTURED => new StructuredColumnSchema($type, ...$info), + ColumnType::JSON => new JsonColumnSchema($type, ...$info), + default => new StringColumnSchema($type, ...$info), }; - - return $column->load($info); } /** diff --git a/src/Schema/Column/AbstractColumnSchema.php b/src/Schema/Column/AbstractColumnSchema.php index a6b4ef8a0..377d0f952 100644 --- a/src/Schema/Column/AbstractColumnSchema.php +++ b/src/Schema/Column/AbstractColumnSchema.php @@ -9,7 +9,7 @@ use Yiisoft\Db\Constraint\ForeignKeyConstraint; -use function is_array; +use function property_exists; /** * Represents the metadata of a column in a database table. @@ -37,29 +37,69 @@ */ abstract class AbstractColumnSchema implements ColumnSchemaInterface { - private bool $autoIncrement = false; - private string|null $check = null; - private string|null $comment = null; - private bool $computed = false; - private string|null $dbType = null; - private mixed $defaultValue = null; - private array|null $enumValues = null; - private string|null $extra = null; - private bool $isPrimaryKey = false; - private string|null $name = null; - private bool $notNull = false; - private ForeignKeyConstraint|null $reference = null; - private int|null $scale = null; - private int|null $size = null; - private bool $unique = false; - private bool $unsigned = false; + /** + * @var string The default column abstract type + * @psalm-var ColumnType::* + */ + protected const DEFAULT_TYPE = ColumnType::STRING; + + /** + * @var string The column abstract type + * @psalm-var ColumnType::* + */ + private string $type; /** + * @param string|null $type The column's abstract type. + * @param bool $autoIncrement Whether the column is auto-incremental. + * @param string|null $check The check constraint for the column. + * @param string|null $comment The column's comment. + * @param bool $computed Whether the column is a computed column. + * @param string|null $dbType The column's database type. + * @param mixed $defaultValue The default value of the column. + * @param array|null $enumValues The list of possible values for an ENUM column. + * @param string|null $extra Any extra information that needs to be appended to the column's definition. + * @param bool $primaryKey Whether the column is a primary key. + * @param string|null $name The column's name. + * @param bool $notNull Whether the column is not nullable. + * @param ForeignKeyConstraint|null $reference The foreign key constraint. + * @param int|null $scale The number of digits to the right of the decimal point. + * @param int|null $size The column's size. + * @param bool $unique Whether the column is unique. + * @param bool $unsigned Whether the column is unsigned. + * @param mixed ...$args Additional arguments to be passed to the constructor. + * * @psalm-param ColumnType::* $type + * @psalm-param array $args */ public function __construct( - private string $type, + string|null $type = null, + private bool $autoIncrement = false, + private string|null $check = null, + private string|null $comment = null, + private bool $computed = false, + private string|null $dbType = null, + private mixed $defaultValue = null, + private array|null $enumValues = null, + private string|null $extra = null, + private bool $primaryKey = false, + private string|null $name = null, + private bool $notNull = false, + private ForeignKeyConstraint|null $reference = null, + private int|null $scale = null, + private int|null $size = null, + private bool $unique = false, + private bool $unsigned = false, + mixed ...$args, ) { + $this->type = $type ?? static::DEFAULT_TYPE; + + /** @var array $args */ + foreach ($args as $property => $value) { + if (property_exists($this, $property)) { + $this->$property = $value; + } + } } /** @@ -215,7 +255,7 @@ public function isNotNull(): bool public function isPrimaryKey(): bool { - return $this->isPrimaryKey; + return $this->primaryKey; } public function isUnique(): bool @@ -228,40 +268,6 @@ public function isUnsigned(): bool return $this->unsigned; } - public function load(array $info): static - { - foreach ($info as $key => $value) { - /** - * @psalm-suppress PossiblyInvalidCast - * @psalm-suppress InvalidCast - * @psalm-suppress DeprecatedMethod - */ - match ($key) { - 'allow_null' => $this->allowNull((bool) $value), - 'auto_increment' => $this->autoIncrement((bool) $value), - 'check' => $this->check($value !== null ? (string) $value : null), - 'comment' => $this->comment($value !== null ? (string) $value : null), - 'computed' => $this->computed((bool) $value), - 'db_type' => $this->dbType($value !== null ? (string) $value : null), - 'default_value' => $this->defaultValue($value), - 'enum_values' => $this->enumValues(is_array($value) ? $value : null), - 'extra' => $this->extra($value !== null ? (string) $value : null), - 'name' => $this->name($value !== null ? (string) $value : null), - 'not_null' => $this->notNull((bool) $value), - 'primary_key' => $this->primaryKey((bool) $value), - 'precision' => $this->precision($value !== null ? (int) $value : null), - 'reference' => $this->reference($value instanceof ForeignKeyConstraint ? $value : null), - 'scale' => $this->scale($value !== null ? (int) $value : null), - 'size' => $this->size($value !== null ? (int) $value : null), - 'unique' => $this->unique((bool) $value), - 'unsigned' => $this->unsigned((bool) $value), - default => null, - }; - } - - return $this; - } - /** * @deprecated Will be removed in version 2.0. */ @@ -285,9 +291,9 @@ public function precision(int|null $precision): static return $this->size($precision); } - public function primaryKey(bool $isPrimaryKey = true): static + public function primaryKey(bool $primaryKey = true): static { - $this->isPrimaryKey = $isPrimaryKey; + $this->primaryKey = $primaryKey; return $this; } diff --git a/src/Schema/Column/ArrayColumnSchema.php b/src/Schema/Column/ArrayColumnSchema.php index 1f93a5d45..7f60ea92f 100644 --- a/src/Schema/Column/ArrayColumnSchema.php +++ b/src/Schema/Column/ArrayColumnSchema.php @@ -19,17 +19,23 @@ use function is_string; use function iterator_to_array; +/** + * Represents the schema for an array column. + */ class ArrayColumnSchema extends AbstractColumnSchema { + protected const DEFAULT_TYPE = ColumnType::ARRAY; + /** * @var ColumnSchemaInterface|null The column of an array item. */ - private ColumnSchemaInterface|null $column = null; + protected ColumnSchemaInterface|null $column = null; /** * @var int The dimension of array, must be greater than 0. + * @psalm-var positive-int */ - private int $dimension = 1; + protected int $dimension = 1; /** * Returns the parser for the column value. @@ -39,15 +45,6 @@ protected function getParser(): ParserToArrayInterface throw new NotSupportedException(__METHOD__ . '() is not supported. Use concrete DBMS implementation.'); } - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::ARRAY, - ) { - parent::__construct($type); - } - /** * Set column of an array item. */ @@ -74,7 +71,9 @@ public function getColumn(): ColumnSchemaInterface } /** - * Set dimension of an array, must be greater than 0. + * Set dimension of an array, must be greater than + * + * @psalm-param positive-int $dimension */ public function dimension(int $dimension): static { @@ -84,6 +83,8 @@ public function dimension(int $dimension): static /** * @return int the dimension of the array. + * + * @psalm-return positive-int */ public function getDimension(): int { @@ -143,6 +144,8 @@ public function phpTypecast(mixed $value): array|null * @param mixed $value The array or iterable object. * @param int $dimension The array dimension. Should be more than 0. * + * @psalm-param positive-int $dimension + * * @return array|null Converted values. */ protected function dbTypecastArray(mixed $value, int $dimension): array|null diff --git a/src/Schema/Column/BigIntColumnSchema.php b/src/Schema/Column/BigIntColumnSchema.php index ebb9a9c41..30e0b6227 100644 --- a/src/Schema/Column/BigIntColumnSchema.php +++ b/src/Schema/Column/BigIntColumnSchema.php @@ -14,16 +14,12 @@ use const PHP_INT_MAX; use const PHP_INT_MIN; +/** + * Represents the metadata for a bigint column. + */ class BigIntColumnSchema extends AbstractColumnSchema { - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::BIGINT, - ) { - parent::__construct($type); - } + protected const DEFAULT_TYPE = ColumnType::BIGINT; public function dbTypecast(mixed $value): int|string|ExpressionInterface|null { diff --git a/src/Schema/Column/BinaryColumnSchema.php b/src/Schema/Column/BinaryColumnSchema.php index 2109d2e84..b3fc33e9a 100644 --- a/src/Schema/Column/BinaryColumnSchema.php +++ b/src/Schema/Column/BinaryColumnSchema.php @@ -12,16 +12,12 @@ use function gettype; +/** + * Represents the metadata for a binary column. + */ class BinaryColumnSchema extends AbstractColumnSchema { - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::BINARY, - ) { - parent::__construct($type); - } + protected const DEFAULT_TYPE = ColumnType::BINARY; public function dbTypecast(mixed $value): mixed { diff --git a/src/Schema/Column/BitColumnSchema.php b/src/Schema/Column/BitColumnSchema.php index 973a64635..a2cdc30d7 100644 --- a/src/Schema/Column/BitColumnSchema.php +++ b/src/Schema/Column/BitColumnSchema.php @@ -8,16 +8,12 @@ use Yiisoft\Db\Constant\PhpType; use Yiisoft\Db\Expression\ExpressionInterface; +/** + * Represents the metadata for a bit column. + */ class BitColumnSchema extends AbstractColumnSchema { - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::BIT, - ) { - parent::__construct($type); - } + protected const DEFAULT_TYPE = ColumnType::BIT; public function dbTypecast(mixed $value): int|string|ExpressionInterface|null { diff --git a/src/Schema/Column/BooleanColumnSchema.php b/src/Schema/Column/BooleanColumnSchema.php index 6ea80f9b5..4d60ba2dd 100644 --- a/src/Schema/Column/BooleanColumnSchema.php +++ b/src/Schema/Column/BooleanColumnSchema.php @@ -8,16 +8,12 @@ use Yiisoft\Db\Expression\ExpressionInterface; use Yiisoft\Db\Constant\PhpType; +/** + * Represents the metadata for a boolean column. + */ class BooleanColumnSchema extends AbstractColumnSchema { - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::BOOLEAN, - ) { - parent::__construct($type); - } + protected const DEFAULT_TYPE = ColumnType::BOOLEAN; public function dbTypecast(mixed $value): bool|ExpressionInterface|null { diff --git a/src/Schema/Column/ColumnBuilder.php b/src/Schema/Column/ColumnBuilder.php index 9160fffd3..8b35f3a2a 100644 --- a/src/Schema/Column/ColumnBuilder.php +++ b/src/Schema/Column/ColumnBuilder.php @@ -9,7 +9,7 @@ /** * Column builder for database {@see ColumnSchemaInterface} instances. * - * @psalm-import-type ColumnInfo from ColumnSchemaInterface + * @psalm-import-type ColumnInfo from ColumnFactoryInterface */ class ColumnBuilder { @@ -70,8 +70,7 @@ public static function boolean(): ColumnSchemaInterface */ public static function bit(int|null $size = null): ColumnSchemaInterface { - return (new BitColumnSchema(ColumnType::BIT)) - ->size($size); + return new BitColumnSchema(ColumnType::BIT, size: $size); } /** @@ -79,8 +78,7 @@ public static function bit(int|null $size = null): ColumnSchemaInterface */ public static function tinyint(int|null $size = null): ColumnSchemaInterface { - return (new IntegerColumnSchema(ColumnType::TINYINT)) - ->size($size); + return new IntegerColumnSchema(ColumnType::TINYINT, size: $size); } /** @@ -88,8 +86,7 @@ public static function tinyint(int|null $size = null): ColumnSchemaInterface */ public static function smallint(int|null $size = null): ColumnSchemaInterface { - return (new IntegerColumnSchema(ColumnType::SMALLINT)) - ->size($size); + return new IntegerColumnSchema(ColumnType::SMALLINT, size: $size); } /** @@ -97,8 +94,7 @@ public static function smallint(int|null $size = null): ColumnSchemaInterface */ public static function integer(int|null $size = null): ColumnSchemaInterface { - return (new IntegerColumnSchema(ColumnType::INTEGER)) - ->size($size); + return new IntegerColumnSchema(ColumnType::INTEGER, size: $size); } /** @@ -106,8 +102,7 @@ public static function integer(int|null $size = null): ColumnSchemaInterface */ public static function bigint(int|null $size = null): ColumnSchemaInterface { - return (new IntegerColumnSchema(ColumnType::BIGINT)) - ->size($size); + return new IntegerColumnSchema(ColumnType::BIGINT, size: $size); } /** @@ -115,9 +110,7 @@ public static function bigint(int|null $size = null): ColumnSchemaInterface */ public static function float(int|null $size = null, int|null $scale = null): ColumnSchemaInterface { - return (new DoubleColumnSchema(ColumnType::FLOAT)) - ->size($size) - ->scale($scale); + return new DoubleColumnSchema(ColumnType::FLOAT, scale: $scale, size: $size); } /** @@ -125,9 +118,7 @@ public static function float(int|null $size = null, int|null $scale = null): Col */ public static function double(int|null $size = null, int|null $scale = null): ColumnSchemaInterface { - return (new DoubleColumnSchema(ColumnType::DOUBLE)) - ->size($size) - ->scale($scale); + return new DoubleColumnSchema(ColumnType::DOUBLE, scale: $scale, size: $size); } /** @@ -135,9 +126,7 @@ public static function double(int|null $size = null, int|null $scale = null): Co */ public static function decimal(int|null $size = 10, int|null $scale = 0): ColumnSchemaInterface { - return (new DoubleColumnSchema(ColumnType::DECIMAL)) - ->size($size) - ->scale($scale); + return new DoubleColumnSchema(ColumnType::DECIMAL, scale: $scale, size: $size); } /** @@ -145,9 +134,7 @@ public static function decimal(int|null $size = 10, int|null $scale = 0): Column */ public static function money(int|null $size = 19, int|null $scale = 4): ColumnSchemaInterface { - return (new DoubleColumnSchema(ColumnType::MONEY)) - ->size($size) - ->scale($scale); + return new DoubleColumnSchema(ColumnType::MONEY, scale: $scale, size: $size); } /** @@ -155,8 +142,7 @@ public static function money(int|null $size = 19, int|null $scale = 4): ColumnSc */ public static function char(int|null $size = 1): ColumnSchemaInterface { - return (new StringColumnSchema(ColumnType::CHAR)) - ->size($size); + return new StringColumnSchema(ColumnType::CHAR, size: $size); } /** @@ -164,8 +150,7 @@ public static function char(int|null $size = 1): ColumnSchemaInterface */ public static function string(int|null $size = 255): ColumnSchemaInterface { - return (new StringColumnSchema(ColumnType::STRING)) - ->size($size); + return new StringColumnSchema(ColumnType::STRING, size: $size); } /** @@ -173,8 +158,7 @@ public static function string(int|null $size = 255): ColumnSchemaInterface */ public static function text(int|null $size = null): ColumnSchemaInterface { - return (new StringColumnSchema(ColumnType::TEXT)) - ->size($size); + return new StringColumnSchema(ColumnType::TEXT, size: $size); } /** @@ -182,8 +166,7 @@ public static function text(int|null $size = null): ColumnSchemaInterface */ public static function binary(int|null $size = null): ColumnSchemaInterface { - return (new BinaryColumnSchema(ColumnType::BINARY)) - ->size($size); + return new BinaryColumnSchema(ColumnType::BINARY, size: $size); } /** @@ -199,8 +182,7 @@ public static function uuid(): ColumnSchemaInterface */ public static function datetime(int|null $size = 0): ColumnSchemaInterface { - return (new StringColumnSchema(ColumnType::DATETIME)) - ->size($size); + return new StringColumnSchema(ColumnType::DATETIME, size: $size); } /** @@ -208,8 +190,7 @@ public static function datetime(int|null $size = 0): ColumnSchemaInterface */ public static function timestamp(int|null $size = 0): ColumnSchemaInterface { - return (new StringColumnSchema(ColumnType::TIMESTAMP)) - ->size($size); + return new StringColumnSchema(ColumnType::TIMESTAMP, size: $size); } /** @@ -225,8 +206,7 @@ public static function date(): ColumnSchemaInterface */ public static function time(int|null $size = 0): ColumnSchemaInterface { - return (new StringColumnSchema(ColumnType::TIME)) - ->size($size); + return new StringColumnSchema(ColumnType::TIME, size: $size); } /** @@ -236,8 +216,7 @@ public static function time(int|null $size = 0): ColumnSchemaInterface */ public static function array(ColumnSchemaInterface|null $column = null): ColumnSchemaInterface { - return (new ArrayColumnSchema(ColumnType::ARRAY)) - ->column($column); + return new ArrayColumnSchema(ColumnType::ARRAY, column: $column); } /** @@ -250,9 +229,7 @@ public static function array(ColumnSchemaInterface|null $column = null): ColumnS */ public static function structured(string|null $dbType = null, array $columns = []): ColumnSchemaInterface { - return (new StructuredColumnSchema(ColumnType::STRUCTURED)) - ->dbType($dbType) - ->columns($columns); + return new StructuredColumnSchema(ColumnType::STRUCTURED, dbType: $dbType, columns: $columns); } /** diff --git a/src/Schema/Column/ColumnFactoryInterface.php b/src/Schema/Column/ColumnFactoryInterface.php index 61398e35d..57d9251ec 100644 --- a/src/Schema/Column/ColumnFactoryInterface.php +++ b/src/Schema/Column/ColumnFactoryInterface.php @@ -6,12 +6,36 @@ use Yiisoft\Db\Constant\ColumnType; use Yiisoft\Db\Constant\PseudoType; +use Yiisoft\Db\Constraint\ForeignKeyConstraint; /** * The interface must be implemented by a column factory class. It should create a column schema for a database column * type and initialize column information. * - * @psalm-import-type ColumnInfo from ColumnSchemaInterface + * @psalm-type ColumnInfo = array{ + * autoIncrement?: bool, + * check?: string|null, + * column?: ColumnSchemaInterface|null, + * columns?: array, + * comment?: string|null, + * computed?: bool, + * dbType?: string|null, + * defaultValue?: mixed, + * dimension?: positive-int, + * enumValues?: array|null, + * extra?: string|null, + * primaryKey?: bool, + * name?: string|null, + * notNull?: bool, + * reference?: ForeignKeyConstraint|null, + * scale?: int|null, + * schema?: string|null, + * size?: int|null, + * table?: string|null, + * type?: ColumnType::*, + * unique?: bool, + * unsigned?: bool, + * } */ interface ColumnFactoryInterface { @@ -19,9 +43,9 @@ interface ColumnFactoryInterface * Creates a column schema for a database column type and initializes column information. * * @param string $dbType The database column type. - * @param array $info The column information. + * @param array $info The column information. The set of parameters may be different for a specific DBMS. * - * @psalm-param ColumnInfo $info The set of parameters may be different for a specific DBMS. + * @psalm-param ColumnInfo $info */ public function fromDbType(string $dbType, array $info = []): ColumnSchemaInterface; @@ -32,9 +56,9 @@ public function fromDbType(string $dbType, array $info = []): ColumnSchemaInterf * For example, `varchar(255) NOT NULL` is a database type with a size and a NOT NULL constraint. * * @param string $definition The database column definition. - * @param array $info The column information. + * @param array $info The column information. The set of parameters may be different for a specific DBMS. * - * @psalm-param ColumnInfo $info The set of parameters may be different for a specific DBMS. + * @psalm-param ColumnInfo $info */ public function fromDefinition(string $definition, array $info = []): ColumnSchemaInterface; @@ -42,7 +66,7 @@ public function fromDefinition(string $definition, array $info = []): ColumnSche * Creates a column schema for a pseudo-type and initializes column information. * * @param string $pseudoType The pseudo-type. - * @param array $info The column information. + * @param array $info The column information. The set of parameters may be different for a specific DBMS. * * @return ColumnSchemaInterface The column schema. * @@ -55,10 +79,10 @@ public function fromPseudoType(string $pseudoType, array $info = []): ColumnSche * Creates a column schema for an abstract database type and initializes column information. * * @param string $type The abstract database type. - * @param array $info The column information. + * @param array $info The column information. The set of parameters may be different for a specific DBMS. * * @psalm-param ColumnType::* $type - * @psalm-param ColumnInfo $info The set of parameters may be different for a specific DBMS. + * @psalm-param ColumnInfo $info */ public function fromType(string $type, array $info = []): ColumnSchemaInterface; } diff --git a/src/Schema/Column/ColumnSchemaInterface.php b/src/Schema/Column/ColumnSchemaInterface.php index 4c5ff4388..ffaf24330 100644 --- a/src/Schema/Column/ColumnSchemaInterface.php +++ b/src/Schema/Column/ColumnSchemaInterface.php @@ -11,31 +11,6 @@ /** * This interface defines a set of methods that must be implemented by a class that represents the column schema of a * database table column. - * - * @psalm-type ColumnInfo = array{ - * auto_increment?: bool|string, - * check?: string|null, - * column?: ColumnSchemaInterface|null, - * columns?: array, - * 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, - * not_null?: bool|string, - * reference?: ForeignKeyConstraint|null, - * scale?: int|string|null, - * schema?: string|null, - * size?: int|string|null, - * table?: string|null, - * type?: ColumnType::*, - * unique?: bool|string, - * unsigned?: bool|string, - * ... - * } */ interface ColumnSchemaInterface { @@ -322,13 +297,6 @@ public function isUnique(): bool; */ public function isUnsigned(): bool; - /** - * Loads the column's schema information from an array. - * - * @psalm-param ColumnInfo $info - */ - public function load(array $info): static; - /** * Sets a name of the column. * @@ -382,7 +350,7 @@ public function precision(int|null $precision): static; * ]; * ``` */ - public function primaryKey(bool $isPrimaryKey = true): static; + public function primaryKey(bool $primaryKey = true): static; /** * The reference to the foreign key constraint. diff --git a/src/Schema/Column/DoubleColumnSchema.php b/src/Schema/Column/DoubleColumnSchema.php index a84031329..674e2abb0 100644 --- a/src/Schema/Column/DoubleColumnSchema.php +++ b/src/Schema/Column/DoubleColumnSchema.php @@ -10,16 +10,12 @@ use function is_float; +/** + * Represents the metadata for a double column. + */ class DoubleColumnSchema extends AbstractColumnSchema { - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::DOUBLE, - ) { - parent::__construct($type); - } + protected const DEFAULT_TYPE = ColumnType::DOUBLE; public function dbTypecast(mixed $value): float|ExpressionInterface|null { diff --git a/src/Schema/Column/IntegerColumnSchema.php b/src/Schema/Column/IntegerColumnSchema.php index 27cd92b58..30513ed80 100644 --- a/src/Schema/Column/IntegerColumnSchema.php +++ b/src/Schema/Column/IntegerColumnSchema.php @@ -10,16 +10,12 @@ use function is_int; +/** + * Represents the schema for an integer column. + */ class IntegerColumnSchema extends AbstractColumnSchema { - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::INTEGER, - ) { - parent::__construct($type); - } + protected const DEFAULT_TYPE = ColumnType::INTEGER; public function dbTypecast(mixed $value): int|ExpressionInterface|null { diff --git a/src/Schema/Column/JsonColumnSchema.php b/src/Schema/Column/JsonColumnSchema.php index cf4015351..9ddf626f3 100644 --- a/src/Schema/Column/JsonColumnSchema.php +++ b/src/Schema/Column/JsonColumnSchema.php @@ -11,16 +11,12 @@ use function is_string; use function json_decode; +/** + * Represents the schema for a json column. + */ class JsonColumnSchema extends AbstractColumnSchema { - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::JSON, - ) { - parent::__construct($type); - } + protected const DEFAULT_TYPE = ColumnType::JSON; public function dbTypecast(mixed $value): ExpressionInterface|null { diff --git a/src/Schema/Column/StringColumnSchema.php b/src/Schema/Column/StringColumnSchema.php index c2b6c6510..992abe7de 100644 --- a/src/Schema/Column/StringColumnSchema.php +++ b/src/Schema/Column/StringColumnSchema.php @@ -11,16 +11,12 @@ use function gettype; +/** + * Represents the metadata for a string column. + */ class StringColumnSchema extends AbstractColumnSchema { - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::STRING, - ) { - parent::__construct($type); - } + protected const DEFAULT_TYPE = ColumnType::STRING; public function dbTypecast(mixed $value): mixed { diff --git a/src/Schema/Column/StructuredColumnSchema.php b/src/Schema/Column/StructuredColumnSchema.php index 241132989..d71315d41 100644 --- a/src/Schema/Column/StructuredColumnSchema.php +++ b/src/Schema/Column/StructuredColumnSchema.php @@ -12,15 +12,21 @@ use Yiisoft\Db\Syntax\ParserToArrayInterface; use function array_keys; +use function is_array; use function is_string; +/** + * Represents the schema for a structured column. + */ class StructuredColumnSchema extends AbstractColumnSchema { + protected const DEFAULT_TYPE = ColumnType::STRUCTURED; + /** * @var ColumnSchemaInterface[] Columns metadata of the structured type. * @psalm-var array */ - private array $columns = []; + protected array $columns = []; /** * Returns the parser for the column value. @@ -30,15 +36,6 @@ protected function getParser(): ParserToArrayInterface throw new NotSupportedException(__METHOD__ . '() is not supported. Use concrete DBMS implementation.'); } - /** - * @psalm-param ColumnType::* $type - */ - public function __construct( - string $type = ColumnType::STRUCTURED, - ) { - parent::__construct($type); - } - /** * Set columns of the structured type. * diff --git a/src/Syntax/ColumnDefinitionParser.php b/src/Syntax/ColumnDefinitionParser.php index 7c66953d0..1800596bb 100644 --- a/src/Syntax/ColumnDefinitionParser.php +++ b/src/Syntax/ColumnDefinitionParser.php @@ -4,7 +4,7 @@ namespace Yiisoft\Db\Syntax; -use Yiisoft\Db\Schema\Column\ColumnSchemaInterface; +use Yiisoft\Db\Schema\Column\ColumnFactoryInterface; use function explode; use function preg_match; @@ -19,7 +19,7 @@ /** * Parses column definition string. For example, `string(255)` or `int unsigned`. * - * @psalm-import-type ColumnInfo from ColumnSchemaInterface + * @psalm-import-type ColumnInfo from ColumnFactoryInterface */ final class ColumnDefinitionParser { @@ -36,11 +36,11 @@ public function parse(string $definition): array { preg_match('/^(\w*)(?:\(([^)]+)\))?\s*/', $definition, $matches); - $dbType = strtolower($matches[1]); - $info = ['db_type' => $dbType]; + $type = strtolower($matches[1]); + $info = ['type' => $type]; if (isset($matches[2])) { - if ($dbType === 'enum') { + if ($type === 'enum') { $info += $this->enumInfo($matches[2]); } else { $info += $this->sizeInfo($matches[2]); @@ -57,7 +57,7 @@ private function enumInfo(string $values): array { preg_match_all("/'([^']*)'/", $values, $matches); - return ['enum_values' => $matches[1]]; + return ['enumValues' => $matches[1]]; } private function extraInfo(string $extra): array diff --git a/tests/Db/Schema/ColumnSchemaTest.php b/tests/Db/Schema/ColumnSchemaTest.php index 449646517..3f1539653 100644 --- a/tests/Db/Schema/ColumnSchemaTest.php +++ b/tests/Db/Schema/ColumnSchemaTest.php @@ -155,12 +155,10 @@ public function testExtra(): void $this->assertSame('', $column->getExtra()); } - /** @dataProvider \Yiisoft\Db\Tests\Provider\ColumnSchemaProvider::load */ - public function testLoad(string $parameter, mixed $value, string $method, mixed $expected): void + /** @dataProvider \Yiisoft\Db\Tests\Provider\ColumnSchemaProvider::construct */ + public function testConstruct(string $parameter, mixed $value, string $method, mixed $expected): void { - $column = new ColumnSchema(); - - $column->load([$parameter => $value]); + $column = new ColumnSchema(...[$parameter => $value]); $this->assertSame($expected, $column->$method()); } diff --git a/tests/Provider/ColumnDefinitionParserProvider.php b/tests/Provider/ColumnDefinitionParserProvider.php index 2ad24ab29..fe7b2eede 100644 --- a/tests/Provider/ColumnDefinitionParserProvider.php +++ b/tests/Provider/ColumnDefinitionParserProvider.php @@ -9,16 +9,16 @@ class ColumnDefinitionParserProvider public static function parse(): array { return [ - ['', ['db_type' => '']], - ['int', ['db_type' => 'int']], - ['int(10)', ['db_type' => 'int', 'size' => 10]], - ['int UNSIGNED', ['db_type' => 'int', 'unsigned' => true]], - ['int(10) UNSIGNED', ['db_type' => 'int', 'size' => 10, 'unsigned' => true]], - ['int(10) UNSIGNED NOT NULL', ['db_type' => 'int', 'size' => 10, 'unsigned' => true, 'extra' => 'NOT NULL']], - ['int(10) NOT NULL', ['db_type' => 'int', 'size' => 10, 'extra' => 'NOT NULL']], - ['text NOT NULL', ['db_type' => 'text', 'extra' => 'NOT NULL']], - ["enum('a','b','c')", ['db_type' => 'enum', 'enum_values' => ['a', 'b', 'c']]], - ["enum('a','b','c') NOT NULL", ['db_type' => 'enum', 'enum_values' => ['a', 'b', 'c'], 'extra' => 'NOT NULL']], + ['', ['type' => '']], + ['int', ['type' => 'int']], + ['int(10)', ['type' => 'int', 'size' => 10]], + ['int UNSIGNED', ['type' => 'int', 'unsigned' => true]], + ['int(10) UNSIGNED', ['type' => 'int', 'size' => 10, 'unsigned' => true]], + ['int(10) UNSIGNED NOT NULL', ['type' => 'int', 'size' => 10, 'unsigned' => true, 'extra' => 'NOT NULL']], + ['int(10) NOT NULL', ['type' => 'int', 'size' => 10, 'extra' => 'NOT NULL']], + ['text NOT NULL', ['type' => 'text', 'extra' => 'NOT NULL']], + ["enum('a','b','c')", ['type' => 'enum', 'enumValues' => ['a', 'b', 'c']]], + ["enum('a','b','c') NOT NULL", ['type' => 'enum', 'enumValues' => ['a', 'b', 'c'], 'extra' => 'NOT NULL']], ]; } } diff --git a/tests/Provider/ColumnFactoryProvider.php b/tests/Provider/ColumnFactoryProvider.php index 7b7f7f778..77ff08a8a 100644 --- a/tests/Provider/ColumnFactoryProvider.php +++ b/tests/Provider/ColumnFactoryProvider.php @@ -37,7 +37,7 @@ public static function pseudoTypes(): array 'pk' => [PseudoType::PK, ColumnType::INTEGER, IntegerColumnSchema::class, ['isPrimaryKey' => true, 'isAutoIncrement' => true]], 'upk' => [PseudoType::UPK, ColumnType::INTEGER, IntegerColumnSchema::class, ['isPrimaryKey' => true, 'isAutoIncrement' => true, 'isUnsigned' => true]], 'bigpk' => [PseudoType::BIGPK, ColumnType::BIGINT, IntegerColumnSchema::class, ['isPrimaryKey' => true, 'isAutoIncrement' => true]], - 'ubigpk' => [PseudoType::UBIGPK, ColumnType::BIGINT, IntegerColumnSchema::class, ['isPrimaryKey' => true, 'isAutoIncrement' => true, 'isUnsigned' => true]], + 'ubigpk' => [PseudoType::UBIGPK, ColumnType::BIGINT, BigIntColumnSchema::class, ['isPrimaryKey' => true, 'isAutoIncrement' => true, 'isUnsigned' => true]], 'uuid_pk' => [PseudoType::UUID_PK, ColumnType::UUID, StringColumnSchema::class, ['isPrimaryKey' => true, 'isAutoIncrement' => true]], 'uuid_pk_seq' => [PseudoType::UUID_PK_SEQ, ColumnType::UUID, StringColumnSchema::class, ['isPrimaryKey' => true, 'isAutoIncrement' => true]], ]; diff --git a/tests/Provider/ColumnSchemaProvider.php b/tests/Provider/ColumnSchemaProvider.php index 6f00d19b2..806f03457 100644 --- a/tests/Provider/ColumnSchemaProvider.php +++ b/tests/Provider/ColumnSchemaProvider.php @@ -366,46 +366,32 @@ public static function dbTypecastArrayColumns() ]; } - public static function load(): array + public static function construct(): array { return [ // parameter, value, method to get value, expected value - ['allow_null', true, 'isAllowNull', true], - ['allow_null', false, 'isAllowNull', false], - ['allow_null', '1', 'isAllowNull', true], - ['allow_null', '0', 'isAllowNull', false], - ['auto_increment', true, 'isAutoIncrement', true], - ['auto_increment', false, 'isAutoIncrement', false], - ['auto_increment', '1', 'isAutoIncrement', true], - ['auto_increment', '0', 'isAutoIncrement', false], + ['autoIncrement', true, 'isAutoIncrement', true], + ['autoIncrement', false, 'isAutoIncrement', false], ['check', 'age > 0', 'getCheck', 'age > 0'], ['check', null, 'getCheck', null], ['comment', 'Lorem ipsum', 'getComment', 'Lorem ipsum'], ['comment', null, 'getComment', null], ['computed', true, 'isComputed', true], ['computed', false, 'isComputed', false], - ['computed', '1', 'isComputed', true], - ['computed', '0', 'isComputed', false], - ['db_type', 'integer', 'getDbType', 'integer'], - ['db_type', null, 'getDbType', null], - ['default_value', 'default_value', 'getDefaultValue', 'default_value'], - ['default_value', null, 'getDefaultValue', null], - ['enum_values', ['value1', 'value2'], 'getEnumValues', ['value1', 'value2']], - ['enum_values', null, 'getEnumValues', null], + ['dbType', 'integer', 'getDbType', 'integer'], + ['dbType', null, 'getDbType', null], + ['defaultValue', 'default_value', 'getDefaultValue', 'default_value'], + ['defaultValue', null, 'getDefaultValue', null], + ['enumValues', ['value1', 'value2'], 'getEnumValues', ['value1', 'value2']], + ['enumValues', null, 'getEnumValues', null], ['extra', 'CHARACTER SET utf8mb4', 'getExtra', 'CHARACTER SET utf8mb4'], ['extra', null, 'getExtra', null], ['name', 'name', 'getName', 'name'], ['name', null, 'getName', null], - ['not_null', true, 'isNotNull', true], - ['not_null', false, 'isNotNull', false], - ['not_null', '1', 'isNotNull', true], - ['not_null', '0', 'isNotNull', false], - ['precision', 10, 'getPrecision', 10], - ['precision', null, 'getPrecision', null], - ['primary_key', true, 'isPrimaryKey', true], - ['primary_key', false, 'isPrimaryKey', false], - ['primary_key', '1', 'isPrimaryKey', true], - ['primary_key', '0', 'isPrimaryKey', false], + ['notNull', true, 'isNotNull', true], + ['notNull', false, 'isNotNull', false], + ['primaryKey', true, 'isPrimaryKey', true], + ['primaryKey', false, 'isPrimaryKey', false], ['reference', $fk = new ForeignKeyConstraint(), 'getReference', $fk], ['reference', null, 'getReference', null], ['scale', 2, 'getScale', 2], @@ -414,12 +400,8 @@ public static function load(): array ['size', null, 'getSize', null], ['unique', true, 'isUnique', true], ['unique', false, 'isUnique', false], - ['unique', '1', 'isUnique', true], - ['unique', '0', 'isUnique', false], ['unsigned', true, 'isUnsigned', true], ['unsigned', false, 'isUnsigned', false], - ['unsigned', '1', 'isUnsigned', true], - ['unsigned', '0', 'isUnsigned', false], ]; } } diff --git a/tests/Support/Stub/ColumnSchema.php b/tests/Support/Stub/ColumnSchema.php index a01a6b2e7..2d5ab86ee 100644 --- a/tests/Support/Stub/ColumnSchema.php +++ b/tests/Support/Stub/ColumnSchema.php @@ -8,11 +8,7 @@ final class ColumnSchema extends AbstractColumnSchema { - public function __construct( - private string $type = '', - ) { - parent::__construct($type); - } + protected const DEFAULT_TYPE = ''; public function dbTypecast(mixed $value): mixed { From da283930af373f21f698911cbf6946fe32b7f06b Mon Sep 17 00:00:00 2001 From: Tigrov Date: Fri, 18 Oct 2024 18:03:53 +0700 Subject: [PATCH 2/2] Add line to CHANGELOG.md [skip ci] --- CHANGELOG.md | 1 + UPGRADE.md | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f7a5239d..e11cbd3e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ - New #883: Add `ColumnDefinitionBuilder` class and `QueryBuilderInterface::buildColumnDefinition()` method (@Tigrov) - Enh #885: Refactor `AbstractDsn` class (@Tigrov) - Chg #889: Update `AbstractDMLQueryBuilder::insertBatch()` method (@Tigrov) +- Enh #890: Add properties of `AbstractColumnSchema` class to constructor (@Tigrov) ## 1.3.0 March 21, 2024 diff --git a/UPGRADE.md b/UPGRADE.md index 849df852f..a22e6df49 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -75,7 +75,8 @@ and the following changes were made: - `isNotNull()` method is added; - `unique(bool $unique = true)` method is added; - `isUnique()` method is added; -- all `AbstractColumnSchema` class properties moved to constructor; +- all `AbstractColumnSchema` class properties except `$type` moved to constructor; +- added `DEFAULT_TYPE` constant to `AbstractColumnSchema` class; - added method chaining. ### New classes with constants