From 733b64bc907ab597e3cee4f18512a734dd9fa69a Mon Sep 17 00:00:00 2001 From: Jonas Staudenmeir Date: Sat, 31 Aug 2019 05:41:12 +0200 Subject: [PATCH] Quote collation on MySQL --- lib/Doctrine/DBAL/Platforms/MySqlPlatform.php | 10 +++++- .../Schema/MySqlSchemaManagerTest.php | 3 ++ .../AbstractMySQLPlatformTestCase.php | 32 +++++++++---------- .../DBAL/Schema/MySqlInheritCharsetTest.php | 6 ++-- 4 files changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php index 30b065e79d7..57c448ce93e 100644 --- a/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php +++ b/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php @@ -503,7 +503,7 @@ private function buildTableOptions(array $options) $options['collate'] = $options['charset'] . '_unicode_ci'; } - $tableOptions[] = sprintf('COLLATE %s', $options['collate']); + $tableOptions[] = $this->getColumnCollationDeclarationSQL($options['collate']); // Engine if (! isset($options['engine'])) { @@ -965,6 +965,14 @@ public function getColumnCharsetDeclarationSQL($charset) return 'CHARACTER SET ' . $charset; } + /** + * {@inheritDoc} + */ + public function getColumnCollationDeclarationSQL($collation) + { + return 'COLLATE ' . $this->quoteSingleIdentifier($collation); + } + /** * {@inheritDoc} */ diff --git a/tests/Doctrine/Tests/DBAL/Functional/Schema/MySqlSchemaManagerTest.php b/tests/Doctrine/Tests/DBAL/Functional/Schema/MySqlSchemaManagerTest.php index e9a88e52096..cf636a797ff 100644 --- a/tests/Doctrine/Tests/DBAL/Functional/Schema/MySqlSchemaManagerTest.php +++ b/tests/Doctrine/Tests/DBAL/Functional/Schema/MySqlSchemaManagerTest.php @@ -8,6 +8,7 @@ use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Schema\Table; +use Doctrine\DBAL\Types\BlobType; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; use Doctrine\Tests\Types\MySqlPointType; @@ -275,6 +276,7 @@ public function testColumnCollation() : void $table->addColumn('text', 'text'); $table->addColumn('foo', 'text')->setPlatformOption('collation', 'latin1_swedish_ci'); $table->addColumn('bar', 'text')->setPlatformOption('collation', 'utf8_general_ci'); + $table->addColumn('baz', 'text')->setPlatformOption('collation', 'binary'); $this->schemaManager->dropAndCreateTable($table); $columns = $this->schemaManager->listTableColumns('test_collation'); @@ -283,6 +285,7 @@ public function testColumnCollation() : void self::assertEquals('latin1_swedish_ci', $columns['text']->getPlatformOption('collation')); self::assertEquals('latin1_swedish_ci', $columns['foo']->getPlatformOption('collation')); self::assertEquals('utf8_general_ci', $columns['bar']->getPlatformOption('collation')); + self::assertInstanceOf(BlobType::class, $columns['baz']->getType()); } /** diff --git a/tests/Doctrine/Tests/DBAL/Platforms/AbstractMySQLPlatformTestCase.php b/tests/Doctrine/Tests/DBAL/Platforms/AbstractMySQLPlatformTestCase.php index bc71767a766..bbae08c5b2c 100644 --- a/tests/Doctrine/Tests/DBAL/Platforms/AbstractMySQLPlatformTestCase.php +++ b/tests/Doctrine/Tests/DBAL/Platforms/AbstractMySQLPlatformTestCase.php @@ -28,12 +28,12 @@ public function testGenerateMixedCaseTableCreate() : void $table->addColumn('Bar', 'integer'); $sql = $this->platform->getCreateTableSQL($table); - self::assertEquals('CREATE TABLE Foo (Bar INT NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB', array_shift($sql)); + self::assertEquals('CREATE TABLE Foo (Bar INT NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB', 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'; + 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'; } /** @@ -41,7 +41,7 @@ public function getGenerateTableSql() : string */ 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']; + 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']; } /** @@ -209,7 +209,7 @@ public function testGetDateTimeTypeDeclarationSql() : void */ 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"]; + 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"]; } /** @@ -225,7 +225,7 @@ public function getAlterTableColumnCommentsSQL() : array */ 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"]; + 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"]; } /** @@ -250,7 +250,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']; + return ['CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, PRIMARY KEY(`create`)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB']; } /** @@ -258,7 +258,7 @@ protected function getQuotedColumnInPrimaryKeySQL() : array */ 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']; + return ['CREATE TABLE `quoted` (`create` VARCHAR(255) NOT NULL, INDEX IDX_22660D028FD6E0FB (`create`)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB']; } /** @@ -266,7 +266,7 @@ protected function getQuotedColumnInIndexSQL() : array */ 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']; + return ['CREATE TABLE test (column1 VARCHAR(255) NOT NULL, INDEX `key` (column1)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB']; } /** @@ -275,7 +275,7 @@ protected function getQuotedNameInIndexSQL() : array 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', + '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', '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`) REFERENCES foo (`create`, bar, `foo-bar`)', 'ALTER TABLE `quoted` ADD CONSTRAINT FK_WITH_INTENDED_QUOTATION FOREIGN KEY (`create`, foo, `bar`) REFERENCES `foo-bar` (`create`, bar, `foo-bar`)', @@ -293,7 +293,7 @@ public function testCreateTableWithFulltextIndex() : void $index->addFlag('fulltext'); $sql = $this->platform->getCreateTableSQL($table); - self::assertEquals(['CREATE TABLE fulltext_table (text LONGTEXT NOT NULL, FULLTEXT INDEX fulltext_text (text)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = MyISAM'], $sql); + self::assertEquals(['CREATE TABLE fulltext_table (text LONGTEXT NOT NULL, FULLTEXT INDEX fulltext_text (text)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = MyISAM'], $sql); } public function testCreateTableWithSpatialIndex() : void @@ -307,7 +307,7 @@ public function testCreateTableWithSpatialIndex() : void $index->addFlag('spatial'); $sql = $this->platform->getCreateTableSQL($table); - 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'], $sql); + 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'], $sql); } public function testClobTypeDeclarationSQL() : void @@ -571,7 +571,7 @@ public function testDoesNotPropagateForeignKeyCreationForNonSupportingEngines() $table->addOption('engine', 'MyISAM'); self::assertSame( - ['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'], + ['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'], $this->platform->getCreateTableSQL( $table, AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS @@ -583,7 +583,7 @@ public function testDoesNotPropagateForeignKeyCreationForNonSupportingEngines() self::assertSame( [ - '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', + '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', 'ALTER TABLE foreign_table ADD CONSTRAINT FK_5690FFE2A57719D0 FOREIGN KEY (fk_id) REFERENCES foreign_table (id)', ], $this->platform->getCreateTableSQL( @@ -708,7 +708,7 @@ public function testDoesNotPropagateDefaultValuesForUnsupportedColumnTypes() : v $table->addColumn('def_blob_null', 'blob', ['notnull' => false, 'default' => 'def']); self::assertSame( - ['CREATE TABLE text_blob_default_value (def_text LONGTEXT NOT NULL, 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'], + ['CREATE TABLE text_blob_default_value (def_text LONGTEXT NOT NULL, 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) ); @@ -979,7 +979,7 @@ public function testSupportsColumnCollation() : void public function testColumnCollationDeclarationSQL() : void { self::assertSame( - 'COLLATE ascii_general_ci', + 'COLLATE `ascii_general_ci`', $this->platform->getColumnCollationDeclarationSQL('ascii_general_ci') ); } @@ -991,7 +991,7 @@ public function testGetCreateTableSQLWithColumnCollation() : void $table->addColumn('column_collation', 'string')->setPlatformOption('collation', 'ascii_general_ci'); 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'], + ['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'], $this->platform->getCreateTableSQL($table), 'Column "no_collation" will use the default collation from the table/database and "column_collation" overwrites the collation on this column' ); diff --git a/tests/Doctrine/Tests/DBAL/Schema/MySqlInheritCharsetTest.php b/tests/Doctrine/Tests/DBAL/Schema/MySqlInheritCharsetTest.php index b9c0f1d73ec..e65507b7826 100644 --- a/tests/Doctrine/Tests/DBAL/Schema/MySqlInheritCharsetTest.php +++ b/tests/Doctrine/Tests/DBAL/Schema/MySqlInheritCharsetTest.php @@ -45,7 +45,7 @@ public function testTableOptions() : void $table = new Table('foobar', [new Column('aa', Type::getType('integer'))]); self::assertSame( $platform->getCreateTableSQL($table), - ['CREATE TABLE foobar (aa INT NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'] + ['CREATE TABLE foobar (aa INT NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'] ); // explicit utf8 @@ -53,7 +53,7 @@ public function testTableOptions() : void $table->addOption('charset', 'utf8'); self::assertSame( $platform->getCreateTableSQL($table), - ['CREATE TABLE foobar (aa INT NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'] + ['CREATE TABLE foobar (aa INT NOT NULL) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB'] ); // explicit utf8mb4 @@ -61,7 +61,7 @@ public function testTableOptions() : void $table->addOption('charset', 'utf8mb4'); self::assertSame( $platform->getCreateTableSQL($table), - ['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 utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'] ); }