Repository navigation
test: composition sweeps — outer joins, nullable operand pairs, quantifiers, repeated execution, filtered aggregates, declared nullability (#375–#380) - #383
Merged
Conversation
…antifiers, repeated execution, filtered aggregates and declared nullability (#375–#380) Six integration sweeps vary how a translated range, RangeSet or value set call composes inside a query, against a rule (c) reference that never lets a NULL reach the library (Composition/NullRule.cs), plus a reference-free partition check on every call: Where(P) and Where(!P) partition the rows and Select(P) says which side each row is on. - OuterJoinProbeTests (#375): every member over the child of a parent without one, through a navigation, GroupJoin with DefaultIfEmpty and LeftJoin. - NullableOperandPairProbeTests (#376): every binary member over two nullable columns, a CASE and a COALESCE of them. - QuantifierProbeTests (#377): Any/All/Count/Contains over captured lists holding NULL, compound predicates with De Morgan, nested predicates. - RepeatedExecutionProbeTests (#378): one query re-run with its parameter walked through null, finite, empty and infinite; compiled queries. - FilteredAggregateProbeTests (#379): RangeAgg/RangeIntersectAgg over groups a filter empties, all NULL, holding empty, or a LeftJoin key without rows, consumed by every member, HAVING and an ordering; E07 mapped. - DeclaredNullabilityTests (#380): every emitted function's declaration against pg_proc.proisstrict and the server, and every value's null test against its projection. Disagreements are registered as candidates: #381 and #382 (new), #360. Two new seeds prove the re-execution and aggregate sweeps; the existing null seeds now name the sweeps they were shown to catch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 24, 2026
10.x: Contains(element) on a range or RangeSet is NULL in SQL for a NULL element (port of #381)
#387
Closed
Open
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.
Closes #375
Closes #376
Closes #377
Closes #378
Closes #379
Closes #380
Problem
The differential sweeps vary shapes, types and operand kinds, mostly in a projection and over one nullable column at most. #349, #350, #355, #360 and #361 all came from how a translated call composes inside a query: where the NULL comes from, what EF Core's null semantics do around it, and what a later execution reuses. Nothing swept that axis (#362).
Change
Six sweeps in the integration project, each in a database of its own, over
DateRange, itsRangeSetandStringSet, with the members discovered (Composition/CompositionMembers.cs):OuterJoinProbeTestsGroupJoin+DefaultIfEmpty,LeftJoin), the factories over the child's element columns, bounds through??NullableOperandPairProbeTestsCASEand aCOALESCE, on every (null, value) pair; equality andCompareTounder their documented rulesQuantifierProbeTestsAny/All/Count/Containsover captured lists holding NULL;P && Q,P || Qwith De Morgan; predicates over value-producing membersRepeatedExecutionProbeTests(,)→ null and back, lists walked empty → one → duplicate → NULL;EF.CompileQuery/EF.CompileAsyncQueryFilteredAggregateProbeTestsRangeAgg/RangeIntersectAggover groups that are filtered empty, all NULL, holdempty, or are aLeftJoinkey without rows, consumed by every member,HAVING,HAVING NOTand an ordering by a boundDeclaredNullabilityTestspg_proc.proisstrictand the server (typed NULLs,empty,(,),{}); every translated value's null test against its projectionThe reference is
Composition/NullRule.cs: the expression rewritten so a NULL never reaches the library (rule (c) for a predicate, no value for a value-producing member or a missing element, equality andCompareTounder their own documented rules, aggregates skipping NULL). Documented differences are mapped, not reported: E07 (aggregates over zero inputs), E72 (ordering by a bound),CompareTo(#261).CompositionRunneradds a reference-free check to every call:Where(P)andWhere(!P)partition the rows andSelect(P)says which side each row is on.Registered in
test/oracles/oracles.json, named in theheldByof E07, E70, E71 and E72, with the axes intest/oracles/axes.mdand a section indocs/oracles.md. No change tosrc/.What they found
Every disagreement is a filed issue and a
candidates.jsonentry:silent, low):Contains(element)on a range orRangeSetwith a NULL element (outer join, nullable element column) is NULL in SQL, so the negation drops the row EF Core keeps, a projection intoboolthrows, and underAlla positive filter selects the row.silent, medium): the factories over a NULL element build a range (CreateFinite→empty,CreateUnboundedStart/End→(,)), soCreateUnboundedEnd(c.From).Contains(v)selects a parent without a child.array_catandarray_removeare declared strict and are not; reached through an outer join, two nullable columns, a NULL parameter and a nullable element. Measured in a comment there.Clean: predicates, bounds and range/multirange value operations over a missing child; two nullable operands including
CASE/COALESCE; equality andCompareTo; quantifiers over lists holding NULL (apart from #381'sAll); 112 compound predicates with De Morgan; nested predicates; repeated and compiled execution (apart from #360); every aggregate consumption; every other emitted function's declaration.Tests
dotnet run tools/oracles.cs seeds, each CAUGHT by the sweeps it names:range-predicate-over-a-null-column-is-null,value-set-predicate-over-a-null-column-is-null: sweeps 1–4;bound-declared-null-only-for-a-null-argument(fix: declare lower() and upper() NULL for a non-null range #353 reverted): sweeps 1, 2, 5, 6;aggregates-fold-a-null-input: sweep 5;sql-processor-reuses-its-first-output: sweep 4 (no other sweep re-executes a query shape with another parameter);range-agg-declared-never-null: sweep 5.🤖 Generated with Claude Code