nocfbot-0029-Rename-RPR-NFA-constructors-to-make-clone-per-Jia.txt

text/plain

Filename: nocfbot-0029-Rename-RPR-NFA-constructors-to-make-clone-per-Jia.txt
Type: text/plain
Part: 27
Message: Re: Row pattern recognition
From 8a00c552f5f3ecd6c889b53b8062304d43b06252 Mon Sep 17 00:00:00 2001
From: Henson Choi <assam258@gmail.com>
Date: Mon, 1 Jun 2026 11:16:49 +0900
Subject: [PATCH 29/68] Rename RPR NFA constructors to make/clone per Jian He's
 round-3 review

Rename nfa_context_alloc and nfa_state_alloc to _make (a blank
allocation), and nfa_state_create to nfa_state_clone (build a state from
an existing one's counts).  This follows the makeNode precedent and the
regex engine's clonesuccessorstates/cloneouts.  Also reword the
nfa_state_clone header comment from "Create" to "Clone".
---
 src/backend/executor/README.rpr       |  2 +-
 src/backend/executor/execRPR.c        | 58 +++++++++++++--------------
 src/test/regress/expected/rpr_nfa.out |  2 +-
 src/test/regress/sql/rpr_nfa.sql      |  2 +-
 4 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/src/backend/executor/README.rpr b/src/backend/executor/README.rpr
index 467cc03ecff..9396a569fbd 100644
--- a/src/backend/executor/README.rpr
+++ b/src/backend/executor/README.rpr
@@ -579,7 +579,7 @@ VI-2. Context Creation: ExecRPRStartContext()
 
 Creates a new context and performs the initial advance.
 
-  (1) Allocate context via nfa_context_alloc()
+  (1) Allocate context via nfa_context_make()
   (2) Set matchStartRow = pos
   (3) Create initial state: elemIdx=0 (first pattern element),
       counts=all zero
diff --git a/src/backend/executor/execRPR.c b/src/backend/executor/execRPR.c
index 9bad36239f8..4022ca66e84 100644
--- a/src/backend/executor/execRPR.c
+++ b/src/backend/executor/execRPR.c
@@ -54,11 +54,11 @@ nfa_mark_visited(WindowAggState *winstate, int16 elemIdx)
 }
 
 /* Forward declarations - NFA state management */
-static RPRNFAState *nfa_state_alloc(WindowAggState *winstate);
+static RPRNFAState *nfa_state_make(WindowAggState *winstate);
 static void nfa_state_free(WindowAggState *winstate, RPRNFAState *state);
 static void nfa_state_free_list(WindowAggState *winstate, RPRNFAState *list);
