From d3b365f36f5a8b3775cfd71bcf31a938c5da691a Mon Sep 17 00:00:00 2001 From: Allen Lai Date: Mon, 17 Jul 2023 06:58:22 -0700 Subject: [PATCH] Apply the connection filter to indexes 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 --- src/Schema/AbstractSchemaManager.php | 39 +++++++++++++---- .../SchemaManagerFunctionalTestCase.php | 42 +++++++++++++++++++ 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/Schema/AbstractSchemaManager.php b/src/Schema/AbstractSchemaManager.php index 7da2b1178db..d7e9900fc62 100644 --- a/src/Schema/AbstractSchemaManager.php +++ b/src/Schema/AbstractSchemaManager.php @@ -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)); } /** @@ -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, + ), ); } @@ -377,6 +379,26 @@ protected function filterAssetNames($assetNames) return array_values(array_filter($assetNames, $filter)); } + /** + * @param array $indexes + * + * @return array + */ + 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. * @@ -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] ?? [], diff --git a/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php b/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php index a99eb536f1e..e9ca3c12df0 100644 --- a/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php +++ b/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php @@ -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 !== strtolower($t->getName())) { + continue; + } + + $table = $t; + } + + self::assertNotNull($table); + self::assertCount($expectedCount, $this->schemaManager->listTableIndexes($tableName)); + self::assertCount($expectedCount, $table->getIndexes()); + } + + /** @return iterable */ + 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');