@@ -109,6 +109,7 @@ static void distribute_quals_to_rels(PlannerInfo *root, List *clauses,
109109 Relids qualscope ,
110110 Relids ojscope ,
111111 Relids outerjoin_nonnullable ,
112+ Relids incompatible_relids ,
112113 bool allow_equivalence ,
113114 bool has_clone ,
114115 bool is_clone ,
@@ -120,6 +121,7 @@ static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
120121 Relids qualscope ,
121122 Relids ojscope ,
122123 Relids outerjoin_nonnullable ,
124+ Relids incompatible_relids ,
123125 bool allow_equivalence ,
124126 bool has_clone ,
125127 bool is_clone ,
@@ -1132,7 +1134,8 @@ deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem)
11321134 jtitem ,
11331135 NULL ,
11341136 root -> qual_security_level ,
1135- jtitem -> qualscope , NULL , NULL ,
1137+ jtitem -> qualscope ,
1138+ NULL , NULL , NULL ,
11361139 true, false, false,
11371140 NULL );
11381141
@@ -1143,7 +1146,8 @@ deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem)
11431146 jtitem ,
11441147 NULL ,
11451148 root -> qual_security_level ,
1146- jtitem -> qualscope , NULL , NULL ,
1149+ jtitem -> qualscope ,
1150+ NULL , NULL , NULL ,
11471151 true, false, false,
11481152 NULL );
11491153 }
@@ -1226,6 +1230,7 @@ deconstruct_distribute(PlannerInfo *root, JoinTreeItem *jtitem)
12261230 root -> qual_security_level ,
12271231 jtitem -> qualscope ,
12281232 ojscope , jtitem -> nonnullable_rels ,
1233+ NULL , /* incompatible_relids */
12291234 true, /* allow_equivalence */
12301235 false, false, /* not clones */
12311236 postponed_oj_qual_list );
@@ -1285,6 +1290,7 @@ process_security_barrier_quals(PlannerInfo *root,
12851290 jtitem -> qualscope ,
12861291 jtitem -> qualscope ,
12871292 NULL ,
1293+ NULL ,
12881294 true,
12891295 false, false, /* not clones */
12901296 NULL );
@@ -1887,6 +1893,7 @@ deconstruct_distribute_oj_quals(PlannerInfo *root,
18871893 {
18881894 Relids joins_above ;
18891895 Relids joins_below ;
1896+ Relids incompatible_joins ;
18901897 Relids joins_so_far ;
18911898 List * quals ;
18921899 int save_last_rinfo_serial ;
@@ -1920,6 +1927,15 @@ deconstruct_distribute_oj_quals(PlannerInfo *root,
19201927 joins_below ,
19211928 NULL );
19221929
1930+ /*
1931+ * We'll need to mark the lower versions of the quals as not safe to
1932+ * apply above not-yet-processed joins of the stack. This prevents
1933+ * possibly applying a cloned qual at the wrong join level.
1934+ */
1935+ incompatible_joins = bms_union (joins_below , joins_above );
1936+ incompatible_joins = bms_add_member (incompatible_joins ,
1937+ sjinfo -> ojrelid );
1938+
19231939 /*
19241940 * Each time we produce RestrictInfo(s) from these quals, reset the
19251941 * last_rinfo_serial counter, so that the RestrictInfos for the "same"
@@ -1979,13 +1995,19 @@ deconstruct_distribute_oj_quals(PlannerInfo *root,
19791995 * relation B will appear nulled by the syntactically-upper OJ
19801996 * within the Pbc clause, but those of relation C will not. (In
19811997 * the notation used by optimizer/README, we're converting a qual
1982- * of the form Pbc to Pb*c.)
1998+ * of the form Pbc to Pb*c.) Of course, we must also remove that
1999+ * bit from the incompatible_joins value, else we'll make a qual
2000+ * that can't be placed anywhere.
19832001 */
19842002 if (above_sjinfo )
2003+ {
19852004 quals = (List * )
19862005 add_nulling_relids ((Node * ) quals ,
19872006 sjinfo -> syn_lefthand ,
19882007 bms_make_singleton (othersj -> ojrelid ));
2008+ incompatible_joins = bms_del_member (incompatible_joins ,
2009+ othersj -> ojrelid );
2010+ }
19892011
19902012 /* Compute qualscope and ojscope for this join level */
19912013 this_qualscope = bms_union (qualscope , joins_so_far );
@@ -2027,6 +2049,7 @@ deconstruct_distribute_oj_quals(PlannerInfo *root,
20272049 root -> qual_security_level ,
20282050 this_qualscope ,
20292051 this_ojscope , nonnullable_rels ,
2052+ bms_copy (incompatible_joins ),
20302053 allow_equivalence ,
20312054 has_clone ,
20322055 is_clone ,
@@ -2039,13 +2062,17 @@ deconstruct_distribute_oj_quals(PlannerInfo *root,
20392062 * Vars coming from the lower join's RHS. (Again, we are
20402063 * converting a qual of the form Pbc to Pb*c, but now we are
20412064 * putting back bits that were there in the parser output and were
2042- * temporarily stripped above.)
2065+ * temporarily stripped above.) Update incompatible_joins too.
20432066 */
20442067 if (below_sjinfo )
2068+ {
20452069 quals = (List * )
20462070 add_nulling_relids ((Node * ) quals ,
20472071 othersj -> syn_righthand ,
20482072 bms_make_singleton (othersj -> ojrelid ));
2073+ incompatible_joins = bms_del_member (incompatible_joins ,
2074+ othersj -> ojrelid );
2075+ }
20492076
20502077 /* ... and track joins processed so far */
20512078 joins_so_far = bms_add_member (joins_so_far , othersj -> ojrelid );
@@ -2060,6 +2087,7 @@ deconstruct_distribute_oj_quals(PlannerInfo *root,
20602087 root -> qual_security_level ,
20612088 qualscope ,
20622089 ojscope , nonnullable_rels ,
2090+ NULL , /* incompatible_relids */
20632091 true, /* allow_equivalence */
20642092 false, false, /* not clones */
20652093 NULL ); /* no more postponement */
@@ -2086,6 +2114,7 @@ distribute_quals_to_rels(PlannerInfo *root, List *clauses,
20862114 Relids qualscope ,
20872115 Relids ojscope ,
20882116 Relids outerjoin_nonnullable ,
2117+ Relids incompatible_relids ,
20892118 bool allow_equivalence ,
20902119 bool has_clone ,
20912120 bool is_clone ,
@@ -2104,6 +2133,7 @@ distribute_quals_to_rels(PlannerInfo *root, List *clauses,
21042133 qualscope ,
21052134 ojscope ,
21062135 outerjoin_nonnullable ,
2136+ incompatible_relids ,
21072137 allow_equivalence ,
21082138 has_clone ,
21092139 is_clone ,
@@ -2135,6 +2165,9 @@ distribute_quals_to_rels(PlannerInfo *root, List *clauses,
21352165 * base+OJ rels appearing on the outer (nonnullable) side of the join
21362166 * (for FULL JOIN this includes both sides of the join, and must in fact
21372167 * equal qualscope)
2168+ * 'incompatible_relids': the set of outer-join relid(s) that must not be
2169+ * computed below this qual. We only bother to compute this for
2170+ * "clone" quals, otherwise it can be left NULL.
21382171 * 'allow_equivalence': true if it's okay to convert clause into an
21392172 * EquivalenceClass
21402173 * 'has_clone': has_clone property to assign to the qual
@@ -2159,6 +2192,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
21592192 Relids qualscope ,
21602193 Relids ojscope ,
21612194 Relids outerjoin_nonnullable ,
2195+ Relids incompatible_relids ,
21622196 bool allow_equivalence ,
21632197 bool has_clone ,
21642198 bool is_clone ,
@@ -2377,15 +2411,14 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
23772411 restrictinfo = make_restrictinfo (root ,
23782412 (Expr * ) clause ,
23792413 is_pushed_down ,
2414+ has_clone ,
2415+ is_clone ,
23802416 pseudoconstant ,
23812417 security_level ,
23822418 relids ,
2419+ incompatible_relids ,
23832420 outerjoin_nonnullable );
23842421
2385- /* Apply appropriate clone marking, too */
2386- restrictinfo -> has_clone = has_clone ;
2387- restrictinfo -> is_clone = is_clone ;
2388-
23892422 /*
23902423 * If it's a join clause, add vars used in the clause to targetlists of
23912424 * their relations, so that they will be emitted by the plan nodes that
@@ -2750,9 +2783,12 @@ process_implied_equality(PlannerInfo *root,
27502783 restrictinfo = make_restrictinfo (root ,
27512784 (Expr * ) clause ,
27522785 true, /* is_pushed_down */
2786+ false, /* !has_clone */
2787+ false, /* !is_clone */
27532788 pseudoconstant ,
27542789 security_level ,
27552790 relids ,
2791+ NULL , /* incompatible_relids */
27562792 NULL ); /* outer_relids */
27572793
27582794 /*
@@ -2841,9 +2877,12 @@ build_implied_join_equality(PlannerInfo *root,
28412877 restrictinfo = make_restrictinfo (root ,
28422878 clause ,
28432879 true, /* is_pushed_down */
2880+ false, /* !has_clone */
2881+ false, /* !is_clone */
28442882 false, /* pseudoconstant */
28452883 security_level , /* security_level */
28462884 qualscope , /* required_relids */
2885+ NULL , /* incompatible_relids */
28472886 NULL ); /* outer_relids */
28482887
28492888 /* Set mergejoinability/hashjoinability flags */
0 commit comments