Skip to content

Commit

Permalink
Merge pull request #4644 from morozov/issues/4631
Browse files Browse the repository at this point in the history
Remove defaults for MySQL table charset, collation and engine
  • Loading branch information
morozov committed Jun 6, 2021
2 parents a6477e0 + 86df5df commit 893b671
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 78 deletions.
5 changes: 5 additions & 0 deletions UPGRADE.md
Expand Up @@ -8,6 +8,11 @@ awareness about deprecated code.

# Upgrade to 4.0

## Removed defaults for MySQL table charset, collation and engine

The library no longer provides the default values for MySQL table charset, collation and engine.
If omitted in the table definition, MySQL will derive the values from the database options.

## Removed `ReservedWordsCommand::setKeywordListClass()`

To add or replace a keyword list, use `ReservedWordsCommand::setKeywordList()`.
Expand Down
62 changes: 24 additions & 38 deletions src/Platforms/MySQLPlatform.php
Expand Up @@ -28,6 +28,7 @@
use function is_string;
use function sprintf;
use function str_replace;
use function strcasecmp;
use function strtoupper;
use function trim;

Expand Down Expand Up @@ -335,26 +336,32 @@ protected function _getCreateTableSQL(string $name, array $columns, array $optio
$queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')';
}

$query = 'CREATE ';
$sql = ['CREATE'];

if (! empty($options['temporary'])) {
$query .= 'TEMPORARY ';
$sql[] = 'TEMPORARY';
}

$query .= 'TABLE ' . $name . ' (' . $queryFields . ') ';
$query .= $this->buildTableOptions($options);
$query .= $this->buildPartitionOptions($options);
$sql[] = 'TABLE ' . $name . ' (' . $queryFields . ')';

$sql = [$query];
$engine = 'INNODB';
$tableOptions = $this->buildTableOptions($options);

