diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 81ba024bba..4f4aeb2883 100644 --- a/src/backend/executor/nodeWindowAgg.c +++ b/src/backend/executor/nodeWindowAgg.c @@ -2300,7 +2300,27 @@ ExecWindowAgg(PlanState *pstate) continue; } else + { winstate->status = WINDOWAGG_PASSTHROUGH; + + /* + * If we're not the top-window, we'd better NULLify + * the aggregate results. In pass-through mode we no + * longer update these and this avoids the old stale + * results lingering. Some of these might be byref + * types so we can't have them pointing to free'd + * memory. The planner insisted that quals used in + * the runcondition are strict, so the top-level + * WindowAgg will filter these NULLs out in the filter + * clause. + */ + numfuncs = winstate->numfuncs; + for (i = 0; i < numfuncs; i++) + { + econtext->ecxt_aggvalues[i] = (Datum) 0; + econtext->ecxt_aggnulls[i] = true; + } + } } else { diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 03ee6dc832..0c564be7f6 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -2399,6 +2399,18 @@ check_and_push_window_quals(Query *subquery, RangeTblEntry *rte, Index rti, if (list_length(opexpr->args) != 2) return true; + /* + * Currently, we restrict this optimization to strict OpExprs. The reason + * for this is that during execution, once the runcondition becomes false, + * we stop evaluating WindowFuncs. To avoid leaving around stale window + * function result values, we set them to NULL. Having only strict + * OpExprs here ensures that we properly filter out the tuples with NULLs + * in the top-level WindowAgg. + */ + set_opfuncid(opexpr); + if (!func_strict(opexpr->opfuncid)) + return true; + /* * Check for plain Vars that reference window functions in the subquery. * If we find any, we'll ask find_window_run_conditions() if 'opexpr' can