Skip to content
Draft
26 changes: 22 additions & 4 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@ awareness about deprecated code.

# Upgrade to 5.0

## BC BREAK: Introspection reports the indexes backing constraints

`AbstractSchemaManager::introspectTableIndexes()` now returns the indexes the database created to enforce a table's
primary key and unique constraints.

## BC BREAK: No index is created for a foreign key constraint

Declaring a foreign key constraint no longer adds an index over its referencing columns. MySQL and MariaDB create one
themselves; on the other platforms, an application that wants such an index must declare it.

## BC BREAK: A unique constraint to be dropped must have a name

`Comparator::compareTables()` now compares unique constraints, and raises
`Doctrine\DBAL\Schema\Exception\UnspecifiedConstraintName` when one that has to be dropped carries no name.

## BC BREAK: Added `AbstractPlatform::createDerivedObjectProvider()`

`Doctrine\DBAL\Platforms\AbstractPlatform` now declares `createDerivedObjectProvider()`. Platforms extending it must
implement the method.

## BC BREAK: Foreign key constraints are compared by name

`Comparator::compareTables()` compares the names of foreign key constraints, so one whose name differs is reported as
Expand Down Expand Up @@ -282,10 +302,8 @@ The following conflicting index configurations are no longer allowed:

## BC BREAK: Changes in features related to primary key constraints

1. The `Index` class can no longer represent a primary key constraint. As a result:
1. The `Table::getIndexes()` and `AbstractSchemaManager::listTableIndexes()` methods no longer return the index that
backs the primary key constraint.
2. The index that backs the primary key constraint is no longer considered during implicit index management.
1. The `Index` class can no longer represent a primary key constraint. The index that backs one is still reported as an
ordinary index by `Table::getIndexes()` and `AbstractSchemaManager::introspectTableIndexes()`.
2. The `Table::getPrimaryKey()` and `Table::setPrimaryKey()` methods have been removed.
3. The `Table::renameIndex()` method can no longer be used to rename a primary key constraint.
4. The `AbstractPlatform::getCreatePrimaryKeySQL()` method has been removed.
Expand Down
75 changes: 0 additions & 75 deletions docs/en/explanation/implicit-indexes.rst

This file was deleted.

6 changes: 0 additions & 6 deletions docs/en/sidebar.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@
/reference/testing


.. toctree::
:caption: Explanation
:depth: 3

/explanation/implicit-indexes

.. toctree::
:caption: How To
:depth: 3
Expand Down
105 changes: 105 additions & 0 deletions src/Platforms/AbstractDerivedObjectProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Platforms;

use Doctrine\DBAL\Schema\DerivedObject;
use Doctrine\DBAL\Schema\DerivedObjectKind;
use Doctrine\DBAL\Schema\DerivedObjectProvider;
use Doctrine\DBAL\Schema\Index;
use Doctrine\DBAL\Schema\PrimaryKeyConstraint;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\UniqueConstraint;
use Override;

use function array_merge;

