nocfbot-0010-redundant-conditions.txt
text/plain
Filename: nocfbot-0010-redundant-conditions.txt
Type: text/plain
Part: 9
Message:
Re: Row pattern recognition
From 64856e7964bb234e3d87599aafcc13a1d79902c9 Mon Sep 17 00:00:00 2001
From: Henson Choi <assam258@gmail.com>
Date: Thu, 26 Feb 2026 22:06:17 +0900
Subject: [PATCH 10/10] Remove redundant conditions in NFA executor
---
src/backend/executor/nodeWindowAgg.c | 77 ++++++++++------------------
1 file changed, 26 insertions(+), 51 deletions(-)
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index cd41eff394e..701e83b519b 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -5066,8 +5066,8 @@ nfa_process_row(WindowAggState *winstate, int64 currentPos,
bool *varMatched = winstate->nfaVarMatched;
/*
- * Phase 1: Match all contexts (convergence) Evaluate VAR elements, update
- * counts, remove dead states.
+ * Phase 1: Match all contexts (convergence). Evaluate VAR elements,
+ * update counts, remove dead states.
*/
for (ctx = winstate->nfaContext; ctx != NULL; ctx = ctx->next)
{
@@ -5092,8 +5092,8 @@ nfa_process_row(WindowAggState *winstate, int64 currentPos,
}
/*
- * Phase 2: Absorb redundant contexts After match phase, states have
- * converged - ideal for absorption. First update absorption flags that
+ * Phase 2: Absorb redundant contexts. After match phase, states have
+ * converged - ideal for absorption. First update absorption flags that
* may have changed due to state removal.
*/
if (winstate->rpPattern->isAbsorbable)
@@ -5105,7 +5105,7 @@ nfa_process_row(WindowAggState *winstate, int64 currentPos,
}
/*
- * Phase 3: Advance all contexts (divergence) Create new states
+ * Phase 3: Advance all contexts (divergence). Create new states
* (loop/exit) from surviving matched states.
*/
for (ctx = winstate->nfaContext; ctx != NULL; ctx = ctx->next)
@@ -5243,8 +5243,7 @@ nfa_states_equal(WindowAggState *winstate, RPRNFAState *s1, RPRNFAState *s2)
elem = &pattern->elements[s1->elemIdx];
compareDepth = elem->depth + 1; /* depth 0 needs 1 count, etc. */
- if (compareDepth > 0 &&
- memcmp(s1->counts, s2->counts, sizeof(int32) * compareDepth) != 0)
+ if (memcmp(s1->counts, s2->counts, sizeof(int32) * compareDepth) != 0)
return false;
return true;
@@ -5359,11 +5358,10 @@ nfa_context_alloc(WindowAggState *winstate)
ctx->matchEndRow = -1;
ctx->lastProcessedRow = -1;
ctx->matchedState = NULL;
+
/* Initialize two-flag absorption design based on pattern */
- ctx->hasAbsorbableState = (winstate->rpPattern != NULL &&
- winstate->rpPattern->isAbsorbable);
- ctx->allStatesAbsorbable = (winstate->rpPattern != NULL &&
- winstate->rpPattern->isAbsorbable);
+ ctx->hasAbsorbableState = winstate->rpPattern->isAbsorbable;
+ ctx->allStatesAbsorbable = winstate->rpPattern->isAbsorbable;
/* Update statistics */
winstate->nfaContextsActive++;
@@ -5436,40 +5434,23 @@ nfa_start_context(WindowAggState *winstate, int64 startPos)
{
RPRNFAContext *ctx;
RPRPattern *pattern = winstate->rpPattern;
+ RPRPatternElement *elem;
ctx = nfa_context_alloc(winstate);
ctx->matchStartRow = startPos;
ctx->states = nfa_state_alloc(winstate); /* initial state at elem 0 */
- /*--------------------------
- * Initialize two-flag absorption design:
- * hasAbsorbableState: can this context absorb others? (>= 1 absorbable state)
- * allStatesAbsorbable: can this context be absorbed? (ALL states absorbable)
- * Both initialized from pattern->isAbsorbable at context start.
- */
- ctx->hasAbsorbableState = (pattern != NULL && pattern->isAbsorbable);
- ctx->allStatesAbsorbable = (pattern != NULL && pattern->isAbsorbable);
+ elem = &pattern->elements[0];
- if (ctx->states != NULL && pattern != NULL && pattern->numElements > 0)
+ if (RPRElemIsAbsorbableBranch(elem))
{
- RPRPatternElement *elem = &pattern->elements[0];
-
- /*
- * Initial state at element 0. Check if element 0 is in absorbable
- * branch.
- */
- if (RPRElemIsAbsorbableBranch(elem))
- {
- /* Element 0 is in absorbable branch - flags stay true */
- ctx->states->isAbsorbable = true;
- }
- else
- {
- /* Element 0 is NOT in absorbable branch - turn flags OFF */
- ctx->hasAbsorbableState = false;
- ctx->allStatesAbsorbable = false;
- ctx->states->isAbsorbable = false;
- }
+ ctx->states->isAbsorbable = true;
+ }
+ else
+ {
+ ctx->hasAbsorbableState = false;
+ ctx->allStatesAbsorbable = false;
+ ctx->states->isAbsorbable = false;
}
/* Add to tail of active context list (doubly-linked, oldest-first) */
@@ -6369,11 +6350,8 @@ nfa_advance_var(WindowAggState *winstate, RPRNFAContext *ctx,
cloneState->counts[depth] = 0;
nextElem = &elements[cloneState->elemIdx];
- /*
- * When exiting directly to an outer END, increment the END's
- * iteration count.
- */
- if (RPRElemIsEnd(nextElem) && count > 0)
+ /* When exiting directly to an outer END, increment its count */
+ if (RPRElemIsEnd(nextElem))
{
if (cloneState->counts[nextElem->depth] < RPR_COUNT_MAX)
cloneState->counts[nextElem->depth]++;
@@ -6411,14 +6389,11 @@ nfa_advance_var(WindowAggState *winstate, RPRNFAContext *ctx,
nextElem = &elements[state->elemIdx];
/*
- * When exiting directly to an outer END, increment the END's
- * iteration count. Simple VARs (min=max=1) handle this via
- * inline advance in nfa_match, but quantified VARs bypass that
- * path. Only increment when the VAR actually consumed rows
- * (count > 0) to preserve cycle prevention for zero-progress
- * loops.
+ * When exiting directly to an outer END, increment its iteration
+ * count. Simple VARs (min=max=1) handle this via inline advance
+ * in nfa_match, but quantified VARs bypass that path.
*/
- if (RPRElemIsEnd(nextElem) && count > 0)
+ if (RPRElemIsEnd(nextElem))
{
if (state->counts[nextElem->depth] < RPR_COUNT_MAX)
state->counts[nextElem->depth]++;
@@ -6443,7 +6418,7 @@ nfa_advance_var(WindowAggState *winstate, RPRNFAContext *ctx,
nextElem = &elements[state->elemIdx];
/* See comment above: increment outer END count for quantified VARs */
- if (RPRElemIsEnd(nextElem) && count > 0)
+ if (RPRElemIsEnd(nextElem))
{
if (state->counts[nextElem->depth] < RPR_COUNT_MAX)
state->counts[nextElem->depth]++;
--
2.50.1 (Apple Git-155)