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