/** @internal */
abstract class AbstractDerivedObjectProvider implements DerivedObjectProvider
{
/**
* {@inheritDoc}
*
* @return list<DerivedObject>
*/
#[Override]
final public function getDerivedObjects(Table $table): array
{
return array_merge(
$this->derive($table, $table->getIndexes(), $this->deriveObjectFromIndex(...)),
$this->deriveFromPrimaryKeyConstraint($table),
$this->derive($table, $table->getUniqueConstraints(), $this->deriveObjectFromUniqueConstraint(...)),
$this->deriveObjectsFromForeignKeyConstraints($table),
);
}

protected function deriveObjectFromIndex(Table $table, Index $index): ?DerivedObject
{
return null;
}

/** @return list<DerivedObject> */
private function deriveFromPrimaryKeyConstraint(Table $table): array
{
$primaryKeyConstraint = $table->getPrimaryKeyConstraint();

if ($primaryKeyConstraint === null) {
return [];
}

$derivedObject = $this->deriveObjectFromPrimaryKeyConstraint($table, $primaryKeyConstraint);

if ($derivedObject === null) {
return [];
}

return [$derivedObject];
}

protected function deriveObjectFromPrimaryKeyConstraint(
Table $table,
PrimaryKeyConstraint $constraint,
): ?DerivedObject {
return new DerivedObject(DerivedObjectKind::UniqueIndex, $constraint->getColumnNames());
}

protected function deriveObjectFromUniqueConstraint(Table $table, UniqueConstraint $constraint): ?DerivedObject
{
return new DerivedObject(DerivedObjectKind::UniqueIndex, $constraint->getColumnNames());
}

/**
* The foreign key constraints are derived from as a whole: a platform that indexes them may serve
* more than one with a single index.
*
* @return list<DerivedObject>
*/
protected function deriveObjectsFromForeignKeyConstraints(Table $table): array
{
return [];
}

/**
* @param iterable<T> $sources
* @param callable(Table, T): ?DerivedObject $deriveOne
*
* @return list<DerivedObject>
*
* @template T
*/
private function derive(Table $table, iterable $sources, callable $deriveOne): array
{
$derivedObjects = [];

foreach ($sources as $source) {
$derivedObject = $deriveOne($table, $source);

if ($derivedObject !== null) {
$derivedObjects[] = $derivedObject;
}
}

return $derivedObjects;
}
}
15 changes: 15 additions & 0 deletions src/Platforms/AbstractMySQLPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception\InvalidColumnType\ColumnValuesRequired;
use Doctrine\DBAL\Platforms\MySQL\MySQLDerivedObjectProvider;
use Doctrine\DBAL\Platforms\MySQL\MySQLMetadataProvider;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
use Doctrine\DBAL\Schema\ForeignKeyConstraint\MatchType;
Expand Down Expand Up @@ -329,6 +330,10 @@ public function getAlterTableSQL(TableDiff $diff): array
$sql[] = $this->getDropForeignKeySQL($constraintName->toSQL($this), $tableNameSQL);
}

foreach ($diff->getDroppedUniqueConstraintNames() as $constraintName) {
$sql[] = $this->getDropUniqueConstraintSQL($constraintName->toSQL($this), $tableNameSQL);
}

$queryParts = [];

foreach ($diff->getAddedColumns() as $column) {
Expand Down Expand Up @@ -383,6 +388,10 @@ public function getAlterTableSQL(TableDiff $diff): array
$sql[] = $this->getCreateForeignKeySQL($addedForeignKeyConstraint, $tableNameSQL);
}

foreach ($diff->getAddedUniqueConstraints() as $uniqueConstraint) {
$sql[] = $this->getCreateUniqueConstraintSQL($uniqueConstraint, $tableNameSQL);
}

return $sql;
}

Expand Down Expand Up @@ -637,6 +646,12 @@ public function createMetadataProvider(Connection $connection): MySQLMetadataPro
return new MySQLMetadataProvider($connection, $this);
}

#[Override]
public function createDerivedObjectProvider(): MySQLDerivedObjectProvider
{
return new MySQLDerivedObjectProvider($this->getUnquotedIdentifierFolding());
}

