diff --git a/UPGRADE.md b/UPGRADE.md index bfc6101e783..90e306eadb4 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -666,6 +666,10 @@ Use `toIterable()` instead. # Upgrade to 2.17 +## Deprecate `Doctrine\ORM\Query\Exec\AbstractSqlExecutor::_sqlStatements` + +Use `Doctrine\ORM\Query\Exec\AbstractSqlExecutor::sqlStatements` instead. + ## Undeprecate `Doctrine\ORM\Proxy\Autoloader` It will be a full-fledged class, no longer extending @@ -675,16 +679,17 @@ It will be a full-fledged class, no longer extending When the `AUTO` identifier generation strategy was introduced, the best strategy at the time was selected for each database platform. -A lot of time has passed since then, and support for better strategies has been -added. +A lot of time has passed since then, and with ORM 3.0.0 and DBAL 4.0.0, support +for better strategies will be added. Because of that, it is now deprecated to rely on the historical defaults when -they differ from what we recommend now. +they differ from what we will be recommended in the future. Instead, you should pick a strategy for each database platform you use, and it will be used when using `AUTO`. As of now, only PostgreSQL is affected by this. -It is recommended that PostgreSQL user configure their new applications to use -`IDENTITY`: + +It is recommended that PostgreSQL users configure their existing and new +applications to use `SEQUENCE` until `doctrine/dbal` 4.0.0 is released: ```php use Doctrine\DBAL\Platforms\PostgreSQLPlatform; @@ -692,12 +697,12 @@ use Doctrine\ORM\Configuration; assert($configuration instanceof Configuration); $configuration->setIdentityGenerationPreferences([ - PostgreSQLPlatform::CLASS => ClassMetadata::GENERATOR_TYPE_IDENTITY, + PostgreSQLPlatform::CLASS => ClassMetadata::GENERATOR_TYPE_SEQUENCE, ]); ``` -If migrating an existing application is too costly, the deprecation can be -addressed by configuring `SEQUENCE` as the default strategy. +When DBAL 4 is released, `AUTO` will result in `IDENTITY`, and the above +configuration should be removed to migrate to it. ## Deprecate `EntityManagerInterface::getPartialReference()` diff --git a/docs/en/reference/basic-mapping.rst b/docs/en/reference/basic-mapping.rst index 8c31983f721..9624b9fb4dd 100644 --- a/docs/en/reference/basic-mapping.rst +++ b/docs/en/reference/basic-mapping.rst @@ -330,7 +330,8 @@ vendor preferred at the time that strategy was introduced: ``AUTO_INCREMENT`` with MySQL, sequences with PostgreSQL and Oracle and so on. If you are using `doctrine/dbal` 4, we now recommend using ``IDENTITY`` -for PostgreSQL, and you can achieve that while still using the ``AUTO`` +for PostgreSQL, and ``AUTO`` resolves to it because of that. +You can stick with ``SEQUENCE`` while still using the ``AUTO`` strategy, by configuring what it defaults to. .. code-block:: php @@ -341,7 +342,7 @@ strategy, by configuring what it defaults to. $config = new Configuration(); $config->setIdentityGenerationPreferences([ - PostgreSQLPlatform::class => ClassMetadata::GENERATOR_TYPE_IDENTITY, + PostgreSQLPlatform::class => ClassMetadata::GENERATOR_TYPE_SEQUENCE, ]); .. _identifier-generation-strategies: diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index dcddcf3194a..a368f85d788 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -7,6 +7,7 @@ use Doctrine\Common\EventManager; use Doctrine\DBAL\Platforms; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\Deprecations\Deprecation; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Event\LoadClassMetadataEventArgs; use Doctrine\ORM\Event\OnClassMetadataNotFoundEventArgs; @@ -626,6 +627,30 @@ private function determineIdGeneratorStrategy(AbstractPlatform $platform): int foreach ($nonIdentityDefaultStrategy as $platformFamily => $strategy) { if (is_a($platform, $platformFamily)) { + if ($platform instanceof Platforms\PostgreSQLPlatform) { + Deprecation::trigger( + 'doctrine/orm', + 'https://github.com/doctrine/orm/issues/8893', + <<<'DEPRECATION' + Relying on non-optimal defaults for ID generation is deprecated, and IDENTITY + results in SERIAL, which is not recommended. + Instead, configure identifier generation strategies explicitly through + configuration. + We currently recommend "SEQUENCE" for "%s", when using DBAL 3, + and "IDENTITY" when using DBAL 4, + so you should use probably use the following configuration before upgrading to DBAL 4, + and remove it after deploying that upgrade: + + $configuration->setIdentityGenerationPreferences([ + "%s" => ClassMetadata::GENERATOR_TYPE_SEQUENCE, + ]); + + DEPRECATION, + $platformFamily, + $platformFamily, + ); + } + return $strategy; } } diff --git a/tests/Doctrine/Tests/ORM/Functional/ParserResultSerializationTest.php b/tests/Doctrine/Tests/ORM/Functional/ParserResultSerializationTest.php index 18cc692cbeb..bcf465faeb7 100644 --- a/tests/Doctrine/Tests/ORM/Functional/ParserResultSerializationTest.php +++ b/tests/Doctrine/Tests/ORM/Functional/ParserResultSerializationTest.php @@ -51,13 +51,13 @@ public function testUnserializeSingleSelectResult(string $serialized): void $this->assertInstanceOf(ResultSetMapping::class, $unserialized->getResultSetMapping()); $this->assertEquals(['name' => [0]], $unserialized->getParameterMappings()); $this->assertInstanceOf(SingleSelectExecutor::class, $unserialized->getSqlExecutor()); + $this->assertIsString($unserialized->getSqlExecutor()->getSqlStatements()); } /** @return Generator */ public static function provideSerializedSingleSelectResults(): Generator { - yield '2.14.3' => [rtrim(file_get_contents(__DIR__ . '/ParserResults/single_select_2_14_3.txt'), "\n")]; - yield '2.15.0' => [rtrim(file_get_contents(__DIR__ . '/ParserResults/single_select_2_15_0.txt'), "\n")]; + yield '2.17.0' => [rtrim(file_get_contents(__DIR__ . '/ParserResults/single_select_2_17_0.txt'), "\n")]; } private static function parseQuery(Query $query): ParserResult diff --git a/tests/Doctrine/Tests/ORM/Functional/ParserResults/single_select_2_17_0.txt b/tests/Doctrine/Tests/ORM/Functional/ParserResults/single_select_2_17_0.txt new file mode 100644 index 00000000000..aa854bfab92 Binary files /dev/null and b/tests/Doctrine/Tests/ORM/Functional/ParserResults/single_select_2_17_0.txt differ diff --git a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php index 315dd203600..8dd886a6d9c 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php @@ -144,6 +144,22 @@ public function testPostgresSticksWithSequencesWhenDbal3IsUsed(): void self::assertSame(ClassMetadata::GENERATOR_TYPE_SEQUENCE, $metadata->generatorType); } + public function testRelyingOnLegacyIdGenerationDefaultsIsDeprecatedIfItResultsInADefaultThatWillChange(): void + { + if (! method_exists(AbstractPlatform::class, 'getIdentitySequenceName')) { + self::markTestSkipped('This test requires DBAL 3'); + } + + $cm = $this->createValidClassMetadata(); + $cm->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO); + $cmf = $this->setUpCmfForPlatform(new PostgreSQLPlatform()); + $cmf->setMetadataForClass($cm->name, $cm); + + $metadata = $cmf->getMetadataFor($cm->name); + + self::assertSame(ClassMetadata::GENERATOR_TYPE_SEQUENCE, $metadata->generatorType); + } + public function testPostgresSwitchesToIdentityColumnsWhenDbal4IsUsed(): void { if (method_exists(AbstractPlatform::class, 'getIdentitySequenceName')) {