Skip to content

fix(filter)!: accept a property path on the right side of a comparison - #150

Open
pdevito3 wants to merge 1 commit into
mainfrom
fm/qk-breaking-right-side-path
Open

pdevito3 wants to merge 1 commit into
mainfrom
fm/qk-breaking-right-side-path

Conversation

@pdevito3

@pdevito3 pdevito3 commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

For later consideration in a major version. Do not merge now. #134 restored the v1.14.2 right side to keep v1.x compatible (restore commit 2b1c252). This PR re-applies 71b4c40 (#113). The captain decides on this PR separately.

Summary

-            .XOr(Identifier.Select(v => new RightSideValue(v, false))); // Keep this last to try property paths only if nothing else matches
+            .XOr(Identifier.DelimitedBy(Parse.Char('.')).Select(v => new RightSideValue(string.Join(".", v), false))); // Keep this last to try property paths only if nothing else matches

The right side of a comparison reads a dotted property path, not only one word. The change is in QueryKit/FilterParser.cs only.

v1.14.2 behavior (and main)

The right side reads one identifier. An unquoted dotted word on the right side throws ParsingException. The README shows right-side paths (Email.Value == CollectionEmail.Value, Rating > Author.Score), but these examples throw.

New behavior

An unquoted dotted word on the right side is read as one value:

  • If the word is a property path of the entity, QueryKit compares the two properties.
  • If it is not a property path, the word is a string value. Title == foo.bar compares Title with "foo.bar".

Example

FilterParser.ParseFilter<Recipe>("""Title == Author.Name""");
  • v1.14.2 and main: ParsingException with the inner InvalidOperationException "The binary operator Equal is not defined for the types 'System.String' and ... Author".
  • This PR: x => (x.Title == x.Author.Name).

Justification

The README documents property paths on the right side, and a path works on the left side. The right side must accept the same paths.

Migration

A filter that relied on the ParsingException for an unquoted dotted word now returns rows. To compare with the literal text, quote it: Title == "Author.Name".

Interaction with #136 (item I)

Before #134, main also checked a right-side path with PropertyResolver.Resolve. This check is part of item I (#136), not of this PR. With this PR alone:

After #136 and this PR are both merged, bring back these 2 unit tests from main before #134 (PropertyResolverTests):

  • property_path_on_the_right_side_obeys_max_property_depth
  • prevented_property_path_on_the_right_side_removes_the_clause

I merged the two rebased branches locally and added the 2 tests: 476 unit tests pass, 0 failures. Each test needs both changes, so neither PR can carry them alone.

README

No change. The README already shows right-side paths in "Child Property Comparisons". This PR makes these examples work.

Tests

These tests come back from main before #134:

  • Unit PropertyResolverTests.property_path_on_the_right_side_throws becomes property_path_on_the_right_side_is_compared.
  • Integration PropertyResolverTests.property_path_on_the_right_side_is_compared (Postgres): only the recipe with Title equal to Author.Name comes back.

Unit PropertyResolverTests.unquoted_dotted_word_on_the_right_side_throws is removed. #134 added this pin for the v1.14.2 throw.

dotnet test: 469 unit tests and 298 Postgres integration tests (Testcontainers) pass, 0 failures.

Rebase on main

This branch is rebased on current main. On main, SquareBracketParser already returns a RightSideValue, so the rebase keeps it as it is.

The right side of a comparison read one identifier. Title == Author.Name threw ParsingException, and the README examples with a path on the right side (Rating > Author.Score) did not work. Read a dotted property path on the right side. A path that does not resolve to a property stays a value.

BREAKING CHANGE: an unquoted dotted word on the right side no longer throws ParsingException. Title == Author.Name compares the two properties. Title == foo.bar compares Title with the string "foo.bar".
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