Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ awareness about deprecated code.

# Upgrade to 5.0

## BC BREAK: Removed `Column` methods

The following `Column` methods have been removed:

- `Column::getPlatformOption()`
- `Column::getPlatformOptions()`
- `Column::hasPlatformOption()`

## BC BREAK: Removed support for the `version` column platform option

The `version` column platform option is no longer supported.
Expand Down
74 changes: 42 additions & 32 deletions src/Platforms/MySQL/Comparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,20 @@
namespace Doctrine\DBAL\Platforms\MySQL;

use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\ColumnEditor;
use Doctrine\DBAL\Schema\Comparator as BaseComparator;
use Doctrine\DBAL\Schema\ComparatorConfig;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;

use function array_diff_assoc;
use function count;

/**
* Compares schemas in the context of MySQL platform.
*
* In MySQL, unless specified explicitly, the column's character set and collation are inherited from its containing
* table. So during comparison, an omitted value and the value that matches the default value of table in the
* desired schema must be considered equal.
*
* @phpstan-import-type PlatformOptions from Column
*/
class Comparator extends BaseComparator
{
Expand Down Expand Up @@ -57,43 +55,55 @@
$collation = $this->defaultTableOptions->getCollation();
}

$tableOptions = [
'charset' => $charset,
'collation' => $collation,
];

$table = clone $table;
$editor = null;

foreach ($table->getColumns() as $column) {
$originalOptions = $column->getPlatformOptions();
$normalizedOptions = $this->normalizeOptions($originalOptions);
$originalCharset = $column->getCharset();
$originalCollation = $column->getCollation();

$overrideOptions = array_diff_assoc($normalizedOptions, $tableOptions);
$normalizedCharset = $originalCharset;
$normalizedCollation = $originalCollation;

if ($overrideOptions === $originalOptions) {
continue;
if ($originalCharset !== null && $originalCollation === null) {
$normalizedCollation = $this->charsetMetadataProvider->getDefaultCharsetCollation($originalCharset);
} elseif ($originalCollation !== null && $originalCharset === null) {
$normalizedCharset = $this->collationMetadataProvider->getCollationCharset($originalCollation);
}

/** @phpstan-ignore argument.type */
$column->setPlatformOptions($overrideOptions);
}
$modifications = [];

return $table;
}
if ($normalizedCharset === $charset) {
$modifications[] = static function (ColumnEditor $editor): void {
$editor->setCharset(null);
};
} elseif ($normalizedCharset !== $originalCharset) {
$modifications[] = static function (ColumnEditor $editor) use ($normalizedCharset): void {
$editor->setCharset($normalizedCharset);
};

Check warning on line 82 in src/Platforms/MySQL/Comparator.php

View check run for this annotation

Codecov / codecov/patch

src/Platforms/MySQL/Comparator.php#L80-L82

Added lines #L80 - L82 were not covered by tests
}

/**
* @param PlatformOptions $options
*
* @return PlatformOptions
*/
private function normalizeOptions(array $options): array
{
if (isset($options['charset']) && ! isset($options['collation'])) {
$options['collation'] = $this->charsetMetadataProvider->getDefaultCharsetCollation($options['charset']);
} elseif (isset($options['collation']) && ! isset($options['charset'])) {
$options['charset'] = $this->collationMetadataProvider->getCollationCharset($options['collation']);
if ($normalizedCollation === $collation) {
$modifications[] = static function (ColumnEditor $editor): void {
$editor->setCollation(null);
};
} elseif ($normalizedCollation !== $originalCollation) {
$modifications[] = static function (ColumnEditor $editor) use ($normalizedCollation): void {
$editor->setCollation($normalizedCollation);
};
}

if (count($modifications) === 0) {
continue;
}

$editor ??= $table->edit();
$name = $column->getObjectName();

foreach ($modifications as $modification) {
$editor->modifyColumn($name, $modification);
}
}

return $options;
return $editor === null ? $table : $editor->create();
}
}
15 changes: 9 additions & 6 deletions src/Platforms/SQLServer/Comparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Doctrine\DBAL\Platforms\SQLServer;

use Doctrine\DBAL\Platforms\SQLServerPlatform;
use Doctrine\DBAL\Schema\ColumnEditor;
use Doctrine\DBAL\Schema\Comparator as BaseComparator;
use Doctrine\DBAL\Schema\ComparatorConfig;
use Doctrine\DBAL\Schema\Table;
Expand Down Expand Up @@ -36,19 +37,21 @@ public function compareTables(Table $oldTable, Table $newTable): TableDiff

