fix(filter)!: resolve query names in the grammar again - #154
Merged
Merged
Conversation
This was referenced Oct 1, 2026
pdevito3
force-pushed
the
fm/qk-breaking-query-names
branch
from
October 1, 2026 20:59
e5dbe6b to
b8b4ae9
Compare
pdevito3
added a commit
that referenced
this pull request
Oct 1, 2026
The public method ReplaceAliasesWithPropertyPaths does not replace a query name after a dot anymore. A query name after a dot is a segment of a nested path of another type. For example, with the query name "name" on Title, "Author.Name" stays "Author.Name". The filter parser calls an internal overload that keeps the v1.14.2 match. Filters do not change. #154 owns the filter change for a query name after a dot. BREAKING CHANGE: ReplaceAliasesWithPropertyPaths keeps a query name after a dot. It also does not throw InvalidOperationException for a fully prevented query name after a dot.
pdevito3
force-pushed
the
fm/qk-breaking-query-names
branch
from
October 1, 2026 21:44
b8b4ae9 to
8b21edc
Compare
pdevito3
added a commit
that referenced
this pull request
Oct 1, 2026
The public method ReplaceAliasesWithPropertyPaths does not replace a query name after a dot anymore. A query name after a dot is a segment of a nested path of another type. For example, with the query name "name" on Title, "Author.Name" stays "Author.Name". The filter parser calls an internal overload that keeps the v1.14.2 match. Filters do not change. #154 owns the filter change for a query name after a dot. BREAKING CHANGE: ReplaceAliasesWithPropertyPaths keeps a query name after a dot. It also does not throw InvalidOperationException for a fully prevented query name after a dot.
QueryKit no longer replaces query names in the filter text before the parse. The grammar reads a query name as a property, and the property resolver maps it to its property path. As a result, a query name works in a property list and in arithmetic, and text inside a quoted value does not change. A property query name matches with the case rules of the current culture, like the alias regex of v1.14.2. A derived property or custom operation query name still ignores case with the invariant rules. When the grammar reads such a query name where v1.14.2 read an unknown identifier path, a filter that fails still throws the v1.14.2 exception. A property list skips a property that has PreventFilter by its query name too. Every configured property has its name as its default query name, so a property list also skips a prevented property in another letter case. A property that has PreventFilter and PreventSort still throws InvalidOperationException by its query name in front of an operator. BREAKING CHANGE: a query name inside a quoted value is not replaced anymore. A query name after a dot is not replaced anymore. A query name in a property list or in arithmetic resolves to its property instead of throwing. A property list skips a prevented property in another letter case.
…e each name one time
pdevito3
force-pushed
the
fm/qk-breaking-query-names
branch
from
October 3, 2026 11:53
8b21edc to
0718fca
Compare
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
ParseFilterno longer rewrites query names in the filter text before the parse. The operator and logical alias passes stay.PropertyPathParser(config)reads a configured query name first (longest first), then a normal identifier path. The left side of a comparison and a property list use this parser.PropertyResolver.Resolvemaps a query name to the property path of its mapping before the depth check and the member lookup. Arithmetic and property lists useResolve, so a query name works there too.SortParserpasses the raw sort name toResolve. The right side of a comparison usesResolveWithoutQueryName, because a query name on the right side is a value. TheHasConversioncheck uses the resolved mapping.GetPropertyInfoByQueryNameInCurrentCulture) is deleted.EnsureNoQueryNameOfAPropertyPreventedForFilterAndSortis deleted. A property withPreventFilter()andPreventSort()is now removed by its query name like any prevented property. It does not throwInvalidOperationException.v1.14.2 behavior
QueryKit replaced each query name in front of an operator with its property path, on the raw text, before the parse. As a result:
Title == "first == x"comparedTitlewithFirstName == x.UnknownFilterPropertyException.ArgumentException.Author.name == "Lee"becameAuthor.Title.tr-TR,TIPALPHAdid not match the query nametipalpha.New behavior
HasQueryName("first")onFirstName, andHasQueryName("stars")onRating:Title == "first == x"x => (x.Title == "FirstName == x")x => (x.Title == "first == x")(first, LastName) == "Paul"UnknownFilterPropertyException: 'first'x => ((x.FirstName == "Paul") OrElse (x.LastName == "Paul"))(stars + 0) > 3ArgumentExceptionRatingSTARS > 3intr-TRUnknownFilterPropertyExceptionRating#132 bypass with #136
With #136 and the first commit of this PR together, a name could map two times. One time came from the query name, and one time came from
Resolve:Directions == TitleDirectionsquery nametitle,TitlePreventFilterx.Directions == x.DirectionsDirections _= Titlex.Directions.StartsWith(x.Directions)title ascRatingquery namedirections,Directionsquery nametitlewith PreventSortRatingMigration
tr-TR), the name now matches with the invariant rules.InvalidOperationExceptionfor a query name of a property withPreventFilter()andPreventSort(), the clause is now removed (ortrue == truewithIgnoredClauseBehavior.ReplaceWithTrue).Tests
PropertyResolverTests:prevented_property_on_the_right_side_is_not_compared_when_another_query_name_matches_its_name(==and_=),prevented_sort_property_is_skipped_when_its_property_path_is_another_query_name, and the twoproperty_prevented_for_filter_and_sort_is_removed_by_its_query_name*tests (they expected a throw before).AliasCultureTests:I/imatches intr-TRanden-USin a comparison, a property list, and a sort.ıandİdo not matchIandi.prevented_property_on_the_right_side_is_not_compared_when_another_query_name_matches_its_name,query_name_in_a_property_list_is_filtered,query_name_in_arithmetic_is_filtered, andquery_name_with_i_matches_its_upper_case_in_tr_tr.dotnet test: 527 unit tests and 324 Postgres integration tests pass.