nocfbot-0004-dedicated-define-exprcontext.txt
text/plain
Filename: nocfbot-0004-dedicated-define-exprcontext.txt
Type: text/plain
Part: 3
Message:
Re: Row pattern recognition
From a70f1c1e753425adcec6021c07a0f5af6dc0968f Mon Sep 17 00:00:00 2001
From: Henson Choi <assam258@gmail.com>
Date: Mon, 15 Jun 2026 16:54:13 +0900
Subject: [PATCH 04/13] Use a dedicated ExprContext for RPR DEFINE clause
evaluation
DEFINE clauses were evaluated in the per-output-tuple context. Because
EEOP_RPR_NAV_RESTORE copies pass-by-reference navigation results into that
context, resetting it per row freed window function results before
ExecProject (a use-after-free), while not resetting it leaked across the
partition. tmpcontext cannot be reused either, as ExecQualAndReset() resets
it mid-expression when NEXT re-enters spool_tuples. Use a third ExprContext,
reset once per row and separate from both.
---
src/backend/executor/execRPR.c | 5 ++++-
src/backend/executor/nodeWindowAgg.c | 25 ++++++++++++++++++++++---
src/include/nodes/execnodes.h | 1 +
3 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/src/backend/executor/execRPR.c b/src/backend/executor/execRPR.c
index b326a58bbf5..de78b06d277 100644
--- a/src/backend/executor/execRPR.c
+++ b/src/backend/executor/execRPR.c
@@ -1592,10 +1592,13 @@ static void
nfa_reevaluate_dependent_vars(WindowAggState *winstate, RPRNFAContext *ctx,
int64 currentPos)
{
- ExprContext *econtext = winstate->ss.ps.ps_ExprContext;
+ ExprContext *econtext = winstate->rprContext;
int64 saved_match_start = winstate->nav_match_start;
int64 saved_pos = winstate->currentpos;
+ /* Release the previous evaluation's DEFINE expression memory */
+ ResetExprContext(econtext);
+
/* Temporarily set nav_match_start and currentpos for FIRST/LAST */
winstate->nav_match_start = ctx->matchStartRow;
winstate->currentpos = currentPos;
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 5b2385f1d8d..90f33bdee40 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -2742,12 +2742,28 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
/*
* Create expression contexts. We need two, one for per-input-tuple
- * processing and one for per-output-tuple processing. We cheat a little
- * by using ExecAssignExprContext() to build both.
+ * processing and one for per-output-tuple processing, plus an optional
+ * third for row pattern recognition DEFINE evaluation (built just below
+ * when a DEFINE clause is present). We cheat a little by using
+ * ExecAssignExprContext() to build them all. Each call overwrites
+ * ps_ExprContext, so the last call must establish the output context.
*/
ExecAssignExprContext(estate, &winstate->ss.ps);
tmpcontext = winstate->ss.ps.ps_ExprContext;
winstate->tmpcontext = tmpcontext;
+
+ /*
+ * Row pattern recognition evaluates DEFINE clauses in a third context,
+ * reset before each DEFINE evaluation pass. It must be distinct from
+ * tmpcontext and ps_ExprContext so its reset frees neither input nor
+ * output tuple memory.
+ */
+ if (node->defineClause != NIL)
+ {
+ ExecAssignExprContext(estate, &winstate->ss.ps);
+ winstate->rprContext = winstate->ss.ps.ps_ExprContext;
+ }
+
ExecAssignExprContext(estate, &winstate->ss.ps);
/* Create long-lived context for storage of partition-local memory etc */
@@ -4572,12 +4588,15 @@ static bool
nfa_evaluate_row(WindowObject winobj, int64 pos, bool *varMatched)
{
WindowAggState *winstate = winobj->winstate;
- ExprContext *econtext = winstate->ss.ps.ps_ExprContext;
+ ExprContext *econtext = winstate->rprContext;
int numDefineVars = list_length(winstate->defineVariableList);
int varIdx = 0;
TupleTableSlot *slot;
int64 saved_pos;
+ /* Release the previous row's DEFINE evaluation memory */
+ ResetExprContext(econtext);
+
/* Fetch current row into temp_slot_1 */
slot = winstate->temp_slot_1;
if (!window_gettupleslot(winobj, pos, slot))
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8060b018ef8..5b4ac8a6c33 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -2698,6 +2698,7 @@ typedef struct WindowAggState
MemoryContext aggcontext; /* shared context for aggregate working data */
MemoryContext curaggcontext; /* current aggregate's working data */
ExprContext *tmpcontext; /* short-term evaluation context */
+ ExprContext *rprContext; /* DEFINE clause evaluation context */
bool all_first; /* true if the scan is starting */
bool partition_spooled; /* true if all tuples in current partition
--
2.50.1 (Apple Git-155)