fix(filter): throw ParsingException for a '.' number that the culture cannot read - #159
Merged
Merged
Conversation
… cannot read In a culture whose decimal separator is not '.', v1.14.2 read only the part of a '.' number before the '.'. Then the grammar failed at the '.'. Thus a '.' number on an integer property gave ParsingException, and main gave FormatException. A number that the culture cannot read in full now builds the clause like main. If that build fails, the parser builds it again with the part that the culture reads, and throws ParsingException if this build succeeds. Lists throw ParsingException, like v1.14.2. en-US is unchanged. A '.' number on a decimal property still filters.
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 D4 from the v1.14.2 review report. It is not a breaking change.
In a culture whose decimal separator is not '.', v1.14.2 read a number with the current culture. In de-DE it read only
4of4.4, built the clause with4, and then failed in the grammar at the.. ThusRating > 4.4on anintproperty gaveParsingException. Main reads4.4in every culture. The conversion tointthen fails, so main throwsFormatException.This PR keeps the main grammar. For a number that the current culture cannot read in full, the parser builds the clause like main. If that build fails, the parser does what v1.14.2 did:
4of4.4). If this build fails, its exception goes to the caller, like v1.14.2.ParsingException.In a list, v1.14.2 failed in the grammar at the first
.number, before it built the clause. Thus a list with a.number that does not convert throwsParsingException.Scope against the brief
The brief says to wrap the
FormatExceptiononly for integer target types. This PR uses the general v1.14.2 rule above instead, for these reasons:int,long,short,byte, their nullable forms, andchar. Adecimal,double, orfloatproperty converts4.4and is still accepted. ADateTimeorboolproperty rebuilds with4and throwsFormatException, like v1.14.2.Rating ^^ ["x", 4.0],IsVegetarian ^^ [true, 4.0], andTags ^^ [4.5]threwFormatExceptionorArgumentExceptionon main andParsingExceptionon v1.14.2. An integer-only rule does not restore these.Rating > 4.4still throwsFormatException.Rating > @4.4still throwsFormatException, like v1.14.2.TinyRating > 300.5on abytestill throwsOverflowException, like v1.14.2.Results against v1.14.2 (de-DE)
Rating > 4.4intParsingExceptionFormatExceptionRating == -4.0intParsingExceptionFormatExceptionRating == .5intParsingExceptionFormatExceptionRating ^^ [4.0]intParsingExceptionFormatExceptionTags #== 2.0List<string>countParsingExceptionFormatException(Rating, Title) == 4.0ParsingExceptionFormatExceptionRating > "4.4"intFormatExceptionFormatExceptionRating > 4.4in en-USintFormatExceptionFormatExceptionPrice > 4.4decimalParsingExceptionThe last row is not changed back. PR #134 kept the e032af7 change, so main accepts a
.number on a decimal property in every culture. An input that v1.14.2 rejected and main accepts is not a breaking change.A differential probe ran 125 cases in de-DE, fr-FR, and en-US against v1.14.2 and this branch. It compared the expression, the in-memory rows, and the Postgres SQL. These differences remain, and each is an input that v1.14.2 rejected and main accepts:
.number on adecimalorstringproperty, and in adecimallist.CreatedAt > 4.4on aDateTimeproperty, which main reads as a date in all cultures, like main in en-US..number inside an arithmetic expression, for example(Rating * 2) > 4.5.The inner exception of the restored
ParsingExceptionis the conversion exception. On v1.14.2 it was a SpracheParseException. The outer type and the result are the same.Tests
QueryKit.UnitTests/DotNumberCultureTests.cs: 11 inputs that must throwParsingException(de-DE and fr-FR), 6 inputs that must still throwFormatException, and an integer value that still filters in de-DE. The 11ParsingExceptionpins fail on main.QueryKit.IntegrationTests/Tests/DotNumberCultureTests.cs: in de-DE,Age > 4.4on anint?property throwsParsingException, andRating > 4.5on adecimal?property returns the correct row. It fails on main.dotnet test: unit 428 passed, integration 284 passed.Overlap with other PRs
QueryKit/FilterParser.csand adds new test files. It does not touch the files of fix(filter): resolve non-public members like v1.14.2 #155, fix(filter): find the prevent-filter setting by the property path again #156, or fix(config): match aliases with the case rules of the current culture again #158.