Re: BUG #19732: first_value/last_value/nth_value return NULL with EXCLUDE TIES when the current row is outside its f

From: Andrey Rachitskiy <pl0h0yp1(at)gmail(dot)com>
To: theshallow27(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: BUG #19732: first_value/last_value/nth_value return NULL with EXCLUDE TIES when the current row is outside its f
Date: 2026-09-30 14:33:58
Message-ID: CAB8bMit1Y-YyDowBZ87Fxn6qKz_010EauUrj6K5J4_r_zQaWHw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

ср, 30 сент. 2026 г. в 18:25, Andrey Rachitskiy <pl0h0yp1(at)gmail(dot)com>:

>
>
> ср, 30 сент. 2026 г. в 13:26, PG Bug reporting form <
> noreply(at)postgresql(dot)org>:
>
>> The following bug has been logged on the website:
>>
>> Bug reference: 19732
>> Logged by: Shallow
>> Email address: theshallow27(at)gmail(dot)com
>> PostgreSQL version: 18.6
>> Operating system: Linux
>> Description:
>>
>> With a ROWS frame that does not contain the current row, such as `1
>> FOLLOWING AND UNBOUNDED FOLLOWING`,
>> and `EXCLUDE TIES`, `first_value`, `nth_value` and `last_value` can return
>> NULL although the frame has rows.
>> This happens when the frame edge falls on a peer of the current row.
>> `array_agg` over the same window shows
>> the rows.
>>
>> ```sql
>> SELECT k, first_value(k) OVER w, nth_value(k, 1) OVER w, array_agg(k)
>> OVER w
>> FROM (VALUES (0), (0), (1)) t(k)
>> WINDOW w AS (ORDER BY k ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING
>> EXCLUDE TIES);
>>
>> k | first_value | nth_value | array_agg
>> ---+-------------+-----------+-----------
>> 0 | | | {1} <- expected 1, 1
>> 0 | 1 | 1 | {1}
>> 1 | | |
>>
>> SELECT k, last_value(k) OVER w, array_agg(k) OVER w
>> FROM (VALUES (0), (1), (1)) t(k)
>> WINDOW w AS (ORDER BY k ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
>> EXCLUDE TIES);
>>
>> k | last_value | array_agg
>> ---+------------+-----------
>> 0 | |
>> 1 | 0 | {0}
>> 1 | | {0} <- expected 0
>> ```
>>
>> For the first row of the first query, the frame is rows 2 and 3. Row 2 is
>> a
>> peer of the current row, so
>> `EXCLUDE TIES` removes it, and row 3 (k = 1) remains. Without `EXCLUDE
>> TIES`, the same frame gives the
>> right values.
>>
>> In `WinGetFuncArgInFrame` (nodeWindowAgg.c), the
>> `FRAMEOPTION_EXCLUDE_TIES`
>> case replaces `abs_pos` by
>> `winstate->currentpos` when the frame edge is the first row of the overlap
>> between the frame and the
>> current row's peer group. This is right only when the current row is
>> inside
>> the frame. The comment before
>> the switch expects the out-of-frame case to end with "deciding the row is
>> out of frame", but that returns
>> NULL here although later frame rows remain. The frame-tail branch has the
>> same substitution.
>>
>>
>>
> Hi, Shallow!
>
> Thanks for the report.
>
> Agreed on the WinGetFuncArgInFrame remap. Replacing abs_pos with
> currentpos is only valid when the current row is in the frame.
> When it is not, EXCLUDE TIES should skip the overlap the same way EXCLUDE
> GROUP does.
> The attached patch does that for the frame head and the frame tail.
>
>
v2 attached. The C change is the same. The regress is now two small
queries, first_value on a following frame and last_value on a
preceding frame.

Attachment Content-Type Size
v2-0001-Fix-first_value-nth_value-and-last_value-with-EXC.patch text/x-patch 5.5 KB

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 2026-09-30 15:24:56 Re: BUG #19727: pg-combinebackup fails to link
Previous Message Jiří Kavalík 2026-09-30 13:59:13 Streaming decoding fails with "unexpected table_index_fetch_tuple call during logical decoding" when a relation has a TOASTed conbin (follow-up to BUG #18641)