diff options
Diffstat (limited to 'src/backend/optimizer/plan/initsplan.c')
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 55 |
1 files changed, 47 insertions, 8 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 5cbb7b9a86b..69ef483d283 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -109,6 +109,7 @@ static void distribute_quals_to_rels(PlannerInfo *root, List *clauses, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, + Relids incompatible_relids, bool allow_equivalence, bool has_clone, bool is_clone, @@ -120,6 +121,7 @@ static void distribute_qual_to_rels(PlannerInfo *root, Node *clause, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, + Relids incompatible_relids, bool allow_equivalence, bool has_clone, bool is_clone, @@ -1132,7 +1134,8 @@ deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem) jtitem, NULL, root->qual_security_level, - jtitem->qualscope, NULL, NULL, + jtitem->qualscope, + NULL, NULL, NULL, true, false, false, NULL); @@ -1143,7 +1146,8 @@ deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem) jtitem, NULL, root->qual_security_level, - jtitem->qualscope, NULL, NULL, + jtitem->qualscope, + NULL, NULL, NULL, true, false, false, NULL); } @@ -1226,6 +1230,7 @@ deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem) root->qual_security_level, jtitem->qualscope, ojscope, jtitem->nonnullable_rels, + NULL, /* incompatible_relids */ true, /* allow_equivalence */ false, false, /* not clones */ postponed_oj_qual_list); @@ -1285,6 +1290,7 @@ process_security_barrier_quals(PlannerInfo *root, jtitem->qualscope, jtitem->qualscope, NULL, + NULL, true, false, false, /* not clones */ NULL); @@ -1887,6 +1893,7 @@ deconstruct_distribute_oj_quals(PlannerInfo *root, { Relids joins_above; Relids joins_below; + Relids incompatible_joins; Relids joins_so_far; List *quals; int save_last_rinfo_serial; @@ -1921,6 +1928,15 @@ deconstruct_distribute_oj_quals(PlannerInfo *root, NULL); /* + * We'll need to mark the lower versions of the quals as not safe to + * apply above not-yet-processed joins of the stack. This prevents + * possibly applying a cloned qual at the wrong join level. + */ + incompatible_joins = bms_union(joins_below, joins_above); + incompatible_joins = bms_add_member(incompatible_joins, + sjinfo->ojrelid); + + /* * Each time we produce RestrictInfo(s) from these quals, reset the * last_rinfo_serial counter, so that the RestrictInfos for the "same" * qual condition get identical serial numbers. (This relies on the @@ -1979,13 +1995,19 @@ deconstruct_distribute_oj_quals(PlannerInfo *root, * relation B will appear nulled by the syntactically-upper OJ * within the Pbc clause, but those of relation C will not. (In * the notation used by optimizer/README, we're converting a qual - * of the form Pbc to Pb*c.) + * of the form Pbc to Pb*c.) Of course, we must also remove that + * bit from the incompatible_joins value, else we'll make a qual + * that can't be placed anywhere. */ if (above_sjinfo) + { quals = (List *) add_nulling_relids((Node *) quals, sjinfo->syn_lefthand, bms_make_singleton(othersj->ojrelid)); + incompatible_joins = bms_del_member(incompatible_joins, + othersj->ojrelid); + } /* Compute qualscope and ojscope for this join level */ this_qualscope = bms_union(qualscope, joins_so_far); @@ -2027,6 +2049,7 @@ deconstruct_distribute_oj_quals(PlannerInfo *root, root->qual_security_level, this_qualscope, this_ojscope, nonnullable_rels, + bms_copy(incompatible_joins), allow_equivalence, has_clone, is_clone, @@ -2039,13 +2062,17 @@ deconstruct_distribute_oj_quals(PlannerInfo *root, * Vars coming from the lower join's RHS. (Again, we are * converting a qual of the form Pbc to Pb*c, but now we are * putting back bits that were there in the parser output and were - * temporarily stripped above.) + * temporarily stripped above.) Update incompatible_joins too. */ if (below_sjinfo) + { quals = (List *) add_nulling_relids((Node *) quals, othersj->syn_righthand, bms_make_singleton(othersj->ojrelid)); + incompatible_joins = bms_del_member(incompatible_joins, + othersj->ojrelid); + } /* ... and track joins processed so far */ joins_so_far = bms_add_member(joins_so_far, othersj->ojrelid); @@ -2060,6 +2087,7 @@ deconstruct_distribute_oj_quals(PlannerInfo *root, root->qual_security_level, qualscope, ojscope, nonnullable_rels, + NULL, /* incompatible_relids */ true, /* allow_equivalence */ false, false, /* not clones */ NULL); /* no more postponement */ @@ -2086,6 +2114,7 @@ distribute_quals_to_rels(PlannerInfo *root, List *clauses, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, + Relids incompatible_relids, bool allow_equivalence, bool has_clone, bool is_clone, @@ -2104,6 +2133,7 @@ distribute_quals_to_rels(PlannerInfo *root, List *clauses, qualscope, ojscope, outerjoin_nonnullable, + incompatible_relids, allow_equivalence, has_clone, is_clone, @@ -2135,6 +2165,9 @@ distribute_quals_to_rels(PlannerInfo *root, List *clauses, * base+OJ rels appearing on the outer (nonnullable) side of the join * (for FULL JOIN this includes both sides of the join, and must in fact * equal qualscope) + * 'incompatible_relids': the set of outer-join relid(s) that must not be + * computed below this qual. We only bother to compute this for + * "clone" quals, otherwise it can be left NULL. * 'allow_equivalence': true if it's okay to convert clause into an * EquivalenceClass * 'has_clone': has_clone property to assign to the qual @@ -2159,6 +2192,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, Relids qualscope, Relids ojscope, Relids outerjoin_nonnullable, + Relids incompatible_relids, bool allow_equivalence, bool has_clone, bool is_clone, @@ -2377,15 +2411,14 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, restrictinfo = make_restrictinfo(root, (Expr *) clause, is_pushed_down, + has_clone, + is_clone, pseudoconstant, security_level, relids, + incompatible_relids, outerjoin_nonnullable); - /* Apply appropriate clone marking, too */ - restrictinfo->has_clone = has_clone; - restrictinfo->is_clone = is_clone; - /* * If it's a join clause, add vars used in the clause to targetlists of * their relations, so that they will be emitted by the plan nodes that @@ -2750,9 +2783,12 @@ process_implied_equality(PlannerInfo *root, restrictinfo = make_restrictinfo(root, (Expr *) clause, true, /* is_pushed_down */ + false, /* !has_clone */ + false, /* !is_clone */ pseudoconstant, security_level, relids, + NULL, /* incompatible_relids */ NULL); /* outer_relids */ /* @@ -2841,9 +2877,12 @@ build_implied_join_equality(PlannerInfo *root, restrictinfo = make_restrictinfo(root, clause, true, /* is_pushed_down */ + false, /* !has_clone */ + false, /* !is_clone */ false, /* pseudoconstant */ security_level, /* security_level */ qualscope, /* required_relids */ + NULL, /* incompatible_relids */ NULL); /* outer_relids */ /* Set mergejoinability/hashjoinability flags */ |