Skip to content

Commit

Permalink
Apply the connection filter to indexes
Browse files Browse the repository at this point in the history
When there are indexes that are not supported by doctrine present in
a database, they will consistently create "DROP" migrations.  By
applying the schema filter to the indexes one will be able to exclude
these indexes from future migrations preventing the manual work of
removing the DROP statement each time a migration is created.

Fixes: #5420
  • Loading branch information
Allen Lai committed Jul 17, 2023
1 parent 1c462ee commit a56327c
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 8 deletions.
39 changes: 31 additions & 8 deletions src/Schema/AbstractSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ public function listTableIndexes($table)

$tableIndexes = $this->_conn->fetchAllAssociative($sql);

return $this->_getPortableTableIndexesList($tableIndexes, $table);
return $this->filterIndexAssets($this->_getPortableTableIndexesList($tableIndexes, $table));
}

/**
Expand All @@ -289,12 +289,14 @@ protected function doListTableIndexes($table): array
$database = $this->getDatabase(__METHOD__);
$table = $this->normalizeName($table);

return $this->_getPortableTableIndexesList(
$this->selectIndexColumns(
$database,
return $this->filterIndexAssets(
$this->_getPortableTableIndexesList(
$this->selectIndexColumns(
$database,
$table,
)->fetchAllAssociative(),
$table,
)->fetchAllAssociative(),
$table,
),
);
}

Expand Down Expand Up @@ -377,6 +379,26 @@ protected function filterAssetNames($assetNames)
return array_values(array_filter($assetNames, $filter));
}

/**
* @param array<int|string, Index> $indexes
*
* @return array<int|string, Index>
*/
protected function filterIndexAssets(array $indexes): array
{
$filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter();
if ($filter === null) {
return $indexes;
}

return array_filter(
$indexes,
static function (Index $i) use ($filter): bool {
return $filter($i->getName());
},
);
}

/**
* Lists the tables for this connection.
*
Expand Down Expand Up @@ -418,10 +440,11 @@ protected function doListTables(): array
continue;
}

$tables[] = new Table(
$tableIndexes = $this->_getPortableTableIndexesList($indexColumnsByTable[$tableName] ?? [], $tableName);
$tables[] = new Table(
$tableName,
$this->_getPortableTableColumnList($tableName, $database, $tableColumns),
$this->_getPortableTableIndexesList($indexColumnsByTable[$tableName] ?? [], $tableName),
$this->filterIndexAssets($tableIndexes),
[],
$this->_getPortableTableForeignKeysList($foreignKeyColumnsByTable[$tableName] ?? []),
$tableOptionsByTable[$tableName] ?? [],
Expand Down
42 changes: 42 additions & 0 deletions tests/Functional/Schema/SchemaManagerFunctionalTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,48 @@ public static function tableFilterProvider(): iterable
yield 'Two tables' => ['filter_test_', 2];
}

/** @dataProvider indexFilterProvider */
public function testListTableIndexesWithFilter(string $prefix, int $expectedCount): void
{
$tableName = 'list_table_indexes_test';
$table = $this->getTestTable($tableName);
$table->addUniqueIndex(['test'], 'test_index_name');
$table->addIndex(['id', 'test'], 'test_composite_idx');

$this->dropAndCreateTable($table);

$this->markConnectionNotReusable();

$this->connection->getConfiguration()->setSchemaAssetsFilter(
static function (string $name) use ($prefix): bool {
return substr(strtolower($name), 0, strlen($prefix)) !== $prefix;
},
);

$table = null;
foreach ($this->schemaManager->listTables() as $t) {
if ($tableName !== $t->getName()) {
continue;
}

$table = $t;
}

self::assertNotNull($table);
self::assertCount($expectedCount, $this->schemaManager->listTableIndexes($tableName));
self::assertCount($expectedCount, $table->getIndexes());
}

/** @return iterable<string, array{string, int}> */
public static function indexFilterProvider(): iterable
{
// index count includes the primary key on the table
yield 'Filter index' => ['test_index_', 2];
yield 'Filter unique index' => ['test_composite', 2];
yield 'No indexes returned' => ['test_', 1];
yield 'Both indexes returned' => ['includes_all', 3];
}

public function testRenameTable(): void
{
$this->createTestTable('old_name');
Expand Down

0 comments on commit a56327c

Please sign in to comment.