1 | <?php |
||
2 | /* |
||
3 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||
4 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||
5 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||
6 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||
7 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||
8 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||
9 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
10 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
11 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
12 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||
13 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
14 | * |
||
15 | * This software consists of voluntary contributions made by many individuals |
||
16 | * and is licensed under the MIT license. For more information, see |
||
17 | * <http://www.doctrine-project.org>. |
||
18 | */ |
||
19 | |||
20 | namespace Doctrine\DBAL\Schema; |
||
21 | |||
22 | use Doctrine\DBAL\Types; |
||
23 | |||
24 | /** |
||
25 | * Compares two Schemas and return an instance of SchemaDiff. |
||
26 | * |
||
27 | * @link www.doctrine-project.org |
||
28 | * @since 2.0 |
||
29 | * @author Benjamin Eberlei <[email protected]> |
||
30 | */ |
||
31 | class Comparator |
||
32 | { |
||
33 | /** |
||
34 | * @param \Doctrine\DBAL\Schema\Schema $fromSchema |
||
35 | * @param \Doctrine\DBAL\Schema\Schema $toSchema |
||
36 | * |
||
37 | * @return \Doctrine\DBAL\Schema\SchemaDiff |
||
38 | */ |
||
39 | 17 | public static function compareSchemas(Schema $fromSchema, Schema $toSchema) |
|
40 | { |
||
41 | 17 | $c = new self(); |
|
42 | |||
43 | 17 | return $c->compare($fromSchema, $toSchema); |
|
44 | } |
||
45 | |||
46 | /** |
||
47 | * Returns a SchemaDiff object containing the differences between the schemas $fromSchema and $toSchema. |
||
48 | * |
||
49 | * The returned differences are returned in such a way that they contain the |
||
50 | * operations to change the schema stored in $fromSchema to the schema that is |
||
51 | * stored in $toSchema. |
||
52 | * |
||
53 | * @param \Doctrine\DBAL\Schema\Schema $fromSchema |
||
54 | * @param \Doctrine\DBAL\Schema\Schema $toSchema |
||
55 | * |
||
56 | * @return \Doctrine\DBAL\Schema\SchemaDiff |
||
57 | */ |
||
58 | 27 | public function compare(Schema $fromSchema, Schema $toSchema) |
|
59 | { |
||
60 | 27 | $diff = new SchemaDiff(); |
|
61 | 27 | $diff->fromSchema = $fromSchema; |
|
62 | |||
63 | 27 | $foreignKeysToTable = []; |
|
64 | |||
65 | 27 | foreach ($toSchema->getNamespaces() as $namespace) { |
|
66 | 2 | if ( ! $fromSchema->hasNamespace($namespace)) { |
|
67 | 2 | $diff->newNamespaces[$namespace] = $namespace; |
|
68 | } |
||
69 | } |
||
70 | |||
71 | 27 | foreach ($fromSchema->getNamespaces() as $namespace) { |
|
72 | 2 | if ( ! $toSchema->hasNamespace($namespace)) { |
|
73 | 2 | $diff->removedNamespaces[$namespace] = $namespace; |
|
74 | } |
||
75 | } |
||
76 | |||
77 | 27 | foreach ($toSchema->getTables() as $table) { |
|
78 | 21 | $tableName = $table->getShortestName($toSchema->getName()); |
|
79 | 21 | if ( ! $fromSchema->hasTable($tableName)) { |
|
80 | 5 | $diff->newTables[$tableName] = $toSchema->getTable($tableName); |
|
81 | } else { |
||
82 | 19 | $tableDifferences = $this->diffTable($fromSchema->getTable($tableName), $toSchema->getTable($tableName)); |
|
83 | 19 | if ($tableDifferences !== false) { |
|
84 | 21 | $diff->changedTables[$tableName] = $tableDifferences; |
|
85 | } |
||
86 | } |
||
87 | } |
||
88 | |||
89 | /* Check if there are tables removed */ |
||
90 | 27 | foreach ($fromSchema->getTables() as $table) { |
|
91 | 20 | $tableName = $table->getShortestName($fromSchema->getName()); |
|
92 | |||
93 | 20 | $table = $fromSchema->getTable($tableName); |
|
94 | 20 | if ( ! $toSchema->hasTable($tableName)) { |
|
95 | 5 | $diff->removedTables[$tableName] = $table; |
|
96 | } |
||
97 | |||
98 | // also remember all foreign keys that point to a specific table |
||
99 | 20 | foreach ($table->getForeignKeys() as $foreignKey) { |
|
100 | 2 | $foreignTable = strtolower($foreignKey->getForeignTableName()); |
|
101 | 2 | if (!isset($foreignKeysToTable[$foreignTable])) { |
|
102 | 2 | $foreignKeysToTable[$foreignTable] = []; |
|
103 | } |
||
104 | 20 | $foreignKeysToTable[$foreignTable][] = $foreignKey; |
|
105 | } |
||
106 | } |
||
107 | |||
108 | 27 | foreach ($diff->removedTables as $tableName => $table) { |
|
109 | 5 | if (isset($foreignKeysToTable[$tableName])) { |
|
110 | 2 | $diff->orphanedForeignKeys = array_merge($diff->orphanedForeignKeys, $foreignKeysToTable[$tableName]); |
|
111 | |||
112 | // deleting duplicated foreign keys present on both on the orphanedForeignKey |
||
113 | // and the removedForeignKeys from changedTables |
||
114 | 2 | foreach ($foreignKeysToTable[$tableName] as $foreignKey) { |
|
115 | // strtolower the table name to make if compatible with getShortestName |
||
116 | 2 | $localTableName = strtolower($foreignKey->getLocalTableName()); |
|
117 | 2 | if (isset($diff->changedTables[$localTableName])) { |
|
118 | 2 | foreach ($diff->changedTables[$localTableName]->removedForeignKeys as $key => $removedForeignKey) { |
|
119 | // We check if the key is from the removed table if not we skip. |
||
120 | 2 | if ($tableName !== strtolower($removedForeignKey->getForeignTableName())) { |
|
121 | 1 | continue; |
|
122 | } |
||
123 | 5 | unset($diff->changedTables[$localTableName]->removedForeignKeys[$key]); |
|
124 | } |
||
125 | } |
||
126 | } |
||
127 | } |
||
128 | } |
||
129 | |||
130 | 27 | foreach ($toSchema->getSequences() as $sequence) { |
|
131 | 4 | $sequenceName = $sequence->getShortestName($toSchema->getName()); |
|
132 | 4 | if ( ! $fromSchema->hasSequence($sequenceName)) { |
|
133 | 3 | if ( ! $this->isAutoIncrementSequenceInSchema($fromSchema, $sequence)) { |
|
134 | 3 | $diff->newSequences[] = $sequence; |
|
135 | } |
||
136 | } else { |
||
137 | 2 | if ($this->diffSequence($sequence, $fromSchema->getSequence($sequenceName))) { |
|
138 | 4 | $diff->changedSequences[] = $toSchema->getSequence($sequenceName); |
|
139 | } |
||
140 | } |
||
141 | } |
||
142 | |||
143 | 27 | foreach ($fromSchema->getSequences() as $sequence) { |
|
144 | 4 | if ($this->isAutoIncrementSequenceInSchema($toSchema, $sequence)) { |
|
145 | 1 | continue; |
|
146 | } |
||
147 | |||
148 | 3 | $sequenceName = $sequence->getShortestName($fromSchema->getName()); |
|
149 | |||
150 | 3 | if ( ! $toSchema->hasSequence($sequenceName)) { |
|
151 | 3 | $diff->removedSequences[] = $sequence; |
|
152 | } |
||
153 | } |
||
154 | |||
155 | 27 | return $diff; |
|
156 | } |
||
157 | |||
158 | /** |
||
159 | * @param \Doctrine\DBAL\Schema\Schema $schema |
||
160 | * @param \Doctrine\DBAL\Schema\Sequence $sequence |
||
161 | * |
||
162 | * @return boolean |
||
163 | */ |
||
164 | 6 | private function isAutoIncrementSequenceInSchema($schema, $sequence) |
|
165 | { |
||
166 | 6 | foreach ($schema->getTables() as $table) { |
|
167 | 2 | if ($sequence->isAutoIncrementsFor($table)) { |
|
168 | 2 | return true; |
|
169 | } |
||
170 | } |
||
171 | |||
172 | 4 | return false; |
|
173 | } |
||
174 | |||
175 | /** |
||
176 | * @param \Doctrine\DBAL\Schema\Sequence $sequence1 |
||
177 | * @param \Doctrine\DBAL\Schema\Sequence $sequence2 |
||
178 | * |
||
179 | * @return boolean |
||
180 | */ |
||
181 | 3 | public function diffSequence(Sequence $sequence1, Sequence $sequence2) |
|
182 | { |
||
183 | 3 | if ($sequence1->getAllocationSize() != $sequence2->getAllocationSize()) { |
|
184 | 2 | return true; |
|
185 | } |
||
186 | |||
187 | 2 | if ($sequence1->getInitialValue() != $sequence2->getInitialValue()) { |
|
188 | 1 | return true; |
|
189 | } |
||
190 | |||
191 | 1 | return false; |
|
192 | } |
||
193 | |||
194 | /** |
||
195 | * Returns the difference between the tables $table1 and $table2. |
||
196 | * |
||
197 | * If there are no differences this method returns the boolean false. |
||
198 | * |
||
199 | * @param \Doctrine\DBAL\Schema\Table $table1 |
||
200 | * @param \Doctrine\DBAL\Schema\Table $table2 |
||
201 | * |
||
202 | * @return boolean|\Doctrine\DBAL\Schema\TableDiff |
||
203 | */ |
||
204 | 112 | public function diffTable(Table $table1, Table $table2) |
|
205 | { |
||
206 | 112 | $changes = 0; |
|
207 | 112 | $tableDifferences = new TableDiff($table1->getName()); |
|
208 | 112 | $tableDifferences->fromTable = $table1; |
|
209 | |||
210 | 112 | $table1Columns = $table1->getColumns(); |
|
211 | 112 | $table2Columns = $table2->getColumns(); |
|
212 | |||
213 | /* See if all the fields in table 1 exist in table 2 */ |
||
214 | 112 | foreach ($table2Columns as $columnName => $column) { |
|
215 | 107 | if ( !$table1->hasColumn($columnName)) { |
|
216 | 26 | $tableDifferences->addedColumns[$columnName] = $column; |
|
217 | 107 | $changes++; |
|
218 | } |
||
219 | } |
||
220 | /* See if there are any removed fields in table 2 */ |
||
221 | 112 | foreach ($table1Columns as $columnName => $column) { |
|
222 | // See if column is removed in table 2. |
||
223 | 107 | if ( ! $table2->hasColumn($columnName)) { |
|
224 | 27 | $tableDifferences->removedColumns[$columnName] = $column; |
|
225 | 27 | $changes++; |
|
226 | 27 | continue; |
|
227 | } |
||
228 | |||
229 | // See if column has changed properties in table 2. |
||
230 | 88 | $changedProperties = $this->diffColumn($column, $table2->getColumn($columnName)); |
|
231 | |||
232 | 88 | if ( ! empty($changedProperties)) { |
|
233 | 41 | $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); |
|
234 | 41 | $columnDiff->fromColumn = $column; |
|
235 | 41 | $tableDifferences->changedColumns[$column->getName()] = $columnDiff; |
|
236 | 88 | $changes++; |
|
237 | } |
||
238 | } |
||
239 | |||
240 | 112 | $this->detectColumnRenamings($tableDifferences); |
|
241 | |||
242 | 112 | $table1Indexes = $table1->getIndexes(); |
|
243 | 112 | $table2Indexes = $table2->getIndexes(); |
|
244 | |||
245 | /* See if all the indexes in table 1 exist in table 2 */ |
||
246 | 112 | foreach ($table2Indexes as $indexName => $index) { |
|
247 | 42 | if (($index->isPrimary() && $table1->hasPrimaryKey()) || $table1->hasIndex($indexName)) { |
|
248 | 29 | continue; |
|
249 | } |
||
250 | |||
251 | 13 | $tableDifferences->addedIndexes[$indexName] = $index; |
|
252 | 13 | $changes++; |
|
253 | } |
||
254 | /* See if there are any removed indexes in table 2 */ |
||
255 | 112 | foreach ($table1Indexes as $indexName => $index) { |
|
256 | // See if index is removed in table 2. |
||
257 | 40 | if (($index->isPrimary() && ! $table2->hasPrimaryKey()) || |
|
258 | 40 | ! $index->isPrimary() && ! $table2->hasIndex($indexName) |
|
259 | ) { |
||
260 | 15 | $tableDifferences->removedIndexes[$indexName] = $index; |
|
261 | 15 | $changes++; |
|
262 | 15 | continue; |
|
263 | } |
||
264 | |||
265 | // See if index has changed in table 2. |
||
266 | 29 | $table2Index = $index->isPrimary() ? $table2->getPrimaryKey() : $table2->getIndex($indexName); |
|
267 | |||
268 | 29 | if ($this->diffIndex($index, $table2Index)) { |
|
269 | 11 | $tableDifferences->changedIndexes[$indexName] = $table2Index; |
|
270 | 29 | $changes++; |
|
271 | } |
||
272 | } |
||
273 | |||
274 | 112 | $this->detectIndexRenamings($tableDifferences); |
|
275 | |||
276 | 112 | $fromFkeys = $table1->getForeignKeys(); |
|
277 | 112 | $toFkeys = $table2->getForeignKeys(); |
|
278 | |||
279 | 112 | foreach ($fromFkeys as $key1 => $constraint1) { |
|
280 | 10 | foreach ($toFkeys as $key2 => $constraint2) { |
|
281 | 4 | if ($this->diffForeignKey($constraint1, $constraint2) === false) { |
|
282 | 1 | unset($fromFkeys[$key1]); |
|
283 | 1 | unset($toFkeys[$key2]); |
|
284 | } else { |
||
285 | 3 | if (strtolower($constraint1->getName()) == strtolower($constraint2->getName())) { |
|
286 | 2 | $tableDifferences->changedForeignKeys[] = $constraint2; |
|
287 | 2 | $changes++; |
|
288 | 2 | unset($fromFkeys[$key1]); |
|
289 | 10 | unset($toFkeys[$key2]); |
|
290 | } |
||
291 | } |
||
292 | } |
||
293 | } |
||
294 | |||
295 | 112 | foreach ($fromFkeys as $constraint1) { |
|
296 | 7 | $tableDifferences->removedForeignKeys[] = $constraint1; |
|
297 | 7 | $changes++; |
|
298 | } |
||
299 | |||
300 | 112 | foreach ($toFkeys as $constraint2) { |
|
301 | 2 | $tableDifferences->addedForeignKeys[] = $constraint2; |
|
302 | 2 | $changes++; |
|
303 | } |
||
304 | |||
305 | 112 | return $changes ? $tableDifferences : false; |
|
306 | } |
||
307 | |||
308 | /** |
||
309 | * Try to find columns that only changed their name, rename operations maybe cheaper than add/drop |
||
310 | * however ambiguities between different possibilities should not lead to renaming at all. |
||
311 | * |
||
312 | * @param \Doctrine\DBAL\Schema\TableDiff $tableDifferences |
||
313 | * |
||
314 | * @return void |
||
315 | */ |
||
316 | 112 | View Code Duplication | private function detectColumnRenamings(TableDiff $tableDifferences) |
317 | { |
||
318 | 112 | $renameCandidates = []; |
|
319 | 112 | foreach ($tableDifferences->addedColumns as $addedColumnName => $addedColumn) { |
|
320 | 26 | foreach ($tableDifferences->removedColumns as $removedColumn) { |
|
321 | 21 | if (count($this->diffColumn($addedColumn, $removedColumn)) == 0) { |
|
322 | 26 | $renameCandidates[$addedColumn->getName()][] = [$removedColumn, $addedColumn, $addedColumnName]; |
|
323 | } |
||
324 | } |
||
325 | } |
||
326 | |||
327 | 112 | foreach ($renameCandidates as $candidateColumns) { |
|
328 | 21 | if (count($candidateColumns) == 1) { |
|
329 | 20 | list($removedColumn, $addedColumn) = $candidateColumns[0]; |
|
330 | 20 | $removedColumnName = strtolower($removedColumn->getName()); |
|
331 | 20 | $addedColumnName = strtolower($addedColumn->getName()); |
|
332 | |||
333 | 20 | if ( ! isset($tableDifferences->renamedColumns[$removedColumnName])) { |
|
334 | 20 | $tableDifferences->renamedColumns[$removedColumnName] = $addedColumn; |
|
335 | 20 | unset($tableDifferences->addedColumns[$addedColumnName]); |
|
336 | 21 | unset($tableDifferences->removedColumns[$removedColumnName]); |
|
337 | } |
||
338 | } |
||
339 | } |
||
340 | 112 | } |
|
341 | |||
342 | /** |
||
343 | * Try to find indexes that only changed their name, rename operations maybe cheaper than add/drop |
||
344 | * however ambiguities between different possibilities should not lead to renaming at all. |
||
345 | * |
||
346 | * @param \Doctrine\DBAL\Schema\TableDiff $tableDifferences |
||
347 | * |
||
348 | * @return void |
||
349 | */ |
||
350 | 112 | View Code Duplication | private function detectIndexRenamings(TableDiff $tableDifferences) |
351 | { |
||
352 | 112 | $renameCandidates = []; |
|
353 | |||
354 | // Gather possible rename candidates by comparing each added and removed index based on semantics. |
||
355 | 112 | foreach ($tableDifferences->addedIndexes as $addedIndexName => $addedIndex) { |
|
356 | 13 | foreach ($tableDifferences->removedIndexes as $removedIndex) { |
|
357 | 6 | if (! $this->diffIndex($addedIndex, $removedIndex)) { |
|
358 | 13 | $renameCandidates[$addedIndex->getName()][] = [$removedIndex, $addedIndex, $addedIndexName]; |
|
359 | } |
||
360 | } |
||
361 | } |
||
362 | |||
363 | 112 | foreach ($renameCandidates as $candidateIndexes) { |
|
364 | // If the current rename candidate contains exactly one semantically equal index, |
||
365 | // we can safely rename it. |
||
366 | // Otherwise it is unclear if a rename action is really intended, |
||
367 | // therefore we let those ambiguous indexes be added/dropped. |
||
368 | 3 | if (count($candidateIndexes) === 1) { |
|
369 | 2 | list($removedIndex, $addedIndex) = $candidateIndexes[0]; |
|
370 | |||
371 | 2 | $removedIndexName = strtolower($removedIndex->getName()); |
|
372 | 2 | $addedIndexName = strtolower($addedIndex->getName()); |
|
373 | |||
374 | 2 | if (! isset($tableDifferences->renamedIndexes[$removedIndexName])) { |
|
375 | 2 | $tableDifferences->renamedIndexes[$removedIndexName] = $addedIndex; |
|
376 | 2 | unset($tableDifferences->addedIndexes[$addedIndexName]); |
|
377 | 3 | unset($tableDifferences->removedIndexes[$removedIndexName]); |
|
378 | } |
||
379 | } |
||
380 | } |
||
381 | 112 | } |
|
382 | |||
383 | /** |
||
384 | * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $key1 |
||
385 | * @param \Doctrine\DBAL\Schema\ForeignKeyConstraint $key2 |
||
386 | * |
||
387 | * @return boolean |
||
388 | */ |
||
389 | 7 | public function diffForeignKey(ForeignKeyConstraint $key1, ForeignKeyConstraint $key2) |
|
390 | { |
||
391 | 7 | if (array_map('strtolower', $key1->getUnquotedLocalColumns()) != array_map('strtolower', $key2->getUnquotedLocalColumns())) { |
|
392 | 1 | return true; |
|
393 | } |
||
394 | |||
395 | 6 | if (array_map('strtolower', $key1->getUnquotedForeignColumns()) != array_map('strtolower', $key2->getUnquotedForeignColumns())) { |
|
396 | return true; |
||
397 | } |
||
398 | |||
399 | 6 | if ($key1->getUnqualifiedForeignTableName() !== $key2->getUnqualifiedForeignTableName()) { |
|
400 | 1 | return true; |
|
401 | } |
||
402 | |||
403 | 5 | if ($key1->onUpdate() != $key2->onUpdate()) { |
|
404 | 1 | return true; |
|
405 | } |
||
406 | |||
407 | 4 | if ($key1->onDelete() != $key2->onDelete()) { |
|
408 | return true; |
||
409 | } |
||
410 | |||
411 | 4 | return false; |
|
412 | } |
||
413 | |||
414 | /** |
||
415 | * Returns the difference between the fields $field1 and $field2. |
||
416 | * |
||
417 | * If there are differences this method returns $field2, otherwise the |
||
418 | * boolean false. |
||
419 | * |
||
420 | * @param \Doctrine\DBAL\Schema\Column $column1 |
||
421 | * @param \Doctrine\DBAL\Schema\Column $column2 |
||
422 | * |
||
423 | * @return array |
||
424 | */ |
||
425 | 129 | public function diffColumn(Column $column1, Column $column2) |
|
426 | { |
||
427 | 129 | $properties1 = $column1->toArray(); |
|
428 | 129 | $properties2 = $column2->toArray(); |
|
429 | |||
430 | 129 | $changedProperties = []; |
|
431 | |||
432 | 129 | foreach (['type', 'notnull', 'unsigned', 'autoincrement'] as $property) { |
|
433 | 129 | if ($properties1[$property] != $properties2[$property]) { |
|
434 | 129 | $changedProperties[] = $property; |
|
435 | } |
||
436 | } |
||
437 | |||
438 | // This is a very nasty hack to make comparator work with the legacy json_array type, which should be killed in v3 |
||
439 | 129 | if ($this->isALegacyJsonComparison($properties1['type'], $properties2['type'])) { |
|
0 ignored issues
–
show
Deprecated Code
introduced
by
Loading history...
|
|||
440 | 1 | array_shift($changedProperties); |
|
441 | |||
442 | 1 | $changedProperties[] = 'comment'; |
|
443 | } |
||
444 | |||
445 | 129 | if ($properties1['default'] != $properties2['default'] || |
|
446 | // Null values need to be checked additionally as they tell whether to create or drop a default value. |
||
447 | // null != 0, null != false, null != '' etc. This affects platform's table alteration SQL generation. |
||
448 | 126 | (null === $properties1['default'] && null !== $properties2['default']) || |
|
449 | 129 | (null === $properties2['default'] && null !== $properties1['default']) |
|
450 | ) { |
||
451 | 4 | $changedProperties[] = 'default'; |
|
452 | } |
||
453 | |||
454 | 129 | if (($properties1['type'] instanceof Types\StringType && ! $properties1['type'] instanceof Types\GuidType) || |
|
455 | 129 | $properties1['type'] instanceof Types\BinaryType |
|
456 | ) { |
||
457 | // check if value of length is set at all, default value assumed otherwise. |
||
458 | 25 | $length1 = $properties1['length'] ?: 255; |
|
459 | 25 | $length2 = $properties2['length'] ?: 255; |
|
460 | 25 | if ($length1 != $length2) { |
|
461 | 12 | $changedProperties[] = 'length'; |
|
462 | } |
||
463 | |||
464 | 25 | if ($properties1['fixed'] != $properties2['fixed']) { |
|
465 | 25 | $changedProperties[] = 'fixed'; |
|
466 | } |
||
467 | 114 | } elseif ($properties1['type'] instanceof Types\DecimalType) { |
|
468 | 2 | if (($properties1['precision'] ?: 10) != ($properties2['precision'] ?: 10)) { |
|
469 | $changedProperties[] = 'precision'; |
||
470 | } |
||
471 | 2 | if ($properties1['scale'] != $properties2['scale']) { |
|
472 | $changedProperties[] = 'scale'; |
||
473 | } |
||
474 | } |
||
475 | |||
476 | // A null value and an empty string are actually equal for a comment so they should not trigger a change. |
||
477 | 129 | if ($properties1['comment'] !== $properties2['comment'] && |
|
478 | 129 | ! (null === $properties1['comment'] && '' === $properties2['comment']) && |
|
479 | 129 | ! (null === $properties2['comment'] && '' === $properties1['comment']) |
|
480 | ) { |
||
481 | 44 | $changedProperties[] = 'comment'; |
|
482 | } |
||
483 | |||
484 | 129 | $customOptions1 = $column1->getCustomSchemaOptions(); |
|
485 | 129 | $customOptions2 = $column2->getCustomSchemaOptions(); |
|
486 | |||
487 | 129 | foreach (array_merge(array_keys($customOptions1), array_keys($customOptions2)) as $key) { |
|
488 | 2 | if ( ! array_key_exists($key, $properties1) || ! array_key_exists($key, $properties2)) { |
|
489 | 1 | $changedProperties[] = $key; |
|
490 | 2 | } elseif ($properties1[$key] !== $properties2[$key]) { |
|
491 | 2 | $changedProperties[] = $key; |
|
492 | } |
||
493 | } |
||
494 | |||
495 | 129 | $platformOptions1 = $column1->getPlatformOptions(); |
|
496 | 129 | $platformOptions2 = $column2->getPlatformOptions(); |
|
497 | |||
498 | 129 | foreach (array_keys(array_intersect_key($platformOptions1, $platformOptions2)) as $key) { |
|
499 | 2 | if ($properties1[$key] !== $properties2[$key]) { |
|
500 | 2 | $changedProperties[] = $key; |
|
501 | } |
||
502 | } |
||
503 | |||
504 | 129 | return array_unique($changedProperties); |
|
505 | } |
||
506 | |||
507 | /** |
||
508 | * TODO: kill with fire on v3.0 |
||
509 | * |
||
510 | * @deprecated |
||
511 | */ |
||
512 | 129 | private function isALegacyJsonComparison(Types\Type $one, Types\Type $other) : bool |
|
513 | { |
||
514 | 129 | if ( ! $one instanceof Types\JsonType || ! $other instanceof Types\JsonType) { |
|
515 | 127 | return false; |
|
516 | } |
||
517 | |||
518 | 2 | return ( ! $one instanceof Types\JsonArrayType && $other instanceof Types\JsonArrayType) |
|
519 | 2 | || ( ! $other instanceof Types\JsonArrayType && $one instanceof Types\JsonArrayType); |
|
520 | } |
||
521 | |||
522 | /** |
||
523 | * Finds the difference between the indexes $index1 and $index2. |
||
524 | * |
||
525 | * Compares $index1 with $index2 and returns $index2 if there are any |
||
526 | * differences or false in case there are no differences. |
||
527 | * |
||
528 | * @param \Doctrine\DBAL\Schema\Index $index1 |
||
529 | * @param \Doctrine\DBAL\Schema\Index $index2 |
||
530 | * |
||
531 | * @return boolean |
||
532 | */ |
||
533 | 35 | public function diffIndex(Index $index1, Index $index2) |
|
534 | { |
||
535 | 35 | if ($index1->isFullfilledBy($index2) && $index2->isFullfilledBy($index1)) { |
|
536 | 21 | return false; |
|
537 | } |
||
538 | |||
539 | 14 | return true; |
|
540 | } |
||
541 | } |
||
542 |