未验证 提交 58b3ad3d 编写于 作者: R Richard Guo 提交者: GitHub

Revise min_lefthand/min_righthand in SpecialJoinInfo for LASJ.

Previously, we did not consider LASJ when calculating the minimum sets
of Relids required on each side of the join to form the outer join. As a
result, the min_lefthand/min_righthand for LASJ was not correct.

One of the consequences is that join_is_legal() works incorrectly for
some queries, such as

	select * from a where a.i not in
		(select b.i from b left join c on b.i = c.i);

For this query, join_is_legal() treats the join of Rel B and C as being
illegal, because the min_righthand of the LASJ includes only B, rather
than B and C. That would make us fail to find any legal join order and
end up with "ERROR:  failed to build any 2-way joins".

This patch revises min_lefthand/min_righthand in SpecialJoinInfo for
LASJ. It also removes the FIXME in join_is_legal(), which is an ugly
workaround to make the query above work.
Reviewed-by: NMelanie Plageman <mplageman@pivotal.io>
上级 4366e73c
......@@ -499,16 +499,11 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
/*
* The proposed join could still be legal, but only if we're
* allowed to associate it into the RHS of this SJ. That means
* this SJ must be a LEFT join (not SEMI or ANTI, and certainly
* not FULL) and the proposed join must not overlap the LHS.
* this SJ must be a LEFT join (not SEMI, ANTI or LASJ, and
* certainly not FULL) and the proposed join must not overlap the
* LHS.
*/
/*
* GPDB_94_MERGE_STABLE_FIXME: As soon as possible.
*
* explain select * from a where a.i not in
* (select b.i from b left join c on b.i = c.i);
*/
if ((sjinfo->jointype != JOIN_LEFT && sjinfo->jointype != JOIN_LASJ_NOTIN) ||
if (sjinfo->jointype != JOIN_LEFT ||
bms_overlap(joinrelids, sjinfo->min_lefthand))
return false; /* invalid join path */
......
......@@ -1128,7 +1128,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
* left_rels: the base Relids syntactically on outer side of join
* right_rels: the base Relids syntactically on inner side of join
* inner_join_rels: base Relids participating in inner joins below this one
* jointype: what it says (must always be LEFT, FULL, SEMI, or ANTI)
* jointype: what it says (must always be LEFT, FULL, SEMI, ANTI, or LASJ)
* clause: the outer join's join condition (in implicit-AND format)
*
* The node should eventually be appended to root->join_info_list, but we
......@@ -1273,7 +1273,7 @@ make_outerjoininfo(PlannerInfo *root,
* min_lefthand + min_righthand. This is because there might be other
* OJs below this one that this one can commute with, but we cannot
* commute with them if we don't with this one.) Also, if the current
* join is a semijoin or antijoin, we must preserve ordering
* join is a semijoin, antijoin or lasj, we must preserve ordering
* regardless of strictness.
*
* Note: I believe we have to insist on being strict for at least one
......@@ -1283,6 +1283,7 @@ make_outerjoininfo(PlannerInfo *root,
{
if (bms_overlap(clause_relids, otherinfo->syn_righthand) &&
(jointype == JOIN_SEMI || jointype == JOIN_ANTI ||
jointype == JOIN_LASJ_NOTIN ||
!bms_overlap(strict_relids, otherinfo->min_righthand)))
{
min_lefthand = bms_add_members(min_lefthand,
......@@ -1304,7 +1305,7 @@ make_outerjoininfo(PlannerInfo *root,
* confuse join_is_legal (see discussion in backend/optimizer/README).
*
* Also, we must preserve ordering anyway if either the current join
* or the lower OJ is either a semijoin or an antijoin.
* or the lower OJ is a semijoin, antijoin or lasj.
*
* Here, we have to consider that "our join condition" includes any
* clauses that syntactically appeared above the lower OJ and below
......@@ -1323,8 +1324,10 @@ make_outerjoininfo(PlannerInfo *root,
!bms_overlap(clause_relids, otherinfo->min_lefthand) ||
jointype == JOIN_SEMI ||
jointype == JOIN_ANTI ||
jointype == JOIN_LASJ_NOTIN ||
otherinfo->jointype == JOIN_SEMI ||
otherinfo->jointype == JOIN_ANTI ||
otherinfo->jointype == JOIN_LASJ_NOTIN ||
!otherinfo->lhs_strict || otherinfo->delay_upper_joins)
{
min_righthand = bms_add_members(min_righthand,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册