diff --git a/UPGRADE.md b/UPGRADE.md index 008ff2b251..11356dd63d 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -8,6 +8,17 @@ awareness about deprecated code. # Upgrade to 5.0 +## BC BREAK: Disallowed mixing unqualified and qualified names in a schema without a default namespace + +If a schema lacks a default namespace configuration and has at least one object with an unqualified name, adding or +referencing objects with qualified names is forbidden. + +If a schema lacks a default namespace configuration and has at least one object with a qualified name, adding or +referencing objects with unqualified names is forbidden. + +Mixing unqualified and qualified names is permitted as long as the schema is configured to use a default namespace. In +this case, the default namespace will be used to resolve unqualified names. + ## BC BREAK: Removed `AbstractAsset::getQuotedName()` The `AbstractAsset::getQuotedName()` method has been removed. diff --git a/src/Schema/Exception/ImproperlyQualifiedName.php b/src/Schema/Exception/ImproperlyQualifiedName.php new file mode 100644 index 0000000000..b43333b069 --- /dev/null +++ b/src/Schema/Exception/ImproperlyQualifiedName.php @@ -0,0 +1,25 @@ +toString())); + } + + public static function fromQualifiedName(OptionallyQualifiedName $name): self + { + return new self(sprintf('Schema uses unqualified names, but %s is qualified.', $name->toString())); + } +} diff --git a/src/Schema/Schema.php b/src/Schema/Schema.php index 3b0887350f..991aa35ca8 100644 --- a/src/Schema/Schema.php +++ b/src/Schema/Schema.php @@ -6,6 +6,7 @@ use Doctrine\DBAL\Exception; use Doctrine\DBAL\Platforms\AbstractPlatform; +use Doctrine\DBAL\Schema\Exception\ImproperlyQualifiedName; use Doctrine\DBAL\Schema\Exception\InvalidName; use Doctrine\DBAL\Schema\Exception\NamespaceAlreadyExists; use Doctrine\DBAL\Schema\Exception\SequenceAlreadyExists; @@ -20,7 +21,6 @@ use Doctrine\DBAL\Schema\Name\UnqualifiedName; use Doctrine\DBAL\SQL\Builder\CreateSchemaObjectsSQLBuilder; use Doctrine\DBAL\SQL\Builder\DropSchemaObjectsSQLBuilder; -use Doctrine\Deprecations\Deprecation; use function array_values; use function count; @@ -217,22 +217,12 @@ private function getKeyFromResolvedName(OptionallyQualifiedName $name): string if ($qualifier !== null) { if ($this->usesUnqualifiedNames) { - Deprecation::trigger( - 'doctrine/dbal', - 'https://github.com/doctrine/dbal/pull/6677#user-content-qualified-names', - 'Using qualified names to create or reference objects in a schema that uses unqualified ' - . 'names is deprecated.', - ); + throw ImproperlyQualifiedName::fromQualifiedName($name); } $key = $qualifier->getValue() . '.' . $key; } elseif (count($this->namespaces) > 0) { - Deprecation::trigger( - 'doctrine/dbal', - 'https://github.com/doctrine/dbal/pull/6677#user-content-unqualified-names', - 'Using unqualified names to create or reference objects in a schema that uses qualified ' - . 'names and lacks a default namespace configuration is deprecated.', - ); + throw ImproperlyQualifiedName::fromUnqualifiedName($name); } return strtolower($key); @@ -271,26 +261,14 @@ private function resolveName(OptionallyQualifiedName $name): OptionallyQualified return $name; } - /** - * Returns the unquoted representation of a given asset name. - */ - private function getUnquotedAssetName(string $assetName): string - { - if ($this->isIdentifierQuoted($assetName)) { - return $this->trimQuotes($assetName); - } - - return $assetName; - } - /** * Does this schema have a namespace with the given name? */ public function hasNamespace(string $name): bool { - $name = strtolower($this->getUnquotedAssetName($name)); + $key = $this->getNamespaceKey($name); - return isset($this->namespaces[$name]); + return isset($this->namespaces[$key]); } /** @@ -333,17 +311,33 @@ public function getSequences(): array */ public function createNamespace(string $name): self { - $unquotedName = strtolower($this->getUnquotedAssetName($name)); + $key = $this->getNamespaceKey($name); - if (isset($this->namespaces[$unquotedName])) { - throw NamespaceAlreadyExists::new($unquotedName); + if (isset($this->namespaces[$key])) { + throw NamespaceAlreadyExists::new($name); } - $this->namespaces[$unquotedName] = $name; + $this->namespaces[$key] = $name; return $this; } + /** + * Returns the key that will be used to store the given namespace name in the collection of namespaces. + */ + private function getNamespaceKey(string $name): string + { + $parser = Parsers::getUnqualifiedNameParser(); + + try { + $parsedName = $parser->parse($name); + } catch (Parser\Exception $e) { + throw InvalidName::fromParserException($name, $e); + } + + return strtolower($parsedName->getIdentifier()->getValue()); + } + /** * Creates a new table. */ diff --git a/tests/Schema/SchemaTest.php b/tests/Schema/SchemaTest.php index a2f1da9897..011fb84927 100644 --- a/tests/Schema/SchemaTest.php +++ b/tests/Schema/SchemaTest.php @@ -5,6 +5,7 @@ namespace Doctrine\DBAL\Tests\Schema; use Doctrine\DBAL\Exception; +use Doctrine\DBAL\Schema\Exception\ImproperlyQualifiedName; use Doctrine\DBAL\Schema\Exception\InvalidName; use Doctrine\DBAL\Schema\Name\Identifier; use Doctrine\DBAL\Schema\Schema; @@ -13,7 +14,6 @@ use Doctrine\DBAL\Schema\Sequence; use Doctrine\DBAL\Schema\Table; use Doctrine\DBAL\Types\Types; -use Doctrine\Deprecations\PHPUnit\VerifyDeprecations; use PHPUnit\Framework\TestCase; use function array_shift; @@ -21,8 +21,6 @@ class SchemaTest extends TestCase { - use VerifyDeprecations; - public function testAddTable(): void { $tableName = 'public.foo'; @@ -345,18 +343,14 @@ public function testCreatesNamespaceThroughAddingSequenceImplicitly(): void public function testAddObjectWithQualifiedNameAfterUnqualifiedName(): void { - $this->expectDeprecationWithIdentifier( - 'https://github.com/doctrine/dbal/pull/6677#user-content-qualified-names', - ); + $this->expectException(ImproperlyQualifiedName::class); new Schema([new Table('t'), new Table('public.t')]); } public function testAddObjectWithUnqualifiedNameAfterQualifiedName(): void { - $this->expectDeprecationWithIdentifier( - 'https://github.com/doctrine/dbal/pull/6677#user-content-unqualified-names', - ); + $this->expectException(ImproperlyQualifiedName::class); new Schema([new Table('public.t'), new Table('t')]); } @@ -365,9 +359,7 @@ public function testReferenceByQualifiedNameAmongUnqualifiedNames(): void { $schema = new Schema([new Table('t')]); - $this->expectDeprecationWithIdentifier( - 'https://github.com/doctrine/dbal/pull/6677#user-content-qualified-names', - ); + $this->expectException(ImproperlyQualifiedName::class); $schema->hasTable('public.t'); } @@ -376,9 +368,7 @@ public function testReferenceByUnqualifiedNameAmongQualifiedNames(): void { $schema = new Schema([new Table('public.t')]); - $this->expectDeprecationWithIdentifier( - 'https://github.com/doctrine/dbal/pull/6677#user-content-unqualified-names', - ); + $this->expectException(ImproperlyQualifiedName::class); $schema->hasTable('t'); } @@ -388,11 +378,10 @@ public function testAddObjectWithQualifiedNameAfterUnqualifiedNameWithDefaultNam $schemaConfig = new SchemaConfig(); $schemaConfig->setName('public'); - $this->expectNoDeprecationWithIdentifier( - 'https://github.com/doctrine/dbal/pull/6677#user-content-qualified-names', - ); + $schema = new Schema([new Table('t'), new Table('public.s')], [], $schemaConfig); - new Schema([new Table('t'), new Table('public.s')], [], $schemaConfig); + self::assertTrue($schema->hasTable('t')); + self::assertTrue($schema->hasTable('public.s')); } public function testAddObjectWithUnqualifiedNameAfterQualifiedNameWithDefaultNamespace(): void @@ -400,11 +389,10 @@ public function testAddObjectWithUnqualifiedNameAfterQualifiedNameWithDefaultNam $schemaConfig = new SchemaConfig(); $schemaConfig->setName('public'); - $this->expectNoDeprecationWithIdentifier( - 'https://github.com/doctrine/dbal/pull/6677#user-content-unqualified-names', - ); + $schema = new Schema([new Table('public.t'), new Table('s')], [], $schemaConfig); - new Schema([new Table('public.t'), new Table('s')], [], $schemaConfig); + self::assertTrue($schema->hasTable('public.t')); + self::assertTrue($schema->hasTable('s')); } public function testReferencingByUnqualifiedNameAmongQualifiedNamesWithDefaultNamespace(): void