| 148 |
lars |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
namespace Doctrine\DBAL\Platforms\MySQL;
|
|
|
4 |
|
|
|
5 |
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
|
|
|
6 |
use Doctrine\DBAL\Schema\Comparator as BaseComparator;
|
|
|
7 |
use Doctrine\DBAL\Schema\Table;
|
|
|
8 |
use Doctrine\DBAL\Schema\TableDiff;
|
|
|
9 |
|
|
|
10 |
use function array_diff_assoc;
|
|
|
11 |
use function array_intersect_key;
|
|
|
12 |
|
|
|
13 |
/**
|
|
|
14 |
* Compares schemas in the context of MySQL platform.
|
|
|
15 |
*
|
|
|
16 |
* In MySQL, unless specified explicitly, the column's character set and collation are inherited from its containing
|
|
|
17 |
* table. So during comparison, an omitted value and the value that matches the default value of table in the
|
|
|
18 |
* desired schema must be considered equal.
|
|
|
19 |
*/
|
|
|
20 |
class Comparator extends BaseComparator
|
|
|
21 |
{
|
|
|
22 |
/** @var CollationMetadataProvider */
|
|
|
23 |
private $collationMetadataProvider;
|
|
|
24 |
|
|
|
25 |
/** @internal The comparator can be only instantiated by a schema manager. */
|
|
|
26 |
public function __construct(AbstractMySQLPlatform $platform, CollationMetadataProvider $collationMetadataProvider)
|
|
|
27 |
{
|
|
|
28 |
parent::__construct($platform);
|
|
|
29 |
|
|
|
30 |
$this->collationMetadataProvider = $collationMetadataProvider;
|
|
|
31 |
}
|
|
|
32 |
|
|
|
33 |
public function compareTables(Table $fromTable, Table $toTable): TableDiff
|
|
|
34 |
{
|
|
|
35 |
return parent::compareTables(
|
|
|
36 |
$this->normalizeColumns($fromTable),
|
|
|
37 |
$this->normalizeColumns($toTable),
|
|
|
38 |
);
|
|
|
39 |
}
|
|
|
40 |
|
|
|
41 |
/**
|
|
|
42 |
* {@inheritDoc}
|
|
|
43 |
*/
|
|
|
44 |
public function diffTable(Table $fromTable, Table $toTable)
|
|
|
45 |
{
|
|
|
46 |
return parent::diffTable(
|
|
|
47 |
$this->normalizeColumns($fromTable),
|
|
|
48 |
$this->normalizeColumns($toTable),
|
|
|
49 |
);
|
|
|
50 |
}
|
|
|
51 |
|
|
|
52 |
private function normalizeColumns(Table $table): Table
|
|
|
53 |
{
|
|
|
54 |
$tableOptions = array_intersect_key($table->getOptions(), [
|
|
|
55 |
'charset' => null,
|
|
|
56 |
'collation' => null,
|
|
|
57 |
]);
|
|
|
58 |
|
|
|
59 |
$table = clone $table;
|
|
|
60 |
|
|
|
61 |
foreach ($table->getColumns() as $column) {
|
|
|
62 |
$originalOptions = $column->getPlatformOptions();
|
|
|
63 |
$normalizedOptions = $this->normalizeOptions($originalOptions);
|
|
|
64 |
|
|
|
65 |
$overrideOptions = array_diff_assoc($normalizedOptions, $tableOptions);
|
|
|
66 |
|
|
|
67 |
if ($overrideOptions === $originalOptions) {
|
|
|
68 |
continue;
|
|
|
69 |
}
|
|
|
70 |
|
|
|
71 |
$column->setPlatformOptions($overrideOptions);
|
|
|
72 |
}
|
|
|
73 |
|
|
|
74 |
return $table;
|
|
|
75 |
}
|
|
|
76 |
|
|
|
77 |
/**
|
|
|
78 |
* @param array<string,string> $options
|
|
|
79 |
*
|
|
|
80 |
* @return array<string,string>
|
|
|
81 |
*/
|
|
|
82 |
private function normalizeOptions(array $options): array
|
|
|
83 |
{
|
|
|
84 |
if (isset($options['collation']) && ! isset($options['charset'])) {
|
|
|
85 |
$charset = $this->collationMetadataProvider->getCollationCharset($options['collation']);
|
|
|
86 |
|
|
|
87 |
if ($charset !== null) {
|
|
|
88 |
$options['charset'] = $charset;
|
|
|
89 |
}
|
|
|
90 |
}
|
|
|
91 |
|
|
|
92 |
return $options;
|
|
|
93 |
}
|
|
|
94 |
}
|