-static RPRNFAState *nfa_state_create(WindowAggState *winstate, int16 elemIdx,
-									 int32 *counts, bool sourceAbsorbable);
+static RPRNFAState *nfa_state_clone(WindowAggState *winstate, int16 elemIdx,
+									int32 *counts, bool sourceAbsorbable);
 static bool nfa_states_equal(WindowAggState *winstate, RPRNFAState *s1,
 							 RPRNFAState *s2);
 static void nfa_add_state_unique(WindowAggState *winstate, RPRNFAContext *ctx,
@@ -67,7 +67,7 @@ static void nfa_add_matched_state(WindowAggState *winstate, RPRNFAContext *ctx,
 								  RPRNFAState *state, int64 matchEndRow);
 
 /* Forward declarations - NFA context management (internal) */
-static RPRNFAContext *nfa_context_alloc(WindowAggState *winstate);
+static RPRNFAContext *nfa_context_make(WindowAggState *winstate);
 static void nfa_unlink_context(WindowAggState *winstate, RPRNFAContext *ctx);
 
 /* Forward declarations - NFA statistics */
@@ -199,14 +199,14 @@ static void nfa_advance(WindowAggState *winstate, RPRNFAContext *ctx,
  */
 
 /*
- * nfa_state_alloc
+ * nfa_state_make
  *
  * Allocate an NFA state, reusing from freeList if available.
  * freeList is stored in WindowAggState for reuse across match attempts.
  * Uses flexible array member for counts[].
  */
 static RPRNFAState *
-nfa_state_alloc(WindowAggState *winstate)
+nfa_state_make(WindowAggState *winstate)
 {
 	RPRNFAState *state;
 
@@ -265,21 +265,21 @@ nfa_state_free_list(WindowAggState *winstate, RPRNFAState *list)
 }
 
 /*
- * nfa_state_create
+ * nfa_state_clone
  *
- * Create a new state with given elemIdx and counts.
+ * Clone a state from the given elemIdx and counts.
  * isAbsorbable is computed immediately: inherited AND new element's flag.
  * Monotonic property: once false, stays false through all transitions.
  *
  * Caller is responsible for linking the returned state.
  */
 static RPRNFAState *
-nfa_state_create(WindowAggState *winstate, int16 elemIdx,
-				 int32 *counts, bool sourceAbsorbable)
+nfa_state_clone(WindowAggState *winstate, int16 elemIdx,
+				int32 *counts, bool sourceAbsorbable)
 {
 	RPRPattern *pattern = winstate->rpPattern;
 	int			maxDepth = pattern->maxDepth;
-	RPRNFAState *state = nfa_state_alloc(winstate);
+	RPRNFAState *state = nfa_state_make(winstate);
 	RPRPatternElement *elem = &pattern->elements[elemIdx];
 
 	state->elemIdx = elemIdx;
@@ -418,12 +418,12 @@ nfa_add_matched_state(WindowAggState *winstate, RPRNFAContext *ctx,
 }
 
 /*
- * nfa_context_alloc
+ * nfa_context_make
  *
  * Allocate an NFA context, reusing from free list if available.
  */
 static RPRNFAContext *
-nfa_context_alloc(WindowAggState *winstate)
+nfa_context_make(WindowAggState *winstate)
 {
 	RPRNFAContext *ctx;
 
@@ -931,8 +931,8 @@ nfa_route_to_elem(WindowAggState *winstate, RPRNFAContext *ctx,
 
 		/* Create skip state before add_unique, which may free state */
 		if (RPRElemCanSkip(nextElem))
-			skipState = nfa_state_create(winstate, nextElem->next,
-										 state->counts, state->isAbsorbable);
+			skipState = nfa_state_clone(winstate, nextElem->next,
+										state->counts, state->isAbsorbable);
 
 		nfa_add_state_unique(winstate, ctx, state);
 
@@ -978,8 +978,8 @@ nfa_advance_alt(WindowAggState *winstate, RPRNFAContext *ctx,
 			break;
 
 		/* Create independent state for each branch */
-		newState = nfa_state_create(winstate, altIdx,
-									state->counts, state->isAbsorbable);
+		newState = nfa_state_clone(winstate, altIdx,
+								   state->counts, state->isAbsorbable);
 
 		/* Recursively process this branch before next */
 		nfa_advance_state(winstate, ctx, newState, currentPos);
@@ -1011,8 +1011,8 @@ nfa_advance_begin(WindowAggState *winstate, RPRNFAContext *ctx,
 	/* Optional group: create skip path (but don't route yet) */
 	if (elem->min == 0)
 	{
-		skipState = nfa_state_create(winstate, elem->jump,
-									 state->counts, state->isAbsorbable);
+		skipState = nfa_state_clone(winstate, elem->jump,
+									state->counts, state->isAbsorbable);
 	}
 
 	if (skipState != NULL && RPRElemIsReluctant(elem))
@@ -1094,8 +1094,8 @@ nfa_advance_end(WindowAggState *winstate, RPRNFAContext *ctx,
 		 *----------
 		 */
 		if (RPRElemCanEmptyLoop(elem))
-			ffState = nfa_state_create(winstate, state->elemIdx,
-									   state->counts, state->isAbsorbable);
+			ffState = nfa_state_clone(winstate, state->elemIdx,
+									  state->counts, state->isAbsorbable);
 
 		/* Primary path: loop back for real matches */
 		for (int d = depth + 1; d < pattern->maxDepth; d++)
@@ -1163,8 +1163,8 @@ nfa_advance_end(WindowAggState *winstate, RPRNFAContext *ctx,
 		 * Create exit state first (need original counts before modifying
 		 * state)
 		 */
-		exitState = nfa_state_create(winstate, elem->next,
-									 state->counts, state->isAbsorbable);
+		exitState = nfa_state_clone(winstate, elem->next,
+									state->counts, state->isAbsorbable);
 		exitState->counts[depth] = 0;
 		nextElem = &elements[exitState->elemIdx];
 
@@ -1255,8 +1255,8 @@ nfa_advance_var(WindowAggState *winstate, RPRNFAContext *ctx,
 			RPRNFAState *savedMatch = ctx->matchedState;
 
 			/* Clone for exit, original stays for loop */
-			cloneState = nfa_state_create(winstate, elem->next,
-										  state->counts, state->isAbsorbable);
+			cloneState = nfa_state_clone(winstate, elem->next,
+										 state->counts, state->isAbsorbable);
 			cloneState->counts[depth] = 0;
 			nextElem = &elements[cloneState->elemIdx];
 
@@ -1287,8 +1287,8 @@ nfa_advance_var(WindowAggState *winstate, RPRNFAContext *ctx,
 		else
 		{
 			/* Clone for loop, original used for exit */
-			cloneState = nfa_state_create(winstate, state->elemIdx,
-										  state->counts, state->isAbsorbable);
+			cloneState = nfa_state_clone(winstate, state->elemIdx,
+										 state->counts, state->isAbsorbable);
 
 			/* Loop first (preferred for greedy) */
 			nfa_add_state_unique(winstate, ctx, cloneState);
@@ -1505,9 +1505,9 @@ ExecRPRStartContext(WindowAggState *winstate, int64 startPos)
 	RPRPattern *pattern = winstate->rpPattern;
 	RPRPatternElement *elem;
 
-	ctx = nfa_context_alloc(winstate);
+	ctx = nfa_context_make(winstate);
 	ctx->matchStartRow = startPos;
-	ctx->states = nfa_state_alloc(winstate);	/* initial state at elem 0 */
+	ctx->states = nfa_state_make(winstate); /* initial state at elem 0 */
 
 	elem = &pattern->elements[0];
 
diff --git a/src/test/regress/expected/rpr_nfa.out b/src/test/regress/expected/rpr_nfa.out
index 1f494d2db34..72dbf080a37 100644
--- a/src/test/regress/expected/rpr_nfa.out
+++ b/src/test/regress/expected/rpr_nfa.out
@@ -3844,7 +3844,7 @@ WINDOW w AS (
 
 -- Non-absorbable context during absorption
 -- Pattern (A B)+ C: A,B in absorbable group, C is not.
--- When END exits to C via nfa_state_create, isAbsorbable becomes false.
+-- When END exits to C via nfa_state_clone, isAbsorbable becomes false.
 WITH test_non_absorbable AS (
     SELECT * FROM (VALUES
         (1, ARRAY['A']),
diff --git a/src/test/regress/sql/rpr_nfa.sql b/src/test/regress/sql/rpr_nfa.sql
index 76dfc4d88bc..128476aa1d1 100644
--- a/src/test/regress/sql/rpr_nfa.sql
+++ b/src/test/regress/sql/rpr_nfa.sql
@@ -2790,7 +2790,7 @@ WINDOW w AS (
 
 -- Non-absorbable context during absorption
 -- Pattern (A B)+ C: A,B in absorbable group, C is not.
--- When END exits to C via nfa_state_create, isAbsorbable becomes false.
+-- When END exits to C via nfa_state_clone, isAbsorbable becomes false.
 WITH test_non_absorbable AS (
     SELECT * FROM (VALUES
         (1, ARRAY['A']),
-- 
2.50.1 (Apple Git-155)