diff --git a/src/Platforms/SQLServerPlatform.php b/src/Platforms/SQLServerPlatform.php index 16d7bd4e73..eed1cbab4d 100644 --- a/src/Platforms/SQLServerPlatform.php +++ b/src/Platforms/SQLServerPlatform.php @@ -38,6 +38,7 @@ use function preg_match; use function preg_match_all; use function sprintf; +use function str_contains; use function str_ends_with; use function str_replace; use function str_starts_with; @@ -1777,11 +1778,17 @@ private function generateIdentifierName($identifier): string protected function getCommentOnTableSQL(string $tableName, ?string $comment): string { + if (str_contains($tableName, '.')) { + [$schemaName, $tableName] = explode('.', $tableName); + } else { + $schemaName = 'dbo'; + } + return $this->getAddExtendedPropertySQL( 'MS_Description', $comment, 'SCHEMA', - $this->quoteStringLiteral('dbo'), + $this->quoteStringLiteral($schemaName), 'TABLE', $this->quoteStringLiteral($this->unquoteSingleIdentifier($tableName)), ); diff --git a/src/Schema/PostgreSQLSchemaManager.php b/src/Schema/PostgreSQLSchemaManager.php index bfa9a182db..716d5da576 100644 --- a/src/Schema/PostgreSQLSchemaManager.php +++ b/src/Schema/PostgreSQLSchemaManager.php @@ -733,7 +733,8 @@ protected function selectForeignKeyColumns(string $databaseName, ?string $tableN protected function fetchTableOptionsByTable(string $databaseName, ?string $tableName = null): array { $sql = <<<'SQL' -SELECT c.relname, +SELECT n.nspname AS schema_name, + c.relname AS table_name, CASE c.relpersistence WHEN 'u' THEN true ELSE false END as unlogged, obj_description(c.oid, 'pg_class') AS comment FROM pg_class c @@ -745,7 +746,12 @@ protected function fetchTableOptionsByTable(string $databaseName, ?string $table $sql .= ' WHERE ' . implode(' AND ', $conditions); - return $this->_conn->fetchAllAssociativeIndexed($sql); + $tableOptions = []; + foreach ($this->_conn->iterateAssociative($sql) as $row) { + $tableOptions[$this->_getPortableTableDefinition($row)] = $row; + } + + return $tableOptions; } /** diff --git a/src/Schema/SQLServerSchemaManager.php b/src/Schema/SQLServerSchemaManager.php index acef511abe..a46e552147 100644 --- a/src/Schema/SQLServerSchemaManager.php +++ b/src/Schema/SQLServerSchemaManager.php @@ -227,9 +227,15 @@ protected function _getPortableTableForeignKeysList($tableForeignKeys) $name = $tableForeignKey['ForeignKey']; if (! isset($foreignKeys[$name])) { + $referencedTableName = $tableForeignKey['ReferenceTableName']; + + if ($tableForeignKey['ReferenceSchemaName'] !== 'dbo') { + $referencedTableName = $tableForeignKey['ReferenceSchemaName'] . '.' . $referencedTableName; + } + $foreignKeys[$name] = [ 'local_columns' => [$tableForeignKey['ColumnName']], - 'foreign_table' => $tableForeignKey['ReferenceTableName'], + 'foreign_table' => $referencedTableName, 'foreign_columns' => [$tableForeignKey['ReferenceColumnName']], 'name' => $name, 'options' => [ @@ -556,31 +562,29 @@ protected function fetchTableOptionsByTable(string $databaseName, ?string $table { $sql = <<<'SQL' SELECT - tbl.name, + scm.name AS schema_name, + tbl.name AS table_name, p.value AS [table_comment] FROM sys.tables AS tbl + JOIN sys.schemas AS scm + ON tbl.schema_id = scm.schema_id INNER JOIN sys.extended_properties AS p ON p.major_id=tbl.object_id AND p.minor_id=0 AND p.class=1 SQL; - $conditions = ["SCHEMA_NAME(tbl.schema_id) = N'dbo'", "p.name = N'MS_Description'"]; - $params = []; + $conditions = ["p.name = N'MS_Description'"]; if ($tableName !== null) { - $conditions[] = "tbl.name = N'" . $tableName . "'"; + $conditions[] = $this->getTableWhereClause($tableName, 'scm.name', 'tbl.name'); } $sql .= ' WHERE ' . implode(' AND ', $conditions); - /** @var array> $metadata */ - $metadata = $this->_conn->executeQuery($sql, $params) - ->fetchAllAssociativeIndexed(); - $tableOptions = []; - foreach ($metadata as $table => $data) { + foreach ($this->_conn->iterateAssociative($sql) as $data) { $data = array_change_key_case($data, CASE_LOWER); - $tableOptions[$table] = [ + $tableOptions[$this->_getPortableTableDefinition($data)] = [ 'comment' => $data['table_comment'], ]; } diff --git a/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php b/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php index a98bf4d08b..2695b0a31c 100644 --- a/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php +++ b/tests/Functional/Schema/PostgreSQLSchemaManagerTest.php @@ -25,7 +25,6 @@ use function array_map; use function array_merge; -use function array_pop; use function array_unshift; use function assert; use function count; @@ -163,44 +162,6 @@ public function testAlterTableAutoIncrementDrop(callable $comparatorFactory): vo self::assertFalse($tableFinal->getColumn('id')->getAutoincrement()); } - public function testTableWithSchema(): void - { - $this->connection->executeStatement('CREATE SCHEMA nested'); - - $nestedRelatedTable = new Table('nested.schemarelated'); - $column = $nestedRelatedTable->addColumn('id', Types::INTEGER); - $column->setAutoincrement(true); - $nestedRelatedTable->setPrimaryKey(['id']); - - $nestedSchemaTable = new Table('nested.schematable'); - $column = $nestedSchemaTable->addColumn('id', Types::INTEGER); - $column->setAutoincrement(true); - $nestedSchemaTable->setPrimaryKey(['id']); - $nestedSchemaTable->addForeignKeyConstraint($nestedRelatedTable, ['id'], ['id']); - - $this->schemaManager->createTable($nestedRelatedTable); - $this->schemaManager->createTable($nestedSchemaTable); - - $tableNames = $this->schemaManager->listTableNames(); - self::assertContains('nested.schematable', $tableNames); - - $tables = $this->schemaManager->listTables(); - self::assertNotNull($this->findTableByName($tables, 'nested.schematable')); - - $nestedSchemaTable = $this->schemaManager->introspectTable('nested.schematable'); - self::assertTrue($nestedSchemaTable->hasColumn('id')); - - $primaryKey = $nestedSchemaTable->getPrimaryKey(); - - self::assertNotNull($primaryKey); - self::assertEquals(['id'], $primaryKey->getColumns()); - - $relatedFks = $nestedSchemaTable->getForeignKeys(); - self::assertCount(1, $relatedFks); - $relatedFk = array_pop($relatedFks); - self::assertEquals('nested.schemarelated', $relatedFk->getForeignTableName()); - } - public function testListSameTableNameColumnsWithDifferentSchema(): void { $this->connection->executeStatement('CREATE SCHEMA another'); diff --git a/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php b/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php index 1e4ec5ab76..1eebf4be95 100644 --- a/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php +++ b/tests/Functional/Schema/SchemaManagerFunctionalTestCase.php @@ -1905,6 +1905,49 @@ protected function findTableByName(array $tables, string $name): ?Table return null; } + + public function testTableWithSchema(): void + { + if (! $this->connection->getDatabasePlatform()->supportsSchemas()) { + self::markTestSkipped('The currently used database platform does not support schemas.'); + } + + $this->connection->executeStatement('CREATE SCHEMA nested'); + + $nestedRelatedTable = new Table('nested.schemarelated'); + $column = $nestedRelatedTable->addColumn('id', Types::INTEGER); + $column->setAutoincrement(true); + $nestedRelatedTable->setPrimaryKey(['id']); + + $nestedSchemaTable = new Table('nested.schematable'); + $column = $nestedSchemaTable->addColumn('id', Types::INTEGER); + $column->setAutoincrement(true); + $nestedSchemaTable->setPrimaryKey(['id']); + $nestedSchemaTable->addForeignKeyConstraint($nestedRelatedTable->getName(), ['id'], ['id']); + $nestedSchemaTable->setComment('This is a comment'); + + $this->schemaManager->createTable($nestedRelatedTable); + $this->schemaManager->createTable($nestedSchemaTable); + + $tableNames = $this->schemaManager->listTableNames(); + self::assertContains('nested.schematable', $tableNames); + + $tables = $this->schemaManager->listTables(); + self::assertNotNull($this->findTableByName($tables, 'nested.schematable')); + + $nestedSchemaTable = $this->schemaManager->introspectTable('nested.schematable'); + self::assertTrue($nestedSchemaTable->hasColumn('id')); + + $primaryKey = $nestedSchemaTable->getPrimaryKey(); + self::assertNotNull($primaryKey); + self::assertEquals(['id'], $primaryKey->getColumns()); + + $relatedFks = array_values($nestedSchemaTable->getForeignKeys()); + self::assertCount(1, $relatedFks); + $relatedFk = $relatedFks[0]; + self::assertEquals('nested.schemarelated', $relatedFk->getForeignTableName()); + self::assertEquals('This is a comment', $nestedSchemaTable->getComment()); + } } interface ListTableColumnsDispatchEventListener