fix(filter)!: read a quoted "null" as text for a string property - #172
Merged
Merged
Conversation
A quoted "null" became a real null, so Title == "null" matched the row with a null Title and not the row with the text "null". Now a quoted "null" is text for a string property. An unquoted null is still a null, and a quoted "null" is still a null for other types.
pdevito3
force-pushed
the
fix/quoted-null-is-text
branch
from
October 2, 2026 20:11
1f51058 to
45ca127
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
A quoted
"null"on a string property is now the textnull. Before this change, the parser read it as a real null. An unquotednulldoes not change.Title == "null"x.Title == nullx.Title == "null"Title != "null"x.Title != nullx.Title != "null"Title @= "null"x.Title.Contains(null)x.Title.Contains("null")Title == nullx.Title == nullx.Title == null(no change)Age == "null"x.Age == nullx.Age == null(no change, an int has no text value)Notes:
Title @= "null"is a text search, not a null value.@=on a row with a null property throws aNullReferenceException. That is a separate bug, and fix(operators)!: check for null in case-sensitive string operators #145 corrects it. Postgres is not affected.ConvertStringToBasicType, which still maps a quoted"null"to null. This PR does not change that path.^^ ["null"]was already the textnullfor a string, because the grammar removes the quotes. An unquoted[null]in a list is also text. This PR does not change the list path.Evidence
Harness:
verify-querykit, runqk-20261002-223925-97048. The seed data has no row with the textnullinDirections. One row (Plain Water) has a nullDirections.Before (main
d81242c):Directions == "null": expressionx.Directions == null, returns Plain Water on memory and Postgres.Directions != "null": expressionx.Directions != null, returns 3 rows.Directions @= "null": expressionContains(null), memory throwsArgumentNullException, Postgres returns[].After (labels with
-fixed):Directions == "null": expressionx.Directions == "null", returns[]on both targets.Directions != "null": returns all 4 rows on both targets.Directions @= "null": expressionContains("null"), Postgres returns[]. Memory throws the fix(operators)!: check for null in case-sensitive string operators #145 NRE on the null row.== nulland!= nullreturn the same rows as before.Tests:
quoted_null_is_text_for_a_string(==,!=,@=,!@=,==*),unquoted_null_is_null_for_a_string_not_equal,quoted_null_is_null_for_a_type_that_has_no_text, and the enumerable theoryquoted_null_matches_the_text_null_and_unquoted_null_matches_null.NullFilteringTests.quoted_null_matches_the_text_null_and_unquoted_null_matches_nullwith==,!=,@=,^^ ["null"],== null, and!= null. Without the fix, the==,!=, and@=cases fail.Merge Danger
Door: two-way
The change is one condition in the parser. A revert puts back the old behavior.
Blast Radius: consumers
This is a breaking change. A consumer that sends
Prop == "null"to find null rows on a string property now gets the rows with the textnull. Change the filter toProp == null(no quotes) to find null rows.