From 3b633b071c7eb7445553761440b3caf8157af1d7 Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Wed, 8 Oct 2025 13:26:57 +0900 Subject: [PATCH v1] Fix window function lead/lag incorrect results. Window function lead/lag returned incorrect results if IGNORE NULLS option is specified. Also this commit fixes if "offse=0" is given to lead/lag, they returned incorrect results. --- src/backend/executor/nodeWindowAgg.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 0698aae37a7..f9a9700dfa8 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -3727,12 +3727,13 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno, Assert(WindowObjectIsValid(winobj)); winstate = winobj->winstate; - if (winobj->ignore_nulls == IGNORE_NULLS && relpos != 0) + /* prepare thing if IGNORE NULLS */ + if (winobj->ignore_nulls == IGNORE_NULLS) { - null_treatment = true; - notnull_offset = 0; - notnull_relpos = abs(relpos); - forward = relpos > 0 ? 1 : -1; + null_treatment = true; /* we need to consider IGNORE NULLS */ + notnull_offset = 0; /* last NOT NULL row offset */ + notnull_relpos = abs(relpos); /* NOT NULL row absolute pos */ + forward = relpos >= 0 ? 1 : -1; /* 1: move forward, -1: otherwise */ } switch (seektype) @@ -3778,18 +3779,18 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno, * Get the next nonnull value in the partition, moving forward or backward * until we find a value or reach the partition's end. */ - do + for (; abs_pos >= 0; abs_pos += forward) { int nn_info; /* NOT NULL info */ - abs_pos += forward; - if (abs_pos < 0) /* apparently out of partition */ - break; - /* check NOT NULL cached info */ nn_info = get_notnull_info(winobj, abs_pos); if (nn_info == NN_NOTNULL) /* this row is known to be NOT NULL */ + { notnull_offset++; + if (notnull_offset > notnull_relpos) + break; /* target row found */ + } else if (nn_info == NN_NULL) /* this row is known to be NULL */ continue; /* keep on moving forward or backward */ @@ -3802,11 +3803,15 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno, if (myisout) /* out of partition? */ break; if (!*isnull) + { notnull_offset++; + if (notnull_offset > notnull_relpos) + break; /* target row found */ + } /* record the row status */ put_notnull_info(winobj, abs_pos, *isnull); } - } while (notnull_offset < notnull_relpos); + } /* get tupple and evaluate in a partition */ datum = gettuple_eval_partition(winobj, argno, -- 2.43.0