Skip to content

Commit

Permalink
Merge pull request #6602 from morozov/sqlserver-rename-to-quoted
Browse files Browse the repository at this point in the history
Fix renaming to quoted names on SQL Server
  • Loading branch information
morozov authored Nov 15, 2024
2 parents 727bd6b + 1300542 commit 579c4dd
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 30 deletions.
51 changes: 25 additions & 26 deletions src/Platforms/SQLServerPlatform.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Doctrine\DBAL\Types\Types;
use InvalidArgumentException;

use function array_map;
use function array_merge;
use function array_unique;
use function array_values;
Expand Down Expand Up @@ -406,18 +407,20 @@ public function getAlterTableSQL(TableDiff $diff): array
$tableNameSQL = $table->getQuotedName($this);

foreach ($diff->getChangedColumns() as $columnDiff) {
$newColumn = $columnDiff->getNewColumn();
$newColumnName = $newColumn->getQuotedName($this);
$newColumn = $columnDiff->getNewColumn();
$oldColumn = $columnDiff->getOldColumn();
$nameChanged = $columnDiff->hasNameChanged();

$oldColumn = $columnDiff->getOldColumn();
$oldColumnName = $oldColumn->getQuotedName($this);
$nameChanged = $columnDiff->hasNameChanged();

// Column names in SQL server are case insensitive and automatically uppercased on the server.
if ($nameChanged) {
// sp_rename accepts the old name as a qualified name, so it should be quoted.
$oldColumnNameSQL = $oldColumn->getQuotedName($this);

// sp_rename accepts the new name as a literal value, so it cannot be quoted.
$newColumnName = $newColumn->getName();

$sql = array_merge(
$sql,
$this->getRenameColumnSQL($tableNameSQL, $oldColumnName, $newColumnName),
$this->getRenameColumnSQL($tableNameSQL, $oldColumnNameSQL, $newColumnName),
);
}

Expand Down Expand Up @@ -492,11 +495,7 @@ public function getAlterTableSQL(TableDiff $diff): array

public function getRenameTableSQL(string $oldName, string $newName): string
{
return sprintf(
'sp_rename %s, %s',
$this->quoteStringLiteral($oldName),
$this->quoteStringLiteral($newName),
);
return $this->getRenameSQL($oldName, $newName);
}

/**
Expand Down Expand Up @@ -630,13 +629,7 @@ protected function getDropColumnCommentSQL(string $tableName, string $columnName
*/
protected function getRenameIndexSQL(string $oldIndexName, Index $index, string $tableName): array
{
return [sprintf(
"EXEC sp_rename N'%s.%s', N'%s', N'INDEX'",
$tableName,
$oldIndexName,
$index->getQuotedName($this),
),
];
return [$this->getRenameSQL($tableName . '.' . $oldIndexName, $index->getName(), 'INDEX')];
}

/**
Expand All @@ -650,12 +643,18 @@ protected function getRenameIndexSQL(string $oldIndexName, Index $index, string
*/
protected function getRenameColumnSQL(string $tableName, string $oldColumnName, string $newColumnName): array
{
return [sprintf(
"EXEC sp_rename %s, %s, 'COLUMN'",
$this->quoteStringLiteral($tableName . '.' . $oldColumnName),
$this->quoteStringLiteral($newColumnName),
),
];
return [$this->getRenameSQL($tableName . '.' . $oldColumnName, $newColumnName)];
}

/**
* Returns the SQL statement that will execute sp_rename with the given arguments.
*/
private function getRenameSQL(string ...$arguments): string
{
return 'EXEC sp_rename '
. implode(', ', array_map(function (string $argument): string {
return 'N' . $this->quoteStringLiteral($argument);
}, $arguments));
}

/**
Expand Down
28 changes: 28 additions & 0 deletions tests/Functional/Platform/RenameColumnTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Doctrine\DBAL\Tests\Functional\Platform;

use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Table;
use Doctrine\DBAL\Schema\TableDiff;
Expand Down Expand Up @@ -94,4 +95,31 @@ public static function columnNameProvider(): iterable
yield ['C1', 'c1_x'];
yield ['importantColumn', 'veryImportantColumn'];
}

/** @throws Exception */
public function testRenameColumToQuoted(): void
{
$table = new Table('test_rename');
$table->addColumn('c1', Types::INTEGER);

$this->dropAndCreateTable($table);

$table->dropColumn('c1')
->addColumn('"c2"', Types::INTEGER);

$schemaManager = $this->connection->createSchemaManager();
$comparator = $schemaManager->createComparator();

$diff = $comparator->compareTables($schemaManager->introspectTable('test_rename'), $table);
self::assertFalse($diff->isEmpty());

$schemaManager->alterTable($diff);

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

self::assertEquals(1, $this->connection->insert(
'test_rename',
[$platform->quoteSingleIdentifier('c2') => 1],
));
}
}
8 changes: 4 additions & 4 deletions tests/Platforms/SQLServerPlatformTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -848,8 +848,8 @@ protected function getAlterTableRenameIndexSQL(): array
protected function getQuotedAlterTableRenameIndexSQL(): array
{
return [
"EXEC sp_rename N'[table].[create]', N'[select]', N'INDEX'",
"EXEC sp_rename N'[table].[foo]', N'[bar]', N'INDEX'",
"EXEC sp_rename N'[table].[create]', N'select', N'INDEX'",
"EXEC sp_rename N'[table].[foo]', N'bar', N'INDEX'",
];
}

Expand All @@ -867,8 +867,8 @@ protected function getAlterTableRenameIndexInSchemaSQL(): array
protected function getQuotedAlterTableRenameIndexInSchemaSQL(): array
{
return [
"EXEC sp_rename N'[schema].[table].[create]', N'[select]', N'INDEX'",
"EXEC sp_rename N'[schema].[table].[foo]', N'[bar]', N'INDEX'",
"EXEC sp_rename N'[schema].[table].[create]', N'select', N'INDEX'",
"EXEC sp_rename N'[schema].[table].[foo]', N'bar', N'INDEX'",
];
}

Expand Down

0 comments on commit 579c4dd

Please sign in to comment.