From 39b611293ff48b52692b462dc86efec6e04de2e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Wed, 16 Feb 2022 10:08:19 +0100 Subject: [PATCH 1/3] Stop giving charset examples On PostgreSQL, UTF8 is a good recommendation. On MySQL though, it will result in the usage of a deprecated charset, and using uppercase like in the example is known to cause bugs when diffing schemas. --- Resources/doc/configuration.rst | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/Resources/doc/configuration.rst b/Resources/doc/configuration.rst index 629148aa6..9e9617e7f 100644 --- a/Resources/doc/configuration.rst +++ b/Resources/doc/configuration.rst @@ -27,7 +27,10 @@ Configuration Reference port: ~ user: root password: ~ - charset: "UTF8" + + # RDBMS specific; Refer to the manual of your RDBMS for more information + charset: ~ + dbname_suffix: ~ # SQLite specific @@ -132,8 +135,8 @@ Configuration Reference default_table_options: # Affects schema-tool. If absent, DBAL chooses defaults # based on the platform. Examples here are for MySQL. - # charset: utf8 - # collate: utf8_unicode_ci + # charset: utf8mb4 + # collate: utf8mb4_unicode_ci # engine: InnoDB replicas: @@ -443,7 +446,7 @@ Configuration Reference port="null" user="root" password="null" - charset="UTF8" + charset="null" path="" memory="" unix-socket="" @@ -485,8 +488,8 @@ Configuration Reference string - utf8 - utf8_unicode_ci + utf8mb4 + utf8mb4_unicode_ci InnoDB @@ -959,7 +962,7 @@ can configure. The following block shows all possible configuration keys: sslkey: postgresql-key.pem # PostgreSQL specific (LIBPQ-CONNECT-SSLKEY) sslcrl: postgresql.crl # PostgreSQL specific (LIBPQ-CONNECT-SSLCRL) wrapper_class: MyDoctrineDbalConnectionWrapper - charset: UTF8 + charset: ~ # RDBMS-specific. Refer to the manual of your RDBMS for more information. logging: "%kernel.debug%" platform_service: MyOwnDatabasePlatformService auto_commit: false @@ -970,9 +973,10 @@ can configure. The following block shows all possible configuration keys: custom: Acme\HelloBundle\MyCustomType default_table_options: # Affects schema-tool. If absent, DBAL chooses defaults - # based on the platform. - charset: utf8 - collate: utf8_unicode_ci + # based on the platform. These defaults might be + # sub-optimal for backward compatibility reasons. + charset: utf8mb4 + collate: utf8mb4_unicode_ci engine: InnoDB .. code-block:: xml @@ -1048,7 +1052,7 @@ can configure. The following block shows all possible configuration keys: sslkey="postgresql-key.pem" sslcrl="postgresql.crl" wrapper-class="MyDoctrineDbalConnectionWrapper" - charset="UTF8" + charset="" logging="%kernel.debug%" platform-service="MyOwnDatabasePlatformService" auto-commit="false" @@ -1056,8 +1060,8 @@ can configure. The following block shows all possible configuration keys: > bar string - utf8 - utf8_unicode_ci + utf8mb4 + utf8mb4_unicode_ci InnoDB Acme\HelloBundle\MyCustomType From eb7f3a25a483152238d63c377bba8a304ce3538c Mon Sep 17 00:00:00 2001 From: kschusternetformic <92304129+kschusternetformic@users.noreply.github.com> Date: Sat, 26 Feb 2022 20:21:14 +0100 Subject: [PATCH 2/3] Fix db name suffix parsing for replica (#1470) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Gabriel Ostrolucký Co-authored-by: Gabriel Ostrolucký --- ConnectionFactory.php | 32 +++++++++++++++++++++++++++----- Resources/doc/configuration.rst | 2 ++ Tests/ConnectionFactoryTest.php | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/ConnectionFactory.php b/ConnectionFactory.php index c0fd16761..81d245f42 100644 --- a/ConnectionFactory.php +++ b/ConnectionFactory.php @@ -69,13 +69,9 @@ public function createConnection(array $params, ?Configuration $config = null, ? } $connection = DriverManager::getConnection($params, $config, $eventManager); - $params = array_merge($connection->getParams(), $overriddenOptions); + $params = $this->addDatabaseSuffix(array_merge($connection->getParams(), $overriddenOptions)); $driver = $connection->getDriver(); - if (isset($params['dbname']) && isset($params['dbname_suffix'])) { - $params['dbname'] .= $params['dbname_suffix']; - } - if (! isset($params['charset'])) { if ($driver instanceof AbstractMySQLDriver) { $params['charset'] = 'utf8mb4'; @@ -160,4 +156,30 @@ private function initializeTypes(): void $this->initialized = true; } + + /** + * @param array $params + * + * @return array + */ + private function addDatabaseSuffix(array $params): array + { + if (isset($params['dbname']) && isset($params['dbname_suffix'])) { + $params['dbname'] .= $params['dbname_suffix']; + } + + foreach ($params['replica'] ?? [] as $key => $replicaParams) { + if (! isset($replicaParams['dbname'], $replicaParams['dbname_suffix'])) { + continue; + } + + $params['replica'][$key]['dbname'] .= $replicaParams['dbname_suffix']; + } + + if (isset($params['primary']['dbname'], $params['primary']['dbname_suffix'])) { + $params['primary']['dbname'] .= $params['primary']['dbname_suffix']; + } + + return $params; + } } diff --git a/Resources/doc/configuration.rst b/Resources/doc/configuration.rst index 9e9617e7f..88c44f26e 100644 --- a/Resources/doc/configuration.rst +++ b/Resources/doc/configuration.rst @@ -148,6 +148,7 @@ Configuration Reference user: root password: ~ charset: ~ + dbname_suffix: ~ path: ~ memory: ~ @@ -516,6 +517,7 @@ Configuration Reference user="root" password="null" charset="" + dbname_suffix="" path="" memory="" unix-socket="" diff --git a/Tests/ConnectionFactoryTest.php b/Tests/ConnectionFactoryTest.php index 116a63de1..5edb58d05 100644 --- a/Tests/ConnectionFactoryTest.php +++ b/Tests/ConnectionFactoryTest.php @@ -167,6 +167,31 @@ public function testDbnameSuffix(): void $this->assertSame('main_test', $connection->getParams()['dbname']); } + + public function testDbnameSuffixForReplicas(): void + { + $connection = (new ConnectionFactory([]))->createConnection([ + 'driver' => 'pdo_mysql', + 'primary' => [ + 'url' => 'mysql://root:password@database:3306/primary?serverVersion=mariadb-10.5.8', + 'dbname_suffix' => '_test', + ], + 'replica' => [ + 'replica1' => [ + 'url' => 'mysql://root:password@database:3306/replica?serverVersion=mariadb-10.5.8', + 'dbname_suffix' => '_test', + ], + ], + ]); + + $parsedParams = $connection->getParams(); + $this->assertArrayHasKey('primary', $parsedParams); + $this->assertArrayHasKey('replica', $parsedParams); + $this->assertArrayHasKey('replica1', $parsedParams['replica']); + + $this->assertSame('primary_test', $parsedParams['primary']['dbname']); + $this->assertSame('replica_test', $parsedParams['replica']['replica1']['dbname']); + } } /** From 1e0d1d7a5982eeebc37dcb4d77bb1a5c5961d96d Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Sat, 5 Mar 2022 11:29:13 +0100 Subject: [PATCH 3/3] Fix default MySQL charset with doctrine/dbal > 2 (#1481) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Grégoire Paris Co-authored-by: Gabriel Ostrolucký --- ConnectionFactory.php | 7 +++++-- Tests/ConnectionFactoryTest.php | 14 +++++--------- psalm.xml.dist | 8 ++++++++ 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ConnectionFactory.php b/ConnectionFactory.php index 81d245f42..2488effe0 100644 --- a/ConnectionFactory.php +++ b/ConnectionFactory.php @@ -5,11 +5,12 @@ use Doctrine\Common\EventManager; use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\AbstractMySQLDriver; use Doctrine\DBAL\DriverManager; use Doctrine\DBAL\Exception as DBALException; use Doctrine\DBAL\Exception\DriverException; +use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Platforms\MySqlPlatform; use Doctrine\DBAL\Types\Type; use function array_merge; @@ -71,9 +72,11 @@ public function createConnection(array $params, ?Configuration $config = null, ? $connection = DriverManager::getConnection($params, $config, $eventManager); $params = $this->addDatabaseSuffix(array_merge($connection->getParams(), $overriddenOptions)); $driver = $connection->getDriver(); + $platform = $driver->getDatabasePlatform(); if (! isset($params['charset'])) { - if ($driver instanceof AbstractMySQLDriver) { + /** @psalm-suppress UndefinedClass AbstractMySQLPlatform exists since DBAL 3.x only */ + if ($platform instanceof AbstractMySQLPlatform || $platform instanceof MySqlPlatform) { $params['charset'] = 'utf8mb4'; /* PARAM_ASCII_STR_ARRAY is defined since doctrine/dbal 3.3 diff --git a/Tests/ConnectionFactoryTest.php b/Tests/ConnectionFactoryTest.php index 5edb58d05..008ac81cf 100644 --- a/Tests/ConnectionFactoryTest.php +++ b/Tests/ConnectionFactoryTest.php @@ -13,14 +13,13 @@ use Doctrine\DBAL\Exception\DriverException; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\MySQLPlatform; +use Doctrine\DBAL\Platforms\SqlitePlatform; use Doctrine\DBAL\Schema\AbstractSchemaManager; use Exception; -use Throwable; use function array_intersect_key; use function class_exists; use function defined; -use function strpos; // Compatibility with DBAL < 3 class_exists(\Doctrine\DBAL\Platforms\MySqlPlatform::class); @@ -47,19 +46,16 @@ public function testContainer(): void try { $factory->createConnection($params, $config, $eventManager, $mappingTypes); - } catch (Throwable $e) { - $this->assertTrue(strpos($e->getMessage(), 'can circumvent this by setting') > 0); - - throw $e; } finally { FakeDriver::$exception = null; } } - public function testDefaultCharset(): void + public function testDefaultCharsetNonMySql(): void { - $factory = new ConnectionFactory([]); - $params = [ + FakeDriver::$platform = new SqlitePlatform(); + $factory = new ConnectionFactory([]); + $params = [ 'driverClass' => FakeDriver::class, 'wrapperClass' => FakeConnection::class, ]; diff --git a/psalm.xml.dist b/psalm.xml.dist index 536ff0ce0..dc843675e 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -45,5 +45,13 @@ + + + + + + + +