From f1423b2a640b6ac545b6e0c02575427a4dc1e9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Tue, 8 Feb 2022 21:08:04 +0100 Subject: [PATCH] Remap collate to collation when appropriate collate was never supposed to be supported and used in the first place, and DBAL 3.3.2 fixed that. Here, we avoid the situation where a user willing to use the correct option ends up with both collate and collation defined, and we remap collate to collation when DBAL 3.3 is detected. DBAL 3.3.0 and 3.3.1 are avoided thanks to a composer version constraint. --- ConnectionFactory.php | 16 +++++++++-- Tests/ConnectionFactoryTest.php | 51 +++++++++++++++++++++++++++++++++ composer.json | 2 +- psalm.xml.dist | 6 ++++ 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/ConnectionFactory.php b/ConnectionFactory.php index fc3911aa1..c0fd16761 100644 --- a/ConnectionFactory.php +++ b/ConnectionFactory.php @@ -13,6 +13,7 @@ use Doctrine\DBAL\Types\Type; use function array_merge; +use function defined; use function is_subclass_of; use function trigger_deprecation; @@ -79,8 +80,19 @@ public function createConnection(array $params, ?Configuration $config = null, ? if ($driver instanceof AbstractMySQLDriver) { $params['charset'] = 'utf8mb4'; - if (! isset($params['defaultTableOptions']['collate'])) { - $params['defaultTableOptions']['collate'] = 'utf8mb4_unicode_ci'; + /* PARAM_ASCII_STR_ARRAY is defined since doctrine/dbal 3.3 + doctrine/dbal 3.3.2 adds support for the option "collation" + Checking for that constant will no longer be necessary + after dropping support for doctrine/dbal 2, since this + package requires doctrine/dbal 3.3.2 or higher. */ + if (isset($params['defaultTableOptions']['collate']) && defined('Doctrine\DBAL\Connection::PARAM_ASCII_STR_ARRAY')) { + $params['defaultTableOptions']['collation'] = $params['defaultTableOptions']['collate']; + unset($params['defaultTableOptions']['collate']); + } + + $collationOption = defined('Doctrine\DBAL\Connection::PARAM_ASCII_STR_ARRAY') ? 'collation' : 'collate'; + if (! isset($params['defaultTableOptions'][$collationOption])) { + $params['defaultTableOptions'][$collationOption] = 'utf8mb4_unicode_ci'; } } else { $params['charset'] = 'utf8'; diff --git a/Tests/ConnectionFactoryTest.php b/Tests/ConnectionFactoryTest.php index af75a1db2..116a63de1 100644 --- a/Tests/ConnectionFactoryTest.php +++ b/Tests/ConnectionFactoryTest.php @@ -19,6 +19,7 @@ use function array_intersect_key; use function class_exists; +use function defined; use function strpos; // Compatibility with DBAL < 3 @@ -81,6 +82,56 @@ public function testDefaultCharsetMySql(): void $this->assertSame('utf8mb4', $connection->getParams()['charset']); } + public function testDefaultCollateMySql(): void + { + if (defined('Doctrine\DBAL\Connection::PARAM_ASCII_STR_ARRAY')) { + self::markTestSkipped('This test is only relevant for DBAL < 3.3'); + } + + $factory = new ConnectionFactory([]); + $connection = $factory->createConnection(['driver' => 'pdo_mysql']); + + $this->assertSame( + 'utf8mb4_unicode_ci', + $connection->getParams()['defaultTableOptions']['collate'] + ); + } + + public function testDefaultCollationMySql(): void + { + if (! defined('Doctrine\DBAL\Connection::PARAM_ASCII_STR_ARRAY')) { + self::markTestSkipped('This test is only relevant for DBAL >= 3.3'); + } + + $factory = new ConnectionFactory([]); + $connection = $factory->createConnection(['driver' => 'pdo_mysql']); + + $this->assertSame( + 'utf8mb4_unicode_ci', + $connection->getParams()['defaultTableOptions']['collation'] + ); + } + + public function testCollateMapsToCollationForMySql(): void + { + if (! defined('Doctrine\DBAL\Connection::PARAM_ASCII_STR_ARRAY')) { + self::markTestSkipped('This test is only relevant for DBAL >= 3.3'); + } + + $factory = new ConnectionFactory([]); + $connection = $factory->createConnection([ + 'driver' => 'pdo_mysql', + 'defaultTableOptions' => ['collate' => 'my_collation'], + ]); + + $tableOptions = $connection->getParams()['defaultTableOptions']; + $this->assertArrayNotHasKey('collate', $tableOptions); + $this->assertSame( + 'my_collation', + $tableOptions['collation'] + ); + } + /** @group legacy */ public function testConnectionOverrideOptions(): void { diff --git a/composer.json b/composer.json index d21288c5f..7aa7a5fcb 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "php": "^7.1 || ^8.0", "doctrine/annotations": "^1", "doctrine/cache": "^1.11 || ^2.0", - "doctrine/dbal": "^2.13.1|^3.1", + "doctrine/dbal": "^2.13.1|^3.3.2", "doctrine/persistence": "^2.2", "doctrine/sql-formatter": "^1.0.1", "symfony/cache": "^4.3.3|^5.0|^6.0", diff --git a/psalm.xml.dist b/psalm.xml.dist index 8d686af10..536ff0ce0 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -39,5 +39,11 @@ + + + + + +