Skip to content

Commit 9e8eef6

Browse files
committed
Propagate TypeRegistry through SchemaConfig to Table
SchemaConfig now carries a TypeRegistry that is populated by AbstractSchemaManager::createSchemaConfig() from the connection configuration. Schema::createTable() forwards it to each Table so that Table::addColumn() resolves types from the per-connection TypeRegistry instead of falling back to the global static registry. Table's constructor parameter is changed from ?Configuration to ?TypeRegistry directly, since Configuration was only needed to reach its TypeRegistry. A TODO comment is added to ColumnDiff::hasTypeChanged() noting that the current class-based comparison is insufficient now that types are services: same-class aliases (json / json_object) produce false negatives, and distinct service instances of the same class would not be detected. The fix (identity comparison) is left for a follow-up.
1 parent b5bd71c commit 9e8eef6

5 files changed

Lines changed: 26 additions & 4 deletions

File tree

src/Schema/AbstractSchemaManager.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,6 +1456,7 @@ public function createSchemaConfig(): SchemaConfig
14561456
}
14571457

14581458
$schemaConfig->setDefaultTableOptions($params['defaultTableOptions']);
1459+
$schemaConfig->setTypeRegistry($this->connection->getConfiguration()->getTypeRegistry());
14591460

14601461
return $schemaConfig;
14611462
}

src/Schema/ColumnDiff.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,13 @@ public function hasNameChanged(): bool
5454

5555
public function hasTypeChanged(): bool
5656
{
57+
// TODO: This comparison by class is insufficient now that types can be distinct services sharing the same
58+
// class (e.g. two differently configured instances of the same Type subclass). It also produces false
59+
// negatives for built-in aliases that share a class: json and json_object both map to JsonType::class,
60+
// so switching between them is not detected as a change.
61+
// The fix is to compare Type instances by identity (===) once both the introspected schema and the
62+
// target schema are guaranteed to resolve types from the same TypeRegistry, so the flyweight invariant
63+
// (one instance per registered name) holds across both sides of the diff.
5764
return $this->newColumn->getType()::class !== $this->oldColumn->getType()::class;
5865
}
5966

src/Schema/Schema.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class Schema extends AbstractAsset
7272

7373
protected SchemaConfig $_schemaConfig;
7474

75+
7576
/**
7677
* Indicates whether the schema uses unqualified names for its objects. Once this flag is set to true, it won't be
7778
* unset even after the objects with unqualified names have been dropped from the schema.
@@ -391,7 +392,7 @@ public function createNamespace(string $name): self
391392
*/
392393
public function createTable(string $name): Table
393394
{
394-
$table = new Table($name, [], [], [], [], [], $this->_schemaConfig->toTableConfiguration());
395+
$table = new Table($name, [], [], [], [], [], $this->_schemaConfig->toTableConfiguration(), null, $this->_schemaConfig->getTypeRegistry());
395396
$this->_addTable($table);
396397

397398
foreach ($this->_schemaConfig->getDefaultTableOptions() as $option => $value) {

src/Schema/SchemaConfig.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44

55
namespace Doctrine\DBAL\Schema;
66

7+
use Doctrine\DBAL\Types\TypeRegistry;
8+
79
/**
810
* Configuration for a Schema.
911
*/
1012
class SchemaConfig
1113
{
14+
private ?TypeRegistry $typeRegistry = null;
1215
/** @var positive-int */
1316
protected int $maxIdentifierLength = 63;
1417

@@ -67,6 +70,16 @@ public function setDefaultTableOptions(array $defaultTableOptions): void
6770
$this->defaultTableOptions = $defaultTableOptions;
6871
}
6972

73+
public function getTypeRegistry(): ?TypeRegistry
74+
{
75+
return $this->typeRegistry;
76+
}
77+
78+
public function setTypeRegistry(TypeRegistry $typeRegistry): void
79+
{
80+
$this->typeRegistry = $typeRegistry;
81+
}
82+
7083
public function toTableConfiguration(): TableConfiguration
7184
{
7285
return new TableConfiguration($this->maxIdentifierLength);

src/Schema/Table.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
namespace Doctrine\DBAL\Schema;
66

7-
use Doctrine\DBAL\Configuration;
87
use Doctrine\DBAL\Schema\Exception\ColumnAlreadyExists;
98
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
109
use Doctrine\DBAL\Schema\Exception\ForeignKeyDoesNotExist;
@@ -21,6 +20,7 @@
2120
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
2221
use Doctrine\DBAL\Types\Exception\TypesException;
2322
use Doctrine\DBAL\Types\Type;
23+
use Doctrine\DBAL\Types\TypeRegistry;
2424
use Doctrine\Deprecations\Deprecation;
2525
use LogicException;
2626

@@ -101,7 +101,7 @@ public function __construct(
101101
array $options = [],
102102
?TableConfiguration $configuration = null,
103103
?PrimaryKeyConstraint $primaryKeyConstraint = null,
104-
private ?Configuration $dbalConfiguration = null,
104+
private ?TypeRegistry $typeRegistry = null,
105105
) {
106106
if ($name === '') {
107107
throw InvalidTableName::new($name);
@@ -388,7 +388,7 @@ public function columnsAreIndexed(array $columnNames): bool
388388
*/
389389
public function addColumn(string $name, string $typeName, array $options = []): Column
390390
{
391-
$type = $this->dbalConfiguration?->getTypeRegistry()->get($typeName) ?? Type::getType($typeName);
391+
$type = $this->typeRegistry !== null ? $this->typeRegistry->get($typeName) : Type::getType($typeName);
392392

393393
$column = new Column($name, $type, $options);
394394

0 commit comments

Comments
 (0)