Skip to content

Commit

Permalink
Merge branch '3.9.x' into 4.2.x
Browse files Browse the repository at this point in the history
  • Loading branch information
morozov committed Feb 2, 2025
2 parents 77a6041 + a1932ce commit dd703ec
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 170 deletions.
8 changes: 7 additions & 1 deletion src/Platforms/SQLServerPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -1198,11 +1198,17 @@ protected function getLikeWildcardCharacters(): 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)),
);
Expand Down
27 changes: 20 additions & 7 deletions src/Schema/PostgreSQLSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,16 @@ protected function _getPortableTableIndexesList(array $tableIndexes, string $tab
foreach ($tableIndexes as $row) {
$colNumbers = array_map('intval', explode(' ', $row['indkey']));
$columnNameSql = sprintf(
'SELECT attnum, attname FROM pg_attribute WHERE attrelid=%d AND attnum IN (%s) ORDER BY attnum ASC',
<<<'SQL'

Check warning on line 164 in src/Schema/PostgreSQLSchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/PostgreSQLSchemaManager.php#L164

Added line #L164 was not covered by tests
SELECT attnum,
quote_ident(attname) AS attname
FROM pg_attribute
WHERE attrelid = %d
AND attnum IN (%s)
ORDER BY attnum
SQL,

Check warning on line 171 in src/Schema/PostgreSQLSchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/PostgreSQLSchemaManager.php#L171

Added line #L171 was not covered by tests
$row['indrelid'],
implode(' ,', $colNumbers),
implode(', ', $colNumbers),

Check warning on line 173 in src/Schema/PostgreSQLSchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/PostgreSQLSchemaManager.php#L173

Added line #L173 was not covered by tests
);

$indexColumns = $this->connection->fetchAllAssociative($columnNameSql);
Expand Down Expand Up @@ -412,7 +419,7 @@ protected function selectTableColumns(string $databaseName, ?string $tableName =
$sql = 'SELECT ';

if ($tableName === null) {
$sql .= 'c.relname AS table_name, n.nspname AS schema_name,';
$sql .= 'quote_ident(c.relname) AS table_name, quote_ident(n.nspname) AS schema_name,';

Check warning on line 422 in src/Schema/PostgreSQLSchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/PostgreSQLSchemaManager.php#L422

Added line #L422 was not covered by tests
}

$sql .= sprintf(<<<'SQL'
Expand Down Expand Up @@ -478,7 +485,7 @@ protected function selectIndexColumns(string $databaseName, ?string $tableName =
$sql = 'SELECT';

if ($tableName === null) {
$sql .= ' tc.relname AS table_name, tn.nspname AS schema_name,';
$sql .= ' quote_ident(tc.relname) AS table_name, quote_ident(tn.nspname) AS schema_name,';

Check warning on line 488 in src/Schema/PostgreSQLSchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/PostgreSQLSchemaManager.php#L488

Added line #L488 was not covered by tests
}

$sql .= <<<'SQL'
Expand Down Expand Up @@ -512,7 +519,7 @@ protected function selectForeignKeyColumns(string $databaseName, ?string $tableN
$sql = 'SELECT';

if ($tableName === null) {
$sql .= ' tc.relname AS table_name, tn.nspname AS schema_name,';
$sql .= ' quote_ident(tc.relname) AS table_name, quote_ident(tn.nspname) AS schema_name,';

Check warning on line 522 in src/Schema/PostgreSQLSchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/PostgreSQLSchemaManager.php#L522

Added line #L522 was not covered by tests
}

$sql .= <<<'SQL'
Expand Down Expand Up @@ -540,7 +547,8 @@ protected function selectForeignKeyColumns(string $databaseName, ?string $tableN
protected function fetchTableOptionsByTable(string $databaseName, ?string $tableName = null): array
{
$sql = <<<'SQL'
SELECT c.relname,
SELECT quote_ident(n.nspname) AS schema_name,
quote_ident(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
Expand All @@ -552,7 +560,12 @@ protected function fetchTableOptionsByTable(string $databaseName, ?string $table

$sql .= ' WHERE ' . implode(' AND ', $conditions);

return $this->connection->fetchAllAssociativeIndexed($sql);
$tableOptions = [];
foreach ($this->connection->iterateAssociative($sql) as $row) {
$tableOptions[$this->_getPortableTableDefinition($row)] = $row;

Check warning on line 565 in src/Schema/PostgreSQLSchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/PostgreSQLSchemaManager.php#L563-L565

Added lines #L563 - L565 were not covered by tests
}

return $tableOptions;

Check warning on line 568 in src/Schema/PostgreSQLSchemaManager.php

View check run for this annotation

Codecov / codecov/patch

src/Schema/PostgreSQLSchemaManager.php#L568

Added line #L568 was not covered by tests
}

/** @return list<string> */
Expand Down
26 changes: 15 additions & 11 deletions src/Schema/SQLServerSchemaManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,15 @@ protected function _getPortableTableForeignKeysList(array $tableForeignKeys): ar
$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' => [
Expand Down Expand Up @@ -443,31 +449,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<string,array<string,mixed>> $metadata */
$metadata = $this->connection->executeQuery($sql, $params)
->fetchAllAssociativeIndexed();

$tableOptions = [];
foreach ($metadata as $table => $data) {
foreach ($this->connection->iterateAssociative($sql) as $data) {
$data = array_change_key_case($data, CASE_LOWER);

$tableOptions[$table] = [
$tableOptions[$this->_getPortableTableDefinition($data)] = [
'comment' => $data['table_comment'],
];
}
Expand Down
112 changes: 0 additions & 112 deletions tests/Functional/Schema/OracleSchemaManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,118 +69,6 @@ public function testAlterTableColumnNotNull(): void
self::assertTrue($columns['bar']->getNotnull());
}

public function testListTableDetailsWithDifferentIdentifierQuotingRequirements(): void
{
$primaryTableName = '"Primary_Table"';
$offlinePrimaryTable = new Table($primaryTableName);
$offlinePrimaryTable->addColumn(
'"Id"',
Types::INTEGER,
['autoincrement' => true],
);
$offlinePrimaryTable->addColumn('select', Types::INTEGER);
$offlinePrimaryTable->addColumn('foo', Types::INTEGER);
$offlinePrimaryTable->addColumn('BAR', Types::INTEGER);
$offlinePrimaryTable->addColumn('"BAZ"', Types::INTEGER);
$offlinePrimaryTable->addIndex(['select'], 'from');
$offlinePrimaryTable->addIndex(['foo'], 'foo_index');
$offlinePrimaryTable->addIndex(['BAR'], 'BAR_INDEX');
$offlinePrimaryTable->addIndex(['"BAZ"'], 'BAZ_INDEX');
$offlinePrimaryTable->setPrimaryKey(['"Id"']);

$foreignTableName = 'foreign';
$offlineForeignTable = new Table($foreignTableName);
$offlineForeignTable->addColumn('id', Types::INTEGER, ['autoincrement' => true]);
$offlineForeignTable->addColumn('"Fk"', Types::INTEGER);
$offlineForeignTable->addIndex(['"Fk"'], '"Fk_index"');
$offlineForeignTable->addForeignKeyConstraint(
$primaryTableName,
['"Fk"'],
['"Id"'],
[],
'"Primary_Table_Fk"',
);
$offlineForeignTable->setPrimaryKey(['id']);

$this->dropTableIfExists($foreignTableName);
$this->dropTableIfExists($primaryTableName);

$this->schemaManager->createTable($offlinePrimaryTable);
$this->schemaManager->createTable($offlineForeignTable);

$onlinePrimaryTable = $this->schemaManager->introspectTable($primaryTableName);
$onlineForeignTable = $this->schemaManager->introspectTable($foreignTableName);

$platform = $this->connection->getDatabasePlatform();

// Primary table assertions
self::assertSame($primaryTableName, $onlinePrimaryTable->getQuotedName($platform));

self::assertTrue($onlinePrimaryTable->hasColumn('"Id"'));
self::assertSame('"Id"', $onlinePrimaryTable->getColumn('"Id"')->getQuotedName($platform));

$onlinePrimaryTablePrimaryKey = $onlinePrimaryTable->getPrimaryKey();
self::assertNotNull($onlinePrimaryTablePrimaryKey);
self::assertSame(['"Id"'], $onlinePrimaryTablePrimaryKey->getQuotedColumns($platform));

self::assertTrue($onlinePrimaryTable->hasColumn('select'));
self::assertSame('"select"', $onlinePrimaryTable->getColumn('select')->getQuotedName($platform));

self::assertTrue($onlinePrimaryTable->hasColumn('foo'));
self::assertSame('FOO', $onlinePrimaryTable->getColumn('foo')->getQuotedName($platform));

self::assertTrue($onlinePrimaryTable->hasColumn('BAR'));
self::assertSame('BAR', $onlinePrimaryTable->getColumn('BAR')->getQuotedName($platform));

self::assertTrue($onlinePrimaryTable->hasColumn('"BAZ"'));
self::assertSame('BAZ', $onlinePrimaryTable->getColumn('"BAZ"')->getQuotedName($platform));

self::assertTrue($onlinePrimaryTable->hasIndex('from'));
self::assertTrue($onlinePrimaryTable->getIndex('from')->hasColumnAtPosition('"select"'));
self::assertSame(['"select"'], $onlinePrimaryTable->getIndex('from')->getQuotedColumns($platform));

self::assertTrue($onlinePrimaryTable->hasIndex('foo_index'));
self::assertTrue($onlinePrimaryTable->getIndex('foo_index')->hasColumnAtPosition('foo'));
self::assertSame(['FOO'], $onlinePrimaryTable->getIndex('foo_index')->getQuotedColumns($platform));

self::assertTrue($onlinePrimaryTable->hasIndex('BAR_INDEX'));
self::assertTrue($onlinePrimaryTable->getIndex('BAR_INDEX')->hasColumnAtPosition('BAR'));
self::assertSame(['BAR'], $onlinePrimaryTable->getIndex('BAR_INDEX')->getQuotedColumns($platform));

self::assertTrue($onlinePrimaryTable->hasIndex('BAZ_INDEX'));
self::assertTrue($onlinePrimaryTable->getIndex('BAZ_INDEX')->hasColumnAtPosition('"BAZ"'));
self::assertSame(['BAZ'], $onlinePrimaryTable->getIndex('BAZ_INDEX')->getQuotedColumns($platform));

// Foreign table assertions
self::assertTrue($onlineForeignTable->hasColumn('id'));
self::assertSame('ID', $onlineForeignTable->getColumn('id')->getQuotedName($platform));

$onlineForeignTablePrimaryKey = $onlineForeignTable->getPrimaryKey();
self::assertNotNull($onlineForeignTablePrimaryKey);
self::assertSame(['ID'], $onlineForeignTablePrimaryKey->getQuotedColumns($platform));

self::assertTrue($onlineForeignTable->hasColumn('"Fk"'));
self::assertSame('"Fk"', $onlineForeignTable->getColumn('"Fk"')->getQuotedName($platform));

self::assertTrue($onlineForeignTable->hasIndex('"Fk_index"'));
self::assertTrue($onlineForeignTable->getIndex('"Fk_index"')->hasColumnAtPosition('"Fk"'));
self::assertSame(['"Fk"'], $onlineForeignTable->getIndex('"Fk_index"')->getQuotedColumns($platform));

self::assertTrue($onlineForeignTable->hasForeignKey('"Primary_Table_Fk"'));
self::assertSame(
$primaryTableName,
$onlineForeignTable->getForeignKey('"Primary_Table_Fk"')->getQuotedForeignTableName($platform),
);
self::assertSame(
['"Fk"'],
$onlineForeignTable->getForeignKey('"Primary_Table_Fk"')->getQuotedLocalColumns($platform),
);
self::assertSame(
['"Id"'],
$onlineForeignTable->getForeignKey('"Primary_Table_Fk"')->getQuotedForeignColumns($platform),
);
}

public function testListTableColumnsSameTableNamesInDifferentSchemas(): void
{
$table = $this->createListTableColumns();
Expand Down
39 changes: 0 additions & 39 deletions tests/Functional/Schema/PostgreSQLSchemaManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
use PHPUnit\Framework\Attributes\DataProvider;

use function array_map;
use function array_pop;
use function count;
use function sprintf;
use function strtolower;
Expand Down Expand Up @@ -121,44 +120,6 @@ public function testAlterTableAutoIncrementDrop(): void
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->getName(), ['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::assertNotNull($relatedFk);
self::assertEquals('nested.schemarelated', $relatedFk->getForeignTableName());
}

public function testListSameTableNameColumnsWithDifferentSchema(): void
{
$this->connection->executeStatement('CREATE SCHEMA another');
Expand Down
Loading

0 comments on commit dd703ec

Please sign in to comment.