diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c index 81ba024bba..110c594edd 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; + + /* + * Otherwise, if we're not the top-window, we'd better + * NULLify the aggregate results, else, by-ref result + * types will point to freed memory. We can get away + * without storing the final result of the WindowFunc + * because in the planner we insisted that the + * runcondition is strict. Setting these to NULL will + * ensure the top-level WindowAgg filter will always + * filter out the rows produced in this WindowAgg when + * not in WINDOWAGG_RUN state. + */ + 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 4ddaed31a4..a25956200e 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -2399,6 +2399,22 @@ 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 we stop evaluating WindowFuncs + * on lower-level WindowAgg nodes, since we're no longer updating them, + * we NULLify the aggregate and window aggregate results to prevent by-ref + * result typed window aggregates from pointing to free'd memory (this can + * happen on non-FLOAT8PASSBYVAL builds). Upper-level WindowAgg nodes may + * make reference to these results in their filter clause and we can + * ensure the filter remain false by making sure the operator is strict + * and by performing the NULLification when the run-condition is no longer + * true. + */ + set_opfuncid(opexpr); + if (!func_strict(opexpr->opfuncid)) + return false; + /* * 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