public inbox for [email protected]  
help / color / mirror / Atom feed
From: Tatsuo Ishii <[email protected]>
To: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Subject: Re: Row pattern recognition
Date: Tue, 24 Feb 2026 11:56:25 +0900 (JST)
Message-ID: <[email protected]> (raw)
In-Reply-To: <CAAAe_zAxEqdyoOgx4u0A2RXu829CE-RJbJjg1jVz00j3aSYryQ@mail.gmail.com>
References: <CAAAe_zDcrF9_m5FnWFgdrCpxjTqdH2ZMDmpKXevMG4KBHJsw4w@mail.gmail.com>
	<[email protected]>
	<CAAAe_zAxEqdyoOgx4u0A2RXu829CE-RJbJjg1jVz00j3aSYryQ@mail.gmail.com>

Hi Henson,

> Hi Tatsuo,
> 
> Here are six incremental patches on top of v43.
> 
> nocfbot-0001 through nocfbot-0004 are the same patches from the
> previous round (32-bit test fix, PREV/NEXT restriction, ALT lexical
> ordering, reluctant quantifiers).
> 
> nocfbot-0005: Detect zero-consumption NFA cycles
> 
> Adds a per-element visited bitmap to detect zero-consumption cycles
> during DFS epsilon expansion.  Before each state's DFS, the bitmap
> is cleared; as nfa_advance_state() recurses through epsilon
> transitions, each elemIdx is marked visited.  If the same elemIdx
> is reached again within the same DFS, it means an epsilon-only
> loop -- the state is freed immediately.
> 
> The ad-hoc (count == 0 && min == 0) exit condition in
> nfa_advance_end() is removed.  The FIXME test cases are resolved
> and renamed to "Zero-Consumption Cycle Detection".
> 
> nocfbot-0006: Allow A{0} quantifier
> 
> With cycle detection in place, this becomes straightforward.
> Lowers the {n} bound minimum from 1 to 0.  A{0} is treated as an
> epsilon transition -- the variable is skipped entirely.

Great!

> Next I plan to work on test reorganization, cross-database result
> comparison, and a review pass over the NFA executor.

Looking forward to seeing next patches.

BTW, in create_windowagg_plan (createplan.c),
around:
/* Build RPR pattern and filter defineClause */

collectPatternVariables, filterDefineClause and buildRPRPattern are
called in a block without any if or any other conditional
statements. This is an unusual codiing style in PostgreSQL.  I suggest
to fix this.  Attached is a proposed patch for this.

Best regards,
--
Tatsuo Ishii
SRA OSS K.K.
English: http://www.sraoss.co.jp/index_en/
Japanese:http://www.sraoss.co.jp

diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index bbc2c7e71f4..e7aafc89700 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2484,6 +2484,10 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
 	Oid		   *ordOperators;
 	Oid		   *ordCollations;
 	ListCell   *lc;
+	List	   *defineVariableList = NIL;
+	List	   *filteredDefineClause = NIL;
+	RPRPattern *compiledPattern = NULL;
+
 
 	/*
 	 * Choice of tlist here is motivated by the fact that WindowAgg will be
@@ -2535,50 +2539,45 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
 	}
 
 	/* Build RPR pattern and filter defineClause */
+	if (wc->rpPattern)
 	{
-		List	   *defineVariableList = NIL;
-		List	   *filteredDefineClause = NIL;
-		RPRPattern *compiledPattern = NULL;
-
-		if (wc->rpPattern)
-		{
-			List	   *patternVars;
+		List	   *patternVars;
 
-			/*
-			 * Filter defineClause to include only variables used in PATTERN.
-			 * This eliminates unnecessary DEFINE evaluations at runtime.
-			 */
-			patternVars = collectPatternVariables(wc->rpPattern);
-			filteredDefineClause = filterDefineClause(wc->defineClause,
-													  patternVars,
-													  &defineVariableList);
-
-			compiledPattern = buildRPRPattern(wc->rpPattern,
-											  defineVariableList,
-											  wc->rpSkipTo,
-											  wc->frameOptions);
-		}
-
-		/* And finally we can make the WindowAgg node */
-		plan = make_windowagg(tlist,
-							  wc,
-							  partNumCols,
-							  partColIdx,
-							  partOperators,
-							  partCollations,
-							  ordNumCols,
-							  ordColIdx,
-							  ordOperators,
-							  ordCollations,
-							  best_path->runCondition,
-							  wc->rpSkipTo,
-							  compiledPattern,
-							  filteredDefineClause,
-							  best_path->qual,
-							  best_path->topwindow,
-							  subplan);
+		/*
+		 * Filter defineClause to include only variables used in PATTERN. This
+		 * eliminates unnecessary DEFINE evaluations at runtime.
+		 */
+		patternVars = collectPatternVariables(wc->rpPattern);
+		filteredDefineClause = filterDefineClause(wc->defineClause,
+												  patternVars,
+												  &defineVariableList);
+
+		/* Compile and optimize RPR patterns */
+		compiledPattern = buildRPRPattern(wc->rpPattern,
+										  defineVariableList,
+										  wc->rpSkipTo,
+										  wc->frameOptions);
 	}
 
