Skip to content

Commit

Permalink
Remove ColumnSchema::load(), add properties to constructor (#890)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov authored Oct 18, 2024
1 parent ee6f00e commit d04a9c4
Show file tree
Hide file tree
Showing 24 changed files with 257 additions and 322 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ 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 except `$type` moved to constructor;
- added `DEFAULT_TYPE` constant to `AbstractColumnSchema` class;
- added method chaining.

### New classes with constants
Expand Down
2 changes: 1 addition & 1 deletion src/Connection/AbstractDsn.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down
89 changes: 52 additions & 37 deletions src/Schema/Column/AbstractColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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);
}
Expand All @@ -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);
}

/**
Expand Down
116 changes: 61 additions & 55 deletions src/Schema/Column/AbstractColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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<string, mixed> $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<string, mixed> $args */
foreach ($args as $property => $value) {
if (property_exists($this, $property)) {
$this->$property = $value;
}
}
}

/**
Expand Down Expand Up @@ -215,7 +255,7 @@ public function isNotNull(): bool

public function isPrimaryKey(): bool
{
return $this->isPrimaryKey;
return $this->primaryKey;
}

public function isUnique(): bool
Expand All @@ -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.
*/
Expand All @@ -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;
}

Expand Down
27 changes: 15 additions & 12 deletions src/Schema/Column/ArrayColumnSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
*/
Expand All @@ -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
{
Expand All @@ -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
{
Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit d04a9c4

Please sign in to comment.