From 252b1e9b361feb82a12931787bb6108b11063598 Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Tue, 7 Jul 2026 08:10:58 -0700
Subject: [PATCH v1] Fix duplicate detection for null-treatment window
 functions

`ExecInitWindowAgg()` checks `perfunc[i].ignore_nulls` when deciding
whether a window function call can reuse an existing `WindowStatePerFunc`
entry. However, that field was never initialized when filling the
`perfuncstate` data, so it remained zero from `palloc0_array()`.

As a result, duplicate calls using `IGNORE NULLS` or explicit
`RESPECT NULLS` failed to reuse the existing entry, because their
`wfunc->ignore_nulls` value did not match the zeroed per-function state.
Plain calls were unaffected because their null-treatment value is also zero.

Copy `wfunc->ignore_nulls` into `perfuncstate->ignore_nulls` during
initialization so duplicate null-treatment window function calls are
deduplicated as intended.

Oversight in 25a30bbd423.

Author: Chao Li <lic@highgo.com>
---
 src/backend/executor/nodeWindowAgg.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index f1c524d00df..676fe024965 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -2749,11 +2749,23 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 		}
 		if (i <= wfuncno && wfunc->ignore_nulls == perfunc[i].ignore_nulls)
 		{
+			/* TODO: remove this log before pushing */
+			elog(INFO, "WindowAgg duplicate cache hit: existing wfuncno %d, ignore_nulls %d",
+				 i, wfunc->ignore_nulls);
+
 			/* Found a match to an existing entry, so just mark it */
 			wfuncstate->wfuncno = i;
 			continue;
 		}
 
+		/* TODO: remove this log before pushing */
+		if (i <= wfuncno)
+			elog(INFO, "WindowAgg duplicate cache miss: matched wfuncno %d, ignore_nulls %d, cached ignore_nulls %d",
+				 i, wfunc->ignore_nulls, perfunc[i].ignore_nulls);
+		else
+			elog(INFO, "WindowAgg duplicate cache miss: no previous match, ignore_nulls %d",
+				 wfunc->ignore_nulls);
+
 		/* Nope, so assign a new PerAgg record */
 		perfuncstate = &perfunc[++wfuncno];
 
@@ -2773,6 +2785,7 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 		perfuncstate->wfunc = wfunc;
 		perfuncstate->numArguments = list_length(wfuncstate->args);
 		perfuncstate->winCollation = wfunc->inputcollid;
+		perfuncstate->ignore_nulls = wfunc->ignore_nulls;
 
 		get_typlenbyval(wfunc->wintype,
 						&perfuncstate->resulttypeLen,
-- 
2.50.1 (Apple Git-155)

