Skip to content

Commit 579c4dd

Browse files
authored
Merge pull request #6602 from morozov/sqlserver-rename-to-quoted
Fix renaming to quoted names on SQL Server
2 parents 727bd6b + 1300542 commit 579c4dd

File tree

3 files changed

+57
-30
lines changed

3 files changed

+57
-30
lines changed

src/Platforms/SQLServerPlatform.php

+25-26
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Doctrine\DBAL\Types\Types;
2323
use InvalidArgumentException;
2424

25+
use function array_map;
2526
use function array_merge;
2627
use function array_unique;
2728
use function array_values;
@@ -406,18 +407,20 @@ public function getAlterTableSQL(TableDiff $diff): array
406407
$tableNameSQL = $table->getQuotedName($this);
407408

408409
foreach ($diff->getChangedColumns() as $columnDiff) {
409-
$newColumn = $columnDiff->getNewColumn();
410-
$newColumnName = $newColumn->getQuotedName($this);
410+
$newColumn = $columnDiff->getNewColumn();
411+
$oldColumn = $columnDiff->getOldColumn();
412+
$nameChanged = $columnDiff->hasNameChanged();
411413

412-
$oldColumn = $columnDiff->getOldColumn();
413-
$oldColumnName = $oldColumn->getQuotedName($this);
414-
$nameChanged = $columnDiff->hasNameChanged();
415-
416-
// Column names in SQL server are case insensitive and automatically uppercased on the server.
417414
if ($nameChanged) {
415+
// sp_rename accepts the old name as a qualified name, so it should be quoted.
416+
$oldColumnNameSQL = $oldColumn->getQuotedName($this);
417+
418+
// sp_rename accepts the new name as a literal value, so it cannot be quoted.
419+
$newColumnName = $newColumn->getName();
420+
418421
$sql = array_merge(
419422
$sql,
420-
$this->getRenameColumnSQL($tableNameSQL, $oldColumnName, $newColumnName),
423+
$this->getRenameColumnSQL($tableNameSQL, $oldColumnNameSQL, $newColumnName),
421424
);
422425
}
423426

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

493496
public function getRenameTableSQL(string $oldName, string $newName): string
494497
{
495-
return sprintf(
496-
'sp_rename %s, %s',
497-
$this->quoteStringLiteral($oldName),
498-
$this->quoteStringLiteral($newName),
499-
);
498+
return $this->getRenameSQL($oldName, $newName);
500499
}
501500

502501
/**
@@ -630,13 +629,7 @@ protected function getDropColumnCommentSQL(string $tableName, string $columnName
630629
*/
631630
protected function getRenameIndexSQL(string $oldIndexName, Index $index, string $tableName): array
632631
{
633-
return [sprintf(
634-
"EXEC sp_rename N'%s.%s', N'%s', N'INDEX'",
635-
$tableName,
636-
$oldIndexName,
637-
$index->getQuotedName($this),
638-
),
639-
];
632+
return [$this->getRenameSQL($tableName . '.' . $oldIndexName, $index->getName(), 'INDEX')];
640633
}
641634

642635
/**
@@ -650,12 +643,18 @@ protected function getRenameIndexSQL(string $oldIndexName, Index $index, string
650643
*/
651644
protected function getRenameColumnSQL(string $tableName, string $oldColumnName, string $newColumnName): array
652645
{
653-
return [sprintf(
654-
"EXEC sp_rename %s, %s, 'COLUMN'",
655-
$this->quoteStringLiteral($tableName . '.' . $oldColumnName),
656-
$this->quoteStringLiteral($newColumnName),
657-
),
658-
];
646+
return [$this->getRenameSQL($tableName . '.' . $oldColumnName, $newColumnName)];
647+
}
648+
649+
/**
650+
* Returns the SQL statement that will execute sp_rename with the given arguments.
651+
*/
652+
private function getRenameSQL(string ...$arguments): string
653+
{
654+
return 'EXEC sp_rename '
655+
. implode(', ', array_map(function (string $argument): string {
656+
return 'N' . $this->quoteStringLiteral($argument);
657+
}, $arguments));
659658
}
660659

661660
/**

tests/Functional/Platform/RenameColumnTest.php

+28
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Doctrine\DBAL\Tests\Functional\Platform;
66

7+
use Doctrine\DBAL\Exception;
78
use Doctrine\DBAL\Schema\Column;
89
use Doctrine\DBAL\Schema\Table;
910
use Doctrine\DBAL\Schema\TableDiff;
@@ -94,4 +95,31 @@ public static function columnNameProvider(): iterable
9495
yield ['C1', 'c1_x'];
9596
yield ['importantColumn', 'veryImportantColumn'];
9697
}
98+
99+
/** @throws Exception */
100+
public function testRenameColumToQuoted(): void
101+
{
102+
$table = new Table('test_rename');
103+
$table->addColumn('c1', Types::INTEGER);
104+
105+
$this->dropAndCreateTable($table);
106+
107+
$table->dropColumn('c1')
108+
->addColumn('"c2"', Types::INTEGER);
109+
110+
$schemaManager = $this->connection->createSchemaManager();
111+
$comparator = $schemaManager->createComparator();
112+
113+
$diff = $comparator->compareTables($schemaManager->introspectTable('test_rename'), $table);
114+
self::assertFalse($diff->isEmpty());
115+
116+
$schemaManager->alterTable($diff);
117+
118+
$platform = $this->connection->getDatabasePlatform();
119+
120+
self::assertEquals(1, $this->connection->insert(
121+
'test_rename',
122+
[$platform->quoteSingleIdentifier('c2') => 1],
123+
));
124+
}
97125
}

tests/Platforms/SQLServerPlatformTest.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -848,8 +848,8 @@ protected function getAlterTableRenameIndexSQL(): array
848848
protected function getQuotedAlterTableRenameIndexSQL(): array
849849
{
850850
return [
851-
"EXEC sp_rename N'[table].[create]', N'[select]', N'INDEX'",
852-
"EXEC sp_rename N'[table].[foo]', N'[bar]', N'INDEX'",
851+
"EXEC sp_rename N'[table].[create]', N'select', N'INDEX'",
852+
"EXEC sp_rename N'[table].[foo]', N'bar', N'INDEX'",
853853
];
854854
}
855855

@@ -867,8 +867,8 @@ protected function getAlterTableRenameIndexInSchemaSQL(): array
867867
protected function getQuotedAlterTableRenameIndexInSchemaSQL(): array
868868
{
869869
return [
870-
"EXEC sp_rename N'[schema].[table].[create]', N'[select]', N'INDEX'",
871-
"EXEC sp_rename N'[schema].[table].[foo]', N'[bar]', N'INDEX'",
870+
"EXEC sp_rename N'[schema].[table].[create]', N'select', N'INDEX'",
871+
"EXEC sp_rename N'[schema].[table].[foo]', N'bar', N'INDEX'",
872872
];
873873
}
874874

0 commit comments

Comments
 (0)