Skip to content

fix(snowflake): rewrite COUNT(*) FILTER to COUNT_IF [CLAUDE]#7900

Merged
geooo109 merged 1 commit into
tobymao:mainfrom
chuenchen309:fix/snowflake-count-star-filter
Jul 20, 2026
Merged

fix(snowflake): rewrite COUNT(*) FILTER to COUNT_IF [CLAUDE]#7900
geooo109 merged 1 commit into
tobymao:mainfrom
chuenchen309:fix/snowflake-count-star-filter

Conversation

@chuenchen309

Copy link
Copy Markdown
Contributor

filter_sql rewrites an aggregate FILTER (WHERE cond) into a conditional
argument by wrapping the aggregate's input in IFF(cond, input, NULL). When the
aggregate is COUNT(*), that input is a star, so the output is
COUNT(IFF(cond, *, NULL)) — a star isn't a valid IFF argument and Snowflake
rejects it.

COUNT(*) FILTER (WHERE cond) is just a count of qualifying rows, which is
exactly Snowflake's native COUNT_IF(cond), so emit that instead. Other
aggregates and COUNT(expr) / COUNT(DISTINCT ...) are untouched.

COUNT(*) FILTER (WHERE b > 0)   duckdb -> snowflake
  before: SELECT COUNT(IFF(b > 0, *, NULL)) FROM t   (invalid)
  after:  SELECT COUNT_IF(b > 0) FROM t

This completes #7884, which handled the DISTINCT / ORDER BY argument shapes
but not the star case. Added a regression test alongside the existing
FILTER-rewrite cases in test_duckdb.py; make unit and make style pass.


This PR was authored by an AI coding agent (Claude Code) running on this account:
the AI found the bug, ran the repro, wrote the test, and wrote this description.
The human account holder reviews every change and is accountable for it. The
verification above is real and re-runnable from the diff. If this isn't the kind
of contribution you want, say so and I'll close it.

filter_sql rewrites aggregate FILTER into a conditional argument by wrapping
the aggregate's input in IFF(cond, input, NULL). For COUNT(*) that input is a
star, producing COUNT(IFF(cond, *, NULL)) -- a star is not a valid IFF
argument, so Snowflake rejects it.

COUNT(*) FILTER (WHERE cond) counts qualifying rows, which is exactly
Snowflake's native COUNT_IF(cond); emit that instead. Other aggregates and
COUNT(expr)/COUNT(DISTINCT ...) are unaffected.

This completes #7884, which handled the DISTINCT/ORDER BY argument shapes but
not the star.

Co-authored-by AI: Claude (Claude Code). [CLAUDE]
@geooo109 geooo109 self-assigned this Jul 20, 2026
Comment on lines +369 to +370
self.validate_all(
"SELECT COUNT(*) FILTER (WHERE b > 0) FROM t",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actual the current approach works

snowflake output: SELECT COUNT(IFF(b > 0, *, NULL)) FROM t

WITH t(b) AS (
  SELECT * FROM VALUES (1), (2)
)
SELECT COUNT(IFF(b > 0, *, NULL)) FROM t;
> 2

WITH t(b, c) AS (
  SELECT * FROM VALUES (1, 'x'), (-1, 'x'), (5, 'y'), (0, 'y')
)
SELECT COUNT(IFF(b > 0, *, NULL)) FROM t;
* expands to 2 arguments and we get:
> SQL compilation error: error line 4 at position 13 too many arguments for function [IFF(T.B > 0, T.B, T.C, null)] expected 3, got 4

 

If t contains only 1 column.

@geooo109
geooo109 merged commit 47e255d into tobymao:main Jul 20, 2026
8 checks passed
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.

2 participants