diff --git a/src/test/regress/expected/rpr_explain.out b/src/test/regress/expected/rpr_explain.out index d8343c9accc..11c51d6f764 100644 --- a/src/test/regress/expected/rpr_explain.out +++ b/src/test/regress/expected/rpr_explain.out @@ -906,6 +906,50 @@ WINDOW w AS ( -> Function Scan on generate_series s (actual rows=50.00 loops=1) (10 rows) +-- Context absorption with a bounded outer group whose body starts with A+ +-- The outer count {2,3} is bounded, but A+ is still the first unbounded portion +-- of the pattern, so it remains the absorption comparison point (a+ keeps the " +-- marker and contexts are absorbed). A bounded outer group must not, by itself, +-- disable absorption of the leading unbounded child. +CREATE VIEW rpr_ev_ctx_absorb_bounded_outer AS +SELECT count(*) OVER w +FROM generate_series(1, 50) AS s(v) +WINDOW w AS ( + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP PAST LAST ROW + PATTERN ((A+ B){2,3}) + DEFINE A AS v % 5 <> 0, B AS v % 5 = 0 +); +SELECT line FROM unnest(string_to_array(pg_get_viewdef('rpr_ev_ctx_absorb_bounded_outer'), E'\n')) AS line WHERE line ~ 'PATTERN'; + line +-------------------------- + PATTERN ((a+ b){2,3}) +(1 row) + +SELECT rpr_explain_filter(' +EXPLAIN (ANALYZE, BUFFERS OFF, COSTS OFF, TIMING OFF, SUMMARY OFF) +SELECT count(*) OVER w +FROM generate_series(1, 50) AS s(v) +WINDOW w AS ( + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP PAST LAST ROW + PATTERN ((A+ B){2,3}) + DEFINE A AS v % 5 <> 0, B AS v % 5 = 0 +);'); + rpr_explain_filter +---------------------------------------------------------------------- + WindowAgg (actual rows=50.00 loops=1) + Window: w AS (ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) + Pattern: (a+" b){2,3} + Nav Mark Lookback: 0 + Storage: Memory Maximum Storage: NkB + NFA States: 6 peak, 118 total, 0 merged + NFA Contexts: 3 peak, 51 total, 4 pruned + NFA: 3 matched (len 15/15/15.0), 1 mismatched (len 5/5/5.0) + NFA: 30 absorbed (len 1/1/1.0), 12 skipped (len 1/5/3.0) + -> Function Scan on generate_series s (actual rows=50.00 loops=1) +(10 rows) + -- Contexts skipped by SKIP PAST LAST ROW CREATE VIEW rpr_ev_ctx_skip AS SELECT count(*) OVER w diff --git a/src/test/regress/sql/rpr_explain.sql b/src/test/regress/sql/rpr_explain.sql index 3cd94af6bb8..5a9c83e7886 100644 --- a/src/test/regress/sql/rpr_explain.sql +++ b/src/test/regress/sql/rpr_explain.sql @@ -570,6 +570,32 @@ WINDOW w AS ( DEFINE A AS v % 5 <> 0, B AS v % 5 = 0 );'); +-- Context absorption with a bounded outer group whose body starts with A+ +-- The outer count {2,3} is bounded, but A+ is still the first unbounded portion +-- of the pattern, so it remains the absorption comparison point (a+ keeps the " +-- marker and contexts are absorbed). A bounded outer group must not, by itself, +-- disable absorption of the leading unbounded child. +CREATE VIEW rpr_ev_ctx_absorb_bounded_outer AS +SELECT count(*) OVER w +FROM generate_series(1, 50) AS s(v) +WINDOW w AS ( + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP PAST LAST ROW + PATTERN ((A+ B){2,3}) + DEFINE A AS v % 5 <> 0, B AS v % 5 = 0 +); +SELECT line FROM unnest(string_to_array(pg_get_viewdef('rpr_ev_ctx_absorb_bounded_outer'), E'\n')) AS line WHERE line ~ 'PATTERN'; +SELECT rpr_explain_filter(' +EXPLAIN (ANALYZE, BUFFERS OFF, COSTS OFF, TIMING OFF, SUMMARY OFF) +SELECT count(*) OVER w +FROM generate_series(1, 50) AS s(v) +WINDOW w AS ( + ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING + AFTER MATCH SKIP PAST LAST ROW + PATTERN ((A+ B){2,3}) + DEFINE A AS v % 5 <> 0, B AS v % 5 = 0 +);'); + -- Contexts skipped by SKIP PAST LAST ROW CREATE VIEW rpr_ev_ctx_skip AS SELECT count(*) OVER w