Skip to content

fix: restore v1.14.2 behavior for audit items A, C, E, H, and N - #122

Merged
pdevito3 merged 5 commits into
mainfrom
fm/qk-restore-compat
Sep 30, 2026
Merged

pdevito3 merged 5 commits into
mainfrom
fm/qk-restore-compat

Conversation

@pdevito3

@pdevito3 pdevito3 commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

This PR restores the v1.14.2 behavior on main for the audit items A, C, E, H, and N. After this PR, main keeps only the security fixes B, I, M, and P as breaking changes. Each item returns later as its own PR, so each change can get a separate decision.

There is one commit for each item. Each commit has a test that shows the v1.14.2 behavior.

Restored items

  • A. Parse limits on IQueryKitConfiguration. MaxNestingDepth and MaxInputLength move to a new interface, IQueryKitParseLimits. QueryKitConfiguration implements both interfaces. IQueryKitConfiguration is the same as in v1.14.2 again. A configuration that implements only IQueryKitConfiguration gets the default limits, so the limits of item B stay in force.
  • C. ArithmeticOperator.FromSymbol. The method is back with the v1.14.2 signature and body. It has [Obsolete].
  • E. Filter values as parameters. Filter values are constants again by default, with the v1.14.2 expression text. The new setting ParameterizeFilterValues (default false) sends the values as query parameters.
  • H. Prevented and unknown clauses. By default, a clause on a prevented or unknown property becomes true == true again, the same as v1.14.2. The new setting IgnoredClauseBehavior has the values ReplaceWithTrue (default) and Remove. Remove keeps the behavior of main.
  • N. ReplaceAliasesWithPropertyPaths. The public method replaces a query name after a dot again. The parser does not call this method, so filters do not change.

Item D (message text) stays as it is on main. This PR does not change B, I, M, P, or the bug fixes.

Tests

  • dotnet test: 370 unit tests and 274 integration tests passed.
  • v1.14.2 integration tests against this branch: 205 passed, 1 skipped.
  • v1.14.2 unit tests against this branch: 174 passed, 2 skipped, 13 failed. The 5 failures from the audit for E and H now pass. The 13 failures are expression text from two fixes that PR fix(parser): correct parser and value-conversion bugs #114 kept:
    • 9 tests: the case-sensitive string operators add a null check, for example (x.Title != null) AndAlso x.Title.EndsWith("b").
    • 4 tests: a DateTimeOffset value with an offset is sent in UTC, for example new DateTimeOffset(637922232030000000, 00:00:00) in place of new DateTimeOffset(637922304030000000, 02:00:00). The instant is the same.

IQueryKitConfiguration got MaxNestingDepth and MaxInputLength after v1.14.2. A class that implements the interface directly did not compile, and a library built against v1.14.2 failed with TypeLoadException.

The limits are now on the new interface IQueryKitParseLimits, which QueryKitConfiguration implements. A configuration without this interface uses the default limits of 32 levels and 5000 characters.
v1.14.2 had the public method ArithmeticOperator.FromSymbol. Its removal broke the source and the binaries of callers. The method is back with the same body. It is marked obsolete, because QueryKit does not use it and the next major version removes it.
…lues is on

After v1.14.2, each filter value became a field read that EF Core sends as a SQL parameter. This changed the expression text, the SQL text, and the in-list SQL. On SQL Server at compatibility level 120 or less, in-list filters failed.

The new setting ParameterizeFilterValues is false by default. When it is false, filter values are the same constants and constructor calls as in v1.14.2. When it is true, filter values are parameters, as before this change.
v1.14.2 replaced a clause on a prevented or unknown property with (true == true). Main removed the clause, which changes the rows that an OR returns. The new setting IgnoredClauseBehavior has the default ReplaceWithTrue, which gives the v1.14.2 behavior again. The value Remove keeps the behavior of main.
In v1.14.2, the public ReplaceAliasesWithPropertyPaths replaced a query name also after a dot. Main skipped it, which changed the result for direct callers. The parser does not call this method, so filters do not change.
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