Bug #103666
closedChanging database schema of existing columns in ext_tables.sql fails in 13.0
100%
Description
In previous versions it has been possible to override columns in ext_tables.sql in order to change the field type or length. This breaks in TYPO3 13.0. I'm not entirely sure if this is a deliberate decision or a bug. However, although discouraged, it's still documented and there is no other way to achive the same result. It seems to me that this is still intended to work.
To reproduce, create an extension that modifies the structure of an existing table column from the core - e.g. in "tt_content" ...
-- ext_tables.sql
CREATE TABLE tt_content (
frame_class VARCHAR(255)
);
... which should change the default length of tt_content.frame_class from 60 to 255 bytes when running the database analyzer.
In v13 this fails. Trying to update the database structure reults in the following exception:
Doctrine\DBAL\Schema\Exception\ColumnAlreadyExists The column "frame_class" on table "tt_content" already exists.
This happens because of a breaking change that has been introduced in doctrine/dbal 4.0: Doctrine\DBAL\Schema\Table::getColumns() no longer returns an associative array.
However in the current main, TYPO3\CMS\Core\Database\Schema\SchemaMigrator::mergeTableDefinitions still tries to use array_merge() to override table columns, which results in merging two arrays with numeric index, no longer overriding columns but appending them to the returned array:
$return[$tableName] = new Table(
$tableName,
array_merge($currentTableDefinition->getColumns(), $table->getColumns()),
array_merge($currentTableDefinition->getIndexes(), $table->getIndexes()),
[],
array_merge($currentTableDefinition->getForeignKeys(), $table->getForeignKeys()),
array_merge($currentTableDefinition->getOptions(), $table->getOptions())
);
Changing it into something like this fixes the problem at first glance. I guess the same problem exists for indexes and keys but I haven't checked.
// merge by name ($table->getColumns() does no longer return an associative array
// so we cannot use array_merge if we want to overwrite values)
$columns = [];
foreach ($currentTableDefinition->getColumns() as $column) {
$columns[$column->getName()] = $column;
}
foreach ($table->getColumns() as $column) {
$columns[$column->getName()] = $column;
}
$return[$tableName] = new Table(
$tableName,
$columns,
array_merge($currentTableDefinition->getIndexes(), $table->getIndexes()),
[],
array_merge($currentTableDefinition->getForeignKeys(), $table->getForeignKeys()),
array_merge($currentTableDefinition->getOptions(), $table->getOptions())
);
Updated by Stefan Bürk 13 days ago
- Related to Task #103015: Move table definition merge SchemaMigrator added
- Related to Task #102875: Require doctrine/dbal 4.x added
Updated by Gerrit Code Review 13 days ago
- Status changed from Accepted to Under Review
Patch set 1 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/83934
Updated by Gerrit Code Review 13 days ago
Patch set 2 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/83934
Updated by Stefan Bürk 13 days ago
- Status changed from Under Review to Resolved
- % Done changed from 0 to 100
Applied in changeset 7da78595bbdc785fb9c4657c2914da80e0ee6bef.