@@ -2103,23 +2103,33 @@ match_eclasses_to_foreign_key_col(PlannerInfo *root,
2103
2103
2104
2104
/*
2105
2105
* add_child_rel_equivalences
2106
- * Search for EC members that reference the parent_rel , and
2106
+ * Search for EC members that reference the root parent of child_rel , and
2107
2107
* add transformed members referencing the child_rel.
2108
2108
*
2109
2109
* Note that this function won't be called at all unless we have at least some
2110
2110
* reason to believe that the EC members it generates will be useful.
2111
2111
*
2112
2112
* parent_rel and child_rel could be derived from appinfo, but since the
2113
2113
* caller has already computed them, we might as well just pass them in.
2114
+ *
2115
+ * The passed-in AppendRelInfo is not used when the parent_rel is not a
2116
+ * top-level baserel, since it shows the mapping from the parent_rel but
2117
+ * we need to translate EC expressions that refer to the top-level parent.
2118
+ * Using it is faster than using adjust_appendrel_attrs_multilevel(), though,
2119
+ * so we prefer it when we can.
2114
2120
*/
2115
2121
void
2116
2122
add_child_rel_equivalences (PlannerInfo * root ,
2117
2123
AppendRelInfo * appinfo ,
2118
2124
RelOptInfo * parent_rel ,
2119
2125
RelOptInfo * child_rel )
2120
2126
{
2127
+ Relids top_parent_relids = child_rel -> top_parent_relids ;
2128
+ Relids child_relids = child_rel -> relids ;
2121
2129
ListCell * lc1 ;
2122
2130
2131
+ Assert (IS_SIMPLE_REL (parent_rel ));
2132
+
2123
2133
foreach (lc1 , root -> eq_classes )
2124
2134
{
2125
2135
EquivalenceClass * cur_ec = (EquivalenceClass * ) lfirst (lc1 );
@@ -2137,7 +2147,7 @@ add_child_rel_equivalences(PlannerInfo *root,
2137
2147
* No point in searching if child's topmost parent rel is not
2138
2148
* mentioned in eclass.
2139
2149
*/
2140
- if (!bms_is_subset (child_rel -> top_parent_relids , cur_ec -> ec_relids ))
2150
+ if (!bms_is_subset (top_parent_relids , cur_ec -> ec_relids ))
2141
2151
continue ;
2142
2152
2143
2153
foreach (lc2 , cur_ec -> ec_members )
@@ -2152,13 +2162,14 @@ add_child_rel_equivalences(PlannerInfo *root,
2152
2162
* already-transformed child members. Otherwise, if some original
2153
2163
* member expression references more than one appendrel, we'd get
2154
2164
* an O(N^2) explosion of useless derived expressions for
2155
- * combinations of children.
2165
+ * combinations of children. (But add_child_join_rel_equivalences
2166
+ * may add targeted combinations for partitionwise-join purposes.)
2156
2167
*/
2157
2168
if (cur_em -> em_is_child )
2158
2169
continue ; /* ignore children here */
2159
2170
2160
2171
/* Does this member reference child's topmost parent rel? */
2161
- if (bms_overlap (cur_em -> em_relids , child_rel -> top_parent_relids ))
2172
+ if (bms_overlap (cur_em -> em_relids , top_parent_relids ))
2162
2173
{
2163
2174
/* Yes, generate transformed child version */
2164
2175
Expr * child_expr ;
@@ -2179,8 +2190,8 @@ add_child_rel_equivalences(PlannerInfo *root,
2179
2190
child_expr = (Expr * )
2180
2191
adjust_appendrel_attrs_multilevel (root ,
2181
2192
(Node * ) cur_em -> em_expr ,
2182
- child_rel -> relids ,
2183
- child_rel -> top_parent_relids );
2193
+ child_relids ,
2194
+ top_parent_relids );
2184
2195
}
2185
2196
2186
2197
/*
@@ -2190,22 +2201,141 @@ add_child_rel_equivalences(PlannerInfo *root,
2190
2201
* don't want the child member to be marked as constant.
2191
2202
*/
2192
2203
new_relids = bms_difference (cur_em -> em_relids ,
2193
- child_rel -> top_parent_relids );
2194
- new_relids = bms_add_members (new_relids , child_rel -> relids );
2204
+ top_parent_relids );
2205
+ new_relids = bms_add_members (new_relids , child_relids );
2195
2206
2196
2207
/*
2197
2208
* And likewise for nullable_relids. Note this code assumes
2198
2209
* parent and child relids are singletons.
2199
2210
*/
2200
2211
new_nullable_relids = cur_em -> em_nullable_relids ;
2201
- if (bms_overlap (new_nullable_relids ,
2202
- child_rel -> top_parent_relids ))
2212
+ if (bms_overlap (new_nullable_relids , top_parent_relids ))
2203
2213
{
2204
2214
new_nullable_relids = bms_difference (new_nullable_relids ,
2205
- child_rel -> top_parent_relids );
2215
+ top_parent_relids );
2206
2216
new_nullable_relids = bms_add_members (new_nullable_relids ,
2207
- child_rel -> relids );
2217
+ child_relids );
2218
+ }
2219
+
2220
+ (void ) add_eq_member (cur_ec , child_expr ,
2221
+ new_relids , new_nullable_relids ,
2222
+ true, cur_em -> em_datatype );
2223
+ }
2224
+ }
2225
+ }
2226
+ }
2227
+
2228
+ /*
2229
+ * add_child_join_rel_equivalences
2230
+ * Like add_child_rel_equivalences(), but for joinrels
2231
+ *
2232
+ * Here we find the ECs relevant to the top parent joinrel and add transformed
2233
+ * member expressions that refer to this child joinrel.
2234
+ *
2235
+ * Note that this function won't be called at all unless we have at least some
2236
+ * reason to believe that the EC members it generates will be useful.
2237
+ */
2238
+ void
2239
+ add_child_join_rel_equivalences (PlannerInfo * root ,
2240
+ int nappinfos , AppendRelInfo * * appinfos ,
2241
+ RelOptInfo * parent_joinrel ,
2242
+ RelOptInfo * child_joinrel )
2243
+ {
2244
+ Relids top_parent_relids = child_joinrel -> top_parent_relids ;
2245
+ Relids child_relids = child_joinrel -> relids ;
2246
+ ListCell * lc1 ;
2247
+
2248
+ Assert (IS_JOIN_REL (child_joinrel ) && IS_JOIN_REL (parent_joinrel ));
2249
+
2250
+ foreach (lc1 , root -> eq_classes )
2251
+ {
2252
+ EquivalenceClass * cur_ec = (EquivalenceClass * ) lfirst (lc1 );
2253
+ ListCell * lc2 ;
2254
+
2255
+ /*
2256
+ * If this EC contains a volatile expression, then generating child
2257
+ * EMs would be downright dangerous, so skip it. We rely on a
2258
+ * volatile EC having only one EM.
2259
+ */
2260
+ if (cur_ec -> ec_has_volatile )
2261
+ continue ;
2262
+
2263
+ /*
2264
+ * No point in searching if child's topmost parent rel is not
2265
+ * mentioned in eclass.
2266
+ */
2267
+ if (!bms_overlap (top_parent_relids , cur_ec -> ec_relids ))
2268
+ continue ;
2269
+
2270
+ foreach (lc2 , cur_ec -> ec_members )
2271
+ {
2272
+ EquivalenceMember * cur_em = (EquivalenceMember * ) lfirst (lc2 );
2273
+
2274
+ if (cur_em -> em_is_const )
2275
+ continue ; /* ignore consts here */
2276
+
2277
+ /*
2278
+ * We consider only original EC members here, not
2279
+ * already-transformed child members.
2280
+ */
2281
+ if (cur_em -> em_is_child )
2282
+ continue ; /* ignore children here */
2283
+
2284
+ /*
2285
+ * We may ignore expressions that reference a single baserel,
2286
+ * because add_child_rel_equivalences should have handled them.
2287
+ */
2288
+ if (bms_membership (cur_em -> em_relids ) != BMS_MULTIPLE )
2289
+ continue ;
2290
+
2291
+ /* Does this member reference child's topmost parent rel? */
2292
+ if (bms_overlap (cur_em -> em_relids , top_parent_relids ))
2293
+ {
2294
+ /* Yes, generate transformed child version */
2295
+ Expr * child_expr ;
2296
+ Relids new_relids ;
2297
+ Relids new_nullable_relids ;
2298
+
2299
+ if (parent_joinrel -> reloptkind == RELOPT_JOINREL )
2300
+ {
2301
+ /* Simple single-level transformation */
2302
+ child_expr = (Expr * )
2303
+ adjust_appendrel_attrs (root ,
2304
+ (Node * ) cur_em -> em_expr ,
2305
+ nappinfos , appinfos );
2208
2306
}
2307
+ else
2308
+ {
2309
+ /* Must do multi-level transformation */
2310
+ Assert (parent_joinrel -> reloptkind == RELOPT_OTHER_JOINREL );
2311
+ child_expr = (Expr * )
2312
+ adjust_appendrel_attrs_multilevel (root ,
2313
+ (Node * ) cur_em -> em_expr ,
2314
+ child_relids ,
2315
+ top_parent_relids );
2316
+ }
2317
+
2318
+ /*
2319
+ * Transform em_relids to match. Note we do *not* do
2320
+ * pull_varnos(child_expr) here, as for example the
2321
+ * transformation might have substituted a constant, but we
2322
+ * don't want the child member to be marked as constant.
2323
+ */
2324
+ new_relids = bms_difference (cur_em -> em_relids ,
2325
+ top_parent_relids );
2326
+ new_relids = bms_add_members (new_relids , child_relids );
2327
+
2328
+ /*
2329
+ * For nullable_relids, we must selectively replace parent
2330
+ * nullable relids with child ones.
2331
+ */
2332
+ new_nullable_relids = cur_em -> em_nullable_relids ;
2333
+ if (bms_overlap (new_nullable_relids , top_parent_relids ))
2334
+ new_nullable_relids =
2335
+ adjust_child_relids_multilevel (root ,
2336
+ new_nullable_relids ,
2337
+ child_relids ,
2338
+ top_parent_relids );
2209
2339
2210
2340
(void ) add_eq_member (cur_ec , child_expr ,
2211
2341
new_relids , new_nullable_relids ,
0 commit comments