BUG Resolve issue where schema changes between enum / non-enum types

This commit is contained in:
Damian Mooyman 2019-03-26 14:12:59 +13:00
parent 7e34167ddf
commit 83ec0b69fa
No known key found for this signature in database
GPG Key ID: 4327857F75021D92
1 changed files with 26 additions and 25 deletions

View File

@ -2,12 +2,13 @@
namespace SilverStripe\ORM\Connect;
use Exception;
use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\FieldType\DBPrimaryKey;
use SilverStripe\ORM\DB;
use SilverStripe\ORM\FieldType\DBField;
use Exception;
use SilverStripe\ORM\FieldType\DBPrimaryKey;
/**
* Represents and handles all schema management for a database
@ -710,33 +711,33 @@ MESSAGE
} elseif ($fieldValue != $specValue) {
// If enums/sets are being modified, then we need to fix existing data in the table.
// Update any records where the enum is set to a legacy value to be set to the default.
foreach (array('enum', 'set') as $enumtype) {
if (preg_match("/^$enumtype/i", $specValue)) {
$newStr = preg_replace("/(^$enumtype\\s*\\(')|('\\).*)/i", "", $spec_orig);
$new = preg_split("/'\\s*,\\s*'/", $newStr);
$enumValuesExpr = "/^(enum|set)\\s*\\(['\"](?<values>[^'\"]+)['\"]\\).*/i";
if (preg_match($enumValuesExpr, $specValue, $specMatches)
&& preg_match($enumValuesExpr, $spec_orig, $oldMatches)
) {
$new = preg_split("/'\\s*,\\s*'/", $specMatches['values']);
$old = preg_split("/'\\s*,\\s*'/", $oldMatches['values']);
$oldStr = preg_replace("/(^$enumtype\\s*\\(')|('\\).*)/i", "", $fieldValue);
$old = preg_split("/'\\s*,\\s*'/", $oldStr);
$holder = array();
foreach ($old as $check) {
if (!in_array($check, $new)) {
$holder[] = $check;
}
$holder = array();
foreach ($old as $check) {
if (!in_array($check, $new)) {
$holder[] = $check;
}
if (count($holder)) {
}
if (count($holder)) {
// Get default pre-escaped for SQL. We just use this directly, as we don't have a real way to
// de-encode SQL values
$default = explode('default ', $spec_orig);
$default = $default[1];
$query = "UPDATE \"$table\" SET $field=$default WHERE $field IN (";
for ($i = 0; $i + 1 < count($holder); $i++) {
$query .= "'{$holder[$i]}', ";
}
$query .= "'{$holder[$i]}')";
$this->query($query);
$defaultSQL = isset($default[1]) ? $default[1] : 'NULL';
// Reset to default any value in that is in the old enum, but not the new one
$placeholders = DB::placeholders($holder);
$query = "UPDATE \"{$table}\" SET \"{$field}\" = {$defaultSQL} WHERE \"{$field}\" IN ({$placeholders})";
$this->preparedQuery($query, $holder);
$amount = $this->database->affectedRows();
$this->alterationMessage("Changed $amount rows to default value of field $field"
. " (Value: $default)");
}
$this->alterationMessage(
"Changed $amount rows to default value of field $field (Value: $defaultSQL)"
);
}
}
$this->transAlterField($table, $field, $spec_orig);