Skip to content

fix(binder): give a new aggregate its own name when an earlier clause has it - #1289

Open
zahariash wants to merge 1 commit into
LadybugDB:mainfrom
zahariash:fix/aggregate-key-name
Open

zahariash wants to merge 1 commit into
LadybugDB:mainfrom
zahariash:fix/aggregate-key-name

Conversation

@zahariash

Copy link
Copy Markdown
Contributor

This work was produced with the help of language models.

Fixes #1246.

UNWIND [1, 1, 2] AS x WITH x, count(x) AS c RETURN c, count(x) returned 1|1 twice instead of 2|1 and 1|1; sum(x), count(DISTINCT x) and count(x) + x after WITH x, count(x) + x AS c went wrong the same way. An aggregate is named after its function and arguments, so the RETURN's count(x) had the name of the expression carried in c, or of a part of it, and read that column instead of being computed.

Fix. An aggregate in a projection list whose structural name an expression in scope already has, at any depth, now gets a fresh name, as count(*) always did; the same aggregate repeated in one list shares it, so it is computed once. In WHERE and ORDER BY an aggregate keeps its structural name, so WITH x, count(x) AS c WHERE count(x) > 1 still filters on c and ORDER BY count(x) still sorts by it, and so does an aggregate inside a lambda body, which the projection does not compute.

Tests. agg/multi_query_part.test gets RepeatedAggregateAfterWithGroupKey: the four queries above, a list with count(x) twice, and the WHERE, ORDER BY and all(i IN [1] WHERE i < count(x)) cases that must keep reading c. On main the first five statements return wrong rows and the last three pass; all eight pass here. Full suite: no failures.

… has it

UNWIND [1, 1, 2] AS x WITH x, count(x) AS c RETURN c, count(x) returned
1|1 twice instead of 2|1 and 1|1; sum(x) and count(DISTINCT x) did the
same, and so did count(x) + x after WITH x, count(x) + x AS c. An
aggregate is named after its function and arguments, so the RETURN's
count(x) had the name of the expression carried in c, or of a part of it,
and took that column. An aggregate in a projection list whose name an
expression in scope already has, at any depth, now gets a fresh name,
reused for each occurrence in the list. In WHERE and ORDER BY an
aggregate keeps its structural name, so WITH x, count(x) AS c WHERE
count(x) > 1 still filters on c, and so does an aggregate inside a
lambda body, which the projection does not compute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

Bug: a new count(x) in RETURN overwrites the group key c from an earlier WITH x, count(x) AS c

1 participant