BUG #19731: `first_value` returns an excluded peer for a nonempty `EXCLUDE TIES` frame

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: theshallow27(at)gmail(dot)com
Subject: BUG #19731: `first_value` returns an excluded peer for a nonempty `EXCLUDE TIES` frame
Date: 2026-09-29 19:16:36
Message-ID: 19731-bf41225d46718e0d@postgresql.org
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 19731
Logged by: Shallow
Email address: theshallow27(at)gmail(dot)com
PostgreSQL version: 18.6
Operating system: Linux
Description:

Summary

When a `ROWS` frame does not include the current row, PostgreSQL can make
`first_value` return a peer excluded from the frame. In this reproducer, the
first row's frame contains only `1` after `EXCLUDE TIES`, and `array_agg`
confirms that frame, but `first_value` returns `0`.

## Reproducer

```sql
WITH t(x) AS (
VALUES (0), (0), (1)
)
SELECT x,
first_value(x) OVER w AS first_in_frame,
array_agg(x) OVER w AS frame_values
FROM t
WINDOW w AS (
ORDER BY x
ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING
EXCLUDE TIES
);
```

The SQL window frame is nonempty, so `first_value` should return its first
value. `EXCLUDE TIES` removes peers of the current row but retains non-peer
rows; it must not cause an excluded peer to be returned as though it were
still in the frame.
The related `last_value` case also fails for a frame ending before the
current row. The local triage identifies `WinGetFuncInFrame` in
`src/backend/executor/nodeWindowAgg.c` as the common path: its
current-position fallback appears to assume the current row is in the frame.

Browse pgsql-bugs by date

  From Date Subject
Next Message Masahiko Sawada 2026-09-30 02:19:33 Re: autovacuum: automatically propagate updated parameters
Previous Message Ross Burton 2026-09-29 16:45:07 Re: BUG #19727: pg-combinebackup fails to link