Skip to content

identifier_case: keep the case of backtick-, acute- and bracket-quoted identifiers - #884

Open
dylanpulver wants to merge 1 commit into
andialbrecht:masterfrom
dylanpulver:fix-identifier-case-delimited-identifiers
Open

identifier_case: keep the case of backtick-, acute- and bracket-quoted identifiers#884
dylanpulver wants to merge 1 commit into
andialbrecht:masterfrom
dylanpulver:fix-identifier-case-delimited-identifiers

Conversation

@dylanpulver

Copy link
Copy Markdown

Addresses the case-mangling half of #433.

IdentifierCaseFilter exempts only "..." from case conversion, but SQL_REGEX recognizes four quoting styles for identifiers. The other three — `x` (keywords.py:132), ´x´ (:133) and [x] (:173) — arrive as plain T.Name and get converted:

>>> sqlparse.format('select * from `MyTbl`', identifier_case='upper')
'select * from `MYTBL`'

That breaks the statement on MySQL with lower_case_table_names=0 (the Unix default, docs) and on SQL Server under a case-sensitive collation — and backticking the name is precisely the workaround suggested on #433. test_identifiercase_quotes already pins the intended behaviour for "..."; this extends it to the other three. sqlparse/utils.py:58 already counts ` as a quote character, so the filter was the odd one out.

Ran: make test515 passed on 3.10/3.11/3.12/3.13/3.14 (unmodified master in the same session: 506 passed; the 9 extra are the new parametrized cases). make lint clean — it was clean before the change too.

Two mutants, same command and env: reverting only filters/tokens.py fails 9/9 of the new cases; a naive fix that exempts just the backtick still fails 6/9. So the test does discriminate between remedies rather than merely passing.

Alternative I did not take: make the lexer emit T.String.Symbol for all four styles, which is where the asymmetry originates. That changes a public token type, so it is breaking and belongs on its own.

Not covered: dialects where a delimited identifier is case-insensitive anyway — there this is a no-op rather than a fix.

How I found it: a systematic audit of sqlparse's tables, diffing the quoting styles SQL_REGEX recognizes against the ones each filter knows about. Not from hitting it in production — weigh it accordingly. #433 turned up afterwards and matches.


  • ran the tests (pytest, via make test)
  • all style issues addressed (ruff check sqlparse/)
  • your changes are covered by tests
  • your changes are documented, if needed (CHANGELOG)

AI disclosure: prepared with assistance from Claude Opus 5 (claude-opus-5). Every command and number above I ran and read myself.

IdentifierCaseFilter exempted only double-quoted identifiers, but
SQL_REGEX recognizes four quoting styles. The other three reach the
filter as plain T.Name and had their case changed, so `MyTbl` became
`MYTBL` (issue433).
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.

1 participant