From a396683ced1a9bc9149898d447e6f2b847dc0772 Mon Sep 17 00:00:00 2001 From: Rebecca Le Date: Wed, 4 Feb 2026 14:36:00 +0800 Subject: [PATCH] fix: use `array_agg` instead of `any_value` when `include_nil?` is true On PostgreSQL 16+, `any_value()` was used for `first` aggregates as an optimization. However, `any_value()` by PostgreSQL design returns "an arbitrary value from the non-null input values" - it inherently skips NULLs. This broke `include_nil?: true` for `first` aggregates. When `include_nil?` is true, we now always use `array_agg` with `[1]` indexing, since only `array_agg` can include NULL values in the result. Reference: https://www.postgresql.org/docs/16/functions-aggregate.html --- lib/aggregate.ex | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/aggregate.ex b/lib/aggregate.ex index 972ebad..e3f1135 100644 --- a/lib/aggregate.ex +++ b/lib/aggregate.ex @@ -1890,7 +1890,13 @@ defmodule AshSql.Aggregate do has_sort? = has_sort?(aggregate.query) array_agg = - query.__ash_bindings__.sql_behaviour.list_aggregate(aggregate.query.resource) + if aggregate.include_nil? do + # any_value() ignores NULLs by design in PostgreSQL, so we must use + # array_agg with [1] indexing when include_nil? is true + "array_agg" + else + query.__ash_bindings__.sql_behaviour.list_aggregate(aggregate.query.resource) + end {sorted, include_nil_filter_field, query} = if has_sort? || first_relationship.sort not in [nil, []] do