+	/* And finally we can make the WindowAgg node */
+	plan = make_windowagg(tlist,
+						  wc,
+						  partNumCols,
+						  partColIdx,
+						  partOperators,
+						  partCollations,
+						  ordNumCols,
+						  ordColIdx,
+						  ordOperators,
+						  ordCollations,
+						  best_path->runCondition,
+						  wc->rpSkipTo,
+						  compiledPattern,
+						  filteredDefineClause,
+						  best_path->qual,
+						  best_path->topwindow,
+						  subplan);
+
 	copy_generic_path_info(&plan->plan, (Path *) best_path);
 
 	return plan;


Attachments:

  [text/plain] fix_plan.txt (2.9K, 2-fix_plan.txt)
  download | inline diff:
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index bbc2c7e71f4..e7aafc89700 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -2484,6 +2484,10 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
 	Oid		   *ordOperators;
 	Oid		   *ordCollations;
 	ListCell   *lc;
+	List	   *defineVariableList = NIL;
+	List	   *filteredDefineClause = NIL;
+	RPRPattern *compiledPattern = NULL;
+
 
 	/*
 	 * Choice of tlist here is motivated by the fact that WindowAgg will be
@@ -2535,50 +2539,45 @@ create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
 	}
 
 	/* Build RPR pattern and filter defineClause */
+	if (wc->rpPattern)
 	{
-		List	   *defineVariableList = NIL;
-		List	   *filteredDefineClause = NIL;
-		RPRPattern *compiledPattern = NULL;
-
-		if (wc->rpPattern)
-		{
-			List	   *patternVars;
+		List	   *patternVars;
 
-			/*
-			 * Filter defineClause to include only variables used in PATTERN.
-			 * This eliminates unnecessary DEFINE evaluations at runtime.
-			 */
-			patternVars = collectPatternVariables(wc->rpPattern);
-			filteredDefineClause = filterDefineClause(wc->defineClause,
-													  patternVars,
-													  &defineVariableList);
-
-			compiledPattern = buildRPRPattern(wc->rpPattern,
-											  defineVariableList,
-											  wc->rpSkipTo,
-											  wc->frameOptions);
-		}
-
-		/* And finally we can make the WindowAgg node */
-		plan = make_windowagg(tlist,
-							  wc,
-							  partNumCols,
-							  partColIdx,
-							  partOperators,
-							  partCollations,
-							  ordNumCols,
-							  ordColIdx,
-							  ordOperators,
-							  ordCollations,
-							  best_path->runCondition,
-							  wc->rpSkipTo,
-							  compiledPattern,
-							  filteredDefineClause,
-							  best_path->qual,
-							  best_path->topwindow,
-							  subplan);
+		/*
+		 * Filter defineClause to include only variables used in PATTERN. This
+		 * eliminates unnecessary DEFINE evaluations at runtime.
+		 */
+		patternVars = collectPatternVariables(wc->rpPattern);
+		filteredDefineClause = filterDefineClause(wc->defineClause,
+												  patternVars,
+												  &defineVariableList);
+
+		/* Compile and optimize RPR patterns */
+		compiledPattern = buildRPRPattern(wc->rpPattern,
+										  defineVariableList,
+										  wc->rpSkipTo,
+										  wc->frameOptions);
 	}
 
+	/* And finally we can make the WindowAgg node */
+	plan = make_windowagg(tlist,
+						  wc,
+						  partNumCols,
+						  partColIdx,
+						  partOperators,
+						  partCollations,
+						  ordNumCols,
+						  ordColIdx,
+						  ordOperators,
+						  ordCollations,
+						  best_path->runCondition,
+						  wc->rpSkipTo,
+						  compiledPattern,
+						  filteredDefineClause,
+						  best_path->qual,
+						  best_path->topwindow,
+						  subplan);
+
 	copy_generic_path_info(&plan->plan, (Path *) best_path);
 
 	return plan;


reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: Row pattern recognition
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox