Skip to content

Preserve quoting when detecting renamed indexes - #7507

Open
raphyabak wants to merge 1 commit into
doctrine:4.4.xfrom
raphyabak:fix/oracle-quoted-index-rename
Open

Preserve quoting when detecting renamed indexes#7507
raphyabak wants to merge 1 commit into
doctrine:4.4.xfrom
raphyabak:fix/oracle-quoted-index-rename

Conversation

@raphyabak

Copy link
Copy Markdown

Summary

Fixes #6565

Comparator::detectRenamedIndexes() used strtolower($index->getName()) as the array key for a renamed index's old name. getName() strips quoting metadata and returns the bare identifier, so any information about whether the original index name was quoted was lost, and the name was unconditionally folded to lower case regardless of the target platform's identifier folding rules.

Downstream, AbstractPlatform::getAlterTableSQL() re-wraps this bare string in a new Identifier() to decide whether to quote the old name in the generated SQL. Since the quoting information was already gone, the old name was never quoted, even when it originally required quoting to preserve case (e.g. Oracle, which folds unquoted identifiers to upper case). This produced statements like:

ALTER INDEX idx_test_col RENAME TO "idx_test_type"

instead of:

ALTER INDEX "idx_test_col" RENAME TO "idx_test_type"

which Oracle rejects with an index-not-found error, since the generated statement no longer refers to the original, case-sensitive index name.

Fix

Use getQuotedName($this->platform) instead, which already contains the exact logic needed to conditionally quote the identifier (based on whether it was originally quoted, or is a reserved keyword) while leaving already-safe unquoted names untouched — this is the same mechanism AbstractPlatform::getAlterTableSQL() and other index/column name handling already rely on elsewhere.

Test plan

  • Added AbstractComparatorTestCase::testDetectRenameIndexPreservesQuoting(), exercised against all three concrete Comparator subclasses (SQLite, MySQL, SQLServer) so the assertion works across each platform's own quoting character (", `, [...]).
  • Verified the new test fails against the pre-fix code with the exact reported symptom (old index name silently un-quoted / case-folded), and passes with the fix.
  • Reproduced the original report directly against OraclePlatform + Comparator::compareTables(): before the fix, ALTER INDEX idx_test_col RENAME TO "idx_test_type"; after the fix, ALTER INDEX "idx_test_col" RENAME TO "idx_test_type".
  • Confirmed no regression for unquoted index renames (still emitted unquoted, unchanged).
  • Ran the full test suite (vendor/bin/phpunit tests --exclude-group=performance): 3932 tests, all passing (3929 pre-existing + 3 new), same pre-existing skip/incomplete counts (604 skipped / 13 incomplete, all DB-connection-dependent functional tests unrelated to this change).
  • vendor/bin/phpcs and vendor/bin/phpstan on the changed files: clean.

Comparator::detectRenamedIndexes() used strtolower($index->getName())
as the array key for a renamed index's old name. getName() strips
quoting metadata and returns the bare identifier, so any information
about whether the original index name was quoted was lost, and the
name was unconditionally folded to lower case regardless of the
target platform's identifier folding rules.

Downstream, AbstractPlatform::getAlterTableSQL() re-wraps this bare
string in a new Identifier() to decide whether to quote the old name
in the generated SQL. Since the quoting information was already gone,
the old name was never quoted, even when it originally required
quoting to preserve case (e.g. Oracle, which folds unquoted
identifiers to upper case). This produced statements like:

    ALTER INDEX idx_test_col RENAME TO "idx_test_type"

instead of:

    ALTER INDEX "idx_test_col" RENAME TO "idx_test_type"

which Oracle rejects with an index-not-found error, since the
generated statement no longer refers to the original, case-sensitive
index name.

Use getQuotedName($this->platform) instead, which already contains
the exact logic needed to conditionally quote the identifier (based
on whether it was originally quoted, or is a reserved keyword) while
leaving already-safe unquoted names untouched.

Fixes doctrine#6565
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Oracle platform fails on quoted indexes

1 participant