create_unique_path(root, rel2, rel2->cheapest_total_path,
sjinfo) != NULL)
{
- /*
+ /*----------
* For a semijoin, we can join the RHS to anything else by
* unique-ifying the RHS (if the RHS can be unique-ified).
+ * We will only get here if we have the full RHS but less
+ * than min_lefthand on the LHS.
+ *
+ * The reason to consider such a join path is exemplified by
+ * SELECT ... FROM a,b WHERE (a.x,b.y) IN (SELECT c1,c2 FROM c)
+ * If we insist on doing this as a semijoin we will first have
+ * to form the cartesian product of A*B. But if we unique-ify
+ * C then the semijoin becomes a plain innerjoin and we can join
+ * in any order, eg C to A and then to B. When C is much smaller
+ * than A and B this can be a huge win. So we allow C to be
+ * joined to just A or just B here, and then make_join_rel has
+ * to handle the case properly.
+ *
+ * Note that actually we'll allow unique-ified C to be joined to
+ * some other relation D here, too. That is legal, if usually not
+ * very sane, and this routine is only concerned with legality not
+ * with whether the join is good strategy.
+ *----------
*/
if (match_sjinfo)
return false; /* invalid join path */
break;
case JOIN_SEMI:
/*
- * Do these steps only if we actually have a regular semijoin,
- * as opposed to a case where we should unique-ify the RHS.
+ * We might have a normal semijoin, or a case where we don't have
+ * enough rels to do the semijoin but can unique-ify the RHS and
+ * then do an innerjoin (see comments in join_is_legal). In the
+ * latter case we can't apply JOIN_SEMI joining.
*/
if (bms_is_subset(sjinfo->min_lefthand, rel1->relids) &&
bms_is_subset(sjinfo->min_righthand, rel2->relids))