| From: | Tender Wang <tndrwang(at)gmail(dot)com> |
|---|---|
| To: | Andrey Rachitskiy <pl0h0yp1(at)gmail(dot)com> |
| Cc: | syzhong16(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org, Alexander Korotkov <aekorotkov(at)gmail(dot)com> |
| Subject: | Re: BUG #19626: Segmentation fault planning self-join IN subquery with LATERAL UNION ALL |
| Date: | 2026-08-19 02:28:20 |
| Message-ID: | CAHewXNmN17cKAn6fOOii7nRnKN7ruJ-rKSFkqihg9A4EzaO8kA@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
Andrey Rachitskiy <pl0h0yp1(at)gmail(dot)com> 于2026年8月18日周二 21:29写道:
>
>
> вт, 18 авг. 2026 г. в 17:16, PG Bug reporting form <noreply(at)postgresql(dot)org>:
>>
>> CREATE TABLE t0(c2 INT PRIMARY KEY, c3 INT);
>>
>> SELECT count(*) FROM t0
>> INNER JOIN LATERAL (SELECT t0.c3 UNION ALL SELECT t0.c3) AS s ON (s.c3 IS
>> NOT NULL)
>> WHERE t0.c2 IN (SELECT c2 FROM t0);
> The LATERAL UNION ALL is flattened to an appendrel. The leaf expressions t0.c3 are stored in AppendRelInfo.translated_vars. The IN subquery on the primary key is reduced to an inner join and then removed by self-join elimination. SJE rewrites Vars in the Query tree, PlaceHolderVars, RestrictInfos and EquivalenceClasses. It does not touch root->append_rel_list. After that it NULLs the removed rel's slots in simple_rel_array and simple_rte_array.
>
> add_other_rels_to_query runs later. apply_child_basequals() substitutes the stale translated_vars into s.c3 IS NOT NULL. eval_const_expressions() then asks var_is_nonnullable() about a Var whose varno has no RTE. planner_rt_fetch() returns NULL because simple_rte_array is already built and that slot is empty. The subsequent rte->rtekind dereference crashes.
>
In apply_child_basequals(), it calls adjust_appendrel_attrs() to
adjust childqual's varno to childRTIndex according to appinfo; the
current info is below:
(gdb) pgprint rinfo->clause <=== parent qual
NullTest [nulltesttype=IS_NOT_NULL argisrow=false location=103]
[arg] Var [varno=2 varattno=1 vartype=23
varreturningtype=VAR_RETURNING_DEFAULT varnosyn=2 varattnosyn=1]
(gdb) pgprint appinfo
AppendRelInfo [parent_relid=2 child_relid=7 parent_reltype=0
child_reltype=0 num_child_cols=1 parent_colnos=0x5fcd7f621d58
parent_reloid=0]
[translated_vars]
Var [varno=1 varattno=2 vartype=23
varreturningtype=VAR_RETURNING_DEFAULT varnosyn=1 varattnosyn=2]
Then the childqual was adjusted to:
(gdb) pgprint childqual
NullTest [nulltesttype=IS_NOT_NULL argisrow=false location=103]
[arg] Var [varno=1 varattno=2 vartype=23
varreturningtype=VAR_RETURNING_DEFAULT varnosyn=1 varattnosyn=2]
"varno=1" is the reference to the first rtable in parse->rtable. But
that rtable was set to NULL after SJE. So the crash occurs in
var_is_nonnullable().
> The attached patch runs ChangeVarNodesExtended() over append_rel_list in remove_self_join_rel(), same as for the Query tree.
The patch looks good to me.
--
Thanks,
Tender Wang
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Kyotaro Horiguchi | 2026-08-19 02:56:36 | Re: BUG #19627: 32,768 trigger arguments wrap `tgnargs` and are silently lost at runtime |
| Previous Message | Dan Stefura | 2026-08-18 19:53:46 | Re: B-tree index scan ~2x slower on PG18 vs PG17 for skewed equality-prefix + range-condition lookups, with essentially the same plan |