Project

General

Profile

Bug #103666

Updated by Thomas Prangenberg 29 days ago

In previous versions TYPO3 v12 it has been was 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 result and it seems to me that this is it's 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" ... 

 <pre><code class="sql"> 
 -- ext_tables.sql 
 CREATE TABLE tt_content    ( 
   frame_class VARCHAR(255) 
 ); 
 </code></pre> 

 ... 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: 

 <pre> 
 Doctrine\DBAL\Schema\Exception\ColumnAlreadyExists 
 The column "frame_class" on table "tt_content" already exists. 
 </pre> 

 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 resulting array: 

 <pre><code class="php"> 
             $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()) 
             ); 
 </code></pre> 


 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. 

 <pre><code class="php"> 
             // 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()) 
             ); 
 </code></pre> 

Back