Skip to content

Commit

Permalink
[Schema checker] (Database FIX) Add support for checking NULL and DEF…
Browse files Browse the repository at this point in the history
…AULT column attributes (#17351)

* [Schema checker] (Database FIX) Add support for checking NULL and DEFAULT column attributes

* CS

* Update en-GB.com_installer.ini

* english
  • Loading branch information
ggppdk authored and Michael Babker committed Feb 26, 2018
1 parent 5ce95a7 commit a6f9021
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 4 deletions.
2 changes: 1 addition & 1 deletion administrator/language/en-GB/en-GB.com_installer.ini
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ COM_INSTALLER_MINIMUM_STABILITY_RC="Release Candidate"
COM_INSTALLER_MSG_DATABASE="This screen allows to you check that your database table structure is up to date with changes from the previous versions."
COM_INSTALLER_MSG_DATABASE_ADD_COLUMN="Table %2$s does not have column %3$s. (From file %1$s.)"
COM_INSTALLER_MSG_DATABASE_ADD_INDEX="Table %2$s does not have index %3$s. (From file %1$s.)"
COM_INSTALLER_MSG_DATABASE_CHANGE_COLUMN_TYPE="Table %2$s does not have column %3$s with type %4$s. (From file %1$s.)"
COM_INSTALLER_MSG_DATABASE_CHANGE_COLUMN_TYPE="Table %2$s has the wrong type or attributes for column %3$s with type %4$s. (From file %1$s.)"
COM_INSTALLER_MSG_DATABASE_CHECKED_OK="%s database changes were checked."
COM_INSTALLER_MSG_DATABASE_CREATE_TABLE="Table %2$s does not exist. (From file %1$s.)"
COM_INSTALLER_MSG_DATABASE_DRIVER="Database driver: %s."
Expand Down
88 changes: 85 additions & 3 deletions libraries/src/Schema/ChangeItem/MysqlChangeItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ protected function buildCheckQuery()
$find = array('#((\s*)\(\s*([^)\s]+)\s*)(\))#', '#(\s)(\s*)#');
$replace = array('($3)', '$1');
$updateQuery = preg_replace($find, $replace, $this->updateQuery);
$wordArray = explode(' ', $updateQuery);
$wordArray = preg_split("~'[^']*'(*SKIP)(*F)|\s+~u", trim($updateQuery, "; \t\n\r\0\x0B"));

// First, make sure we have an array of at least 6 elements
// if not, we can't make a check query for this one
Expand Down Expand Up @@ -153,14 +153,21 @@ protected function buildCheckQuery()
$type = $this->fixInteger($wordArray[5], $wordArray[6]);
}

// Detect changes in NULL and in DEFAULT column attributes
$changesArray = array_slice($wordArray, 6);
$defaultCheck = $this->checkDefault($changesArray, $type);
$nullCheck = $this->checkNull($changesArray);

/**
* When we made the UTF8MB4 conversion then text becomes medium text - so loosen the checks to these two types
* otherwise (for example) the profile fields profile_value check fails - see https://github.com/joomla/joomla-cms/issues/9258
*/
$typeCheck = $this->fixUtf8mb4TypeChecks($type);

$result = 'SHOW COLUMNS IN ' . $wordArray[2] . ' WHERE field = ' . $this->fixQuote($wordArray[4])
. ' AND ' . $typeCheck;
. ' AND ' . $typeCheck
. ($defaultCheck ? ' AND ' . $defaultCheck : '')
. ($nullCheck ? ' AND ' . $nullCheck : '');
$this->queryType = 'CHANGE_COLUMN_TYPE';
$this->msgElements = array($this->fixQuote($wordArray[2]), $this->fixQuote($wordArray[4]), $type);
}
Expand All @@ -173,6 +180,11 @@ protected function buildCheckQuery()
{
$type = $this->fixInteger($wordArray[6], $wordArray[7]);
}

// Detect changes in NULL and in DEFAULT column attributes
$changesArray = array_slice($wordArray, 6);
$defaultCheck = $this->checkDefault($changesArray, $type);
$nullCheck = $this->checkNull($changesArray);

/**
* When we made the UTF8MB4 conversion then text becomes medium text - so loosen the checks to these two types
Expand All @@ -181,7 +193,9 @@ protected function buildCheckQuery()
$typeCheck = $this->fixUtf8mb4TypeChecks($type);

$result = 'SHOW COLUMNS IN ' . $wordArray[2] . ' WHERE field = ' . $this->fixQuote($wordArray[5])
. ' AND ' . $typeCheck;
. ' AND ' . $typeCheck
. ($defaultCheck ? ' AND ' . $defaultCheck : '')
. ($nullCheck ? ' AND ' . $nullCheck : '');
$this->queryType = 'CHANGE_COLUMN_TYPE';
$this->msgElements = array($this->fixQuote($wordArray[2]), $this->fixQuote($wordArray[5]), $type);
}
Expand Down Expand Up @@ -307,4 +321,72 @@ private function fixUtf8mb4TypeChecks($type)

return $typeCheck;
}

/**
* Create query clause for column changes/modifications for NULL attribute
*
* @param array $changesArray The array of words after COLUMN name
*
* @return string The query clause for NULL check in the check query
*
* @since __DEPLOY_VERSION__
*/
private function checkNull($changesArray)
{
// Find NULL keyword
$index = array_search('null', array_map('strtolower', $changesArray));

// Create the check
if ($index !== false)
{
if ($index == 0 || strtolower($changesArray[$index - 1]) !== 'not')
{
return ' `null` = ' . $this->db->quote('YES');
}
else
{
return ' `null` = ' . $this->db->quote('NO');
}
}

return false;
}

/**
* Create query clause for column changes/modifications for DEFAULT attribute
*
* @param array $changesArray The array of words after COLUMN name
* @param string $type The type of the COLUMN
*
* @return string The query clause for DEFAULT check in the check query
*
* @since __DEPLOY_VERSION__
*/
private function checkDefault($changesArray, $type)
{
// Skip types that do not support default values
$type = strtolower($type);
if (substr($type, -4) === 'text' || substr($type, -4) === 'blob')
{
return false;
}

// Find DEFAULT keyword
$index = array_search('default', array_map('strtolower', $changesArray));

// Create the check
if ($index !== false)
{
if (strtolower($changesArray[$index + 1]) === 'null')
{
return ' `default` IS NULL';
}
else
{
return ' `default` = ' . $changesArray[$index + 1];
}
}

return false;
}
}

0 comments on commit a6f9021

Please sign in to comment.