private function normalizeColumns(Table $table): Table
{
$table = clone $table;
$editor = null;

foreach ($table->getColumns() as $column) {
$options = $column->getPlatformOptions();
$collation = $column->getCollation();

if (! isset($options['collation']) || $options['collation'] !== $this->databaseCollation) {
if ($collation !== $this->databaseCollation) {
continue;
}

unset($options['collation']);
$column->setPlatformOptions($options);
($editor ??= $table->edit())
->modifyColumn($column->getObjectName(), static function (ColumnEditor $editor): void {
$editor->setCollation(null);
});
}

return $table;
return $editor === null ? $table : $editor->create();
}
}
8 changes: 4 additions & 4 deletions src/Platforms/SQLServerPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -494,16 +494,16 @@ private function getAlterTableAddDefaultConstraintClause(string $tableName, Colu
*/
private function getAlterTableDropDefaultConstraintClause(Column $column): string
{
if (! $column->hasPlatformOption(self::OPTION_DEFAULT_CONSTRAINT_NAME)) {
$constraintName = $column->getDefaultConstraintName();

if ($constraintName === null) {
throw new InvalidArgumentException(
'Column ' . $column->getName() . ' was not properly introspected as it has a default value'
. ' but does not have the default constraint name.',
);
}

return 'DROP CONSTRAINT ' . $this->quoteSingleIdentifier(
$column->getPlatformOption(self::OPTION_DEFAULT_CONSTRAINT_NAME),
);
return 'DROP CONSTRAINT ' . $this->quoteSingleIdentifier($constraintName);
}

/**
Expand Down
15 changes: 9 additions & 6 deletions src/Platforms/SQLite/Comparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Doctrine\DBAL\Platforms\SQLite;

use Doctrine\DBAL\Platforms\SQLitePlatform;
use Doctrine\DBAL\Schema\ColumnEditor;
use Doctrine\DBAL\Schema\Comparator as BaseComparator;
use Doctrine\DBAL\Schema\ComparatorConfig;
use Doctrine\DBAL\Schema\Table;
Expand Down Expand Up @@ -35,19 +36,21 @@ public function compareTables(Table $oldTable, Table $newTable): TableDiff

private function normalizeColumns(Table $table): Table
{
$table = clone $table;
$editor = null;

foreach ($table->getColumns() as $column) {
$options = $column->getPlatformOptions();
$collation = $column->getCollation();

if (! isset($options['collation']) || strcasecmp($options['collation'], 'binary') !== 0) {
if ($collation === null || strcasecmp($collation, 'binary') !== 0) {
continue;
}

unset($options['collation']);
$column->setPlatformOptions($options);
($editor ??= $table->edit())
->modifyColumn($column->getObjectName(), static function (ColumnEditor $editor): void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently

unset($options['collation']);
$column->setPlatformOptions($options);

and modifyColumn are not equivalent, because it loosing all the extra platform options not handled in the ColumnEditor, like enumType (cf #7238)

$editor->setCollation(null);
});
}

return $table;
return $editor === null ? $table : $editor->create();
}
}
34 changes: 0 additions & 34 deletions src/Schema/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,40 +270,6 @@ public function getDefaultConstraintName(): ?string
return $this->_platformOptions[SQLServerPlatform::OPTION_DEFAULT_CONSTRAINT_NAME] ?? null;
}

/**
* @deprecated Use {@see getCharset()}, {@see getCollation()}, {@see getMinimumValue()} or {@see getMaximumValue()}
* instead.
*
* @return PlatformOptions
*/
public function getPlatformOptions(): array
{
return $this->_platformOptions;
}

/**
* @deprecated Use {@see getCharset()}, {@see getCollation()}, {@see getMinimumValue()} or {@see getMaximumValue()}
* instead.
*
* @param key-of<PlatformOptions> $name
*/
public function hasPlatformOption(string $name): bool
{
return isset($this->_platformOptions[$name]);
}

/**
* @deprecated Use {@see getCharset()}, {@see getCollation()}, {@see getMinimumValue()} or {@see getMaximumValue()}
* instead.
*
* @param key-of<PlatformOptions> $name
*/
public function getPlatformOption(string $name): mixed
{
/** @phpstan-ignore offsetAccess.notFound */
return $this->_platformOptions[$name];
}

public function getColumnDefinition(): ?string
{
return $this->_columnDefinition;
Expand Down
17 changes: 14 additions & 3 deletions src/Schema/ColumnDiff.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,20 @@

public function hasPlatformOptionsChanged(): bool
{
return $this->hasPropertyChanged(static function (Column $column): array {
return $column->getPlatformOptions();
});
foreach (
[
static fn (Column $column): ?string => $column->getCharset(),
static fn (Column $column): ?string => $column->getCollation(),
static fn (Column $column): mixed => $column->getMinimumValue(),
static fn (Column $column): mixed => $column->getMaximumValue(),
] as $property
Comment on lines +131 to +136
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since more property exists in the PlatformOptions, like, at least, enumType this doesn't give the same behavior (cf #7238)

Before when changing the enumType this method returned true ; now it returns false. (and maybe there are others important platform options)

Not sure of the impact

) {
if ($this->hasPropertyChanged($property)) {
return true;

Check warning on line 139 in src/Schema/ColumnDiff.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/ColumnDiff.php#L139

Added line #L139 was not covered by tests
}
}

return false;
}

private function hasPropertyChanged(callable $property): bool
Expand Down
6 changes: 2 additions & 4 deletions tests/Schema/ColumnTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ public function testGet(): void
self::assertTrue($column->getFixed());
self::assertEquals('baz', $column->getDefault());

self::assertEquals(['charset' => 'utf8'], $column->getPlatformOptions());
self::assertTrue($column->hasPlatformOption('charset'));
self::assertEquals('utf8', $column->getPlatformOption('charset'));
self::assertFalse($column->hasPlatformOption('collation'));
self::assertEquals('utf8', $column->getCharset());
self::assertNull($column->getCollation());
}

public function testToArray(): void
Expand Down