forked from joomla/super-powers
Update 2024-09-28 01:27:31
This commit is contained in:
parent
d2d0222c5a
commit
a980aa9f81
@ -579,41 +579,57 @@ abstract class Schema implements SchemaInterface
|
|||||||
*/
|
*/
|
||||||
protected function isDataTypeChangeSignificant(string $currentType, string $expectedType): bool
|
protected function isDataTypeChangeSignificant(string $currentType, string $expectedType): bool
|
||||||
{
|
{
|
||||||
// Normalize both input types to lowercase for case-insensitive comparison
|
// Normalize both input types to lowercase and remove extra spaces for comparison
|
||||||
$currentType = strtolower($currentType);
|
$currentType = strtolower(trim($currentType));
|
||||||
$expectedType = strtolower($expectedType);
|
$expectedType = strtolower(trim($expectedType));
|
||||||
|
|
||||||
// Regex to extract the base data type and numeric parameters with named groups
|
// Regex to extract the base data type and numeric parameters (size and precision) with named groups
|
||||||
$typePattern = '/^(?<datatype>\w+)(\((?<params>\d+(,\d+)?)\))?/';
|
$typePattern = '/^(?<datatype>\w+)(\((?<params>\s*\d+\s*(,\s*\d+\s*)?)\))?/';
|
||||||
|
|
||||||
// Match types and parameters
|
// Match types and parameters
|
||||||
preg_match($typePattern, $currentType, $currentMatches);
|
preg_match($typePattern, $currentType, $currentMatches);
|
||||||
preg_match($typePattern, $expectedType, $expectedMatches);
|
preg_match($typePattern, $expectedType, $expectedMatches);
|
||||||
|
|
||||||
// Compare base types
|
// Compare base types (datatype without size/precision)
|
||||||
if ($currentMatches['datatype'] !== $expectedMatches['datatype'])
|
if ($currentMatches['datatype'] !== $expectedMatches['datatype'])
|
||||||
{
|
{
|
||||||
return true; // Base types differ
|
return true; // Base types differ
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define types where size and other modifiers are irrelevant
|
// Define numeric types where display width is irrelevant but precision (for DECIMAL) matters
|
||||||
$sizeIrrelevantTypes = [
|
$sizeIrrelevantTypes = [
|
||||||
'int', 'tinyint', 'smallint', 'mediumint', 'bigint',
|
'int', 'tinyint', 'smallint', 'mediumint', 'bigint',
|
||||||
'float', 'double', 'decimal', 'numeric' // Numeric types where display width is irrelevant
|
'float', 'double' // Numeric types where display width is irrelevant
|
||||||
];
|
];
|
||||||
|
|
||||||
// If the type is not in the size irrelevant list, compare full definitions
|
// Handle DECIMAL and NUMERIC types explicitly (precision and scale are relevant)
|
||||||
if (!in_array($currentMatches['datatype'], $sizeIrrelevantTypes))
|
if (in_array($currentMatches['datatype'], ['decimal', 'numeric']))
|
||||||
{
|
{
|
||||||
return $currentType !== $expectedType; // Use full definition for types where size matters
|
// Extract precision and scale (if present)
|
||||||
|
if ($currentMatches['params'] !== $expectedMatches['params'])
|
||||||
|
{
|
||||||
|
return true; // Precision or scale has changed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For size irrelevant types, only compare base type, ignoring size and unsigned
|
// Check if the type is in the list of size-irrelevant types
|
||||||
$currentBaseType = preg_replace('/\(\d+(,\d+)?\)|unsigned/', '', $currentType);
|
if (in_array($currentMatches['datatype'], $sizeIrrelevantTypes))
|
||||||
$expectedBaseType = preg_replace('/\(\d+(,\d+)?\)|unsigned/', '', $expectedType);
|
{
|
||||||
|
// Remove irrelevant parts like display width and "unsigned" for size-irrelevant types, including extra spaces
|
||||||
|
$currentBaseType = preg_replace('/\s*\(\s*\d+(\s*,\s*\d+)?\s*\)\s*|\s*unsigned\s*/', '', $currentType);
|
||||||
|
$expectedBaseType = preg_replace('/\s*\(\s*\d+(\s*,\s*\d+)?\s*\)\s*|\s*unsigned\s*/', '', $expectedType);
|
||||||
|
|
||||||
// Perform a final comparison for numeric types ignoring size
|
// Compare base types after normalization
|
||||||
return $currentBaseType !== $expectedBaseType;
|
return $currentBaseType !== $expectedBaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For types where size is relevant (e.g., VARCHAR, CHAR, etc.), compare the full definitions
|
||||||
|
// Normalize size parameters by removing extra spaces around commas, e.g., "decimal(5 , 2)" -> "decimal(5,2)"
|
||||||
|
$normalizedCurrentType = preg_replace('/\s*,\s*/', ',', $currentType);
|
||||||
|
$normalizedExpectedType = preg_replace('/\s*,\s*/', ',', $expectedType);
|
||||||
|
|
||||||
|
// Perform a full comparison for types where size matters
|
||||||
|
return $normalizedCurrentType !== $normalizedExpectedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -624,7 +640,7 @@ abstract class Schema implements SchemaInterface
|
|||||||
* @param mixed $currentDefault Current default value.
|
* @param mixed $currentDefault Current default value.
|
||||||
* @param mixed $newDefault The new default value to be set.
|
* @param mixed $newDefault The new default value to be set.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return bool True if update was successful, false if no update was needed.
|
||||||
* @since 3.2.1
|
* @since 3.2.1
|
||||||
* @throws \Exception If there is an error updating column defaults.
|
* @throws \Exception If there is an error updating column defaults.
|
||||||
*/
|
*/
|
||||||
@ -640,13 +656,38 @@ abstract class Schema implements SchemaInterface
|
|||||||
$updateTable = 'UPDATE ' . $this->db->quoteName($this->getTable($table));
|
$updateTable = 'UPDATE ' . $this->db->quoteName($this->getTable($table));
|
||||||
$dbField = $this->db->quoteName($column);
|
$dbField = $this->db->quoteName($column);
|
||||||
|
|
||||||
// Update SQL to set new default on existing rows where the default is currently the old default
|
if (isset($this->columns[$column]))
|
||||||
$sql = $updateTable . " SET $dbField = $sqlDefault WHERE $dbField IS NULL OR $dbField = ''";
|
{
|
||||||
|
$fieldType = strtoupper($this->columns[$column]->Type);
|
||||||
|
|
||||||
// Execute the update
|
// If the field is numeric, avoid comparing with empty string
|
||||||
$this->db->setQuery($sql);
|
if (strpos($fieldType, 'INT') !== false ||
|
||||||
return $this->db->execute();
|
strpos($fieldType, 'FLOAT') !== false ||
|
||||||
} catch (\Exception $e) {
|
strpos($fieldType, 'DOUBLE') !== false ||
|
||||||
|
strpos($fieldType, 'DECIMAL') !== false)
|
||||||
|
{
|
||||||
|
$whereCondition = "$dbField IS NULL OR $dbField = 0";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Default condition for non-numeric fields
|
||||||
|
$whereCondition = "$dbField IS NULL OR $dbField = ''";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update SQL to set new default on existing rows where the default is currently the old default
|
||||||
|
$sql = $updateTable . " SET $dbField = $sqlDefault WHERE $whereCondition";
|
||||||
|
|
||||||
|
// Execute the update
|
||||||
|
$this->db->setQuery($sql);
|
||||||
|
return $this->db->execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new \Exception("Error: Column $column does not exist in table $table.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e)
|
||||||
|
{
|
||||||
throw new \Exception("Error: failed to update ($column) column defaults in $table table. " . $e->getMessage());
|
throw new \Exception("Error: failed to update ($column) column defaults in $table table. " . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -552,41 +552,57 @@
|
|||||||
*/
|
*/
|
||||||
protected function isDataTypeChangeSignificant(string $currentType, string $expectedType): bool
|
protected function isDataTypeChangeSignificant(string $currentType, string $expectedType): bool
|
||||||
{
|
{
|
||||||
// Normalize both input types to lowercase for case-insensitive comparison
|
// Normalize both input types to lowercase and remove extra spaces for comparison
|
||||||
$currentType = strtolower($currentType);
|
$currentType = strtolower(trim($currentType));
|
||||||
$expectedType = strtolower($expectedType);
|
$expectedType = strtolower(trim($expectedType));
|
||||||
|
|
||||||
// Regex to extract the base data type and numeric parameters with named groups
|
// Regex to extract the base data type and numeric parameters (size and precision) with named groups
|
||||||
$typePattern = '/^(?<datatype>\w+)(\((?<params>\d+(,\d+)?)\))?/';
|
$typePattern = '/^(?<datatype>\w+)(\((?<params>\s*\d+\s*(,\s*\d+\s*)?)\))?/';
|
||||||
|
|
||||||
// Match types and parameters
|
// Match types and parameters
|
||||||
preg_match($typePattern, $currentType, $currentMatches);
|
preg_match($typePattern, $currentType, $currentMatches);
|
||||||
preg_match($typePattern, $expectedType, $expectedMatches);
|
preg_match($typePattern, $expectedType, $expectedMatches);
|
||||||
|
|
||||||
// Compare base types
|
// Compare base types (datatype without size/precision)
|
||||||
if ($currentMatches['datatype'] !== $expectedMatches['datatype'])
|
if ($currentMatches['datatype'] !== $expectedMatches['datatype'])
|
||||||
{
|
{
|
||||||
return true; // Base types differ
|
return true; // Base types differ
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define types where size and other modifiers are irrelevant
|
// Define numeric types where display width is irrelevant but precision (for DECIMAL) matters
|
||||||
$sizeIrrelevantTypes = [
|
$sizeIrrelevantTypes = [
|
||||||
'int', 'tinyint', 'smallint', 'mediumint', 'bigint',
|
'int', 'tinyint', 'smallint', 'mediumint', 'bigint',
|
||||||
'float', 'double', 'decimal', 'numeric' // Numeric types where display width is irrelevant
|
'float', 'double' // Numeric types where display width is irrelevant
|
||||||
];
|
];
|
||||||
|
|
||||||
// If the type is not in the size irrelevant list, compare full definitions
|
// Handle DECIMAL and NUMERIC types explicitly (precision and scale are relevant)
|
||||||
if (!in_array($currentMatches['datatype'], $sizeIrrelevantTypes))
|
if (in_array($currentMatches['datatype'], ['decimal', 'numeric']))
|
||||||
{
|
{
|
||||||
return $currentType !== $expectedType; // Use full definition for types where size matters
|
// Extract precision and scale (if present)
|
||||||
|
if ($currentMatches['params'] !== $expectedMatches['params'])
|
||||||
|
{
|
||||||
|
return true; // Precision or scale has changed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For size irrelevant types, only compare base type, ignoring size and unsigned
|
// Check if the type is in the list of size-irrelevant types
|
||||||
$currentBaseType = preg_replace('/\(\d+(,\d+)?\)|unsigned/', '', $currentType);
|
if (in_array($currentMatches['datatype'], $sizeIrrelevantTypes))
|
||||||
$expectedBaseType = preg_replace('/\(\d+(,\d+)?\)|unsigned/', '', $expectedType);
|
{
|
||||||
|
// Remove irrelevant parts like display width and "unsigned" for size-irrelevant types, including extra spaces
|
||||||
|
$currentBaseType = preg_replace('/\s*\(\s*\d+(\s*,\s*\d+)?\s*\)\s*|\s*unsigned\s*/', '', $currentType);
|
||||||
|
$expectedBaseType = preg_replace('/\s*\(\s*\d+(\s*,\s*\d+)?\s*\)\s*|\s*unsigned\s*/', '', $expectedType);
|
||||||
|
|
||||||
// Perform a final comparison for numeric types ignoring size
|
// Compare base types after normalization
|
||||||
return $currentBaseType !== $expectedBaseType;
|
return $currentBaseType !== $expectedBaseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For types where size is relevant (e.g., VARCHAR, CHAR, etc.), compare the full definitions
|
||||||
|
// Normalize size parameters by removing extra spaces around commas, e.g., "decimal(5 , 2)" -> "decimal(5,2)"
|
||||||
|
$normalizedCurrentType = preg_replace('/\s*,\s*/', ',', $currentType);
|
||||||
|
$normalizedExpectedType = preg_replace('/\s*,\s*/', ',', $expectedType);
|
||||||
|
|
||||||
|
// Perform a full comparison for types where size matters
|
||||||
|
return $normalizedCurrentType !== $normalizedExpectedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -597,7 +613,7 @@
|
|||||||
* @param mixed $currentDefault Current default value.
|
* @param mixed $currentDefault Current default value.
|
||||||
* @param mixed $newDefault The new default value to be set.
|
* @param mixed $newDefault The new default value to be set.
|
||||||
*
|
*
|
||||||
* @return void
|
* @return bool True if update was successful, false if no update was needed.
|
||||||
* @since 3.2.1
|
* @since 3.2.1
|
||||||
* @throws \Exception If there is an error updating column defaults.
|
* @throws \Exception If there is an error updating column defaults.
|
||||||
*/
|
*/
|
||||||
@ -613,13 +629,38 @@
|
|||||||
$updateTable = 'UPDATE ' . $this->db->quoteName($this->getTable($table));
|
$updateTable = 'UPDATE ' . $this->db->quoteName($this->getTable($table));
|
||||||
$dbField = $this->db->quoteName($column);
|
$dbField = $this->db->quoteName($column);
|
||||||
|
|
||||||
// Update SQL to set new default on existing rows where the default is currently the old default
|
if (isset($this->columns[$column]))
|
||||||
$sql = $updateTable . " SET $dbField = $sqlDefault WHERE $dbField IS NULL OR $dbField = ''";
|
{
|
||||||
|
$fieldType = strtoupper($this->columns[$column]->Type);
|
||||||
|
|
||||||
// Execute the update
|
// If the field is numeric, avoid comparing with empty string
|
||||||
$this->db->setQuery($sql);
|
if (strpos($fieldType, 'INT') !== false ||
|
||||||
return $this->db->execute();
|
strpos($fieldType, 'FLOAT') !== false ||
|
||||||
} catch (\Exception $e) {
|
strpos($fieldType, 'DOUBLE') !== false ||
|
||||||
|
strpos($fieldType, 'DECIMAL') !== false)
|
||||||
|
{
|
||||||
|
$whereCondition = "$dbField IS NULL OR $dbField = 0";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Default condition for non-numeric fields
|
||||||
|
$whereCondition = "$dbField IS NULL OR $dbField = ''";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update SQL to set new default on existing rows where the default is currently the old default
|
||||||
|
$sql = $updateTable . " SET $dbField = $sqlDefault WHERE $whereCondition";
|
||||||
|
|
||||||
|
// Execute the update
|
||||||
|
$this->db->setQuery($sql);
|
||||||
|
return $this->db->execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new \Exception("Error: Column $column does not exist in table $table.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\Exception $e)
|
||||||
|
{
|
||||||
throw new \Exception("Error: failed to update ($column) column defaults in $table table. " . $e->getMessage());
|
throw new \Exception("Error: failed to update ($column) column defaults in $table table. " . $e->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user