Question about pull_up_sublinks_qual_recurse

From: Andy Fan <zhihui(dot)fan1213(at)gmail(dot)com>
To: pgsql-hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Question about pull_up_sublinks_qual_recurse
Date: 2022-10-13 08:45:31
Message-ID: CAKU4AWq0d=b+GqpH7fr5C8jT1e6-RndcFPXdxOLuOy1=kHbkTQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi:

When I was working on another task, the following case caught my mind.

create table t1(a int, b int, c int);
create table t2(a int, b int, c int);
create table t3(a int, b int, c int);

explain (costs off) select * from t1
where exists (select 1 from t2
where exists (select 1 from t3
where t3.c = t1.c
and t2.b = t3.b)
and t2.a = t1.a);

I got the plan like this:

QUERY PLAN
-----------------------------------
Hash Semi Join
Hash Cond: (t1.a = t2.a)
Join Filter: (hashed SubPlan 2)
-> Seq Scan on t1
-> Hash
-> Seq Scan on t2
SubPlan 2
-> Seq Scan on t3
(8 rows)

Note we CAN'T pull up the inner sublink which produced the SubPlan 2.

I traced the reason is after we pull up the outer sublink, we got:

select * from t1 semi join t2 on t2.a = t1.a AND
exists (select 1 from t3
where t3.c = t1.c
and t2.b = t3.b);

Later we tried to pull up the EXISTS sublink to t1 OR t2 *separately*, since
this subselect referenced to t1 *AND* t2, so we CAN'T pull up the sublink. I
am thinking why we have to pull up it t1 OR t2 rather than JoinExpr(t1, t2),
I think the latter one is better.

So I changed the code like this, I got the plan I wanted and 'make
installcheck' didn't find any exception.

QUERY PLAN
------------------------------------------------
Hash Semi Join
Hash Cond: ((t2.b = t3.b) AND (t1.c = t3.c))
-> Hash Semi Join
Hash Cond: (t1.a = t2.a)
-> Seq Scan on t1
-> Hash
-> Seq Scan on t2
-> Hash
-> Seq Scan on t3
(9 rows)

@@ -553,10 +553,10 @@ pull_up_sublinks_qual_recurse(PlannerInfo *root, Node
*node,
*/
j->quals = pull_up_sublinks_qual_recurse(root,
j->quals,
- &j->larg,
- available_rels1,
- &j->rarg,
- child_rels);
+ jtlink1,
+ bms_union(available_rels1, child_rels),
+ NULL,
+ NULL);
/* Return NULL representing constant TRUE */
return NULL;
}

Any feedback is welcome.

--
Best Regards
Andy Fan

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Dmitry Koval 2022-10-13 08:57:33 Re: Add SPLIT PARTITION/MERGE PARTITIONS commands
Previous Message Peter Eisentraut 2022-10-13 08:33:01 libpq support for NegotiateProtocolVersion