You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Elaborate an aggregate's argument: a subquery inside SUM(...) / COUNT(...) never lowers its descriptors #100
elaborate_expr (src/elaborate/mod.rs) recurses into every expression form that can hold a subquery body — Binop, Call, Case, Record, Coalesce, ListComprehension, and the three subquery variants themselves — but Expr::Agg falls through its trailing other => other arm. So a descriptor written inside an aggregate's argument never has its value_filters lowered into a WHERE, and the query does not compile:
MATCH (p:P) RETURNSUM(VALUE { MATCH (x:P {n: 1}) RETURNx.n }) ASs
-- Typeerror: DescriptorforSome("x") stillcarriesvalue_filtersattypecheck
-- time (elaboration bug)
MATCH (p:P) RETURNCOUNT(EXISTS { MATCH (x:P {n: 99}) }) ASc
-- same
-- control: theidenticalsubqueryoutsideanaggregateelaboratesfineMATCH (p:P) RETURNVALUE { MATCH (x:P {n: 1}) RETURNx.n } ASs
-- [1], [1], [1]
It fails loudly, which is the good news
The typechecker's guard — "still carries value_filters at typecheck time (elaboration bug)" — catches it, so this is a rejected legal query, not a silently wrong answer. The filter is never quietly dropped. That is why this is an enhancement rather than a correctness bug, and why it can wait.
Why it surfaced now
Before 2be5d5a a bare aggregate in RETURN was its own ReturnItem::Aggregate variant, which elaborate_query's RETURN loop skipped entirely — so the gap existed for the same shapes and for a second, unrelated reason. Folding the variant into ReturnItem::Expr (#95 follow-up) removed that second cause and left this one as the only thing standing between an aggregate's argument and elaboration. Behaviour is unchanged either way; the refactor just made the omission legible.
optimizer/existential.rs::fold_in_expr already descends into Expr::Agg this way, so the shape has a precedent in the codebase; elaboration is simply missing its counterpart.
Tests belong in a new case in tests/correlated_subquery_test.rs or alongside the aggregate tests: the two repros above, plus a control asserting the descriptor actually filters (a subquery whose descriptor excludes rows must return fewer than the unfiltered form, so the test fails if the filter is lowered but ignored).
Activity