Re: assertion failure with unique index + partitioning + join

From: Tender Wang <tndrwang(at)gmail(dot)com>
To: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Cc: Alexander Kuzmenkov <akuzmenkov(at)tigerdata(dot)com>, Richard Guo <guofenglinux(at)gmail(dot)com>
Subject: Re: assertion failure with unique index + partitioning + join
Date: 2026-06-16 07:45:27
Message-ID: CAHewXNksF-j8Y-zN8-gBi1eGzYUYCnMyQQXrJb-p6rz_4FYdgQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Tender Wang <tndrwang(at)gmail(dot)com> 于2026年6月16日周二 12:06写道:
>
> Hi all,
>
> Tender Wang <tndrwang(at)gmail(dot)com> 于2026年6月16日周二 09:58写道:
> >
> > I can reproduce this issue on HEAD.
> > The root->outer_join_rels is empty, and the i is 3(rel: t r).
> > The left join can be removed in remove_useless_joins(), in which
> > root->outer_join_rels is changed to be empty.
> > But the from->qual in this case has already been distributed to its rel.
> > (gdb) pgprint brel->baserestrictinfo
> > RestrictInfo [is_pushed_down=true can_join=false pseudoconstant=false
> > has_clone=false is_clone=false leakproof=false
> > has_volatile=VOLATILITY_UNKNOWN security_level=0
> > num_base_rels=1 rinfo_serial=1 eval_cost={startup = -1,
> > per_tuple = 0} norm_selec=-1 outer_selec=-1 outer_is_left=false
> > hashjoinoperator=0 left_bucketsize=-1
> > right_bucketsize=-1 left_mcvfreq=-1 right_mcvfreq=-1
> > left_hasheqoperator=0 right_hasheqoperator=0]
> > [clause]
> > PlaceHolderVar [phid=1 phlevelsup=0]
> > [phexpr] Var [varno=2 varattno=1 vartype=16
> > varreturningtype=VAR_RETURNING_DEFAULT varnosyn=2 varattnosyn=1]
> > [phrels] Bitmapset [4 3 2]
> > [clause_relids] Bitmapset [2]
> > [required_relids] Bitmapset [2]
> > I need to dig deeper to find out how to fix it.
>
> I tried on the old version (pg1212), I got the correct plan, no crash.
> And after pulling up the subquery, no PlaceHolderVar. I found after
> commit cc5d98525d43,
>
> commit cc5d98525d43c22b98f360ef0f2c8d7dc57f04dc
> Author: Richard Guo <rguo(at)postgresql(dot)org>
> Date: Thu Mar 13 16:36:03 2025 +0900
>
> Fix incorrect handling of subquery pullup
>
> the from->qual will include PHV, because this query contains groupingsets.
> I reverted this commit, I got correct plan, too:
> postgres=# explain SELECT
> FROM (
> SELECT *
> FROM t
> LEFT JOIN t r USING (a)
> ) ss
> WHERE a
> GROUP BY ();
> QUERY PLAN
> ------------------------------------------
> Result (cost=0.00..0.01 rows=1 width=0)
> (1 row)
>
>
> I added Richard to the cc list. He may know more about this.

In apply_child_basequals(), the restricintinfo->clause_relids of the
child is different from the parent's.
The parent's restricintinfo->clause_relids only contains rel:2, but
the child contains (3,4,5).
The difference is due to pull_varnos_walker() when processing the
PlaceholdVar case.

I do a quick fix as below:
diff --git a/src/backend/optimizer/util/inherit.c
b/src/backend/optimizer/util/inherit.c
index 6a7b9edff3f..fcf0ad7a187 100644
--- a/src/backend/optimizer/util/inherit.c
+++ b/src/backend/optimizer/util/inherit.c
@@ -861,6 +861,21 @@ apply_child_basequals(PlannerInfo *root,
RelOptInfo *parentrel,
ListCell *lc2;

Assert(IsA(rinfo, RestrictInfo));
+ if (IsA(rinfo->clause, PlaceHolderVar))
+ {
+ PlaceHolderVar *phv = (PlaceHolderVar *) rinfo->clause;
+ PlaceHolderInfo *phinfo = NULL;
+ if (phv->phlevelsup == 0)
+ {
+ if (phv->phid < root->placeholder_array_size)
+ phinfo =
root->placeholder_array[phv->phid];
+ }
+ if (phinfo != NULL)
+ {
+ phv->phrels = bms_copy(phinfo->ph_var->phrels);
+ }
+
+ }

The issue has gone, and regression tests all pass.
But this is very simply fixed.
What do you think?

--
Thanks,
Tender Wang

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Pavel Stehule 2026-06-16 07:52:59 Re: POC: PLpgSQL FOREACH IN JSON ARRAY
Previous Message cca5507 2026-06-16 07:34:55 Do not lock tables in get_tables_to_repack