fix(filter): resolve non-public members like v1.14.2 - #155
Merged
Merged
Conversation
Restore the v1.14.2 member lookup of Expression.PropertyOrField. A filter segment matches a public property, a public field, a non-public property, and then a non-public field, in any case. An indexer is an unknown property again, so it throws UnknownFilterPropertyException, or it becomes a True clause when AllowUnknownProperties is on. The test model gets an internal mapped Nickname column on people, so that a Postgres test can pin the SQL path.
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 D1 from the v1.14.2 review report. It is not a breaking change.
v1.14.2 resolved each filter segment with
Expression.PropertyOrField. Main resolves only public members. As a result, main rejects filters on internal, protected, and private members that v1.14.2 accepted. Main also treats an indexer (Item) as a member and throwsArgumentException.This PR makes
PropertyResolveruse the lookup order ofExpression.PropertyOrField, ignoring case:An indexer does not match. It is an unknown property again.
Results against v1.14.2
InternalScore > 30(internal property)x.InternalScore > 30UnknownFilterPropertyExceptionsecretRank == 7(private field)x.secretRank == 7UnknownFilterPropertyExceptionProtectedNote == "a"Author.InternalAlias == "Ann"secretRank > 100withAllowUnknownPropertiesx.secretRank > 100True == TrueItem == "x"(indexer)UnknownFilterPropertyException'Item'ArgumentExceptionItem == "x"withAllowUnknownPropertiesTrue == TrueArgumentExceptionA differential probe ran 23 cases against v1.14.2 and this branch, on the expression, the in-memory rows, and the Postgres SQL. The only remaining difference is the in-list constant type for
InternalScore ^^ [40, 50](ListagainstInListValues). PR #133 made that change on purpose, and it does not change the result or the SQL.Tests
QueryKit.UnitTests/PropertyResolverTests.cs: internal, protected, private, and nested internal members, a property list, a query name on an internal member,AllowUnknownProperties, the public-before-non-public order, and the indexer. 13 of these fail on main.QueryKit.IntegrationTests/Tests/PropertyResolverTests.cs: a filter on an internal EF-mapped property, with and withoutAllowUnknownProperties. Both fail on main withUnknownFilterPropertyException.Nicknameproperty onTestingPerson, mapped to a new nullablenicknamecolumn with a migration.QueryKit.WebApiTestProjectmakes its internals visible to the integration tests.dotnet test: unit 416 passed, integration 285 passed.Overlap with other PRs