Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recommend SEQUENCE until doctrine/dbal 4 is released #11044

Merged
merged 1 commit into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,30 @@ 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;
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()`

Expand Down
14 changes: 0 additions & 14 deletions docs/en/reference/basic-mapping.rst
Original file line number Diff line number Diff line change
Expand Up @@ -427,20 +427,6 @@ defaults to the identifier generation mechanism your current database
vendor preferred at the time that strategy was introduced:
``AUTO_INCREMENT`` with MySQL, sequences with PostgreSQL and Oracle and
so on.
We now recommend using ``IDENTITY`` for PostgreSQL, and you can achieve
that while still using the ``AUTO`` strategy, by configuring what it
defaults to.

.. code-block:: php

<?php
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\ORM\Configuration;

$config = new Configuration();
$config->setIdentityGenerationPreferences([
PostgreSQLPlatform::class => ClassMetadata::GENERATOR_TYPE_IDENTITY,
]);

.. _identifier-generation-strategies:

Expand Down
37 changes: 9 additions & 28 deletions lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@

use function assert;
use function class_exists;
use function constant;
use function count;
use function end;
use function explode;
Expand Down Expand Up @@ -74,26 +73,10 @@ class ClassMetadataFactory extends AbstractClassMetadataFactory
/** @var mixed[] */
private $embeddablesActiveNesting = [];

private const LEGACY_DEFAULTS_FOR_ID_GENERATION = [
'Doctrine\DBAL\Platforms\MySqlPlatform' => ClassMetadata::GENERATOR_TYPE_IDENTITY,
private const NON_IDENTITY_DEFAULT_STRATEGY = [
'Doctrine\DBAL\Platforms\PostgreSqlPlatform' => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
Platforms\DB2Platform::class => ClassMetadata::GENERATOR_TYPE_IDENTITY,
Platforms\MySQLPlatform::class => ClassMetadata::GENERATOR_TYPE_IDENTITY,
Platforms\OraclePlatform::class => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
Platforms\PostgreSQLPlatform::class => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
Platforms\SQLServerPlatform::class => ClassMetadata::GENERATOR_TYPE_IDENTITY,
Platforms\SqlitePlatform::class => ClassMetadata::GENERATOR_TYPE_IDENTITY,
];

private const RECOMMENDED_STRATEGY = [
'Doctrine\DBAL\Platforms\MySqlPlatform' => 'IDENTITY',
'Doctrine\DBAL\Platforms\PostgreSqlPlatform' => 'IDENTITY',
Platforms\DB2Platform::class => 'IDENTITY',
Platforms\MySQLPlatform::class => 'IDENTITY',
Platforms\OraclePlatform::class => 'SEQUENCE',
Platforms\PostgreSQLPlatform::class => 'IDENTITY',
Platforms\SQLServerPlatform::class => 'IDENTITY',
Platforms\SqlitePlatform::class => 'IDENTITY',
];

/** @return void */
Expand Down Expand Up @@ -657,7 +640,7 @@ private function completeIdGeneratorMapping(ClassMetadataInfo $class): void
'https://github.com/doctrine/orm/issues/8850',
<<<'DEPRECATION'
Context: Loading metadata for class %s
Problem: Using the IDENTITY generator strategy with platform "%s" is deprecated and will not be possible in Doctrine ORM 3.0.
Problem: Using identity columns emulated with a sequence is deprecated and will not be possible in Doctrine ORM 3.0.
Solution: Use the SEQUENCE generator strategy instead.
DEPRECATION
,
Expand Down Expand Up @@ -762,27 +745,25 @@ private function determineIdGeneratorStrategy(AbstractPlatform $platform): int
}
}

foreach (self::LEGACY_DEFAULTS_FOR_ID_GENERATION as $platformFamily => $strategy) {
foreach (self::NON_IDENTITY_DEFAULT_STRATEGY as $platformFamily => $strategy) {
if (is_a($platform, $platformFamily)) {
$recommendedStrategyName = self::RECOMMENDED_STRATEGY[$platformFamily];
if ($strategy !== constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $recommendedStrategyName)) {
if ($platform instanceof Platforms\PostgreSQLPlatform || is_a($platform, 'Doctrine\DBAL\Platforms\PostgreSqlPlatform')) {
SenseException marked this conversation as resolved.
Show resolved Hide resolved
Deprecation::trigger(
'doctrine/orm',
'https://github.com/doctrine/orm/issues/8893',
<<<'DEPRECATION'
Relying on non-optimal defaults for ID generation is deprecated.
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 "%s" for "%s", so you should use
We currently recommend "SEQUENCE" for "%s", so you should use
$configuration->setIdentityGenerationPreferences([
"%s" => ClassMetadata::GENERATOR_TYPE_%s,
"%s" => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
]);
DEPRECATION
,
$recommendedStrategyName,
$platformFamily,
$platformFamily,
$recommendedStrategyName
$platformFamily
);
}

Expand Down
1 change: 1 addition & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@
<code>$class</code>
<code>$class</code>
<code>$platformFamily</code>
<code><![CDATA['Doctrine\DBAL\Platforms\PostgreSqlPlatform']]></code>
<code><![CDATA[new $definition['class']()]]></code>
</ArgumentTypeCoercion>
<DeprecatedClass>
Expand Down
22 changes: 11 additions & 11 deletions tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,37 +170,37 @@ private function setUpCmfForPlatform(AbstractPlatform $platform, array $preferen
return $cmf;
}

public function testRelyingOnLegacyIdGenerationDefaultsIsDeprecatedIfItResultsInASuboptimalDefault(): void
public function testRelyingOnLegacyIdGenerationDefaultsIsOKIfItResultsInTheCurrentlyRecommendedStrategyBeingUsed(): void
{
$cm = $this->createValidClassMetadata();
$cm->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO);

$cmf = $this->setUpCmfForPlatform(new PostgreSQLPlatform());
$cmf = $this->setUpCmfForPlatform(new OraclePlatform());
$cmf->setMetadataForClass($cm->name, $cm);

$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issues/8893');
$this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/orm/issues/8893');
$cmf->getMetadataFor($cm->name);
}

public function testSpecifyingIdGenerationStrategyThroughConfigurationFixesTheDeprecation(): void
public function testRelyingOnLegacyIdGenerationDefaultsIsDeprecatedIfItResultsInADefaultThatWillChange(): void
{
$cm = $this->createValidClassMetadata();
$cm->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO);

$cmf = $this->setUpCmfForPlatform(new PostgreSQLPlatform(), [
PostgreSQLPlatform::class => ClassMetadata::GENERATOR_TYPE_IDENTITY,
]);
$cmf = $this->setUpCmfForPlatform(new PostgreSQLPlatform());
$cmf->setMetadataForClass($cm->name, $cm);

$this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/orm/issues/8893');
$this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issues/8893');
$cmf->getMetadataFor($cm->name);
}

public function testRelyingOnLegacyIdGenerationDefaultsIsOKIfItResultsInTheCurrentlyRecommendedStrategyBeingUsed(): void
public function testSpecifyingIdGenerationStrategyThroughConfigurationFixesTheDeprecation(): void
{
$cm = $this->createValidClassMetadata();
$cm->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO);
$cmf = $this->setUpCmfForPlatform(new OraclePlatform());

$cmf = $this->setUpCmfForPlatform(new PostgreSQLPlatform(), [
PostgreSQLPlatform::class => ClassMetadata::GENERATOR_TYPE_SEQUENCE,
]);
$cmf->setMetadataForClass($cm->name, $cm);

$this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/orm/issues/8893');
Expand Down