if (isset($options['engine'])) {
$engine = strtoupper(trim($options['engine']));
if ($tableOptions !== '') {
$sql[] = $tableOptions;
}

if (isset($options['partition_options'])) {
$sql[] = $options['partition_options'];
}

$sql = [implode(' ', $sql)];

// Propagate foreign key constraints only for InnoDB.
if (isset($options['foreignKeys']) && $engine === 'INNODB') {
foreach ((array) $options['foreignKeys'] as $definition) {
if (
isset($options['foreignKeys'])
&& (! isset($options['engine']) || strcasecmp($options['engine'], 'InnoDB') === 0)
) {
foreach ($options['foreignKeys'] as $definition) {
$sql[] = $this->getCreateForeignKeySQL($definition, $name);
}
}
Expand Down Expand Up @@ -388,27 +395,18 @@ private function buildTableOptions(array $options): string

$tableOptions = [];

// Charset
if (! isset($options['charset'])) {
$options['charset'] = 'utf8';
if (isset($options['charset'])) {
$tableOptions[] = sprintf('DEFAULT CHARACTER SET %s', $options['charset']);
}

$tableOptions[] = sprintf('DEFAULT CHARACTER SET %s', $options['charset']);

// Collate
if (! isset($options['collate'])) {
$options['collate'] = $options['charset'] . '_unicode_ci';
if (isset($options['collate'])) {
$tableOptions[] = $this->getColumnCollationDeclarationSQL($options['collate']);
}

$tableOptions[] = $this->getColumnCollationDeclarationSQL($options['collate']);

// Engine
if (! isset($options['engine'])) {
$options['engine'] = 'InnoDB';
if (isset($options['engine'])) {
$tableOptions[] = sprintf('ENGINE = %s', $options['engine']);
}

$tableOptions[] = sprintf('ENGINE = %s', $options['engine']);

// Auto increment
if (isset($options['auto_increment'])) {
$tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']);
Expand All @@ -427,18 +425,6 @@ private function buildTableOptions(array $options): string
return implode(' ', $tableOptions);
}

/**
* Build SQL for partition options.
*
* @param mixed[] $options
*/
private function buildPartitionOptions(array $options): string
{
return isset($options['partition_options'])
? ' ' . $options['partition_options']
: '';
}

/**
* {@inheritDoc}
*/
Expand Down
2 changes: 0 additions & 2 deletions tests/Functional/Schema/MySQLSchemaManagerTest.php
Expand Up @@ -204,15 +204,13 @@ public function testColumnCharset(): void
{
$table = new Table('test_column_charset');
$table->addColumn('id', 'integer');
$table->addColumn('no_charset', 'text');
$table->addColumn('foo', 'text')->setPlatformOption('charset', 'ascii');
$table->addColumn('bar', 'text')->setPlatformOption('charset', 'latin1');
$this->schemaManager->dropAndCreateTable($table);

$columns = $this->schemaManager->listTableColumns('test_column_charset');

self::assertFalse($columns['id']->hasPlatformOption('charset'));
self::assertEquals('utf8', $columns['no_charset']->getPlatformOption('charset'));
self::assertEquals('ascii', $columns['foo']->getPlatformOption('charset'));
self::assertEquals('latin1', $columns['bar']->getPlatformOption('charset'));
}
Expand Down
33 changes: 15 additions & 18 deletions tests/Platforms/AbstractMySQLPlatformTestCase.php
Expand Up @@ -34,15 +34,15 @@ public function testGenerateMixedCaseTableCreate(): void

$sql = $this->platform->getCreateTableSQL($table);
self::assertEquals(
'CREATE TABLE Foo (Bar INT NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
'CREATE TABLE Foo (Bar INT NOT NULL)',
array_shift($sql)
);
}

public function getGenerateTableSql(): string
{
return 'CREATE TABLE test (id INT AUTO_INCREMENT NOT NULL, test VARCHAR(255) DEFAULT NULL, '
. 'PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB';
. 'PRIMARY KEY(id))';
}

/**
Expand All @@ -52,8 +52,7 @@ public function getGenerateTableWithMultiColumnUniqueIndexSql(): array
{
return [
'CREATE TABLE test (foo VARCHAR(255) DEFAULT NULL, bar VARCHAR(255) DEFAULT NULL, '
. 'UNIQUE INDEX UNIQ_D87F7E0C8C73652176FF8CAA (foo, bar))'
. ' DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. 'UNIQUE INDEX UNIQ_D87F7E0C8C73652176FF8CAA (foo, bar))',
];
}

Expand Down Expand Up @@ -206,7 +205,7 @@ public function getCreateTableColumnCommentsSQL(): array
{
return [
"CREATE TABLE test (id INT NOT NULL COMMENT 'This is a comment', "
. 'PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. 'PRIMARY KEY(id))',
];
}

Expand All @@ -229,7 +228,7 @@ public function getCreateTableColumnTypeCommentsSQL(): array
{
return [
"CREATE TABLE test (id INT NOT NULL, data LONGTEXT NOT NULL COMMENT '(DC2Type:array)', "
. 'PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. 'PRIMARY KEY(id))',
];
}

Expand All @@ -253,7 +252,7 @@ public function testChangeIndexWithForeignKeys(): void
protected function getQuotedColumnInPrimaryKeySQL(): array
{
return ['CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, '
. 'PRIMARY KEY(`create`)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. 'PRIMARY KEY(`create`))',
];
}

Expand All @@ -264,8 +263,7 @@ protected function getQuotedColumnInIndexSQL(): array
{
return [
'CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, '
. 'INDEX IDX_22660D028FD6E0FB (`create`)) '
. 'DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. 'INDEX IDX_22660D028FD6E0FB (`create`))',
];
}

Expand All @@ -276,7 +274,7 @@ protected function getQuotedNameInIndexSQL(): array
{
return [
'CREATE TABLE test (column1 VARCHAR(255) NOT NULL, '
. 'INDEX `key` (column1)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. 'INDEX `key` (column1))',
];
}

Expand All @@ -287,7 +285,7 @@ protected function getQuotedColumnInForeignKeySQL(): array
{
return [
'CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, foo VARCHAR(255) NOT NULL, '
. '`bar` VARCHAR(255) NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. '`bar` VARCHAR(255) NOT NULL)',
'ALTER TABLE `quoted` ADD CONSTRAINT FK_WITH_RESERVED_KEYWORD FOREIGN KEY (`create`, foo, `bar`)'
. ' REFERENCES `foreign` (`create`, bar, `foo-bar`)',
'ALTER TABLE `quoted` ADD CONSTRAINT FK_WITH_NON_RESERVED_KEYWORD FOREIGN KEY (`create`, foo, `bar`)'
Expand All @@ -312,7 +310,7 @@ public function testCreateTableWithFulltextIndex(): void
[
'CREATE TABLE fulltext_table (text LONGTEXT NOT NULL, '
. 'FULLTEXT INDEX fulltext_text (text)) '
. 'DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = MyISAM',
. 'ENGINE = MyISAM',
],
$sql
);
Expand All @@ -332,7 +330,7 @@ public function testCreateTableWithSpatialIndex(): void
self::assertEquals(
[
'CREATE TABLE spatial_table (point LONGTEXT NOT NULL, SPATIAL INDEX spatial_text (point)) '
. 'DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = MyISAM',
. 'ENGINE = MyISAM',
],
$sql
);
Expand Down Expand Up @@ -577,7 +575,7 @@ public function testDoesNotPropagateForeignKeyCreationForNonSupportingEngines():
[
'CREATE TABLE foreign_table (id INT NOT NULL, fk_id INT NOT NULL, '
. 'INDEX IDX_5690FFE2A57719D0 (fk_id), PRIMARY KEY(id)) '
. 'DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = MyISAM',
. 'ENGINE = MyISAM',
],
$this->platform->getCreateTableSQL(
$table,
Expand All @@ -592,7 +590,7 @@ public function testDoesNotPropagateForeignKeyCreationForNonSupportingEngines():
[
'CREATE TABLE foreign_table (id INT NOT NULL, fk_id INT NOT NULL, '
. 'INDEX IDX_5690FFE2A57719D0 (fk_id), PRIMARY KEY(id)) '
. 'DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. 'ENGINE = InnoDB',
'ALTER TABLE foreign_table ADD CONSTRAINT FK_5690FFE2A57719D0 FOREIGN KEY (fk_id)'
. ' REFERENCES foreign_table (id)',
],
Expand Down Expand Up @@ -715,7 +713,7 @@ public function testDoesNotPropagateDefaultValuesForUnsupportedColumnTypes(): vo
. 'def_text_null LONGTEXT DEFAULT NULL, '
. 'def_blob LONGBLOB NOT NULL, '
. 'def_blob_null LONGBLOB DEFAULT NULL'
. ') DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. ')',
],
$this->platform->getCreateTableSQL($table)
);
Expand Down Expand Up @@ -970,8 +968,7 @@ public function testGetCreateTableSQLWithColumnCollation(): void
self::assertSame(
[
'CREATE TABLE foo (no_collation VARCHAR(255) NOT NULL, '
. 'column_collation VARCHAR(255) NOT NULL COLLATE `ascii_general_ci`) '
. 'DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
. 'column_collation VARCHAR(255) NOT NULL COLLATE `ascii_general_ci`)',
],
$this->platform->getCreateTableSQL($table)
);
Expand Down
24 changes: 4 additions & 20 deletions tests/Schema/MySQLInheritCharsetTest.php
Expand Up @@ -44,34 +44,18 @@ public function testTableOptions(): void
{
$platform = new MySQLPlatform();

// default, no overrides
// no options
$table = new Table('foobar', [new Column('aa', Type::getType('integer'))]);
self::assertSame(
[
'CREATE TABLE foobar (aa INT NOT NULL)'
. ' DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
],
['CREATE TABLE foobar (aa INT NOT NULL)'],
$platform->getCreateTableSQL($table)
);

// explicit utf8
// charset
$table = new Table('foobar', [new Column('aa', Type::getType('integer'))]);
$table->addOption('charset', 'utf8');
self::assertSame(
[
'CREATE TABLE foobar (aa INT NOT NULL)'
. ' DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB',
],
$platform->getCreateTableSQL($table)
);

// explicit utf8mb4
$table = new Table('foobar', [new Column('aa', Type::getType('integer'))]);
$table->addOption('charset', 'utf8mb4');
self::assertSame(
['CREATE TABLE foobar (aa INT NOT NULL)'
. ' DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB',
],
['CREATE TABLE foobar (aa INT NOT NULL) DEFAULT CHARACTER SET utf8'],
$platform->getCreateTableSQL($table)
);
}
Expand Down

0 comments on commit 893b671

Please sign in to comment.