diff --git a/.github/ISSUE_TEMPLATE/Bug.md b/.github/ISSUE_TEMPLATE/Bug.md deleted file mode 100644 index 127743902f1..00000000000 --- a/.github/ISSUE_TEMPLATE/Bug.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: 🐞 Bug Report -about: Something is broken? 🔨 ---- - -### Bug Report - - - -| Q | A -|------------ | ------ -| Version | x.y.z - -#### Summary - - - -#### Current behaviour - - - -#### How to reproduce - - - -#### Expected behaviour - - - diff --git a/.github/ISSUE_TEMPLATE/Feature_Request.md b/.github/ISSUE_TEMPLATE/Feature_Request.md deleted file mode 100644 index 777fce18607..00000000000 --- a/.github/ISSUE_TEMPLATE/Feature_Request.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: 🎉 Feature Request -about: You have a neat idea that should be implemented? 🎩 ---- - -### Feature Request - - - -| Q | A -|------------ | ------ -| New Feature | yes -| RFC | yes/no - -#### Summary - - diff --git a/.github/ISSUE_TEMPLATE/Support_Question.md b/.github/ISSUE_TEMPLATE/Support_Question.md deleted file mode 100644 index d5bccbd15fa..00000000000 --- a/.github/ISSUE_TEMPLATE/Support_Question.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: ❓ Support Question -about: Have a problem that you can't figure out? 🤔 ---- - - - -| Q | A -|------------ | ----- -| Version | x.y.z - - - -### Support Question - - diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index a1a47674ea1..b7611c8b4bd 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -224,23 +224,23 @@ jobs: - "8.1" postgres-version: - "12" - - "15" - "16" + - "17" extension: - "pgsql" - "pdo_pgsql" include: - php-version: "8.2" - postgres-version: "16" + postgres-version: "17" extension: "pgsql" - php-version: "8.3" - postgres-version: "16" + postgres-version: "17" extension: "pgsql" - php-version: "8.4" - postgres-version: "16" + postgres-version: "17" extension: "pgsql" - php-version: "8.4" - postgres-version: "16" + postgres-version: "17" extension: "pdo_pgsql" services: @@ -370,7 +370,7 @@ jobs: - "8.3" mysql-version: - "8.0" - - "9.0" + - "9.1" extension: - "mysqli" - "pdo_mysql" @@ -399,10 +399,10 @@ jobs: custom-entrypoint: >- --entrypoint sh mysql:8.4 -c "exec docker-entrypoint.sh mysqld --mysql-native-password=ON" - php-version: "8.4" - mysql-version: "9.0" + mysql-version: "9.1" extension: "mysqli" - php-version: "8.4" - mysql-version: "9.0" + mysql-version: "9.1" extension: "pdo_mysql" services: diff --git a/UPGRADE.md b/UPGRADE.md index 4a4d3a33720..6e606beefda 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -19,6 +19,17 @@ all drivers and middleware. * Upgrade to MySQL 8.0 or later. * Upgrade to Postgres 12 or later. +# Upgrade to 4.3 + +## Deprecated dropping columns referenced by constraints + +Dropping columns that are referenced by constraints is deprecated. The constraints should be dropped first. + +## Deprecated `Table::removeForeignKey()` and `::removeUniqueConstraint()` + +The usage of `Table::removeForeignKey()` and `::removeUniqueConstraint()` is deprecated. Use `Table::dropForeignKey()` +and `::dropUniqueConstraint()` respectively instead. + # Upgrade to 4.2 ## Support for new PDO subclasses on PHP 8.4 diff --git a/docs/en/reference/configuration.rst b/docs/en/reference/configuration.rst index eb236b22634..495a38a8aba 100644 --- a/docs/en/reference/configuration.rst +++ b/docs/en/reference/configuration.rst @@ -249,7 +249,7 @@ mysqli - ``ssl_ca`` (string): The path name to the certificate authority file to use for SSL encryption. - ``ssl_capath`` (string): The pathname to a directory that contains trusted SSL CA certificates in PEM format. - ``ssl_cipher`` (string): A list of allowable ciphers to use for SSL encryption. -- ``driverOptions`` Any supported flags for mysqli found on `http://www.php.net/manual/en/mysqli.real-connect.php` +- ``driverOptions`` Any supported flags for mysqli found on `www.php.net/manual/en/mysqli.real-connect.php `_ pdo_pgsql / pgsql ^^^^^^^^^^^^^^^^^ @@ -266,22 +266,22 @@ pdo_pgsql / pgsql - ``sslmode`` (string): Determines whether or with what priority a SSL TCP/IP connection will be negotiated with the server. See the list of available modes: - `https://www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNECT-SSLMODE` + `www.postgresql.org/docs/9.4/libpq-connect.html#LIBPQ-CONNECT-SSLMODE `_ - ``sslrootcert`` (string): specifies the name of a file containing SSL certificate authority (CA) certificate(s). If the file exists, the server's certificate will be verified to be signed by one of these authorities. - See https://www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNECT-SSLROOTCERT + See `www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNECT-SSLROOTCERT `_ - ``sslcert`` (string): specifies the filename of the client SSL certificate. - See `https://www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNECT-SSLCERT` + See `www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNECT-SSLCERT `_ - ``sslkey`` (string): specifies the location for the secret key used for the client certificate. - See `https://www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNECT-SSLKEY` + See `www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNECT-SSLKEY `_ - ``sslcrl`` (string): specifies the filename of the SSL certificate revocation list (CRL). - See `https://www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNECT-SSLCRL` + See `www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-CONNECT-SSLCRL `_ - ``gssencmode`` (string): Optional GSS-encrypted channel/GSSEncMode configuration. - See `https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-GSSENCMODE` + See `www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-GSSENCMODE `_ - ``application_name`` (string): Name of the application that is connecting to database. Optional. It will be displayed at ``pg_stat_activity``. @@ -316,7 +316,7 @@ pdo_oci / oci8 add the INSTANCE_NAME parameter in the connection. It is generally used to connect to an Oracle RAC server to select the name of a particular instance. - ``connectstring`` (string): Complete Easy Connect connection descriptor, - see https://docs.oracle.com/database/121/NETAG/naming.htm. When using this option, + see `docs.oracle.com/en/database/oracle/oracle-database/23/netag/configuring-naming-methods.html `_. When using this option, you will still need to provide the ``user`` and ``password`` parameters, but the other parameters will no longer be used. Note that when using this parameter, the ``getHost`` and ``getPort`` methods from ``Doctrine\DBAL\Connection`` will no longer function as expected. @@ -335,7 +335,7 @@ pdo_sqlsrv / sqlsrv - ``host`` (string): Hostname of the database to connect to. - ``port`` (integer): Port of the database to connect to. - ``dbname`` (string): Name of the database/schema to connect to. -- ``driverOptions`` (array): Any supported options found on `https://learn.microsoft.com/en-us/sql/connect/php/connection-options` +- ``driverOptions`` (array): Any supported options found on `learn.microsoft.com/en-us/sql/connect/php/connection-options `_ ibm_db2 ^^^^^^^ @@ -347,7 +347,7 @@ ibm_db2 - ``host`` (string): Hostname of the database to connect to. - ``port`` (integer): Port of the database to connect to. - ``persistent`` (boolean): Whether to establish a persistent connection. -- ``driverOptions`` (array): Any supported options found on `https://www.php.net/manual/en/function.db2-connect.php#refsect1-function.db2-connect-parameters` +- ``driverOptions`` (array): Any supported options found on `www.php.net/manual/en/function.db2-connect.php#refsect1-function.db2-connect-parameters `_ Automatic platform version detection ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/psalm.xml.dist b/psalm.xml.dist index 5898fc283af..38b08bf5cb5 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -55,6 +55,13 @@ + + + + @@ -119,6 +126,12 @@ + + + + + + @@ -173,6 +186,8 @@ + + @@ -279,6 +294,8 @@ + + diff --git a/src/Schema/Table.php b/src/Schema/Table.php index bfcdb914675..b6deec7348d 100644 --- a/src/Schema/Table.php +++ b/src/Schema/Table.php @@ -14,10 +14,14 @@ use Doctrine\DBAL\Schema\Exception\PrimaryKeyAlreadyExists; use Doctrine\DBAL\Schema\Exception\UniqueConstraintDoesNotExist; use Doctrine\DBAL\Types\Type; +use Doctrine\Deprecations\Deprecation; use LogicException; use function array_merge; use function array_values; +use function count; +use function implode; +use function in_array; use function preg_match; use function sprintf; use function strtolower; @@ -280,10 +284,7 @@ final public function getRenamedColumns(): array return $this->renamedColumns; } - /** - * @throws LogicException - * @throws SchemaException - */ + /** @throws LogicException */ final public function renameColumn(string $oldName, string $newName): Column { $oldName = $this->normalizeIdentifier($oldName); @@ -302,6 +303,10 @@ final public function renameColumn(string $oldName, string $newName): Column unset($this->_columns[$oldName]); $this->_addColumn($column); + $this->renameColumnInIndexes($oldName, $newName); + $this->renameColumnInForeignKeyConstraints($oldName, $newName); + $this->renameColumnInUniqueConstraints($oldName, $newName); + // If a column is renamed multiple times, we only want to know the original and last new name if (isset($this->renamedColumns[$oldName])) { $toRemove = $oldName; @@ -332,6 +337,30 @@ public function dropColumn(string $name): self { $name = $this->normalizeIdentifier($name); + $foreignKeyConstraintNames = $this->getForeignKeyConstraintNamesByLocalColumnName($name); + $uniqueConstraintNames = $this->getUniqueConstraintNamesByColumnName($name); + + if (count($foreignKeyConstraintNames) > 0 || count($uniqueConstraintNames) > 0) { + $constraints = []; + + if (count($foreignKeyConstraintNames) > 0) { + $constraints[] = 'foreign key constraints: ' . implode(', ', $foreignKeyConstraintNames); + } + + if (count($uniqueConstraintNames) > 0) { + $constraints[] = 'unique constraints: ' . implode(', ', $uniqueConstraintNames); + } + + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/6559', + 'Dropping columns referenced by constraints is deprecated.' + . ' Column %s is used by the following constraints: %s ', + $name, + implode('; ', $constraints), + ); + } + unset($this->_columns[$name]); return $this; @@ -409,8 +438,24 @@ public function getForeignKey(string $name): ForeignKeyConstraint /** * Removes the foreign key constraint with the given name. + * + * @deprecated Use {@link dropForeignKey()} instead. */ public function removeForeignKey(string $name): void + { + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/6560', + 'Table::removeForeignKey() is deprecated. Use Table::removeForeignKey() instead.', + ); + + $this->dropForeignKey($name); + } + + /** + * Drops the foreign key constraint with the given name. + */ + public function dropForeignKey(string $name): void { $name = $this->normalizeIdentifier($name); @@ -447,8 +492,24 @@ public function getUniqueConstraint(string $name): UniqueConstraint /** * Removes the unique constraint with the given name. + * + * @deprecated Use {@link dropUniqueConstraint()} instead. */ public function removeUniqueConstraint(string $name): void + { + Deprecation::trigger( + 'doctrine/dbal', + 'https://github.com/doctrine/dbal/pull/6560', + 'Table::removeUniqueConstraint() is deprecated. Use Table::dropUniqueConstraint() instead.', + ); + + $this->dropUniqueConstraint($name); + } + + /** + * Drops the unique constraint with the given name. + */ + public function dropUniqueConstraint(string $name): void { $name = $this->normalizeIdentifier($name); @@ -800,4 +861,120 @@ private function _createIndex( return new Index($indexName, $columns, $isUnique, $isPrimary, $flags, $options); } + + private function renameColumnInIndexes(string $oldName, string $newName): void + { + foreach ($this->_indexes as $key => $index) { + $modified = false; + $columns = []; + foreach ($index->getColumns() as $columnName) { + if ($columnName === $oldName) { + $columns[] = $newName; + $modified = true; + } else { + $columns[] = $columnName; + } + } + + if (! $modified) { + continue; + } + + $this->_indexes[$key] = new Index( + $index->getName(), + $columns, + $index->isUnique(), + $index->isPrimary(), + $index->getFlags(), + $index->getOptions(), + ); + } + } + + private function renameColumnInForeignKeyConstraints(string $oldName, string $newName): void + { + foreach ($this->_fkConstraints as $key => $constraint) { + $modified = false; + $localColumns = []; + foreach ($constraint->getLocalColumns() as $columnName) { + if ($columnName === $oldName) { + $localColumns[] = $newName; + $modified = true; + } else { + $localColumns[] = $columnName; + } + } + + if (! $modified) { + continue; + } + + $this->_fkConstraints[$key] = new ForeignKeyConstraint( + $localColumns, + $constraint->getForeignTableName(), + $constraint->getForeignColumns(), + $constraint->getName(), + $constraint->getOptions(), + ); + } + } + + private function renameColumnInUniqueConstraints(string $oldName, string $newName): void + { + foreach ($this->uniqueConstraints as $key => $constraint) { + $modified = false; + $columns = []; + foreach ($constraint->getColumns() as $columnName) { + if ($columnName === $oldName) { + $columns[] = $newName; + $modified = true; + } else { + $columns[] = $columnName; + } + } + + if (! $modified) { + continue; + } + + $this->uniqueConstraints[$key] = new UniqueConstraint( + $constraint->getName(), + $columns, + $constraint->getFlags(), + $constraint->getOptions(), + ); + } + } + + /** @return list */ + private function getForeignKeyConstraintNamesByLocalColumnName(string $columnName): array + { + $names = []; + + foreach ($this->_fkConstraints as $name => $constraint) { + if (! in_array($columnName, $constraint->getLocalColumns(), true)) { + continue; + } + + $names[] = $name; + } + + return $names; + } + + /** @return list */ + private function getUniqueConstraintNamesByColumnName(string $columnName): array + { + $names = []; + + foreach ($this->uniqueConstraints as $name => $constraint) { + if (! in_array($columnName, $constraint->getColumns(), true)) { + continue; + } + + $names[] = $name; + } + + return $names; + } } diff --git a/src/Types/BigIntType.php b/src/Types/BigIntType.php index 0cb14c5b44c..a9b096785cb 100644 --- a/src/Types/BigIntType.php +++ b/src/Types/BigIntType.php @@ -47,15 +47,18 @@ public function convertToPHPValue(mixed $value, AbstractPlatform $platform): int return $value; } - if ($value > PHP_INT_MIN && $value < PHP_INT_MAX) { - return (int) $value; - } - assert( is_string($value), 'DBAL assumes values outside of the integer range to be returned as string by the database driver.', ); + if ( + ($value > PHP_INT_MIN && $value < PHP_INT_MAX) + || $value === (string) (int) $value + ) { + return (int) $value; + } + return $value; } } diff --git a/tests/ConnectionTest.php b/tests/ConnectionTest.php index 3d085ca9314..f9702ba303f 100644 --- a/tests/ConnectionTest.php +++ b/tests/ConnectionTest.php @@ -25,6 +25,7 @@ use PHPUnit\Framework\TestCase; use Psr\Cache\CacheItemInterface; use Psr\Cache\CacheItemPoolInterface; +use RuntimeException; /** @psalm-import-type Params from DriverManager */ #[RequiresPhpExtension('pdo_mysql')] @@ -172,6 +173,36 @@ public function testCommitStartsTransactionInNoAutoCommitMode(): void self::assertTrue($conn->isTransactionActive()); } + public function testBeginTransactionFailureAfterCommitInNoAutoCommitMode(): void + { + $driverConnectionMock = $this->createMock(DriverConnection::class); + $driverConnectionMock->expects(self::exactly(2)) + ->method('beginTransaction') + ->willReturnOnConsecutiveCalls( + true, + self::throwException(new RuntimeException()), + ); + + $driver = self::createStub(Driver::class); + $driver + ->method('connect') + ->willReturn( + $driverConnectionMock, + ); + $conn = new Connection([], $driver); + + $conn->setAutoCommit(false); + + /** Invoke protected {@see Connection::connect()} */ + $conn->getServerVersion(); + try { + $conn->commit(); + } catch (RuntimeException) { + } + + self::assertTrue($conn->isTransactionActive()); + } + /** @return bool[][] */ public static function resultProvider(): array { diff --git a/tests/Functional/Schema/ColumnRenameTest.php b/tests/Functional/Schema/ColumnRenameTest.php new file mode 100644 index 00000000000..613855e14cb --- /dev/null +++ b/tests/Functional/Schema/ColumnRenameTest.php @@ -0,0 +1,76 @@ +schemaManager = $this->connection->createSchemaManager(); + $this->comparator = $this->schemaManager->createComparator(); + } + + /** @throws Exception */ + public function testRenameColumnInIndex(): void + { + $this->testRenameColumn(static function (Table $table): void { + $table->addIndex(['c1', 'c2'], 'idx_c1_c2'); + }); + } + + /** @throws Exception */ + public function testRenameColumnInForeignKeyConstraint(): void + { + $this->dropTableIfExists('rename_column_referenced'); + + $referencedTable = new Table('rename_column_referenced'); + $referencedTable->addColumn('c1', Types::INTEGER); + $referencedTable->addColumn('c2', Types::INTEGER); + + // PostgreSQL requires a unique constraint on the referenced table columns + $referencedTable->addUniqueConstraint(['c1', 'c2']); + + $this->connection->createSchemaManager()->createTable($referencedTable); + + $this->testRenameColumn(static function (Table $table): void { + $table->addForeignKeyConstraint('rename_column_referenced', ['c1', 'c2'], ['c1', 'c2'], [], 'fk_c1_c2'); + }); + } + + /** + * @param callable(Table): void $modifier + * + * @throws Exception + */ + private function testRenameColumn(callable $modifier): void + { + $this->dropTableIfExists('rename_column'); + + $table = new Table('rename_column'); + $table->addColumn('c1', Types::INTEGER); + $table->addColumn('c2', Types::INTEGER); + $modifier($table); + $table->renameColumn('c1', 'c1a'); + + $this->connection->createSchemaManager()->createTable($table); + + self::assertTrue($this->comparator->compareTables( + $table, + $this->schemaManager->introspectTable('rename_column'), + )->isEmpty()); + } +} diff --git a/tests/Functional/Types/BigIntTypeTest.php b/tests/Functional/Types/BigIntTypeTest.php index 65dbdcfcdb9..386a8e91eec 100644 --- a/tests/Functional/Types/BigIntTypeTest.php +++ b/tests/Functional/Types/BigIntTypeTest.php @@ -10,8 +10,6 @@ use Doctrine\DBAL\Types\Types; use Generator; use PHPUnit\Framework\Attributes\DataProvider; -use PHPUnit\Framework\Constraint\IsIdentical; -use PHPUnit\Framework\Constraint\LogicalOr; use const PHP_INT_MAX; use const PHP_INT_MIN; @@ -49,44 +47,10 @@ public static function provideBigIntLiterals(): Generator yield 'null' => ['null', null]; yield 'positive number' => ['42', 42]; yield 'negative number' => ['-42', -42]; - - if (PHP_INT_SIZE < 8) { - // The following tests only work on 64bit systems. - return; - } - - yield 'large positive number' => ['9223372036854775806', PHP_INT_MAX - 1]; - yield 'large negative number' => ['-9223372036854775807', PHP_INT_MIN + 1]; - } - - #[DataProvider('provideBigIntEdgeLiterals')] - public function testSelectBigIntEdge(int $value): void - { - $table = new Table('bigint_type_test'); - $table->addColumn('id', Types::SMALLINT, ['notnull' => true]); - $table->addColumn('my_integer', Types::BIGINT, ['notnull' => false]); - $table->setPrimaryKey(['id']); - $this->dropAndCreateTable($table); - - $this->connection->executeStatement(<<connection->convertToPHPValue( - $this->connection->fetchOne('SELECT my_integer from bigint_type_test WHERE id = 42'), - Types::BIGINT, - ), - LogicalOr::fromConstraints(new IsIdentical($value), new IsIdentical((string) $value)), - ); - } - - /** @return Generator */ - public static function provideBigIntEdgeLiterals(): Generator - { - yield 'max int' => [PHP_INT_MAX]; - yield 'min int' => [PHP_INT_MIN]; + yield 'large positive number' => [PHP_INT_SIZE === 4 ? '2147483646' : '9223372036854775806', PHP_INT_MAX - 1]; + yield 'large negative number' => [PHP_INT_SIZE === 4 ? '-2147483647' : '-9223372036854775807', PHP_INT_MIN + 1]; + yield 'largest positive number' => [PHP_INT_SIZE === 4 ? '2147483647' : '9223372036854775807', PHP_INT_MAX]; + yield 'largest negative number' => [PHP_INT_SIZE === 4 ? '-2147483648' : '-9223372036854775808', PHP_INT_MIN]; } public function testUnsignedBigIntOnMySQL(): void diff --git a/tests/Schema/TableTest.php b/tests/Schema/TableTest.php index 7293d8cfd67..035313bb6df 100644 --- a/tests/Schema/TableTest.php +++ b/tests/Schema/TableTest.php @@ -15,6 +15,7 @@ use Doctrine\DBAL\Schema\UniqueConstraint; use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Types; +use Doctrine\Deprecations\PHPUnit\VerifyDeprecations; use LogicException; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; @@ -24,6 +25,8 @@ class TableTest extends TestCase { + use VerifyDeprecations; + public function testCreateWithInvalidTableName(): void { $this->expectException(Exception::class); @@ -101,6 +104,36 @@ public function testRenameColumnLoop(): void self::assertCount(0, $table->getRenamedColumns()); } + public function testRenameColumnInIndex(): void + { + $table = new Table('t'); + $table->addColumn('c1', Types::INTEGER); + $table->addColumn('c2', Types::INTEGER); + $table->addIndex(['c1', 'c2'], 'idx_c1_c2'); + $table->renameColumn('c1', 'c1a'); + self::assertSame(['c1a', 'c2'], $table->getIndex('idx_c1_c2')->getColumns()); + } + + public function testRenameColumnInForeignKeyConstraint(): void + { + $table = new Table('t1'); + $table->addColumn('c1', Types::INTEGER); + $table->addColumn('c2', Types::INTEGER); + $table->addForeignKeyConstraint('t2', ['c1', 'c2'], ['c1', 'c2'], [], 'fk_c1_c2'); + $table->renameColumn('c2', 'c2a'); + self::assertSame(['c1', 'c2a'], $table->getForeignKey('fk_c1_c2')->getLocalColumns()); + } + + public function testRenameColumnInUniqueConstraint(): void + { + $table = new Table('t'); + $table->addColumn('c1', Types::INTEGER); + $table->addColumn('c2', Types::INTEGER); + $table->addUniqueConstraint(['c1', 'c2'], 'uq_c1_c2'); + $table->renameColumn('c1', 'c1a'); + self::assertSame(['c1a', 'c2'], $table->getUniqueConstraint('uq_c1_c2')->getColumns()); + } + public function testColumnsCaseInsensitive(): void { $table = new Table('foo'); @@ -905,4 +938,33 @@ public function testRemoveUniqueConstraintUnknownNameThrowsException(): void $table->removeUniqueConstraint('unique_constraint'); } + + public function testDropColumnWithForeignKeyConstraint(): void + { + $table = new Table('t1'); + $table->addColumn('id', Types::INTEGER); + $table->addForeignKeyConstraint('t2', ['id'], ['id']); + + $this->expectDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/6559'); + $table->dropColumn('id'); + } + + public function testDropColumnWithUniqueConstraint(): void + { + $table = new Table('t'); + $table->addColumn('id', Types::INTEGER); + $table->addUniqueConstraint(['id']); + + $this->expectDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/6559'); + $table->dropColumn('id'); + } + + public function testDropColumnWithoutConstraints(): void + { + $table = new Table('t'); + $table->addColumn('id', Types::INTEGER); + + $this->expectNoDeprecationWithIdentifier('https://github.com/doctrine/dbal/pull/6559'); + $table->dropColumn('id'); + } }