Skip to content

fix(parser)!: parse numbers with the invariant culture only - #121

Merged
pdevito3 merged 1 commit into
v2from
fm/qk-breaking-invariant-numbers
Oct 2, 2026
Merged

pdevito3 merged 1 commit into
v2from
fm/qk-breaking-invariant-numbers

Conversation

@pdevito3

@pdevito3 pdevito3 commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

This PR makes the number grammar use the invariant culture only, so a decimal comma is not accepted. This is a breaking change. It is one of the six breaking changes that were removed from #114 so that main stays compatible with v1.14.2.

Status: for later consideration. Do not merge this PR now. The captain decides on each breaking change separately. If this change is accepted, it needs a major version.

Main already reads 4.5 in every culture when the property type converts it, and list numbers always use .. This PR adds only the strict invariant grammar that rejects 4,5.

Old behavior (v1.14.2 and main)

New behavior

The number grammar uses the invariant culture only. Rating > 4.5 means 4.5 in every culture. Rating > 4,5 throws a QueryKitException (ParsingException) in every culture.

The change removes UnsignedNumberParser and ListNumberParser. The number grammar, the list grammar, the count operator value, and the literal checks in IsPropertyPath use the invariant culture only.

Example

Proof from the verify-querykit harness, with the culture set to de-DE. Each row gives the same result in memory and on Postgres.

Filter main This PR
Price > 4,5 0 rows, no error (the parameter value is 45) ParsingException: "unexpected ','; expected end of input (Line 1, Column 10)"
Price > 4.5 Beef Stew Beef Stew

Justification

The v1.14.2 result for 4,5 is 45, which is not the value that any user means. This result is silent, so the API returns wrong rows with no error. A filter string is a machine format, and the same filter must give the same result on every server.

The strict invariant grammar gives one meaning for 4.5 everywhere and rejects 4,5 with a clear error. The break affects only a consumer on a comma culture that sends 4,5 and depends on the value 45.

Migration

Send the number with a . decimal point, for example Rating > 4.5.

Tests

  • The two unit tests for the comma culture are now one theory, decimal_value_with_decimal_comma_is_not_accepted, for de-DE, fr-FR, and en-US. It expects QueryKitException.
  • The case Rating > 4,4 (de-DE, an int property) moves out of the D4 test DotNumberCultureTests.number_that_v1_14_2_also_converted_throws_format_exception. On main, it throws FormatException. On this PR, it throws ParsingException, like every number with a decimal comma.
  • dotnet test on the branch after the rebase on main: 469 unit tests and 297 Postgres integration tests (Testcontainers) pass, 0 failures.

The number grammar also accepted the decimal separator of the current culture. Under de-DE, Rating > 4,5 parsed, and the value conversion read it with the invariant culture as 45. The API returned wrong rows with no error.

The number grammar, the count operator value, and the literal checks in IsPropertyPath now use the invariant culture only. A number always uses the '.' decimal point.

BREAKING CHANGE: a number with a decimal comma, for example Rating > 4,5, throws a QueryKitException in every culture. Before, a server with a comma culture read this value as 45. Send the number with a '.' decimal point, for example Rating > 4.5.
@pdevito3
pdevito3 force-pushed the fm/qk-breaking-invariant-numbers branch from ff747ff to a4c2760 Compare October 2, 2026 19:55
@pdevito3
pdevito3 changed the base branch from main to v2 October 2, 2026 19:55
@pdevito3
pdevito3 merged commit a61c97c into v2 Oct 2, 2026
2 checks passed
@pdevito3
pdevito3 deleted the fm/qk-breaking-invariant-numbers branch October 2, 2026 19:56
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