From ea7a8888e9c0a1f889f111e5928d66fb2e83cd86 Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Fri, 9 Jan 2015 10:01:24 +0000 Subject: [PATCH] Partial retrofit of [3438]: fixes the helper RenameEnumValueInDB which did work only IF the values differ in case (ex. IpPhone to IPPhone) SVN:2.0.3[3488] --- setup/moduleinstaller.class.inc.php | 98 +++++++++++++++++++---------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/setup/moduleinstaller.class.inc.php b/setup/moduleinstaller.class.inc.php index b18f7937b..adf3445db 100644 --- a/setup/moduleinstaller.class.inc.php +++ b/setup/moduleinstaller.class.inc.php @@ -91,6 +91,7 @@ abstract class ModuleInstallerAPI * Helper to modify an enum value * The change is made in the datamodel definition, but the value has to be changed in the DB as well * Must be called BEFORE DB update, i.e within an implementation of BeforeDatabaseCreation() + * This helper does change ONE value at a time * * @param string $sClass A valid class name * @param string $sAttCode The enum attribute code @@ -112,42 +113,73 @@ abstract class ModuleInstallerAPI $aNewValues = array_keys($oValDef->GetValues(array(), "")); if (in_array($sTo, $aNewValues)) { - $aAllValues = $aNewValues; - $aAllValues[] = $sFrom; + $sEnumCol = $oAttDef->Get("sql"); + $aFields = CMDBSource::QueryToArray("SHOW COLUMNS FROM `$sTableName` WHERE Field = '$sEnumCol'"); + if (isset($aFields[0]['Type'])) + { + $sColType = $aFields[0]['Type']; + // Note: the parsing should rely on str_getcsv (requires PHP 5.3) to cope with escaped string + if (preg_match("/^enum\(\'(.*)\'\)$/", $sColType, $aMatches)) + { + $aCurrentValues = explode("','", $aMatches[1]); + } + } if (!in_array($sFrom, $aNewValues)) { - $sEnumCol = $oAttDef->Get("sql"); - $sNullSpec = $oAttDef->IsNullAllowed() ? 'NULL' : 'NOT NULL'; - - if (strtolower($sTo) == strtolower($sFrom)) + if (!in_array($sTo, $aCurrentValues)) // if not already transformed! { - SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo' (just a change in the case)"); - $sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aNewValues)).") $sNullSpec"; - $sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition"; - CMDBSource::Query($sRepair); - } - else - { - // 1st - Allow both values in the column definition - // - SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo'"); - $sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aAllValues)).") $sNullSpec"; - $sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition"; - CMDBSource::Query($sRepair); - - // 2nd - Change the old value into the new value - // - $sRepair = "UPDATE `$sTableName` SET `$sEnumCol` = '$sTo' WHERE `$sEnumCol` = BINARY '$sFrom'"; - CMDBSource::Query($sRepair); - $iAffectedRows = CMDBSource::AffectedRows(); - SetupPage::log_info("Changing enum in DB - $iAffectedRows rows updated"); - - // 3rd - Remove the useless value from the column definition - // - $sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aNewValues)).") $sNullSpec"; - $sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition"; - CMDBSource::Query($sRepair); - SetupPage::log_info("Changing enum in DB - removed useless value '$sFrom'"); + $sNullSpec = $oAttDef->IsNullAllowed() ? 'NULL' : 'NOT NULL'; + + if (strtolower($sTo) == strtolower($sFrom)) + { + SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo' (just a change in the case)"); + $aTargetValues = array(); + foreach ($aCurrentValues as $sValue) + { + if ($sValue == $sFrom) + { + $sValue = $sTo; + } + $aTargetValues[] = $sValue; + } + $sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aTargetValues)).") $sNullSpec"; + $sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition"; + CMDBSource::Query($sRepair); + } + else + { + // 1st - Allow both values in the column definition + // + SetupPage::log_info("Changing enum in DB - $sClass::$sAttCode from '$sFrom' to '$sTo'"); + $aAllValues = $aCurrentValues; + $aAllValues[] = $sTo; + $sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aAllValues)).") $sNullSpec"; + $sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition"; + CMDBSource::Query($sRepair); + + // 2nd - Change the old value into the new value + // + $sRepair = "UPDATE `$sTableName` SET `$sEnumCol` = '$sTo' WHERE `$sEnumCol` = BINARY '$sFrom'"; + CMDBSource::Query($sRepair); + $iAffectedRows = CMDBSource::AffectedRows(); + SetupPage::log_info("Changing enum in DB - $iAffectedRows rows updated"); + + // 3rd - Remove the useless value from the column definition + // + $aTargetValues = array(); + foreach ($aCurrentValues as $sValue) + { + if ($sValue == $sFrom) + { + $sValue = $sTo; + } + $aTargetValues[] = $sValue; + } + $sColumnDefinition = "ENUM(".implode(",", CMDBSource::Quote($aTargetValues)).") $sNullSpec"; + $sRepair = "ALTER TABLE `$sTableName` MODIFY `$sEnumCol` $sColumnDefinition"; + CMDBSource::Query($sRepair); + SetupPage::log_info("Changing enum in DB - removed useless value '$sFrom'"); + } } } else