Fix-non-ASCII-characters.txt
text/plain
Filename: Fix-non-ASCII-characters.txt
Type: text/plain
Part: 0
Message:
Re: Row pattern recognition
From 1cc2ebd59597c672b752d7b6912dedc2bde88d66 Mon Sep 17 00:00:00 2001
From: Henson Choi <assam258@gmail.com>
Date: Tue, 3 Feb 2026 17:30:06 +0900
Subject: [PATCH] Fix non-ASCII characters in RPR code and comments
---
src/backend/executor/nodeWindowAgg.c | 10 ++++-----
src/backend/optimizer/plan/rpr.c | 2 +-
src/include/nodes/execnodes.h | 8 ++++----
src/test/regress/expected/rpr.out | 14 ++++++-------
src/test/regress/expected/rpr_base.out | 28 +++++++++++++-------------
src/test/regress/sql/rpr.sql | 14 ++++++-------
src/test/regress/sql/rpr_base.sql | 28 +++++++++++++-------------
7 files changed, 52 insertions(+), 52 deletions(-)
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index bcdf8b6db81..1176df04b2c 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -4977,7 +4977,7 @@ register_result:
* These functions implement direct NFA execution using the compiled
* RPRPattern structure, avoiding regex compilation overhead.
*
- * Execution Flow: match → absorb → advance
+ * Execution Flow: match -> absorb -> advance
* -----------------------------------------
* The NFA execution follows a three-phase cycle for each row:
*
@@ -4997,7 +4997,7 @@ register_result:
*
* Key Design Decisions:
* ---------------------
- * - VAR→END transition in match phase: When a simple VAR (max=1) matches
+ * - VAR->END transition in match phase: When a simple VAR (max=1) matches
* and the next element is END, we transition immediately in the match
* phase rather than waiting for advance. This is necessary for correct
* absorption: states must be at END to be marked absorbable before the
@@ -5008,7 +5008,7 @@ register_result:
* This ensures patterns like "A B? C" work correctly - we need a state
* waiting for B AND a state that has already skipped to C.
*
- * - END→END count increment: When transitioning from one END to another
+ * - END->END count increment: When transitioning from one END to another
* END within advance, we must increment the outer END's count. This
* handles nested groups like "((A|B)+)+" correctly - exiting the inner
* group counts as one iteration of the outer group.
@@ -6092,7 +6092,7 @@ nfa_advance_end(WindowAggState *winstate, RPRNFAContext *ctx,
state->elemIdx = elem->next;
nextElem = &elements[state->elemIdx];
- /* END→END: increment outer END's count */
+ /* END->END: increment outer END's count */
if (RPRElemIsEnd(nextElem) && state->counts[nextElem->depth] < RPR_COUNT_MAX)
state->counts[nextElem->depth]++;
@@ -6123,7 +6123,7 @@ nfa_advance_end(WindowAggState *winstate, RPRNFAContext *ctx,
exitState->counts[depth] = 0;
nextElem = &elements[exitState->elemIdx];
- /* END→END: increment outer END's count */
+ /* END->END: increment outer END's count */
if (RPRElemIsEnd(nextElem) && exitState->counts[nextElem->depth] < RPR_COUNT_MAX)
exitState->counts[nextElem->depth]++;
diff --git a/src/backend/optimizer/plan/rpr.c b/src/backend/optimizer/plan/rpr.c
index 230c545a631..50043c416c6 100644
--- a/src/backend/optimizer/plan/rpr.c
+++ b/src/backend/optimizer/plan/rpr.c
@@ -1379,7 +1379,7 @@ isUnboundedStart(RPRPattern *pattern, RPRElemIdx idx, RPRDepth parentDepth)
*
* Context absorption eliminates redundant match searches by absorbing
* newer contexts that cannot produce longer matches than older contexts.
- * This achieves O(n²) → O(n) performance improvement.
+ * This achieves O(n^2) -> O(n) performance improvement.
*
* Only greedy unbounded quantifiers at pattern start can be absorbable.
* Reluctant quantifiers are excluded because they don't maintain monotonic
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index b6d6d942de9..e0704742d16 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -2545,11 +2545,11 @@ typedef struct RPRNFAState
* RPRNFAContext - context for NFA pattern matching execution
*
* Two-flag absorption design:
- * hasAbsorbableState: can this context absorb others? (≥1 absorbable state)
- * - Monotonic: true→false only, cannot recover once false
+ * hasAbsorbableState: can this context absorb others? (>=1 absorbable state)
+ * - Monotonic: true->false only, cannot recover once false
* - Used to skip absorption attempts once all absorbable states are gone
* allStatesAbsorbable: can this context be absorbed? (ALL states absorbable)
- * - Dynamic: can change false→true (when non-absorbable states die)
+ * - Dynamic: can change false->true (when non-absorbable states die)
* - Used to determine if this context is eligible for absorption
*/
typedef struct RPRNFAContext
@@ -2564,7 +2564,7 @@ typedef struct RPRNFAContext
RPRNFAState *matchedState; /* FIN state for greedy fallback (cloned) */
/* Two-flag absorption optimization */
- bool hasAbsorbableState; /* can absorb others (≥1 absorbable
+ bool hasAbsorbableState; /* can absorb others (>=1 absorbable
* state) */
bool allStatesAbsorbable; /* can be absorbed (ALL states
* absorbable) */
diff --git a/src/test/regress/expected/rpr.out b/src/test/regress/expected/rpr.out
index c4794c5cd88..d4298860865 100644
--- a/src/test/regress/expected/rpr.out
+++ b/src/test/regress/expected/rpr.out
@@ -3099,11 +3099,11 @@ WINDOW w AS (
5 | {E,_} | |
(5 rows)
--- Row 1: A=T, B=T → matches A
--- Row 2: B=T, C=T → matches B
--- Row 3: C=T, D=T → matches C
--- Row 4: D=T, E=T → matches D
--- Row 5: E=T → matches E
+-- Row 1: A=T, B=T -> matches A
+-- Row 2: B=T, C=T -> matches B
+-- Row 3: C=T, D=T -> matches C
+-- Row 4: D=T, E=T -> matches D
+-- Row 5: E=T -> matches E
-- Result: match 1-5 (A B C D E)
-- Test 6: Diagonal pattern with multi-TRUE (shifted overlap)
WITH test_diagonal AS (
@@ -3138,8 +3138,8 @@ WINDOW w AS (
(5 rows)
-- Possible matches:
--- Start Row 1: A(1) B(2) C(3) D(4) → 1-4
--- Start Row 2: A(2) B(3) C(4) D(5) → 2-5 (because Row 2 has A too!)
+-- Start Row 1: A(1) B(2) C(3) D(4) -> 1-4
+-- Start Row 2: A(2) B(3) C(4) D(5) -> 2-5 (because Row 2 has A too!)
-- ===================================================================
-- Context Absorption Tests
-- ===================================================================
diff --git a/src/test/regress/expected/rpr_base.out b/src/test/regress/expected/rpr_base.out
index b34b9e59d25..23851c5a11c 100644
--- a/src/test/regress/expected/rpr_base.out
+++ b/src/test/regress/expected/rpr_base.out
@@ -336,9 +336,9 @@ INSERT INTO rpr_frame VALUES
-- Valid frame options
-- ROWS: counts physical rows (1 FOLLOWING = next 1 physical row)
-- Expected result: Each row can see 1 physical row ahead
--- id=1,2,3 (val=10): can see next row → cnt=2
--- id=4,5 (val=20): can see next row → cnt=2
--- id=6 (val=30): no next row → cnt=1
+-- id=1,2,3 (val=10): can see next row -> cnt=2
+-- id=4,5 (val=20): can see next row -> cnt=2
+-- id=6 (val=30): no next row -> cnt=1
-- Result: [2,2,2,2,2,1]
SELECT id, val, COUNT(*) OVER w as cnt
FROM rpr_frame
@@ -598,11 +598,11 @@ ORDER BY id;
-- RANGE: includes all rows with same ORDER BY value
-- Expected result: Includes peer rows (same val) in range calculation
--- id=1 (val=10): range [10,20] includes all val=10 and val=20 peers → cnt=2 (only first in peer group gets match)
--- id=2,3 (val=10): already matched by id=1 → cnt=0
--- id=4 (val=20): range [20,30] includes all val=20 and val=30 peers → cnt=2
--- id=5 (val=20): already matched by id=4 → cnt=0
--- id=6 (val=30): range [30,40] includes only val=30 → cnt=1
+-- id=1 (val=10): range [10,20] includes all val=10 and val=20 peers -> cnt=2 (only first in peer group gets match)
+-- id=2,3 (val=10): already matched by id=1 -> cnt=0
+-- id=4 (val=20): range [20,30] includes all val=20 and val=30 peers -> cnt=2
+-- id=5 (val=20): already matched by id=4 -> cnt=0
+-- id=6 (val=30): range [30,40] includes only val=30 -> cnt=1
-- Result: [2,0,0,2,0,1]
SELECT id, val, COUNT(*) OVER w as cnt
FROM rpr_frame
@@ -626,11 +626,11 @@ ORDER BY id;
-- GROUPS: treats rows with same value as one group (1 FOLLOWING = next group)
-- Expected result: 1 FOLLOWING means current group + 1 next group
--- id=1 (val=10): groups [val=10, val=20] → cnt=2 (only first in group gets match)
--- id=2,3 (val=10): already matched by id=1 → cnt=0
--- id=4 (val=20): groups [val=20, val=30] → cnt=2
--- id=5 (val=20): already matched by id=4 → cnt=0
--- id=6 (val=30): groups [val=30] (no next group) → cnt=1
+-- id=1 (val=10): groups [val=10, val=20] -> cnt=2 (only first in group gets match)
+-- id=2,3 (val=10): already matched by id=1 -> cnt=0
+-- id=4 (val=20): groups [val=20, val=30] -> cnt=2
+-- id=5 (val=20): already matched by id=4 -> cnt=0
+-- id=6 (val=30): groups [val=30] (no next group) -> cnt=1
-- Result: [2,0,0,2,0,1]
SELECT id, val, COUNT(*) OVER w as cnt
FROM rpr_frame
@@ -3549,7 +3549,7 @@ WINDOW w AS (ORDER BY id ROWS BETWEEN CURRENT ROW AND 10 FOLLOWING
-- ============================================================
-- Absorption Analysis Tests
-- ============================================================
--- Tests context absorption optimization (O(n²) → O(n))
+-- Tests context absorption optimization (O(n^2) -> O(n))
-- Files: rpr.c (computeAbsorbability)
-- Simple Absorbable Pattern: A+ B
-- Pattern starts with unbounded VAR
diff --git a/src/test/regress/sql/rpr.sql b/src/test/regress/sql/rpr.sql
index 8ab1daf87d6..788a77e5279 100644
--- a/src/test/regress/sql/rpr.sql
+++ b/src/test/regress/sql/rpr.sql
@@ -1527,11 +1527,11 @@ WINDOW w AS (
D AS 'D' = ANY(flags),
E AS 'E' = ANY(flags)
);
--- Row 1: A=T, B=T → matches A
--- Row 2: B=T, C=T → matches B
--- Row 3: C=T, D=T → matches C
--- Row 4: D=T, E=T → matches D
--- Row 5: E=T → matches E
+-- Row 1: A=T, B=T -> matches A
+-- Row 2: B=T, C=T -> matches B
+-- Row 3: C=T, D=T -> matches C
+-- Row 4: D=T, E=T -> matches D
+-- Row 5: E=T -> matches E
-- Result: match 1-5 (A B C D E)
-- Test 6: Diagonal pattern with multi-TRUE (shifted overlap)
@@ -1558,8 +1558,8 @@ WINDOW w AS (
D AS 'D' = ANY(flags)
);
-- Possible matches:
--- Start Row 1: A(1) B(2) C(3) D(4) → 1-4
--- Start Row 2: A(2) B(3) C(4) D(5) → 2-5 (because Row 2 has A too!)
+-- Start Row 1: A(1) B(2) C(3) D(4) -> 1-4
+-- Start Row 2: A(2) B(3) C(4) D(5) -> 2-5 (because Row 2 has A too!)
-- ===================================================================
-- Context Absorption Tests
diff --git a/src/test/regress/sql/rpr_base.sql b/src/test/regress/sql/rpr_base.sql
index 88f0a2c2083..a5a66d2ca81 100644
--- a/src/test/regress/sql/rpr_base.sql
+++ b/src/test/regress/sql/rpr_base.sql
@@ -280,9 +280,9 @@ INSERT INTO rpr_frame VALUES
-- ROWS: counts physical rows (1 FOLLOWING = next 1 physical row)
-- Expected result: Each row can see 1 physical row ahead
--- id=1,2,3 (val=10): can see next row → cnt=2
--- id=4,5 (val=20): can see next row → cnt=2
--- id=6 (val=30): no next row → cnt=1
+-- id=1,2,3 (val=10): can see next row -> cnt=2
+-- id=4,5 (val=20): can see next row -> cnt=2
+-- id=6 (val=30): no next row -> cnt=1
-- Result: [2,2,2,2,2,1]
SELECT id, val, COUNT(*) OVER w as cnt
FROM rpr_frame
@@ -464,11 +464,11 @@ ORDER BY id;
-- RANGE: includes all rows with same ORDER BY value
-- Expected result: Includes peer rows (same val) in range calculation
--- id=1 (val=10): range [10,20] includes all val=10 and val=20 peers → cnt=2 (only first in peer group gets match)
--- id=2,3 (val=10): already matched by id=1 → cnt=0
--- id=4 (val=20): range [20,30] includes all val=20 and val=30 peers → cnt=2
--- id=5 (val=20): already matched by id=4 → cnt=0
--- id=6 (val=30): range [30,40] includes only val=30 → cnt=1
+-- id=1 (val=10): range [10,20] includes all val=10 and val=20 peers -> cnt=2 (only first in peer group gets match)
+-- id=2,3 (val=10): already matched by id=1 -> cnt=0
+-- id=4 (val=20): range [20,30] includes all val=20 and val=30 peers -> cnt=2
+-- id=5 (val=20): already matched by id=4 -> cnt=0
+-- id=6 (val=30): range [30,40] includes only val=30 -> cnt=1
-- Result: [2,0,0,2,0,1]
SELECT id, val, COUNT(*) OVER w as cnt
FROM rpr_frame
@@ -483,11 +483,11 @@ ORDER BY id;
-- GROUPS: treats rows with same value as one group (1 FOLLOWING = next group)
-- Expected result: 1 FOLLOWING means current group + 1 next group
--- id=1 (val=10): groups [val=10, val=20] → cnt=2 (only first in group gets match)
--- id=2,3 (val=10): already matched by id=1 → cnt=0
--- id=4 (val=20): groups [val=20, val=30] → cnt=2
--- id=5 (val=20): already matched by id=4 → cnt=0
--- id=6 (val=30): groups [val=30] (no next group) → cnt=1
+-- id=1 (val=10): groups [val=10, val=20] -> cnt=2 (only first in group gets match)
+-- id=2,3 (val=10): already matched by id=1 -> cnt=0
+-- id=4 (val=20): groups [val=20, val=30] -> cnt=2
+-- id=5 (val=20): already matched by id=4 -> cnt=0
+-- id=6 (val=30): groups [val=30] (no next group) -> cnt=1
-- Result: [2,0,0,2,0,1]
SELECT id, val, COUNT(*) OVER w as cnt
FROM rpr_frame
@@ -2331,7 +2331,7 @@ WINDOW w AS (ORDER BY id ROWS BETWEEN CURRENT ROW AND 10 FOLLOWING
-- ============================================================
-- Absorption Analysis Tests
-- ============================================================
--- Tests context absorption optimization (O(n²) → O(n))
+-- Tests context absorption optimization (O(n^2) -> O(n))
-- Files: rpr.c (computeAbsorbability)
-- Simple Absorbable Pattern: A+ B
--
2.50.1 (Apple Git-155)