Re: Row pattern recognition

Tatsuo Ishii <ishii@postgresql.org>

From: Tatsuo Ishii <ishii@postgresql.org>
To: assam258@gmail.com
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-03-04T06:38:22Z
Lists: pgsql-hackers

Attachments

Hi Henson,

> Hi,Tatsuo
> 
> While reviewing the RPR test cases, I noticed that a subquery filter
> on RPR window function results silently returns wrong results.
> 
> For example, given this query:
> 
>   SELECT * FROM (
>       SELECT id, val, COUNT(*) OVER w as cnt
>       FROM rpr_copy
>       WINDOW w AS (
>           ORDER BY id
>           ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
>           PATTERN (A B?)
>           DEFINE A AS val > 10, B AS val > 20
>       )
>   ) sub
>   WHERE cnt > 0
>   ORDER BY id;
> 
> This should return 2 rows, but returns 0 rows instead.

Thanks for the report!

> The EXPLAIN plan shows that "cnt > 0" is pushed down into the
> WindowAgg node as a Run Condition:
> 
>   WindowAgg
>     Run Condition: (count(*) OVER w > 0)    <-- pushed down
>     ->  Sort
>           ->  Seq Scan on rpr_copy
> 
> I will investigate the cause and work on a fix.

I think there are two ways to solve the issue:

1) Fix the executor
2) Fix the planner

I tried #1 but I don't know how to fix it. The run condition is
already pushed in the window function. Existing code forces to stop
the aggregate evaluation if the run condition is not
satisfied. Without RPR, the optimization is correct because once the
run condition is not satisfied, there's no chance that the subsequence
rows satisfy the condition. But RPR is used, a partition/frame is
divided into multiple reduced frames and each should be evaluated to
the end of the partition/frame.

So, I tried #2 so that the planner does not push down the run
condition.

Attached is the patch.

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

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