Re: [PATCH] Allow subquery pull-up past inlineable CTEs

From: Clemenza Zhang <zxlmgsps2(at)gmail(dot)com>
To: Andrey Kazarinov <a(dot)kazarinov(at)postgrespro(dot)ru>
Cc: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: [PATCH] Allow subquery pull-up past inlineable CTEs
Date: 2026-09-07 17:26:16
Message-ID: CAL9_+FFThoygHo91V32t5N7oLF1otuzUCg5m=mcur9BsaK713A@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Andrey,

I tested this patch on current master. The patch applies and builds
successfully, and the main optimization case works as expected in my
testing.
For an inlineable CTE inside the subquery, the patched plan changes to
the same general shape as the equivalent query without the CTE,
allowing the planner to consider the index/merge-join path.

I also tested a few negative cases:
- MATERIALIZED CTE: remains a CTE Scan, as expected.
- CTE containing a volatile function (random()): remains a CTE Scan.
- A default CTE referenced twice: remains materialized and is read
through two CTE Scan nodes.

> Before the patch:
> Hash Right Join
> Hash Cond: (cte.id = s.tid)
> -> CTE Scan on cte
> CTE cte
> -> Seq Scan on cte_pullup_t
> -> Hash
> -> Seq Scan on cte_pullup_s s
> Filter: (id < 5)
I could not reproduce this exact before-patch plan on current master.
With the NOT MATERIALIZED example, current unpatched master already
produces a direct Seq Scan on cte_pullup_t rather than a CTE Scan on
cte.

Hash Right Join
Hash Cond: (cte_pullup_t.id = s.tid)
-> Seq Scan on cte_pullup_t
-> Hash
-> Seq Scan on cte_pullup_s s
Filter: (id < 5)

The patch still changes the higher-level plan shape in my test: the
inlineable-CTE case becomes the same general shape as the equivalent
no-CTE query.
I also noticed a small inconsistency in the comment above
SS_all_ctes_inlineable(). It says that every CTE is either
"unreferenced (SELECT) or passes the inlineability checks", but the
implementation explicitly returns false for:
```
if (cte->cterefcount == 0 && cmdType == CMD_SELECT)
return false;
```
This behavior matches the explanation in your email, so I think the
comment may just need adjustment.

Regards,
Clemenza Zhang

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Ilia Evdokimov 2026-09-07 17:39:55 Re: Improve Hash/Merge Join estimate accuracy when all predicates are Hash/Merge clauses
Previous Message Joshua Drake 2026-09-07 16:36:29 Re: scary patch contest