Index: t3lib/class.t3lib_install.php =================================================================== --- t3lib/class.t3lib_install.php (Revision 4433) +++ t3lib/class.t3lib_install.php (Arbeitskopie) @@ -366,7 +366,14 @@ $newParts = explode(' ',$parts[1],2); $key = $parts[0]=='PRIMARY' ? $parts[0] : $newParts[0]; + $total[$table]['keys'][$key] = $lineV; + + // This is a protection against doing something stupid: Only allow clearing of cache_* and index_* tables. + if (preg_match('/^(cache|index)_/',$table)) { + // Suggest to truncate (clear) this table + $total[$table]['extra']['CLEAR'] = 1; + } } } } @@ -426,7 +433,7 @@ } $keys[] = $kfN; } - $total[$table]['keys'][$kN] = $match[1].'('.join(',',$keys).')'.$match[3]; + $total[$table]['keys'][$kN] = $match[1].'('.implode(',',$keys).')'.$match[3]; } } } @@ -623,6 +630,18 @@ if ($info['whole_table']) { $whole_table[]=$fN.' '.$fV; } else { + // Special case to work around MySQL problems when adding auto_increment fields: + if (stristr($fV, 'auto_increment')) { + // The field can only be set "auto_increment" if there exists a PRIMARY key of that field already. + // The check does not look up which field is primary but just assumes it must be the field with the auto_increment value... + if (isset($diffArr['extra'][$table]['keys']['PRIMARY'])) { + // Remove "auto_increment" from the statement - it will be suggested in a 2nd step after the primary key was created + $fV = str_replace(' auto_increment', '', $fV); + } else { + // In the next step, attempt to clear the table once again (2 = force) + $info['extra']['CLEAR'] = 2; + } + } if ($theKey=='extra') { if ($remove) { if (substr($fN,0,strlen($deletedPrefixKey))!=$deletedPrefixKey) { @@ -669,16 +688,31 @@ if (is_array($info['extra'])) { $extras = array(); $extras_currentValue = array(); + $clear_table = false; + foreach ($info['extra'] as $fN => $fV) { // Only consider statements which are missing in the database but don't remove existing properties if (!$remove) { if (!$info['whole_table']) { // If the whole table is created at once, we take care of this later by imploding all elements of $info['extra'] - $extras[] = $fN.'='.$fV; - $extras_currentValue[] = $fN.'='.$diffArr['diff_currentValues'][$table]['extra'][$fN]; + if ($fN=='CLEAR') { + // Truncate table must happen later, not now + // Valid values for CLEAR: 1=only clear if keys are missing, 2=clear anyway (force) + if (count($info['keys']) || $fV==2) { + $clear_table = true; + } + continue; + } else { + $extras[] = $fN.'='.$fV; + $extras_currentValue[] = $fN.'='.$diffArr['diff_currentValues'][$table]['extra'][$fN]; + } } } } + if ($clear_table) { + $statement = 'TRUNCATE TABLE '.$table.';'; + $statements['clear_table'][md5($statement)] = $statement; + } if (count($extras)) { $statement = 'ALTER TABLE '.$table.' '.implode(' ',$extras).';'; $statements['change'][md5($statement)] = $statement; @@ -702,8 +736,8 @@ $statement = 'CREATE TABLE '.$table." (\n".implode(",\n",$whole_table)."\n)"; if ($info['extra']) { foreach ($info['extra'] as $k=>$v) { - if ($k=='COLLATE') { - continue; // TODO: collation support is currently disabled (needs more testing) + if ($k=='COLLATE' || $k=='CLEAR') { + continue; // Skip these special statements. TODO: collation support is currently disabled (needs more testing) } $statement.= ' '.$k.'='.$v; // Add extra attributes like ENGINE, CHARSET, etc. } @@ -903,14 +937,17 @@ if (is_array($arr)) { foreach($arr as $key => $string) { $ico = ''; + $warnings = array(); + if ($iconDis) { - if (stristr($string,' user_')) { + if (preg_match('/^TRUNCATE/i',$string)) { + $ico.= ' '; + $warnings['clear_table_info'] = 'Clearing the table is sometimes neccessary when adding new keys. In case of cache_* tables this should not hurt at all. However, use it with care.'; + } elseif (stristr($string,' user_')) { $ico.= '(USER) '; - } - if (stristr($string,' app_')) { + } elseif (stristr($string,' app_')) { $ico.= '(APP) '; - } - if (stristr($string,' ttx_') || stristr($string,' tx_')) { + } elseif (stristr($string,' ttx_') || stristr($string,' tx_')) { $ico.= '(EXT) '; } } @@ -927,6 +964,13 @@ '; } } + if (count($warnings)) { + $out[] = ' + + + ' . implode('
',$warnings) . '
+ '; + } // Compile rows: $content = ' Index: typo3/sysext/install/mod/class.tx_install.php =================================================================== --- typo3/sysext/install/mod/class.tx_install.php (Revision 4433) +++ typo3/sysext/install/mod/class.tx_install.php (Arbeitskopie) @@ -3487,6 +3487,8 @@ $diff = $this->getDatabaseExtra($FDdb, $FDfile); $remove_statements = $this->getUpdateSuggestions($diff,'remove'); + $this->performUpdateQueries($update_statements['clear_table'],$this->INSTALL['database_update']); + $this->performUpdateQueries($update_statements['add'],$this->INSTALL['database_update']); $this->performUpdateQueries($update_statements['change'],$this->INSTALL['database_update']); $this->performUpdateQueries($remove_statements['change'],$this->INSTALL['database_update']); @@ -4162,16 +4164,18 @@ $content = ''; switch($type) { case 'get_form': - $content=''; - $content.=$this->generateUpdateDatabaseForm_checkboxes($arr_update['add'],'Add fields'); - $content.=$this->generateUpdateDatabaseForm_checkboxes($arr_update['change'],'Changing fields',(t3lib_extMgm::isLoaded('dbal')?0:1),0,$arr_update['change_currentValue']); - $content.=$this->generateUpdateDatabaseForm_checkboxes($arr_remove['change'],'Remove unused fields (rename with prefix)',$this->setAllCheckBoxesByDefault,1); - $content.=$this->generateUpdateDatabaseForm_checkboxes($arr_remove['drop'],'Drop fields (really!)',$this->setAllCheckBoxesByDefault); + $content = ''; + $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_update['clear_table'],'Clear tables (use with care!)',false,true); - $content.=$this->generateUpdateDatabaseForm_checkboxes($arr_update['create_table'],'Add tables'); - $content.=$this->generateUpdateDatabaseForm_checkboxes($arr_remove['change_table'],'Removing tables (rename with prefix)',$this->setAllCheckBoxesByDefault,1,$arr_remove['tables_count'],1); - $content.=$this->generateUpdateDatabaseForm_checkboxes($arr_remove['drop_table'],'Drop tables (really!)',$this->setAllCheckBoxesByDefault,0,$arr_remove['tables_count'],1); + $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_update['add'],'Add fields'); + $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_update['change'],'Changing fields',(t3lib_extMgm::isLoaded('dbal')?0:1),0,$arr_update['change_currentValue']); + $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_remove['change'],'Remove unused fields (rename with prefix)',$this->setAllCheckBoxesByDefault,1); + $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_remove['drop'],'Drop fields (really!)',$this->setAllCheckBoxesByDefault); + $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_update['create_table'],'Add tables'); + $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_remove['change_table'],'Removing tables (rename with prefix)',$this->setAllCheckBoxesByDefault,1,$arr_remove['tables_count'],1); + $content.= $this->generateUpdateDatabaseForm_checkboxes($arr_remove['drop_table'],'Drop tables (really!)',$this->setAllCheckBoxesByDefault,0,$arr_remove['tables_count'],1); + $content = $this->getUpdateDbFormWrap($action_type, $content); break; default: