v47-0001-remove-nfaStateSize-and-nfaVisitedNWords.no-cfbot

application/octet-stream

Filename: v47-0001-remove-nfaStateSize-and-nfaVisitedNWords.no-cfbot
Type: application/octet-stream
Part: 1
Message: Re: Row pattern recognition
From 6f5c9f8b4c92d7610a86e993525e4fbd87401ef4 Mon Sep 17 00:00:00 2001
From: jian he <jian.universality@gmail.com>
Date: Fri, 29 May 2026 12:27:13 +0800
Subject: [PATCH v47 1/3] remove nfaStateSize and nfaVisitedNWords

Refactor struct WindowAggState: Remove the nfaStateSize and nfaVisitedNWords
fields because they are constant, and we can easily compute it.
---
 src/backend/executor/README.rpr      |  2 --
 src/backend/executor/execRPR.c       | 12 +++++++-----
 src/backend/executor/nodeWindowAgg.c | 10 ++++------
 src/include/nodes/execnodes.h        |  3 ---
 4 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/src/backend/executor/README.rpr b/src/backend/executor/README.rpr
index 2bf7703c777..05e1609a666 100644
--- a/src/backend/executor/README.rpr
+++ b/src/backend/executor/README.rpr
@@ -508,7 +508,6 @@ V-3. RPR Fields of WindowAggState
   nfaStateFree                  Reuse pool for states
   nfaVarMatched                 Per-row cache: varMatched[varId]
   nfaVisitedElems               Bitmap for cycle detection
-  nfaStateSize                  Precomputed size of RPRNFAState
 
 Memory management:
 
@@ -1461,7 +1460,6 @@ Appendix B. Data Structure Relationship Diagram
     |--- defineClauseList: List<ExprState>
     |--- nfaVarMatched: bool[] (per-row cache)
     |--- nfaVisitedElems: bitmapword* (cycle detection)
-    |--- nfaStateSize: Size (pre-calculated RPRNFAState allocation size)
     |--- nfaContext <-> nfaContextTail (doubly-linked list)
     |   +--- RPRNFAContext
     |       |--- states: RPRNFAState* (linked list)
diff --git a/src/backend/executor/execRPR.c b/src/backend/executor/execRPR.c
index f381a84961d..8664cf7acc3 100644
--- a/src/backend/executor/execRPR.c
+++ b/src/backend/executor/execRPR.c
@@ -193,23 +193,25 @@ static void nfa_advance(WindowAggState *winstate, RPRNFAContext *ctx,
 static RPRNFAState *
 nfa_state_alloc(WindowAggState *winstate)
 {
+	int			nfaStateSize;
 	RPRNFAState *state;
 
+	nfaStateSize = offsetof(RPRNFAState, counts) + sizeof(int32) * winstate->rpPattern->maxDepth;
+
 	/* Try to reuse from free list first */
 	if (winstate->nfaStateFree != NULL)
 	{
 		state = winstate->nfaStateFree;
 		winstate->nfaStateFree = state->next;
+		memset(state, 0, nfaStateSize);
 	}
 	else
 	{
 		/* Allocate in partition context for proper lifetime */
-		state = MemoryContextAlloc(winstate->partcontext, winstate->nfaStateSize);
+		state = MemoryContextAllocZero(winstate->partcontext,
+									   nfaStateSize);
 	}
 
-	/* Initialize entire state to zero */
-	memset(state, 0, winstate->nfaStateSize);
-
 	/* Update statistics */
 	winstate->nfaStatesActive++;
 	winstate->nfaStatesTotalCreated++;
@@ -1396,7 +1398,7 @@ nfa_advance(WindowAggState *winstate, RPRNFAContext *ctx, int64 currentPos)
 
 		/* Clear visited bitmap before each state's DFS expansion */
 		memset(winstate->nfaVisitedElems, 0,
-			   sizeof(bitmapword) * winstate->nfaVisitedNWords);
+			   sizeof(bitmapword) * ((winstate->rpPattern->numElements - 1) / BITS_PER_BITMAPWORD + 1));
 
 		state = states;
 		states = states->next;
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index d4d57ffd795..7682a12402c 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -3056,12 +3056,10 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 	/* Calculate NFA state size and allocate cycle detection bitmap */
 	if (node->rpPattern != NULL)
 	{
-		winstate->nfaStateSize = offsetof(RPRNFAState, counts) +
-			sizeof(int32) * node->rpPattern->maxDepth;
-		winstate->nfaVisitedNWords =
-			(node->rpPattern->numElements - 1) / BITS_PER_BITMAPWORD + 1;
-		winstate->nfaVisitedElems = palloc0(sizeof(bitmapword) *
-											winstate->nfaVisitedNWords);
+		int			nfaVisitedNWords;
+
+		nfaVisitedNWords = (node->rpPattern->numElements - 1) / BITS_PER_BITMAPWORD + 1;
+		winstate->nfaVisitedElems = palloc0(sizeof(bitmapword) * nfaVisitedNWords);
 	}
 
 	/* Set up row pattern recognition DEFINE clause */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 0cb01baa949..3ef0127c105 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -2663,7 +2663,6 @@ typedef struct WindowAggState
 									 * traversal) */
 	RPRNFAContext *nfaContextFree;	/* recycled NFA context nodes */
 	RPRNFAState *nfaStateFree;	/* recycled NFA state nodes */
-	Size		nfaStateSize;	/* pre-calculated RPRNFAState size */
 	bool	   *nfaVarMatched;	/* per-row cache: varMatched[varId] for varId
 								 * < numDefines */
 	Bitmapset  *defineMatchStartDependent;	/* DEFINE vars needing per-context
@@ -2671,8 +2670,6 @@ typedef struct WindowAggState
 											 * (match_start-dependent) */
 	bitmapword *nfaVisitedElems;	/* elemIdx visited bitmap for cycle
 									 * detection */
-	int			nfaVisitedNWords;	/* number of bitmapwords in
-									 * nfaVisitedElems */
 	int64		nfaLastProcessedRow;	/* last row processed by NFA (-1 =
 										 * none) */
 
-- 
2.34.1