#[Override]
public function createSchemaManager(Connection $connection): MySQLSchemaManager
{
Expand Down
9 changes: 9 additions & 0 deletions src/Platforms/AbstractPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\DefaultExpression;
use Doctrine\DBAL\Schema\DerivedObjectProvider;
use Doctrine\DBAL\Schema\Exception\InvalidName;
use Doctrine\DBAL\Schema\Exception\UnspecifiedConstraintName;
use Doctrine\DBAL\Schema\ForeignKeyConstraint;
Expand Down Expand Up @@ -2199,6 +2200,14 @@ public function getUnquotedIdentifierFolding(): UnquotedIdentifierFolding
*/
abstract public function createMetadataProvider(Connection $connection): MetadataProvider;

/**
* Creates a provider of the schema objects this platform derives from the ones a table declares.
*
* A caller holding a desired table can ask what the database will add to it: the indexes and
* constraints the table will have without having declared them.
*/
abstract public function createDerivedObjectProvider(): DerivedObjectProvider;

/**
* Creates the schema manager that can be used to inspect and change the underlying
* database schema according to the dialect of the platform.
Expand Down
15 changes: 15 additions & 0 deletions src/Platforms/DB2Platform.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Doctrine\DBAL\Platforms;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\Db2\Db2DerivedObjectProvider;
use Doctrine\DBAL\Platforms\Db2\Db2MetadataProvider;
use Doctrine\DBAL\Platforms\Exception\NotSupported;
use Doctrine\DBAL\Schema\ColumnDiff;
Expand Down Expand Up @@ -260,6 +261,10 @@ public function getAlterTableSQL(TableDiff $diff): array
$sql[] = $this->getDropForeignKeySQL($constraintName->toSQL($this), $tableNameSQL);
}

foreach ($diff->getDroppedUniqueConstraintNames() as $constraintName) {
$sql[] = $this->getDropUniqueConstraintSQL($constraintName->toSQL($this), $tableNameSQL);
}

foreach ($diff->getDroppedIndexes() as $index) {
$sql[] = $this->getDropIndexSQL($index->getObjectName()->toSQL($this), $tableNameSQL);
}
Expand Down Expand Up @@ -349,6 +354,10 @@ public function getAlterTableSQL(TableDiff $diff): array
$sql[] = $this->getCreateForeignKeySQL($foreignKey, $tableNameSQL);
}

foreach ($diff->getAddedUniqueConstraints() as $uniqueConstraint) {
$sql[] = $this->getCreateUniqueConstraintSQL($uniqueConstraint, $tableNameSQL);
}

foreach ($diff->getAddedIndexes() as $index) {
$sql[] = $this->getCreateIndexSQL($index, $tableNameSQL);
}
Expand Down Expand Up @@ -583,6 +592,12 @@ public function createMetadataProvider(Connection $connection): Db2MetadataProvi
return new Db2MetadataProvider($connection, $this);
}

#[Override]
public function createDerivedObjectProvider(): Db2DerivedObjectProvider
{
return new Db2DerivedObjectProvider();
}

#[Override]
public function createSchemaManager(Connection $connection): DB2SchemaManager
{
Expand Down
12 changes: 12 additions & 0 deletions src/Platforms/Db2/Db2DerivedObjectProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Doctrine\DBAL\Platforms\Db2;

use Doctrine\DBAL\Platforms\AbstractDerivedObjectProvider;

/** @internal */
final class Db2DerivedObjectProvider extends AbstractDerivedObjectProvider
{
}
1 change: 0 additions & 1 deletion src/Platforms/Db2/Db2MetadataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,6 @@ private function getIndexColumns(?string $tableName): iterable
AND I.INDNAME = ICU.INDNAME
WHERE %s
AND T.TYPE = 'T'
AND I.UNIQUERULE != 'P'
ORDER BY I.TABNAME,
I.INDNAME,
ICU.COLSEQ
Expand Down
4 changes: 3 additions & 1 deletion src/Platforms/MySQL/Comparator.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Doctrine\DBAL\Schema\ColumnEditor;
use Doctrine\DBAL\Schema\Comparator as BaseComparator;
use Doctrine\DBAL\Schema\ComparatorConfig;
use Doctrine\DBAL\Schema\DerivedObjectProvider;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
use Override;
Expand All @@ -26,12 +27,13 @@ class Comparator extends BaseComparator
/** @internal The comparator can be only instantiated by a schema manager. */
public function __construct(
AbstractMySQLPlatform $platform,
DerivedObjectProvider $derivedObjectProvider,
private readonly CharsetMetadataProvider $charsetMetadataProvider,
private readonly CollationMetadataProvider $collationMetadataProvider,
private readonly DefaultTableOptions $defaultTableOptions,
ComparatorConfig $config = new ComparatorConfig(),
) {
parent::__construct($platform, $config);
parent::__construct($platform, $derivedObjectProvider, $config);
}

#[Override]
Expand Down
Loading
Loading