Skip to content

fix(config)!: keep a query name in a nested path in alias replacement - #127

Open
pdevito3 wants to merge 1 commit into
mainfrom
fm/qk-breaking-alias-dot
Open

pdevito3 wants to merge 1 commit into
mainfrom
fm/qk-breaking-alias-dot

Conversation

@pdevito3

@pdevito3 pdevito3 commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

For later consideration in a major version. Do not merge now. #122 restored the v1.14.2 match to keep v1.x non-breaking. This PR takes the fix back.

Summary

 QueryKitPropertyMappings.ReplaceAliasesWithPropertyPaths
-  regex: \b{QueryName}\b(?=\s*{op})
+  regex: (?<!\.)\b{QueryName}\b(?=\s*{op})
  • v1.14.2: The public method QueryKitPropertyMappings.ReplaceAliasesWithPropertyPaths replaces a query name anywhere in front of an operator, also after a dot.
  • New: A query name after a dot is a segment of a nested path. The method keeps it.
  • Why: The segment after the dot belongs to another type. When name is the query name of a top-level property, the old match changes Author.Name to Author.Title, which is a wrong path.
  • Also: The method does not throw InvalidOperationException for a query name after a dot when the property has PreventFilter() and PreventSort().
  • Filters: The filter parser calls an internal overload, ReplaceAliasesWithPropertyPaths(input, replaceAfterDot: true), that keeps the v1.14.2 match. As a result, filters do not change.

QN1 (a query name after a dot in a filter)

#154 owns QN1, the filter change for Author.name == "Ann". QN1 can not move to this PR. On main, the parser calls this method on the filter text. With the new match in the parser, Author.Name == "Ann" gives x => (x.Author.Name == "Ann") and not UnknownFilterPropertyException. This is QN1. #154 gets the same result, because it removes this call (J5). For this reason, this PR changes only the result of the public method.

Evidence

With config.Property<Recipe>(x => x.Title).HasQueryName("name") (the match ignores case):

ReplaceAliasesWithPropertyPaths("""Author.Name == "x" && name == "y" """)
  v1.14.2 and main: Author.Title == "x" && Title == "y"
  this PR:          Author.Name == "x" && Title == "y"

The restore test is renamed back to alias_replacement_does_not_replace_a_query_name_in_a_nested_path and expects the new result.

The new pin filter_with_a_query_name_in_a_nested_path_still_throws_for_the_replaced_path shows that filters do not change. Author.Name == "x" still throws UnknownFilterPropertyException for 'Title', like v1.14.2 and main.

dotnet test on this branch: 471 unit tests and 297 Postgres integration tests (Testcontainers) pass, 0 failures.

Interaction with other PRs

#154 deletes the call in FilterParser.ParseFilter that this PR changes. This gives a one-line text conflict. If both merge, keep the deletion of #154. Then delete the pin filter_with_a_query_name_in_a_nested_path_still_throws_for_the_replaced_path, because #154 changes that result.

Merge Danger

Door: two-way

The change is one lookbehind in one regex, and one internal overload for the parser.

Blast Radius: direct callers

The parser calls an internal overload that keeps the v1.14.2 match, so filters do not change. Only consumer code that calls ReplaceAliasesWithPropertyPaths directly sees the new result.

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
pdevito3 force-pushed the fm/qk-breaking-alias-dot branch from 5ffcfc9 to f8cb2ab Compare October 1, 2026 21:45
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