diff --git a/core/cmdbsource.class.inc.php b/core/cmdbsource.class.inc.php index d7a48bf4c..4dcdbec7b 100644 --- a/core/cmdbsource.class.inc.php +++ b/core/cmdbsource.class.inc.php @@ -1181,7 +1181,8 @@ class CMDBSource } /** - * There may have some differences between DB : for example in MySQL 5.7 we have "INT", while in MariaDB >= 10.2 you get "int DEFAULT 'NULL'" + * There may have some differences between DB : for example in MySQL 5.7 we have "INT", while in MariaDB >= 10.2 you get "int DEFAULT + * 'NULL'" * * We still do a case sensitive comparison for enum values ! * @@ -1192,6 +1193,7 @@ class CMDBSource * @param string $sDbFieldType * * @return bool true if same type and options (case sensitive comparison only for type options), false otherwise + * @throws \CoreException * @since 2.7.0 N°2490 */ public static function IsSameFieldTypes($sItopGeneratedFieldType, $sDbFieldType) @@ -1245,18 +1247,55 @@ class CMDBSource * 1. data type : for example 'VARCHAR' * 2. type value : for example '255' * 3. other options : for example ' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 0' + * @throws \CoreException */ private static function GetFieldDataTypeAndOptions($sCompleteFieldType) { preg_match('/^([a-zA-Z]+)(\(([^\)]+)\))?( .+)?/', $sCompleteFieldType, $aMatches); $sDataType = isset($aMatches[1]) ? $aMatches[1] : ''; + + if (strcasecmp($sDataType, 'ENUM') === 0){ + return self::GetEnumOptions($sDataType, $sCompleteFieldType); + } + $sTypeOptions = isset($aMatches[2]) ? $aMatches[3] : ''; $sOtherOptions = isset($aMatches[4]) ? $aMatches[4] : ''; return array($sDataType, $sTypeOptions, $sOtherOptions); } + /** + * @since 2.7.4 N°3065 + * Handle ENUM options + * + * @param $sDataType + * @param $sCompleteFieldType + * Example: ENUM('CSP A','CSP (aaaa) M','NA','OEM(ROC)','OPEN(VL)','RETAIL (Boite)') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci + * + * @return string[] consisting of 3 items : + * 1. data type : ENUM or enum here + * 2. type value : in-between EUM parenthesis + * 3. other options : for example ' CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT 0' + * @throws \CoreException + */ + private static function GetEnumOptions($sDataType, $sCompleteFieldType) + { + $iFirstOpeningParenthesis = strpos($sCompleteFieldType, '('); + $iLastEndingParenthesis = strrpos($sCompleteFieldType, ')'); + + if ($iFirstOpeningParenthesis === false || $iLastEndingParenthesis === false ){ + //should never happen as GetFieldDataTypeAndOptions regexp matched. + //except if regexp is modiied/broken somehow one day... + throw new CoreException("GetEnumOptions issue with $sDataType parsing : " . $sCompleteFieldType); + } + + $sTypeOptions = substr($sCompleteFieldType, $iFirstOpeningParenthesis + 1, $iLastEndingParenthesis - 1); + $sOtherOptions = substr($sCompleteFieldType, $iLastEndingParenthesis + 1); + + return array($sDataType, $sTypeOptions, $sOtherOptions); + } + /** * @param string $sTable * @param string $sField diff --git a/core/metamodel.class.php b/core/metamodel.class.php index bf26e01a5..2dbeed108 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -5545,15 +5545,10 @@ abstract class MetaModel // The field already exists, does it have the relevant properties? // - $bToBeChanged = false; $sActualFieldSpec = CMDBSource::GetFieldSpec($sTable, $sField); if (!CMDBSource::IsSameFieldTypes($sDBFieldSpec, $sActualFieldSpec)) { - $bToBeChanged = true; $aErrors[$sClass][$sAttCode][] = "field '$sField' in table '$sTable' has a wrong type: found $sActualFieldSpec while expecting $sDBFieldSpec"; - } - if ($bToBeChanged) - { $aSugFix[$sClass][$sAttCode][] = "ALTER TABLE `$sTable` CHANGE `$sField` $sFieldDefinition"; $aAlterTableItems[$sTable][$sField] = "CHANGE `$sField` $sFieldDefinition"; } diff --git a/test/core/CMDBSourceTest.php b/test/core/CMDBSourceTest.php index db06932e1..132d71292 100644 --- a/test/core/CMDBSourceTest.php +++ b/test/core/CMDBSourceTest.php @@ -35,7 +35,7 @@ class CMDBSourceTest extends ItopTestCase */ public function testCompareFieldTypes($bResult, $sItopFieldType, $sDbFieldType) { - $this->assertEquals($bResult, CMDBSource::IsSameFieldTypes($sItopFieldType, $sDbFieldType)); + $this->assertEquals($bResult, CMDBSource::IsSameFieldTypes($sItopFieldType, $sDbFieldType), "$sItopFieldType\n VS\n $sDbFieldType"); } public function compareFieldTypesProvider() @@ -106,12 +106,12 @@ class CMDBSourceTest extends ItopTestCase "ENUM('CSP A','CSP M','NA','OEM(ROC)','OPEN(VL)','RETAIL (Boite)') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", "enum('CSP A','CSP M','NA','OEM(ROC)','OPEN(VL)','RETAIL (Boite)') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", ), -//FIXME N°3065 before the fix this returns true :( -// 'ENUM with different values, containing parenthesis' => array( -// false, -// "ENUM('value 1 (with parenthesis)','value 2') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", -// "enum('value 1 (with parenthesis)','value 3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", -// ), + //FIXME N°3065 before the fix this returns true :( + 'ENUM with different values, containing parenthesis' => array( + false, + "ENUM('value 1 (with parenthesis)','value 2') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", + "enum('value 1 (with parenthesis)','value 3') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci", + ), ); } }