diff --git a/UPGRADE.md b/UPGRADE.md index b34767137c8..104f824e0ca 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,14 @@ # Upgrade to 2.10 +## BC Break: Removed `TABLE` id generator strategy + +The implementation was unfinished for 14 years. +It is now deprecated to rely on: +- `Doctrine\ORM\Id\TableGenerator`; +- `Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_TABLE`; +- `Doctrine\ORM\Mapping\ClassMetadata::$tableGeneratorDefinition`; +- or `Doctrine\ORM\Mapping\ClassMetadata::isIdGeneratorTable()`. + ## BC Break: Removed possibility to extend the doctrine mapping xml schema with anything If you want to extend it now you have to provide your own validation schema. diff --git a/docs/en/reference/annotations-reference.rst b/docs/en/reference/annotations-reference.rst index b6fa660a0e4..226842d71a4 100644 --- a/docs/en/reference/annotations-reference.rst +++ b/docs/en/reference/annotations-reference.rst @@ -463,7 +463,7 @@ Optional attributes: - **strategy**: Set the name of the identifier generation strategy. - Valid values are ``AUTO``, ``SEQUENCE``, ``TABLE``, ``IDENTITY``, ``UUID`` (deprecated), ``CUSTOM`` and ``NONE``, explained + Valid values are ``AUTO``, ``SEQUENCE``, ``IDENTITY``, ``UUID`` (deprecated), ``CUSTOM`` and ``NONE``, explained in the :ref:`Identifier Generation Strategies ` section. If not specified, default value is AUTO. diff --git a/docs/en/reference/attributes-reference.rst b/docs/en/reference/attributes-reference.rst index ec3a99b0081..4644889d6c7 100644 --- a/docs/en/reference/attributes-reference.rst +++ b/docs/en/reference/attributes-reference.rst @@ -371,8 +371,8 @@ used as default. Optional attributes: - **strategy**: Set the name of the identifier generation strategy. - Valid values are ``AUTO``, ``SEQUENCE``, ``TABLE``, ``IDENTITY``, - ``UUID`` (deprecated), ``CUSTOM`` and ``NONE``. + Valid values are ``AUTO``, ``SEQUENCE``, ``IDENTITY``, ``UUID`` + (deprecated), ``CUSTOM`` and ``NONE``. If not specified, the default value is ``AUTO``. Example: diff --git a/docs/en/reference/basic-mapping.rst b/docs/en/reference/basic-mapping.rst index a21a7de9130..6304e52ea22 100644 --- a/docs/en/reference/basic-mapping.rst +++ b/docs/en/reference/basic-mapping.rst @@ -381,9 +381,6 @@ Here is the list of possible generation strategies: (AUTO\_INCREMENT), MSSQL (IDENTITY) and PostgreSQL (SERIAL). - ``UUID`` (deprecated): Tells Doctrine to use the built-in Universally Unique Identifier generator. This strategy provides full portability. -- ``TABLE``: Tells Doctrine to use a separate table for ID - generation. This strategy provides full portability. - ***This strategy is not yet implemented!*** - ``NONE``: Tells Doctrine that the identifiers are assigned (and thus generated) by your code. The assignment must take place before a new entity is passed to ``EntityManager#persist``. NONE is the diff --git a/doctrine-mapping.xsd b/doctrine-mapping.xsd index 9485a58104c..632b7c63e2e 100644 --- a/doctrine-mapping.xsd +++ b/doctrine-mapping.xsd @@ -240,7 +240,6 @@ - diff --git a/lib/Doctrine/ORM/Id/TableGenerator.php b/lib/Doctrine/ORM/Id/TableGenerator.php index aa2b6698467..c65b5272617 100644 --- a/lib/Doctrine/ORM/Id/TableGenerator.php +++ b/lib/Doctrine/ORM/Id/TableGenerator.php @@ -8,6 +8,8 @@ /** * Id generator that uses a single-row database table and a hi/lo algorithm. + * + * @deprecated no replacement planned */ class TableGenerator extends AbstractIdGenerator { diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php index aa4e3ed479c..b3dca6b047b 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php @@ -18,6 +18,7 @@ use Doctrine\ORM\Id\IdentityGenerator; use Doctrine\ORM\Id\SequenceGenerator; use Doctrine\ORM\Id\UuidGenerator; +use Doctrine\ORM\Mapping\Exception\CannotGenerateIds; use Doctrine\ORM\Mapping\Exception\InvalidCustomGenerator; use Doctrine\ORM\Mapping\Exception\TableGeneratorNotImplementedYet; use Doctrine\ORM\Mapping\Exception\UnknownGeneratorType; @@ -626,11 +627,6 @@ private function completeIdGeneratorMapping(ClassMetadataInfo $class): void $class->setIdGenerator(new UuidGenerator()); break; - case ClassMetadata::GENERATOR_TYPE_TABLE: - throw TableGeneratorNotImplementedYet::create(); - - break; - case ClassMetadata::GENERATOR_TYPE_CUSTOM: $definition = $class->customGeneratorDefinition; if ($definition === null) { @@ -663,7 +659,7 @@ private function determineIdGeneratorStrategy(AbstractPlatform $platform): int return ClassMetadata::GENERATOR_TYPE_SEQUENCE; } - return ClassMetadata::GENERATOR_TYPE_TABLE; + throw CannotGenerateIds::withPlatform($platform); } private function truncateSequenceName(string $schemaElementName): string @@ -689,8 +685,6 @@ private function inheritIdGeneratorMapping(ClassMetadataInfo $class, ClassMetada { if ($parent->isIdGeneratorSequence()) { $class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition); - } elseif ($parent->isIdGeneratorTable()) { - $class->tableGeneratorDefinition = $parent->tableGeneratorDefinition; } if ($parent->generatorType) { diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php index 5fb7bb83e76..a856e8cff05 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php @@ -113,7 +113,10 @@ class ClassMetadataInfo implements ClassMetadata /** * TABLE means a separate table is used for id generation. - * Offers full portability. + * Offers full portability (in that it results in an exception being thrown + * no matter the platform). + * + * @deprecated no replacement planned */ public const GENERATOR_TYPE_TABLE = 3; @@ -628,8 +631,9 @@ class ClassMetadataInfo implements ClassMetadata * READ-ONLY: The definition of the table generator of this class. Only used for the * TABLE generation strategy. * + * @deprecated + * * @var array - * @todo Merge with tableGeneratorDefinition into generic generatorDefinition */ public $tableGeneratorDefinition; @@ -2230,11 +2234,13 @@ public function isIdGeneratorSequence() /** * Checks whether the class uses a table for id generation. * - * @return bool TRUE if the class uses the TABLE generator, FALSE otherwise. + * @deprecated + * + * @return false */ public function isIdGeneratorTable() { - return $this->generatorType === self::GENERATOR_TYPE_TABLE; + return false; } /** diff --git a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php index 6065db88f1f..77ce0224322 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php @@ -386,8 +386,6 @@ public function loadMetadataForClass($className, ClassMetadata $metadata) 'initialValue' => $seqGeneratorAnnot->initialValue, ] ); - } elseif ($this->reader->getPropertyAnnotation($property, TableGenerator::class)) { - throw MappingException::tableIdGeneratorNotImplemented($className); } else { $customGeneratorAnnot = $this->reader->getPropertyAnnotation($property, Mapping\CustomIdGenerator::class); if ($customGeneratorAnnot) { diff --git a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php index 6993d2a3fb0..d6fc9ca8b47 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/XmlDriver.php @@ -383,8 +383,6 @@ public function loadMetadataForClass($className, ClassMetadata $metadata) 'class' => (string) $customGenerator['class'], ] ); - } elseif (isset($idElement->{'table-generator'})) { - throw MappingException::tableIdGeneratorNotImplemented($className); } } diff --git a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php index 9ff1fbfb0ba..97c73eae9a6 100644 --- a/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php +++ b/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php @@ -350,7 +350,7 @@ public function loadMetadataForClass($className, ClassMetadata $metadata) . strtoupper($idElement['generator']['strategy']))); } - // Check for SequenceGenerator/TableGenerator definition + // Check for SequenceGenerator definition if (isset($idElement['sequenceGenerator'])) { $metadata->setSequenceGeneratorDefinition($idElement['sequenceGenerator']); } elseif (isset($idElement['customIdGenerator'])) { @@ -360,8 +360,6 @@ public function loadMetadataForClass($className, ClassMetadata $metadata) 'class' => (string) $customGenerator['class'], ] ); - } elseif (isset($idElement['tableGenerator'])) { - throw MappingException::tableIdGeneratorNotImplemented($className); } } } diff --git a/lib/Doctrine/ORM/Mapping/Exception/CannotGenerateIds.php b/lib/Doctrine/ORM/Mapping/Exception/CannotGenerateIds.php new file mode 100644 index 00000000000..63a845e12b8 --- /dev/null +++ b/lib/Doctrine/ORM/Mapping/Exception/CannotGenerateIds.php @@ -0,0 +1,23 @@ +formatField('Composite identifier?', $metadata->isIdentifierComposite), $this->formatField('Foreign identifier?', $metadata->containsForeignIdentifier), $this->formatField('Sequence generator definition', $metadata->sequenceGeneratorDefinition), - $this->formatField('Table generator definition', $metadata->tableGeneratorDefinition), $this->formatField('Change tracking policy', $metadata->changeTrackingPolicy), $this->formatField('Versioned?', $metadata->isVersioned), $this->formatField('Version field', $metadata->versionField), diff --git a/lib/Doctrine/ORM/Tools/EntityGenerator.php b/lib/Doctrine/ORM/Tools/EntityGenerator.php index 81fd1627bda..8ed08115bdd 100644 --- a/lib/Doctrine/ORM/Tools/EntityGenerator.php +++ b/lib/Doctrine/ORM/Tools/EntityGenerator.php @@ -218,7 +218,6 @@ class EntityGenerator protected static $generatorStrategyMap = [ ClassMetadataInfo::GENERATOR_TYPE_AUTO => 'AUTO', ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE => 'SEQUENCE', - ClassMetadataInfo::GENERATOR_TYPE_TABLE => 'TABLE', ClassMetadataInfo::GENERATOR_TYPE_IDENTITY => 'IDENTITY', ClassMetadataInfo::GENERATOR_TYPE_NONE => 'NONE', ClassMetadataInfo::GENERATOR_TYPE_UUID => 'UUID', diff --git a/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php b/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php index 4c7675fd7bb..1f59747f549 100644 --- a/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php +++ b/lib/Doctrine/ORM/Tools/Export/Driver/AbstractExporter.php @@ -250,9 +250,6 @@ protected function _getIdGeneratorTypeString($type) case ClassMetadataInfo::GENERATOR_TYPE_SEQUENCE: return 'SEQUENCE'; - case ClassMetadataInfo::GENERATOR_TYPE_TABLE: - return 'TABLE'; - case ClassMetadataInfo::GENERATOR_TYPE_IDENTITY: return 'IDENTITY'; diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 38896b1257c..2c57af9d15a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -520,11 +520,6 @@ parameters: count: 1 path: lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php - - - message: "#^Unreachable statement \\- code above always terminates\\.$#" - count: 1 - path: lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php - - message: "#^Array \\(array\\('name' \\=\\> string, 'schema' \\=\\> string, 'indexes' \\=\\> array, 'uniqueConstraints' \\=\\> array\\)\\) does not accept key 'options'\\.$#" count: 1 diff --git a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php index 69e9f18cf95..f41e75ba40c 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php +++ b/tests/Doctrine/Tests/ORM/Mapping/ClassMetadataFactoryTest.php @@ -19,6 +19,7 @@ use Doctrine\ORM\Mapping\DiscriminatorColumn; use Doctrine\ORM\Mapping\DiscriminatorMap; use Doctrine\ORM\Mapping\Entity; +use Doctrine\ORM\Mapping\Exception\CannotGenerateIds; use Doctrine\ORM\Mapping\GeneratedValue; use Doctrine\ORM\Mapping\Id; use Doctrine\ORM\Mapping\InheritanceType; @@ -26,6 +27,7 @@ use Doctrine\Persistence\Mapping\Driver\MappingDriver; use Doctrine\Persistence\Mapping\RuntimeReflectionService; use Doctrine\Tests\Mocks\ConnectionMock; +use Doctrine\Tests\Mocks\DatabasePlatformMock; use Doctrine\Tests\Mocks\DriverMock; use Doctrine\Tests\Mocks\EntityManagerMock; use Doctrine\Tests\Mocks\MetadataDriverMock; @@ -85,6 +87,24 @@ public function testGetMetadataForSingleClass(): void self::assertTrue($cmMap1->hasField('name')); } + public function testItThrowsWhenUsingAutoWithIncompatiblePlatform(): void + { + $cm1 = $this->createValidClassMetadata(); + $cm1->setIdGeneratorType(ClassMetadata::GENERATOR_TYPE_AUTO); + $entityManager = $this->createEntityManager(new MetadataDriverMock()); + $connection = $entityManager->getConnection(); + assert($connection instanceof ConnectionMock); + $platform = $connection->getDatabasePlatform(); + assert($platform instanceof DatabasePlatformMock); + $platform->setSupportsIdentityColumns(false); + $cmf = new ClassMetadataFactoryTestSubject(); + $cmf->setEntityManager($entityManager); + $cmf->setMetadataForClass($cm1->name, $cm1); + $this->expectException(CannotGenerateIds::class); + + $actual = $cmf->getMetadataFor($cm1->name); + } + public function testGetMetadataForReturnsLoadedCustomIdGenerator(): void { $cm1 = $this->createValidClassMetadata(); diff --git a/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php b/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php index 23353fec799..9c243210a9e 100644 --- a/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php +++ b/tests/Doctrine/Tests/ORM/Tools/EntityGeneratorTest.php @@ -754,6 +754,10 @@ public function testGetIdGeneratorTypeString(): void continue; } + if ($name === 'GENERATOR_TYPE_TABLE') { + continue; + } + $expected = preg_replace($pattern, '', $name); $actual = $method->invoke($this->generator, $value);