|
5 | 5 | namespace Doctrine\DBAL\Platforms\MySQL; |
6 | 6 |
|
7 | 7 | use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; |
8 | | -use Doctrine\DBAL\Schema\Column; |
| 8 | +use Doctrine\DBAL\Schema\ColumnEditor; |
9 | 9 | use Doctrine\DBAL\Schema\Comparator as BaseComparator; |
10 | 10 | use Doctrine\DBAL\Schema\ComparatorConfig; |
11 | 11 | use Doctrine\DBAL\Schema\Table; |
12 | 12 | use Doctrine\DBAL\Schema\TableDiff; |
13 | 13 |
|
14 | | -use function array_diff_assoc; |
| 14 | +use function count; |
15 | 15 |
|
16 | 16 | /** |
17 | 17 | * Compares schemas in the context of MySQL platform. |
18 | 18 | * |
19 | 19 | * In MySQL, unless specified explicitly, the column's character set and collation are inherited from its containing |
20 | 20 | * table. So during comparison, an omitted value and the value that matches the default value of table in the |
21 | 21 | * desired schema must be considered equal. |
22 | | - * |
23 | | - * @phpstan-import-type PlatformOptions from Column |
24 | 22 | */ |
25 | 23 | class Comparator extends BaseComparator |
26 | 24 | { |
@@ -57,43 +55,55 @@ private function normalizeTable(Table $table): Table |
57 | 55 | $collation = $this->defaultTableOptions->getCollation(); |
58 | 56 | } |
59 | 57 |
|
60 | | - $tableOptions = [ |
61 | | - 'charset' => $charset, |
62 | | - 'collation' => $collation, |
63 | | - ]; |
64 | | - |
65 | | - $table = clone $table; |
| 58 | + $editor = null; |
66 | 59 |
|
67 | 60 | foreach ($table->getColumns() as $column) { |
68 | | - $originalOptions = $column->getPlatformOptions(); |
69 | | - $normalizedOptions = $this->normalizeOptions($originalOptions); |
| 61 | + $originalCharset = $column->getCharset(); |
| 62 | + $originalCollation = $column->getCollation(); |
70 | 63 |
|
71 | | - $overrideOptions = array_diff_assoc($normalizedOptions, $tableOptions); |
| 64 | + $normalizedCharset = $originalCharset; |
| 65 | + $normalizedCollation = $originalCollation; |
72 | 66 |
|
73 | | - if ($overrideOptions === $originalOptions) { |
74 | | - continue; |
| 67 | + if ($originalCharset !== null && $originalCollation === null) { |
| 68 | + $normalizedCollation = $this->charsetMetadataProvider->getDefaultCharsetCollation($originalCharset); |
| 69 | + } elseif ($originalCollation !== null && $originalCharset === null) { |
| 70 | + $normalizedCharset = $this->collationMetadataProvider->getCollationCharset($originalCollation); |
75 | 71 | } |
76 | 72 |
|
77 | | - /** @phpstan-ignore argument.type */ |
78 | | - $column->setPlatformOptions($overrideOptions); |
79 | | - } |
| 73 | + $modifications = []; |
80 | 74 |
|
81 | | - return $table; |
82 | | - } |
| 75 | + if ($normalizedCharset === $charset) { |
| 76 | + $modifications[] = static function (ColumnEditor $editor): void { |
| 77 | + $editor->setCharset(null); |
| 78 | + }; |
| 79 | + } elseif ($normalizedCharset !== $originalCharset) { |
| 80 | + $modifications[] = static function (ColumnEditor $editor) use ($normalizedCharset): void { |
| 81 | + $editor->setCharset($normalizedCharset); |
| 82 | + }; |
| 83 | + } |
83 | 84 |
|
84 | | - /** |
85 | | - * @param PlatformOptions $options |
86 | | - * |
87 | | - * @return PlatformOptions |
88 | | - */ |
89 | | - private function normalizeOptions(array $options): array |
90 | | - { |
91 | | - if (isset($options['charset']) && ! isset($options['collation'])) { |
92 | | - $options['collation'] = $this->charsetMetadataProvider->getDefaultCharsetCollation($options['charset']); |
93 | | - } elseif (isset($options['collation']) && ! isset($options['charset'])) { |
94 | | - $options['charset'] = $this->collationMetadataProvider->getCollationCharset($options['collation']); |
| 85 | + if ($normalizedCollation === $collation) { |
| 86 | + $modifications[] = static function (ColumnEditor $editor): void { |
| 87 | + $editor->setCollation(null); |
| 88 | + }; |
| 89 | + } elseif ($normalizedCollation !== $originalCollation) { |
| 90 | + $modifications[] = static function (ColumnEditor $editor) use ($normalizedCollation): void { |
| 91 | + $editor->setCollation($normalizedCollation); |
| 92 | + }; |
| 93 | + } |
| 94 | + |
| 95 | + if (count($modifications) === 0) { |
| 96 | + continue; |
| 97 | + } |
| 98 | + |
| 99 | + $editor ??= $table->edit(); |
| 100 | + $name = $column->getObjectName(); |
| 101 | + |
| 102 | + foreach ($modifications as $modification) { |
| 103 | + $editor->modifyColumn($name, $modification); |
| 104 | + } |
95 | 105 | } |
96 | 106 |
|
97 | | - return $options; |
| 107 | + return $editor === null ? $table : $editor->create(); |
98 | 108 | } |
99 | 109 | } |
0 commit comments