identifier_case: keep the case of backtick-, acute- and bracket-quoted identifiers - #884
Open
dylanpulver wants to merge 1 commit into
Open
Conversation
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses the case-mangling half of #433.
IdentifierCaseFilterexempts only"..."from case conversion, butSQL_REGEXrecognizes four quoting styles for identifiers. The other three —`x`(keywords.py:132),´x´(:133) and[x](:173) — arrive as plainT.Nameand get converted: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_quotesalready pins the intended behaviour for"..."; this extends it to the other three.sqlparse/utils.py:58already counts`as a quote character, so the filter was the odd one out.Ran:
make test→ 515 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 lintclean — it was clean before the change too.Two mutants, same command and env: reverting only
filters/tokens.pyfails 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.Symbolfor 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_REGEXrecognizes against the ones each filter knows about. Not from hitting it in production — weigh it accordingly. #433 turned up afterwards and matches.pytest, viamake test)ruff check sqlparse/)AI disclosure: prepared with assistance from Claude Opus 5 (
claude-opus-5). Every command and number above I ran and read myself.