Skip to content

Commit

Permalink
Refactor AbstractColumnFactory (#897)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tigrov authored Nov 8, 2024
1 parent 42181e1 commit e29b097
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 96 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
- Enh #865: Raise minimum PHP version to `^8.1` with minor refactoring (@Tigrov, @vjik)
- Enh #798: Allow `QueryInterface::one()` and `QueryInterface::all()` to return objects (@darkdef, @Tigrov)
- Enh #872: Use `#[\SensitiveParameter]` attribute to mark sensitive parameters (@heap-s)
- New #864: Realize column factory (@Tigrov)
- New #864, #897: Realize column factory (@Tigrov)
- Enh #875: Ignore "Packets out of order..." warnings in `AbstractPdoCommand::internalExecute()` method (@Tigrov)
- Enh #877: Separate column type constants (@Tigrov)
- Enh #878: Realize `ColumnBuilder` class (@Tigrov)
Expand Down
132 changes: 79 additions & 53 deletions src/Schema/Column/AbstractColumnFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,18 @@
abstract class AbstractColumnFactory implements ColumnFactoryInterface
{
/**
* Get the abstract database type for a database column type.
*
* @param string $dbType The database column type.
* @param array $info The column information.
* The mapping from physical column types (keys) to abstract column types (values).
*
* @return string The abstract database type.
* @var string[]
*
* @psalm-param ColumnInfo $info
* @psalm-return ColumnType::*
* @psalm-var array<string, ColumnType::*>
*/
abstract protected function getType(string $dbType, array $info = []): string;

/**
* Checks if the column type is a database type.
*/
abstract protected function isDbType(string $dbType): bool;
protected const TYPE_MAP = [];

public function fromDbType(string $dbType, array $info = []): ColumnSchemaInterface
{
unset($info['dbType']);
$type = $info['type'] ?? $this->getType($dbType, $info);
unset($info['type']);
$info['dbType'] = $dbType;
$type = $info['type'] ?? $this->getType($dbType, $info);

return $this->fromType($type, $info);
}
Expand All @@ -60,77 +49,114 @@ public function fromDefinition(string $definition, array $info = []): ColumnSche
$info += $definitionInfo;

if ($this->isDbType($type)) {
unset($info['dbType']);
return $this->fromDbType($type, $info);
}

if ($this->isType($type)) {
unset($info['type']);
return $this->fromType($type, $info);
}

if ($this->isPseudoType($type)) {
return $this->fromPseudoType($type, $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 => 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),
if ($pseudoType === PseudoType::UPK || $pseudoType === PseudoType::UBIGPK) {
$info['unsigned'] = true;
}

$type = match ($pseudoType) {
PseudoType::PK => ColumnType::INTEGER,
PseudoType::UPK => ColumnType::INTEGER,
PseudoType::BIGPK => ColumnType::BIGINT,
PseudoType::UBIGPK => ColumnType::BIGINT,
PseudoType::UUID_PK => ColumnType::UUID,
PseudoType::UUID_PK_SEQ => ColumnType::UUID,
};

return $this->fromType($type, $info);
}

public function fromType(string $type, array $info = []): ColumnSchemaInterface
{
unset($info['type']);

if ($type === ColumnType::ARRAY && empty($info['column']) && !empty($info['dbType'])) {
$info['column'] = $this->fromDbType($info['dbType'], $info);
}

$columnClass = $this->getColumnClass($type, $info);

return new $columnClass($type, ...$info);
}

/**
* @psalm-suppress InvalidNamedArgument
* Returns the column definition parser.
*/
public function fromType(string $type, array $info = []): ColumnSchemaInterface
protected function columnDefinitionParser(): ColumnDefinitionParser
{
return new ColumnDefinitionParser();
}

/**
* @psalm-param ColumnType::* $type
* @param ColumnInfo $info
*
* @psalm-return class-string<ColumnSchemaInterface>
*/
protected function getColumnClass(string $type, array $info = []): string
{
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::BOOLEAN => BooleanColumnSchema::class,
ColumnType::BIT => BitColumnSchema::class,
ColumnType::TINYINT => IntegerColumnSchema::class,
ColumnType::SMALLINT => IntegerColumnSchema::class,
ColumnType::INTEGER => PHP_INT_SIZE !== 8 && !empty($info['unsigned'])
? new BigIntColumnSchema($type, ...$info)
: new IntegerColumnSchema($type, ...$info),
? BigIntColumnSchema::class
: IntegerColumnSchema::class,
ColumnType::BIGINT => PHP_INT_SIZE !== 8 || !empty($info['unsigned'])
? 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),
? BigIntColumnSchema::class
: IntegerColumnSchema::class,
ColumnType::DECIMAL => DoubleColumnSchema::class,
ColumnType::FLOAT => DoubleColumnSchema::class,
ColumnType::DOUBLE => DoubleColumnSchema::class,
ColumnType::BINARY => BinaryColumnSchema::class,
ColumnType::ARRAY => ArrayColumnSchema::class,
ColumnType::STRUCTURED => StructuredColumnSchema::class,
ColumnType::JSON => JsonColumnSchema::class,
default => StringColumnSchema::class,
};
}

/**
* Returns the column definition parser.
* Get the abstract database type for a database column type.
*
* @param string $dbType The database column type.
* @param array $info The column information.
*
* @return string The abstract database type.
*
* @psalm-param ColumnInfo $info
* @psalm-return ColumnType::*
*/
protected function columnDefinitionParser(): ColumnDefinitionParser
protected function getType(string $dbType, array $info = []): string
{
return new ColumnDefinitionParser();
return static::TYPE_MAP[$dbType] ?? ColumnType::STRING;
}

/**
* Checks if the column type is a database type.
*/
protected function isDbType(string $dbType): bool
{
return isset(static::TYPE_MAP[$dbType]);
}

/**
Expand Down
33 changes: 0 additions & 33 deletions tests/Common/CommonSchemaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -359,39 +359,6 @@ public function testGetSchemaUniques(): void
$db->close();
}

/**
* @dataProvider \Yiisoft\Db\Tests\Provider\SchemaProvider::columnsTypeChar
*/
public function testGetStringFieldsSize(
string $columnName,
string $columnType,
int|null $columnSize,
string $columnDbType
): void {
$db = $this->getConnection(true);

$schema = $db->getSchema();
$tableSchema = $schema->getTableSchema('type');

$this->assertInstanceOf(TableSchemaInterface::class, $tableSchema);

$columns = $tableSchema->getColumns();

foreach ($columns as $name => $column) {
$type = $column->getType();
$size = $column->getSize();
$dbType = $column->getDbType();

if ($name === $columnName) {
$this->assertSame($columnType, $type);
$this->assertSame($columnSize, $size);
$this->assertSame($columnDbType, $dbType);
}
}

$db->close();
}

public function testGetTableChecks(): void
{
$db = $this->getConnection(true);
Expand Down
9 changes: 0 additions & 9 deletions tests/Provider/SchemaProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,6 @@ public static function columns(): array
return [];
}

public static function columnsTypeChar(): array
{
return [
['char_col', 'char', 100, 'char(100)'],
['char_col2', 'string', 100, 'varchar(100)'],
['char_col3', 'text', null, 'text'],
];
}

public static function constraints(): array
{
return [
Expand Down

0 comments on commit e29b097

Please sign in to comment.