Skip to content

feat(duckdb): convert ARRAY_AGG IGNORE NULLS to FILTER clause#7893

Merged
geooo109 merged 2 commits into
tobymao:mainfrom
algolia:upstream-pr/ignore-nulls-filter
Jul 21, 2026
Merged

feat(duckdb): convert ARRAY_AGG IGNORE NULLS to FILTER clause#7893
geooo109 merged 2 commits into
tobymao:mainfrom
algolia:upstream-pr/ignore-nulls-filter

Conversation

@sirockin

Copy link
Copy Markdown
Contributor

Summary

BigQuery's ARRAY_AGG(x IGNORE NULLS ...) silently drops NULLs from the aggregation. DuckDB does not support IGNORE NULLS on aggregate functions, but the same semantics can be expressed with a FILTER clause: ARRAY_AGG(x ...) FILTER(WHERE x IS NOT NULL).

Problem

Previously, the DuckDB generator silently dropped the IGNORE NULLS modifier on ARRAY_AGG, producing incorrect results when the input contained NULL values. The ignorenulls_sql method handled window functions (via IGNORE_RESPECT_NULLS_WINDOW_FUNCTIONS) and converted First to AnyValue, but ArrayAgg was not handled — the IGNORE NULLS was silently lost.

Changes

  • Add ArrayAgg-specific handling in ignorenulls_sql that sets a nulls_excluded flag, which the existing _add_arrayagg_null_filter infrastructure converts to a FILTER(WHERE col IS NOT NULL) clause
  • Add arrayagg_sql override to unwrap Order/Limit nodes so the FILTER clause references the correct column expression (not the ordering wrapper)
  • Update test expectations for ARRAY_AGG DISTINCT IGNORE NULLS to include the FILTER clause

Motivation

We use sqlglot to transpile BigQuery SQL models to DuckDB for local testing via sqlmesh. Our production models use ARRAY_AGG(... IGNORE NULLS ORDER BY ...) extensively, and the silent loss of IGNORE NULLS caused incorrect test results.

BigQuery's `ARRAY_AGG(x IGNORE NULLS ...)` silently drops NULLs from
the aggregation. DuckDB does not support `IGNORE NULLS` on aggregate
functions, but the same semantics can be expressed with a `FILTER`
clause: `ARRAY_AGG(x ...) FILTER(WHERE x IS NOT NULL)`.

Previously, the DuckDB generator silently dropped the `IGNORE NULLS`
modifier on `ARRAY_AGG`, producing incorrect results when the input
contained NULL values.

Adds:
- `ArrayAgg`-specific handling in `ignorenulls_sql` that sets a
  `nulls_excluded` flag, which the existing `_add_arrayagg_null_filter`
  infrastructure converts to a `FILTER(WHERE col IS NOT NULL)` clause
- `arrayagg_sql` override to unwrap `Order`/`Limit` nodes so the
  FILTER clause references the correct column expression
- Updated test expectations for ARRAY_AGG DISTINCT IGNORE NULLS
@geooo109 geooo109 self-assigned this Jul 17, 2026
Comment thread tests/dialects/test_bigquery.py
Comment thread tests/dialects/test_bigquery.py Outdated
Comment thread sqlglot/generators/duckdb.py Outdated
- Move Order/Limit unwrapping from DuckDB override to base generator's
  arrayagg_sql so all dialects benefit
- Emit unsupported warning for LIMIT inside ARRAY_AGG in DuckDB
- Remove invalid LIMIT 1, 10 test (unsupported BigQuery syntax)
- Simplify DuckDB arrayagg_sql to delegate to super()

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

Copy link
Copy Markdown
Collaborator

@sirockin is this still a draft? What's pending?

@geooo109
geooo109 marked this pull request as ready for review July 21, 2026 11:17
@geooo109
geooo109 merged commit 8be76d2 into tobymao:main Jul 21, 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.

3 participants