fix(config): match aliases with the case rules of the current culture again - #158
Merged
Merged
Conversation
… again The alias regex cache kept one Regex for each pattern. RegexOptions.IgnoreCase uses the culture that is current when the Regex is built, so the first parse fixed the case rules for all later cultures. A query name like TIP did not match in en-US after a tr-TR parse, and an operator alias matched in tr-TR after an en-US parse. The cache key now includes CultureInfo.CurrentCulture.Name. Each culture gets the same result as v1.14.2, which built a new Regex for each parse.
This was referenced Oct 1, 2026
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.
Summary
This PR restores D3 from the v1.14.2 review report. It is not a breaking change.
AliasRegexCachekeeps oneRegexfor each alias pattern. The regexes useRegexOptions.IgnoreCase, and that option uses the culture that is current when theRegexis built. On main, the first parse fixes the case rules of an alias for all later parses, in every culture. In tr-TR,Idoes not matchi, so the order of the parses changes the result.v1.14.2 built a new
Regexfor each parse, with the case rules of the current culture. This PR keys the cache by the pattern andCultureInfo.CurrentCulture.Name. It does not useRegexOptions.CultureInvariant, because that option changes the tr-TR result against v1.14.2.Results against v1.14.2
Config A:
Pricehas the query nametip, andTitlehas the query nameisim.Config B:
EqualsOperatoriseşit, andAndOperatorisVE.TIP > 3in en-USx.Price > 3UnknownFilterPropertyExceptionISIM == "Pancakes"in en-USx.Title == "Pancakes"UnknownFilterPropertyExceptionTitle EŞIT "Pancakes"in tr-TRParsingExceptionx.Title == "Pancakes"A differential probe ran 19 cases in two parse orders (tr-TR first and en-US first) against v1.14.2 and this branch. It compared the expression, the in-memory rows, and the Postgres SQL. No difference in result or exception type remains.
The message text of the tr-TR
EŞITcase is different from v1.14.2. Both versions throwParsingException, but main has a different message and a different inner Sprache message. The message text was different before this PR and is not part of D3.Tests
QueryKit.UnitTests/AliasCultureTests.cs: a query name in en-US after tr-TR, a query name in tr-TR after en-US, and an operator alias in tr-TR after en-US. All 3 fail on main.QueryKit.IntegrationTests/Tests/AliasCultureTests.cs: a query name filters the rows in en-US after a tr-TR parse. It fails on main.dotnet test: unit 405 passed, integration 284 passed.Overlap with other PRs
QueryKit/AliasRegexCache.cs. The tests are in new files. This PR merges on main in any order with the other restore PRs (fix(filter): resolve non-public members like v1.14.2 #155, fix(filter): find the prevent-filter setting by the property path again #156) without a rebase.