From 98c46bd8a6138e6dba4f55f35e2d719c5c80ee15 Mon Sep 17 00:00:00 2001 From: Junwang Zhao Date: Sun, 25 Jan 2026 14:16:58 +0800 Subject: [PATCH] Replace COUNT(NULL) with '0'::bigint When count() receives a constant NULL argument, replace it with '0'::bigint constant instead of leaving it as NULL. --- src/backend/utils/adt/int8.c | 16 ++++++++++++++++ src/test/regress/expected/aggregates.out | 15 +++++++-------- src/test/regress/sql/aggregates.sql | 2 +- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c index 37d34685b93..438733684bd 100644 --- a/src/backend/utils/adt/int8.c +++ b/src/backend/utils/adt/int8.c @@ -20,6 +20,7 @@ #include "common/int.h" #include "funcapi.h" #include "libpq/pqformat.h" +#include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "nodes/supportnodes.h" #include "optimizer/optimizer.h" @@ -855,6 +856,21 @@ int8inc_support(PG_FUNCTION_ARGS) PG_RETURN_POINTER(newagg); } + + /* Replace constant NULL argument with '0'::bigint */ + if (IsA(arg, Const) && ((Const *) arg)->constisnull) + { + Const *newconst; + + newconst = makeConst(INT8OID, + -1, + InvalidOid, + sizeof(int64), + Int64GetDatum(0), + false, + true); + PG_RETURN_POINTER(newconst); + } } } diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out index cae8e7bca31..ef15e994e3f 100644 --- a/src/test/regress/expected/aggregates.out +++ b/src/test/regress/expected/aggregates.out @@ -2922,16 +2922,15 @@ select count('bananas') from agg_simplify; Output: a, not_null_col, nullable_col (4 rows) --- Ensure count(null) isn't optimized +-- Ensure count(null) is replaced with '0'::bigint explain (costs off, verbose) select count(null) from agg_simplify; - QUERY PLAN ------------------------------------------------ - Aggregate - Output: count(NULL::unknown) - -> Seq Scan on public.agg_simplify - Output: a, not_null_col, nullable_col -(4 rows) + QUERY PLAN +----------------------------- + Result + Output: '0'::bigint + Replaces: MinMaxAggregate +(3 rows) -- Ensure count(nullable_col) does not use count(*) explain (costs off, verbose) diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql index 850f5a5787f..34990a09823 100644 --- a/src/test/regress/sql/aggregates.sql +++ b/src/test/regress/sql/aggregates.sql @@ -1145,7 +1145,7 @@ select count(not_null_col) from agg_simplify; explain (costs off, verbose) select count('bananas') from agg_simplify; --- Ensure count(null) isn't optimized +-- Ensure count(null) is replaced with '0'::bigint explain (costs off, verbose) select count(null) from agg_simplify; -- 2.41.0