Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor AbstractColumnFactory #897

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
$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

Check warning on line 122 in src/Schema/Column/AbstractColumnFactory.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/Column/AbstractColumnFactory.php#L122

Added line #L122 was not covered by tests
: 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,

Check warning on line 131 in src/Schema/Column/AbstractColumnFactory.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/Column/AbstractColumnFactory.php#L131

Added line #L131 was not covered by tests
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
Loading