Re: Row pattern recognition

Henson Choi <assam258@gmail.com>

From: Henson Choi <assam258@gmail.com>
To: Tatsuo Ishii <ishii@postgresql.org>
Cc: vik@postgresfriends.org, er@xs4all.nl, jacob.champion@enterprisedb.com, david.g.johnston@gmail.com, peter@eisentraut.org, pgsql-hackers@postgresql.org
Date: 2026-02-26T13:34:03Z
Lists: pgsql-hackers

Attachments

Hi Tatsuo,

Here are ten incremental patches on top of v43.

nocfbot-0001 through nocfbot-0005 are the same as the previous round
(32-bit test fix, PREV/NEXT restriction, ALT lexical ordering,
reluctant quantifiers, cycle detection).

As discussed, the A{0} patch (old nocfbot-0006) is withdrawn since
Section 4.14.1 requires n > 0.  Your bare-block refactoring patches
are renumbered accordingly:

nocfbot-0006: Refactor create_windowagg_plan to remove bare
              variable-scoping block (your patch, renumbered)

nocfbot-0007: Remove bare variable-scoping blocks in RPR code

Three new patches:

nocfbot-0008: Fix empty-match iteration for nullable group bodies

This is the fix I mentioned for the Section 7.2.8 behavioral
difference.  When a group body is nullable (e.g. A? in (A?){2,3}),
the visited bitmap blocks re-entry to the skipped variable, so the
END element never gets a chance to produce an exit state for
count < min.

The fix adds a compile-time canEmptyLoop flag on END elements.
The fillRPRPattern functions now return whether each sub-pattern
is nullable, and this information propagates up to set the flag
on the enclosing END element.

At runtime, when the flag is set and count < min,
nfa_advance_end() creates a fast-forward exit state that jumps
directly past the group, treating all remaining required
iterations as empty.  This avoids the cycle detection while
still counting empty iterations toward min, matching the
standard and Perl behavior.

nocfbot-0009: Fix use-after-free in NFA alternation and
              optional-VAR routing

Two use-after-free bugs in the NFA advance phase:

1) nfa_advance_alt() reused the original state for the first ALT
   branch, then created copies for subsequent branches.  If
   nfa_advance_state() freed the original (e.g. via
   nfa_add_state_unique() deduplication), subsequent branches
   would copy from freed memory.  Fix: create independent states
   for all branches and free the original.

2) nfa_route_to_elem() created the skip state for optional VARs
   after calling nfa_add_state_unique(), which may free the
   source state.  Fix: create the skip state before add_unique.

nocfbot-0010: Remove redundant conditions and fix comments in
              NFA executor

Cleanup pass over NFA executor functions:

- nfa_states_equal(): removed always-true compareDepth > 0
  guard (RPRDepth is uint8, so depth + 1 is always >= 1)
- nfa_start_context(): removed always-true NULL/count guards
  and bare variable-scoping block
- nfa_advance_var(): removed always-true count > 0 checks in
  three places (nfa_advance_var is only reached after match
  phase where count++ already executed, and max=0 is forbidden)
- nfa_process_row(): fixed missing periods in phase comments

Best regards,
Henson

Commits

Same data as JSON: GET /api/v1/messages/:b64id/commits the thread's linked commits as JSON, with link sources. API reference →
  1. Adjust cross-version upgrade tests for seg_out() fix

  2. Rationalize error comments in partition split/merge tests

  3. Add fast path for foreign key constraint checks

  4. Fix assorted pretty-trivial memory leaks in the backend.

  5. Add temporal FOREIGN KEY contraints

  6. Add trailing commas to enum definitions

  7. Remove obsolete executor cleanup code