Skip to content

Conditional .Having(...) on a split GroupBy chain is not mask-gated — HAVING renders unconditionally #328

Description

@DJGosnell

Description

A conditional (if-gated) .Having(...) on a GroupBy chain split across a reassigned local variable makes the generator lose the chain root's context type. When two contexts both expose an accessor for the same entity (CteDb and TestDbContext both have IEntityAccessor<Order> Orders()), the chain binds to the wrong context and renders wrong-dialect SQL.

Previously noted only as a prose comment ("Filed as follow-up") with no tracking issue — split out of #314's finding 5.

Location

  • Trailing NOTE documenting the routing-around: src/Quarry.Tests/SqlOutput/CrossDialectConditionalMaskTests.cs (end of file, "NOTE: A conditional-Having test ... currently triggers a generator misattribution")
  • Chain-root context resolution during binding: src/Quarry.Generator/IR/CallSiteBinder.cs / src/Quarry.Generator/Parsing/ChainAnalyzer.cs (context type lost across the GroupBy/Having variable split)

Diagnostics

Repro shape:

var ltG = lt.Orders().GroupBy(o => o.Status).Select(g => (g.Key, Total: Sql.Sum(g.Value.Amount)));
if (cond)
    ltG = ltG.Having(g => Sql.Count() > 1);
var results = await ltG.ExecuteFetchAllAsync();

With both CteDb and TestDbContext in the compilation exposing Orders(), the chain binds to CteDb — SQL renders with CteDb's dialect/schema instead of the actual receiver's.

What Has Been Tried

Nothing — the test that would exercise this was deliberately omitted (single-line GroupBy chains work; see CrossDialectAggregateTests). Note in the test file records the behavior.

Gathered Information

Suggested Approach

During chain-root resolution, retain the receiver's context type through builder-variable reassignment (track the local's declared/inferred builder generic arguments rather than re-resolving by entity type). Failing that, detect the ambiguity (multiple contexts exposing the entity) and emit an actionable QRY diagnostic instead of silently binding to the wrong context.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions