diff --git a/UPGRADE.md b/UPGRADE.md index 1751ca57c8..b2cb9b7d9a 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -66,6 +66,26 @@ method instead: - `Column::setComment()` - use `ColumnEditor::setComment()`. - `Column::setValues()` - use `ColumnEditor::setValues()`. +## Deprecated `Column::getType()`, `Column::setType()` and passing a `Type` instance to `Column::__construct()` + +`Column` now stores the DBAL type name (string) as source of truth. Use +`Column::getTypeName()` / `Column::setTypeName()` and pass the type name to +the constructor instead of a `Type` instance. + +```diff +-use Doctrine\DBAL\Types\Type; + use Doctrine\DBAL\Types\Types; + +-$column = new Column('id', Type::getType(Types::INTEGER)); ++$column = new Column('id', Types::INTEGER); + +-$typeName = Type::getTypeRegistry()->lookupName($column->getType()); ++$typeName = $column->getTypeName(); +``` + +Libraries that need to support older DBAL versions can keep passing a `Type` +instance; the deprecated path stays functional until the next major. + ## Deprecated `Table` features The `Table` constructor has been marked as internal. Use `Table::editor()` to instantiate an editor and diff --git a/src/Platforms/AbstractMySQLPlatform.php b/src/Platforms/AbstractMySQLPlatform.php index 529d9441a8..90f123e806 100644 --- a/src/Platforms/AbstractMySQLPlatform.php +++ b/src/Platforms/AbstractMySQLPlatform.php @@ -366,7 +366,7 @@ public function getAlterTableSQL(TableDiff $diff): array $queryParts = []; foreach ($diff->getAddedColumns() as $column) { - $columnProperties = array_merge($column->toArray(), [ + $columnProperties = array_merge($column->toArray(true), [ 'comment' => $column->getComment(), ]); @@ -383,7 +383,7 @@ public function getAlterTableSQL(TableDiff $diff): array foreach ($diff->getChangedColumns() as $columnDiff) { $newColumn = $columnDiff->getNewColumn(); - $newColumnProperties = array_merge($newColumn->toArray(), [ + $newColumnProperties = array_merge($newColumn->toArray(true), [ 'comment' => $newColumn->getComment(), ]); @@ -536,7 +536,7 @@ private function getPreAlterTableAlterPrimaryKeySQL(TableDiff $diff, Index $inde $column->setAutoincrement(false); $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' MODIFY ' . - $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray(true)); // original autoincrement information might be needed later on by other parts of the table alteration $column->setAutoincrement(true); @@ -593,7 +593,7 @@ private function getPreAlterTableAlterIndexForeignKeySQL(TableDiff $diff): array $column->setAutoincrement(false); $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' MODIFY ' . - $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray(true)); // Restore the autoincrement attribute as it might be needed later on // by other parts of the table alteration. diff --git a/src/Platforms/AbstractPlatform.php b/src/Platforms/AbstractPlatform.php index a51bdc7904..04ee9be0e6 100644 --- a/src/Platforms/AbstractPlatform.php +++ b/src/Platforms/AbstractPlatform.php @@ -889,6 +889,15 @@ final protected function getCreateTableWithoutForeignKeysSQL(Table $table): arra return $this->buildCreateTableSQL($table, false); } + /** + * Resolves the DBAL type instance for a column type name. + */ + protected function getType(string $typeName): Type + { + // @phpstan-ignore missingType.checkedException + return Type::getType($typeName); + } + /** @return list */ private function buildCreateTableSQL(Table $table, bool $createForeignKeys): array { @@ -1493,7 +1502,7 @@ public function getColumnDeclarationSQL(string $name, array $column): string $notnull = ! empty($column['notnull']) ? ' NOT NULL' : ''; - $typeDecl = $column['type']->getSQLDeclaration($column, $this); + $typeDecl = $this->getType($column['typeName'])->getSQLDeclaration($column, $this); $declaration = $typeDecl . $charset . $default . $notnull . $collation; if ($this->supportsInlineColumnComments() && isset($column['comment']) && $column['comment'] !== '') { @@ -1544,12 +1553,14 @@ public function getDefaultValueDeclarationSQL(array $column): string return ' DEFAULT ' . $default->toSQL($this); } - if (! isset($column['type'])) { + if (isset($column['typeName']) && is_string($column['typeName'])) { + $type = $this->getType($column['typeName']); + } elseif (isset($column['type']) && $column['type'] instanceof Type) { + $type = $column['type']; + } else { return " DEFAULT '" . $default . "'"; } - $type = $column['type']; - if ($type instanceof Types\PhpIntegerMappingType) { return ' DEFAULT ' . $default; } @@ -2382,7 +2393,7 @@ final public function escapeStringForLike(string $inputString, string $escapeCha */ private function columnToArray(Column $column): array { - return array_merge($column->toArray(), [ + return array_merge($column->toArray(true), [ 'name' => $column->getQuotedName($this), 'version' => $column->hasPlatformOption('version') ? $column->getPlatformOption('version') : false, 'comment' => $column->getComment(), diff --git a/src/Platforms/DB2Platform.php b/src/Platforms/DB2Platform.php index ee3411c376..68246b7651 100644 --- a/src/Platforms/DB2Platform.php +++ b/src/Platforms/DB2Platform.php @@ -19,6 +19,7 @@ use Doctrine\DBAL\SQL\Builder\SelectSQLBuilder; use Doctrine\DBAL\TransactionIsolationLevel; use Doctrine\DBAL\Types\PhpDateTimeMappingType; +use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Doctrine\Deprecations\Deprecation; @@ -27,6 +28,7 @@ use function current; use function explode; use function implode; +use function is_string; use function sprintf; use function str_contains; @@ -284,7 +286,7 @@ public function getAlterTableSQL(TableDiff $diff): array $queryParts = []; foreach ($diff->getAddedColumns() as $column) { - $columnDef = $column->toArray(); + $columnDef = $column->toArray(true); $queryPart = 'ADD COLUMN ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnDef); // Adding non-nullable columns to a table requires a default value to be specified. @@ -400,7 +402,7 @@ private function gatherAlterColumnSQL( private function getAlterColumnClausesSQL(ColumnDiff $columnDiff, bool &$needsReorg): array { $newColumn = $columnDiff->getNewColumn(); - $columnArray = $newColumn->toArray(); + $columnArray = $newColumn->toArray(true); $newName = $columnDiff->getNewColumn()->getQuotedName($this); $oldName = $columnDiff->getOldColumn()->getQuotedName($this); @@ -427,7 +429,7 @@ private function getAlterColumnClausesSQL(ColumnDiff $columnDiff, bool &$needsRe $columnDiff->hasFixedChanged() ) { $needsReorg = true; - $clauses[] = $alterClause . ' SET DATA TYPE ' . $newColumn->getType() + $clauses[] = $alterClause . ' SET DATA TYPE ' . $this->getType($newColumn->getTypeName()) ->getSQLDeclaration($columnArray, $this); } @@ -484,7 +486,15 @@ public function getDefaultValueDeclarationSQL(array $column): string 'The "version" column platform option is deprecated.', ); - if ($column['type'] instanceof PhpDateTimeMappingType) { + if (isset($column['typeName']) && is_string($column['typeName'])) { + $type = $this->getType($column['typeName']); + } elseif (isset($column['type']) && $column['type'] instanceof Type) { + $type = $column['type']; + } else { + $type = null; + } + + if ($type instanceof PhpDateTimeMappingType) { $column['default'] = '1'; } } diff --git a/src/Platforms/MariaDBPlatform.php b/src/Platforms/MariaDBPlatform.php index e0c436d3af..1830ce3dda 100644 --- a/src/Platforms/MariaDBPlatform.php +++ b/src/Platforms/MariaDBPlatform.php @@ -149,7 +149,11 @@ public function getColumnDeclarationSQL(string $name, array $column): string { // MariaDb forces column collation to utf8mb4_bin where the column was declared as JSON so ignore // collation and character set for json columns as attempting to set them can cause an error. - if ($this->getJsonTypeDeclarationSQL([]) === 'JSON' && ($column['type'] ?? null) instanceof JsonType) { + if ( + $this->getJsonTypeDeclarationSQL([]) === 'JSON' + && isset($column['typeName']) + && $this->getType($column['typeName']) instanceof JsonType + ) { unset($column['collation']); unset($column['charset']); } diff --git a/src/Platforms/MySQLPlatform.php b/src/Platforms/MySQLPlatform.php index ad804b36aa..715b64f370 100644 --- a/src/Platforms/MySQLPlatform.php +++ b/src/Platforms/MySQLPlatform.php @@ -11,8 +11,11 @@ use Doctrine\DBAL\SQL\Builder\WithSQLBuilder; use Doctrine\DBAL\Types\BlobType; use Doctrine\DBAL\Types\TextType; +use Doctrine\DBAL\Types\Type; use Doctrine\Deprecations\Deprecation; +use function is_string; + /** * Provides the behavior, features and SQL dialect of the Oracle MySQL database platform * of the oldest supported version. @@ -30,8 +33,16 @@ class MySQLPlatform extends AbstractMySQLPlatform */ public function getDefaultValueDeclarationSQL(array $column): string { - if ($column['type'] instanceof TextType || $column['type'] instanceof BlobType) { - unset($column['default']); + if (isset($column['typeName']) && is_string($column['typeName'])) { + $type = $this->getType($column['typeName']); + } elseif (isset($column['type']) && $column['type'] instanceof Type) { + $type = $column['type']; + } else { + $type = null; + } + + if ($type instanceof TextType || $type instanceof BlobType) { + $column['default'] = null; } return parent::getDefaultValueDeclarationSQL($column); diff --git a/src/Platforms/OraclePlatform.php b/src/Platforms/OraclePlatform.php index 3fdab094c4..16b1bb8c64 100644 --- a/src/Platforms/OraclePlatform.php +++ b/src/Platforms/OraclePlatform.php @@ -577,7 +577,7 @@ public function getAlterTableSQL(TableDiff $diff): array $tableNameSQL = $diff->getOldTable()->getQuotedName($this); foreach ($diff->getAddedColumns() as $column) { - $addColumnSQL[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray()); + $addColumnSQL[] = $this->getColumnDeclarationSQL($column->getQuotedName($this), $column->toArray(true)); $comment = $column->getComment(); if ($comment !== '') { @@ -614,7 +614,7 @@ public function getAlterTableSQL(TableDiff $diff): array // Oracle only supports binary type columns with variable length. // Avoids unnecessary table alteration statements. if ( - $newColumn->getType() instanceof BinaryType && + $this->getType($newColumn->getTypeName()) instanceof BinaryType && $columnDiff->hasFixedChanged() && $countChangedProperties === 1 ) { @@ -627,9 +627,9 @@ public function getAlterTableSQL(TableDiff $diff): array * Do not add query part if only comment has changed */ if ($countChangedProperties > ($columnHasChangedComment ? 1 : 0)) { - $newColumnProperties = $newColumn->toArray(); + $newColumnProperties = $newColumn->toArray(true); - $oldSQL = $this->getColumnDeclarationSQL('', $oldColumn->toArray()); + $oldSQL = $this->getColumnDeclarationSQL('', $oldColumn->toArray(true)); $newSQL = $this->getColumnDeclarationSQL('', $newColumnProperties); if ($newSQL !== $oldSQL) { @@ -690,7 +690,7 @@ public function getColumnDeclarationSQL(string $name, array $column): string $notnull = $column['notnull'] ? ' NOT NULL' : ' NULL'; } - $typeDecl = $column['type']->getSQLDeclaration($column, $this); + $typeDecl = $this->getType($column['typeName'])->getSQLDeclaration($column, $this); $declaration = $typeDecl . $default . $notnull; } diff --git a/src/Platforms/PostgreSQLPlatform.php b/src/Platforms/PostgreSQLPlatform.php index 48b598e5ce..f3e7ab1e24 100644 --- a/src/Platforms/PostgreSQLPlatform.php +++ b/src/Platforms/PostgreSQLPlatform.php @@ -217,7 +217,7 @@ public function getAlterTableSQL(TableDiff $diff): array foreach ($diff->getAddedColumns() as $addedColumn) { $query = 'ADD ' . $this->getColumnDeclarationSQL( $addedColumn->getQuotedName($this), - $addedColumn->toArray(), + $addedColumn->toArray(true), ); $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' ' . $query; @@ -272,7 +272,7 @@ public function getAlterTableSQL(TableDiff $diff): array if ($columnDiff->hasDefaultChanged()) { $defaultClause = $newColumn->getDefault() === null ? ' DROP DEFAULT' - : ' SET' . $this->getDefaultValueDeclarationSQL($newColumn->toArray()); + : ' SET' . $this->getDefaultValueDeclarationSQL($newColumn->toArray(true)); $query = 'ALTER ' . $newColumnName . $defaultClause; $sql[] = 'ALTER TABLE ' . $tableNameSQL . ' ' . $query; @@ -312,10 +312,10 @@ public function getAlterTableSQL(TableDiff $diff): array private function getTypeSQLDeclaration(Column $column): string { - $type = $column->getType(); + $type = $this->getType($column->getTypeName()); // SERIAL/BIGSERIAL are not "real" types and we can't alter a column to that type - $columnDefinition = $column->toArray(); + $columnDefinition = $column->toArray(true); $columnDefinition['autoincrement'] = false; return $type->getSQLDeclaration($columnDefinition, $this); diff --git a/src/Platforms/SQLServerPlatform.php b/src/Platforms/SQLServerPlatform.php index 70c712a50c..54d1b9d53c 100644 --- a/src/Platforms/SQLServerPlatform.php +++ b/src/Platforms/SQLServerPlatform.php @@ -50,6 +50,8 @@ /** * Provides the behavior, features and SQL dialect of the Microsoft SQL Server database platform * of the oldest supported version. + * + * @phpstan-import-type ColumnProperties from Column */ class SQLServerPlatform extends AbstractPlatform { @@ -325,7 +327,7 @@ protected function getCreateColumnCommentSQL(string $tableName, string $columnNa * * @internal The method should be only used by the {@see SQLServerPlatform} class. * - * @param mixed[] $column Column definition. + * @param ColumnProperties $column Column definition. */ protected function getDefaultConstraintDeclarationSQL(array $column): string { @@ -393,7 +395,7 @@ public function getAlterTableSQL(TableDiff $diff): array $tableName = $table->getName(); foreach ($diff->getAddedColumns() as $column) { - $columnProperties = $column->toArray(); + $columnProperties = $column->toArray(true); $addColumnSql = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnProperties); @@ -469,8 +471,8 @@ public function getAlterTableSQL(TableDiff $diff): array $columnNameSQL = $newColumn->getQuotedName($this); - $newDeclarationSQL = $this->getColumnDeclarationSQL($columnNameSQL, $newColumn->toArray()); - $oldDeclarationSQL = $this->getColumnDeclarationSQL($columnNameSQL, $oldColumn->toArray()); + $newDeclarationSQL = $this->getColumnDeclarationSQL($columnNameSQL, $newColumn->toArray(true)); + $oldDeclarationSQL = $this->getColumnDeclarationSQL($columnNameSQL, $oldColumn->toArray(true)); $declarationSQLChanged = $newDeclarationSQL !== $oldDeclarationSQL; $defaultChanged = $columnDiff->hasDefaultChanged(); @@ -522,7 +524,7 @@ public function getRenameTableSQL(string $oldName, string $newName): string */ private function getAlterTableAddDefaultConstraintClause(string $tableName, Column $column): string { - $columnDef = $column->toArray(); + $columnDef = $column->toArray(true); $columnDef['name'] = $column->getQuotedName($this); return 'ADD' . $this->getDefaultConstraintDeclarationSQL($columnDef); @@ -1244,7 +1246,7 @@ public function getColumnDeclarationSQL(string $name, array $column): string $notnull = ! empty($column['notnull']) ? ' NOT NULL' : ''; - $typeDecl = $column['type']->getSQLDeclaration($column, $this); + $typeDecl = $this->getType($column['typeName'])->getSQLDeclaration($column, $this); $declaration = $typeDecl . $collation . $notnull; } @@ -1265,8 +1267,8 @@ public function columnsEqual(Column $column1, Column $column2): bool return false; } - return $this->getDefaultValueDeclarationSQL($column1->toArray()) - === $this->getDefaultValueDeclarationSQL($column2->toArray()); + return $this->getDefaultValueDeclarationSQL($column1->toArray(true)) + === $this->getDefaultValueDeclarationSQL($column2->toArray(true)); } /** diff --git a/src/Platforms/SQLitePlatform.php b/src/Platforms/SQLitePlatform.php index 1a34fa8080..342c21981f 100644 --- a/src/Platforms/SQLitePlatform.php +++ b/src/Platforms/SQLitePlatform.php @@ -756,9 +756,9 @@ private function getSimpleAlterTableSQL(TableDiff $diff): array|false $sql = []; foreach ($diff->getAddedColumns() as $column) { - $definition = $column->toArray(); + $definition = $column->toArray(true); - $type = $definition['type']; + $type = $this->getType($definition['typeName']); switch (true) { case isset($definition['columnDefinition']): diff --git a/src/Schema/Column.php b/src/Schema/Column.php index e7795fd66c..8780282461 100644 --- a/src/Schema/Column.php +++ b/src/Schema/Column.php @@ -9,11 +9,18 @@ use Doctrine\DBAL\Schema\Name\Parser\UnqualifiedNameParser; use Doctrine\DBAL\Schema\Name\Parsers; use Doctrine\DBAL\Schema\Name\UnqualifiedName; +use Doctrine\DBAL\Types\Exception\TypesException; use Doctrine\DBAL\Types\Type; use Doctrine\Deprecations\Deprecation; +use TypeError; use function array_merge; +use function func_get_arg; +use function func_num_args; +use function get_debug_type; +use function is_bool; use function method_exists; +use function sprintf; /** * Object representation of a database column. @@ -22,7 +29,8 @@ * @extends AbstractNamedObject * @phpstan-type ColumnProperties = array{ * name: string, - * type: Type, + * type?: Type, + * typeName: string, * default: mixed, * notnull?: bool, * autoincrement: bool, @@ -42,8 +50,11 @@ */ class Column extends AbstractNamedObject { + /** @deprecated use $_typeName instead */ protected Type $_type; + protected string $_typeName; + protected ?int $_length = null; protected ?int $_precision = null; @@ -75,13 +86,29 @@ class Column extends AbstractNamedObject * @internal Use {@link Column::editor()} to instantiate an editor and {@link ColumnEditor::create()} to create a * column. * + * @param Type|string $type Passing a {@see Type} instance is deprecated; pass the type name instead. * @param array $options + * + * @throws TypesException */ - public function __construct(string $name, Type $type, array $options = []) + public function __construct(string $name, Type|string $type, array $options = []) { parent::__construct($name); - $this->setType($type); + if ($type instanceof Type) { + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/7490', + 'Passing a %s instance to %s() is deprecated, pass the type name instead.', + Type::class, + __METHOD__, + ); + + $this->setType($type); + } else { + $this->setTypeName($type); + } + $this->setOptions($options); } @@ -118,20 +145,29 @@ public function setOptions(array $options): self } /** - * @deprecated since doctrine/dbal 4.5. Use {@see Column::editor()} and {@see ColumnEditor::setType()} or - * {@see ColumnEditor::setTypeName()} instead. + * @deprecated since doctrine/dbal 4.5. Use {@see Column::editor()} and {@see ColumnEditor::setTypeName()} instead. + * + * @throws TypesException */ public function setType(Type $type): self { Deprecation::triggerIfCalledFromOutside( 'doctrine/dbal', 'https://github.com/doctrine/dbal/pull/7381', - '%s is deprecated. Use Column::editor() and ColumnEditor::setType() or ColumnEditor::setTypeName()' - . ' instead.', + '%s is deprecated. Use Column::editor() and ColumnEditor::setTypeName() instead.', __METHOD__, ); - $this->_type = $type; + $this->_type = $type; + $this->_typeName = Type::getTypeRegistry()->lookupName($type); + + return $this; + } + + public function setTypeName(string $typeName): self + { + $this->_typeName = $typeName; + unset($this->_type); return $this; } @@ -326,9 +362,32 @@ public function setColumnDefinition(?string $value): self return $this; } + /** + * @deprecated Use {@see getTypeName()} to obtain the type name, or resolve the {@see Type} + * instance from the type registry when needed. + * + * @throws TypesException + */ public function getType(): Type { - return $this->_type; + // Called from toArray() when $skipType is false, which already triggers its own + // deprecation, so triggering unconditionally here would report the same call twice. + Deprecation::triggerIfCalledFromOutside( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/7490', + '%s is deprecated. Use Column::getTypeName() instead.', + __METHOD__, + ); + + return Type::getType($this->_typeName); + } + + /** + * Returns the name of the DBAL type of this column. + */ + public function getTypeName(): string + { + return $this->_typeName; } public function getLength(): ?int @@ -533,12 +592,37 @@ public function getValues(): array return $this->_values; } - /** @return ColumnProperties */ - public function toArray(): array - { + /** + * Pass `true` as the first (virtual) argument to omit the resolved {@see Type} instance from the returned array + * and rely on the `typeName` key instead. Omitting the argument is deprecated. + * + * @return ColumnProperties + */ + public function toArray(/* bool $skipType = false */): array + { + $skipType = func_num_args() > 0 ? func_get_arg(0) : false; + if (! is_bool($skipType)) { + // @phpstan-ignore missingType.checkedException + throw new TypeError(sprintf( + 'Argument 1 passed to %s must be a boolean, %s given', + __METHOD__, + get_debug_type($skipType), + )); + } + + if (! $skipType) { + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/7490', + 'Calling %s() without the $skipType argument is deprecated. Pass true to omit the Type instance from ' + . 'the returned array and read the "typeName" key instead.', + __METHOD__, + ); + } + return array_merge([ 'name' => $this->_name, - 'type' => $this->_type, + 'typeName' => $this->_typeName, 'default' => $this->_default, 'notnull' => $this->_notnull, 'length' => $this->_length, @@ -550,7 +634,8 @@ public function toArray(): array 'columnDefinition' => $this->_columnDefinition, 'comment' => $this->_comment, 'values' => $this->_values, - ], $this->_platformOptions); + // @phpstan-ignore missingType.checkedException + ], $skipType ? [] : ['type' => $this->getType()], $this->_platformOptions); } public static function editor(): ColumnEditor @@ -562,7 +647,7 @@ public function edit(): ColumnEditor { return self::editor() ->setName($this->getObjectName()) - ->setType($this->_type) + ->setTypeName($this->_typeName) ->setLength($this->_length) ->setPrecision($this->_precision) ->setScale($this->_scale) diff --git a/src/Schema/ColumnDiff.php b/src/Schema/ColumnDiff.php index 6c86e92164..6de92a9438 100644 --- a/src/Schema/ColumnDiff.php +++ b/src/Schema/ColumnDiff.php @@ -54,7 +54,7 @@ public function hasNameChanged(): bool public function hasTypeChanged(): bool { - return $this->newColumn->getType()::class !== $this->oldColumn->getType()::class; + return $this->newColumn->getTypeName() !== $this->oldColumn->getTypeName(); } public function hasLengthChanged(): bool diff --git a/src/Schema/ColumnEditor.php b/src/Schema/ColumnEditor.php index 1b2cff2c39..4ed2e77524 100644 --- a/src/Schema/ColumnEditor.php +++ b/src/Schema/ColumnEditor.php @@ -9,12 +9,13 @@ use Doctrine\DBAL\Schema\Name\UnqualifiedName; use Doctrine\DBAL\Types\Exception\TypesException; use Doctrine\DBAL\Types\Type; +use Doctrine\Deprecations\Deprecation; final class ColumnEditor { private ?UnqualifiedName $name = null; - private ?Type $type = null; + private ?string $typeName = null; private ?int $length = null; @@ -84,17 +85,28 @@ public function setQuotedName(string $name): self return $this; } + /** + * @deprecated Use {@link setTypeName()} instead. + * + * @throws TypesException + */ public function setType(Type $type): self { - $this->type = $type; + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/7490', + '%s is deprecated. Use ColumnEditor::setTypeName() instead.', + __METHOD__, + ); + + $this->typeName = Type::getTypeRegistry()->lookupName($type); return $this; } - /** @throws TypesException */ public function setTypeName(string $typeName): self { - $this->type = Type::getType($typeName); + $this->typeName = $typeName; return $this; } @@ -228,13 +240,14 @@ public function setColumnDefinition(?string $columnDefinition): self return $this; } + /** @throws TypesException */ public function create(): Column { if ($this->name === null) { throw InvalidColumnDefinition::nameNotSpecified(); } - if ($this->type === null) { + if ($this->typeName === null) { throw InvalidColumnDefinition::dataTypeNotSpecified($this->name); } @@ -266,7 +279,7 @@ public function create(): Column return new Column( $this->name->toString(), - $this->type, + $this->typeName, [ 'length' => $this->length, 'precision' => $this->precision, diff --git a/src/Schema/DB2SchemaManager.php b/src/Schema/DB2SchemaManager.php index 5f7b29358a..e0ff66e09e 100644 --- a/src/Schema/DB2SchemaManager.php +++ b/src/Schema/DB2SchemaManager.php @@ -6,7 +6,6 @@ use Doctrine\DBAL\Platforms\DB2Platform; use Doctrine\DBAL\Result; -use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use function array_change_key_case; @@ -98,7 +97,7 @@ protected function _getPortableTableColumnDefinition(array $tableColumn): Column $options['precision'] = $precision; } - return new Column($tableColumn['colname'], Type::getType($type), $options); + return new Column($tableColumn['colname'], $type, $options); } /** diff --git a/src/Schema/MySQLSchemaManager.php b/src/Schema/MySQLSchemaManager.php index c8489389ba..f6d7d69fed 100644 --- a/src/Schema/MySQLSchemaManager.php +++ b/src/Schema/MySQLSchemaManager.php @@ -17,7 +17,6 @@ use Doctrine\DBAL\Schema\DefaultExpression\CurrentDate; use Doctrine\DBAL\Schema\DefaultExpression\CurrentTime; use Doctrine\DBAL\Schema\DefaultExpression\CurrentTimestamp; -use Doctrine\DBAL\Types\Type; use function array_change_key_case; use function array_map; @@ -214,7 +213,7 @@ protected function _getPortableTableColumnDefinition(array $tableColumn): Column $options['comment'] = $tableColumn['comment']; } - $column = new Column($tableColumn['field'], Type::getType($type), $options); + $column = new Column($tableColumn['field'], $type, $options); $column->setPlatformOption('charset', $tableColumn['characterset']); $column->setPlatformOption('collation', $tableColumn['collation']); diff --git a/src/Schema/OracleSchemaManager.php b/src/Schema/OracleSchemaManager.php index 47d87400f1..95dc23b41d 100644 --- a/src/Schema/OracleSchemaManager.php +++ b/src/Schema/OracleSchemaManager.php @@ -184,7 +184,7 @@ protected function _getPortableTableColumnDefinition(array $tableColumn): Column $options['comment'] = $tableColumn['comments']; } - return new Column($this->getQuotedIdentifierName($tableColumn['column_name']), Type::getType($type), $options); + return new Column($this->getQuotedIdentifierName($tableColumn['column_name']), $type, $options); } /** diff --git a/src/Schema/PostgreSQLSchemaManager.php b/src/Schema/PostgreSQLSchemaManager.php index 5ce7897f1b..229d61b18c 100644 --- a/src/Schema/PostgreSQLSchemaManager.php +++ b/src/Schema/PostgreSQLSchemaManager.php @@ -285,13 +285,13 @@ protected function _getPortableTableColumnDefinition(array $tableColumn): Column $options['comment'] = $tableColumn['comment']; } - $column = new Column($tableColumn['field'], Type::getType($type), $options); + $column = new Column($tableColumn['field'], $type, $options); if (! empty($tableColumn['collation'])) { $column->setPlatformOption('collation', $tableColumn['collation']); } - if ($column->getType() instanceof JsonType) { + if (Type::getType($column->getTypeName()) instanceof JsonType) { $column->setPlatformOption('jsonb', $jsonb); } diff --git a/src/Schema/SQLServerSchemaManager.php b/src/Schema/SQLServerSchemaManager.php index 86c1c6585b..c561e4bce4 100644 --- a/src/Schema/SQLServerSchemaManager.php +++ b/src/Schema/SQLServerSchemaManager.php @@ -9,7 +9,6 @@ use Doctrine\DBAL\Platforms\SQLServerPlatform; use Doctrine\DBAL\Result; use Doctrine\DBAL\Schema\DefaultExpression\CurrentTimestamp; -use Doctrine\DBAL\Types\Type; use function array_change_key_case; use function assert; @@ -132,7 +131,7 @@ protected function _getPortableTableColumnDefinition(array $tableColumn): Column $options['length'] = $length; } - $column = new Column($tableColumn['name'], Type::getType($type), $options); + $column = new Column($tableColumn['name'], $type, $options); if ($tableColumn['default'] !== null) { $default = $this->parseDefaultExpression($tableColumn['default']); diff --git a/src/Schema/SQLiteSchemaManager.php b/src/Schema/SQLiteSchemaManager.php index 2f6af8f17d..92db79cf4c 100644 --- a/src/Schema/SQLiteSchemaManager.php +++ b/src/Schema/SQLiteSchemaManager.php @@ -127,7 +127,7 @@ protected function _getPortableTableColumnDefinition(array $tableColumn): Column 'scale' => $scale, ]; - $column = new Column($tableColumn['name'], Type::getType($type), $options); + $column = new Column($tableColumn['name'], $type, $options); if ($type === Types::STRING || $type === Types::TEXT) { $column->setPlatformOption('collation', $tableColumn['collation'] ?? 'BINARY'); diff --git a/src/Schema/Table.php b/src/Schema/Table.php index 0464e529cd..1383d78570 100644 --- a/src/Schema/Table.php +++ b/src/Schema/Table.php @@ -465,7 +465,7 @@ public function addColumn(string $name, string $typeName, array $options = []): __METHOD__, ); - $column = new Column($name, Type::getType($typeName), $options); + $column = new Column($name, $typeName, $options); $this->_addColumn($column); diff --git a/tests/Schema/AbstractComparatorTestCase.php b/tests/Schema/AbstractComparatorTestCase.php index 4059b28c87..2cd77a4a3f 100644 --- a/tests/Schema/AbstractComparatorTestCase.php +++ b/tests/Schema/AbstractComparatorTestCase.php @@ -23,7 +23,6 @@ use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Schema\TableDiff; use Doctrine\DBAL\Tests\Functional\Platform\RenameColumnTest; -use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Doctrine\Deprecations\PHPUnit\VerifyDeprecations; use PHPUnit\Framework\Attributes\DataProvider; @@ -215,43 +214,15 @@ public function testCompareChangedColumnsChangeType(): void self::assertFalse($diff11->hasTypeChanged()); } - public function testDifferentTypeInstancesOfTheSameType(): void + public function testSameTypeNameIsNotAChange(): void { - $type1 = Type::getType(Types::INTEGER); - $type2 = clone $type1; - - self::assertNotSame($type1, $type2); - $column1 = Column::editor() ->setUnquotedName('id') - ->setType($type1) - ->create(); - - $column2 = $column1->edit() - ->setType($type2) - ->create(); - - $diff = new ColumnDiff($column2, $column1); - self::assertFalse($diff->hasTypeChanged()); - } - - public function testOverriddenType(): void - { - $defaultStringType = Type::getType(Types::STRING); - $integerType = Type::getType(Types::INTEGER); - - Type::overrideType(Types::STRING, $integerType::class); - $overriddenStringType = Type::getType(Types::STRING); - - Type::overrideType(Types::STRING, $defaultStringType::class); - - $column1 = Column::editor() - ->setUnquotedName('id') - ->setType($integerType) + ->setTypeName(Types::INTEGER) ->create(); $column2 = $column1->edit() - ->setType($overriddenStringType) + ->setTypeName(Types::INTEGER) ->create(); $diff = new ColumnDiff($column2, $column1); diff --git a/tests/Schema/ColumnEditorTest.php b/tests/Schema/ColumnEditorTest.php index e0447cfe66..f91bf117cc 100644 --- a/tests/Schema/ColumnEditorTest.php +++ b/tests/Schema/ColumnEditorTest.php @@ -7,13 +7,15 @@ use Doctrine\DBAL\Schema\Column; use Doctrine\DBAL\Schema\Exception\InvalidColumnDefinition; use Doctrine\DBAL\Schema\Name\UnqualifiedName; -use Doctrine\DBAL\Types\IntegerType; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use Doctrine\Deprecations\PHPUnit\VerifyDeprecations; use PHPUnit\Framework\TestCase; class ColumnEditorTest extends TestCase { + use VerifyDeprecations; + public function testSetUnquotedName(): void { $column = Column::editor() @@ -42,24 +44,28 @@ public function testSetQuotedName(): void public function testSetType(): void { - $type = new IntegerType(); + $type = Type::getType(Types::INTEGER); + + $this->expectDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/7490'); $column = Column::editor() ->setUnquotedName('id') ->setType($type) ->create(); - self::assertSame($type, $column->getType()); + self::assertSame(Types::INTEGER, $column->getTypeName()); } public function testSetTypeName(): void { + $this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/7490'); + $column = Column::editor() ->setUnquotedName('id') ->setTypeName(Types::INTEGER) ->create(); - self::assertEquals(Type::getType(Types::INTEGER), $column->getType()); + self::assertSame(Types::INTEGER, $column->getTypeName()); } public function testSetCollation(): void diff --git a/tests/Schema/ColumnTest.php b/tests/Schema/ColumnTest.php index 3c55f781c4..500c157c51 100644 --- a/tests/Schema/ColumnTest.php +++ b/tests/Schema/ColumnTest.php @@ -12,6 +12,7 @@ use Doctrine\DBAL\Schema\Exception\UnknownColumnOption; use Doctrine\DBAL\Schema\Name\Identifier; use Doctrine\DBAL\Schema\Name\UnqualifiedName; +use Doctrine\DBAL\Types\StringType; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Doctrine\Deprecations\PHPUnit\VerifyDeprecations; @@ -45,11 +46,11 @@ public function testGet(): void self::assertEquals(self::class, $column->getPlatformOption('enumType')); } - public function testToArray(): void + public function testToArrayWithType(): void { $expected = [ 'name' => 'foo', - 'type' => Type::getType(Types::STRING), + 'typeName' => Types::STRING, 'default' => 'baz', 'notnull' => false, 'length' => 200, @@ -61,19 +62,52 @@ public function testToArray(): void 'columnDefinition' => null, 'comment' => '', 'values' => [], + 'type' => Type::getType(Types::STRING), 'charset' => 'utf8', 'enumType' => self::class, ]; + $this->expectDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/7490'); + self::assertSame($expected, $this->createColumn()->toArray()); } + public function testToArray(): void + { + $expected = [ + 'name' => 'foo', + 'typeName' => Types::STRING, + 'default' => 'baz', + 'notnull' => false, + 'length' => 200, + 'precision' => 5, + 'scale' => 2, + 'fixed' => true, + 'unsigned' => true, + 'autoincrement' => false, + 'columnDefinition' => null, + 'comment' => '', + 'values' => [], + 'charset' => 'utf8', + 'enumType' => self::class, + ]; + + $this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/7490'); + + self::assertSame($expected, $this->createColumn()->toArray(true)); + } + public function testSettingUnknownOptionIsStillSupported(): void { + $column = Column::editor() + ->setUnquotedName('foo') + ->setTypeName(Types::STRING) + ->create(); + $this->expectException(UnknownColumnOption::class); $this->expectExceptionMessage('The "unknown_option" column option is not supported.'); - new Column('foo', self::createStub(Type::class), ['unknown_option' => 'bar']); + $column->setOptions(['unknown_option' => 'bar']); } public function testOptionsShouldNotBeIgnored(): void @@ -187,6 +221,31 @@ public function testGetObjectName(): void self::assertEquals(Identifier::unquoted('id'), $column->getObjectName()->getIdentifier()); } + public function testPassingTypeInstanceToConstructorIsDeprecated(): void + { + $this->expectDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/7490'); + + new Column('foo', Type::getType(Types::STRING)); + } + + public function testGetTypeIsDeprecated(): void + { + $column = new Column('foo', Types::STRING); + + $this->expectDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/7490'); + + self::assertInstanceOf(StringType::class, $column->getType()); + } + + public function testGetTypeNameIsNotDeprecated(): void + { + $column = new Column('foo', Types::STRING); + + $this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/7490'); + + self::assertSame(Types::STRING, $column->getTypeName()); + } + public function testSetPlatformOptionJsonb(): void { $column = new Column('jsonb', Type::getType(Types::JSON));