Re: ON EMPTY clause for aggregate and window functions

From: Vik Fearing <vik(at)postgresfriends(dot)org>
To: Jeevan Chalke <jeevan(dot)chalke(at)enterprisedb(dot)com>, PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Cc: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, Isaac Morland <isaac(dot)morland(at)gmail(dot)com>
Subject: Re: ON EMPTY clause for aggregate and window functions
Date: 2026-09-17 12:04:42
Message-ID: fc92fc73-0d18-4b2e-bfcb-f9b4c4d6c4b6@postgresfriends.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers


On 12/09/2026 15:18, Jeevan Chalke wrote:
>
> ON EMPTY is now implemented as exactly:
>
> agg(args, default ON EMPTY)  ==  COALESCE(agg(args), default)

I've taken a quick look at this, and I found a few bugs.

1) The first one is that the constant requirement only looks for actual
constants and not scoped constants.  For example:

CREATE TABLE cust (id INTEGER, name text, def_amount PRIMARY KEY (id));
CREATE TABLE ord (id INTEGER, custid INTEGER, amount INTEGER);
INSERT INTO cust SELECT g, 'c' || g, g FROM generate_series(1, 4) AS g (g);
INSERT INTO ord VALUES (1,1,100), (2,1,50), (3,3,7);

-- rejected: "ON EMPTY expression must be a constant value"
SELECT c.id,
       (SELECT SUM(o.amount, c.def_amount ON EMPTY)
        FROM ord AS o
        WHERE o.custid = c.id)
FROM cust AS c;

Here, the c.def_amount is constant for the subquery and should be
accepted.  The example is perhaps a bit contrived, but the logic is sound.

2) Another bug I found is this:

CREATE TABLE mm (a INTEGER);
INSERT INTO mm SELECT g FROM generate_series(1, 10_000) AS g (g);
ANALYZE mm;

SELECT COALESCE(MAX(a), -1) FROM mm WHERE a > 100_000;  --  -1
SELECT MAX(a, -1 ON EMPTY)  FROM mm WHERE a > 100_000;  --  -1

CREATE INDEX ON mm (a);

SELECT COALESCE(MAX(a), -1) FROM mm WHERE a > 100_000;  -- -1
SELECT MAX(a, -1 ON EMPTY)  FROM mm WHERE a > 100_000;  --  NULL

When MAX and MIN get optimized with an index, the ON EMPTY seems to be
dropped.

3) The set quantifier is not recognized.

SELECT SUM(ALL      a, 0 ON EMPTY) FROM t;
SELECT SUM(DISTINCT a, 0 ON EMPTY) FROM t;

Neither of those parse.

I will keep reviewing this feature.

--

Vik Fearing

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Robert Haas 2026-09-17 12:12:59 issues with eager aggregation
Previous Message Ajit Awekar 2026-09-17 12:01:41 Re: Continuous re-validation of session credentials