@@ -1132,7 +1132,7 @@ generate_join_implied_equalities(PlannerInfo *root,
1132
1132
Relids inner_relids = inner_rel -> relids ;
1133
1133
Relids nominal_inner_relids ;
1134
1134
Relids nominal_join_relids ;
1135
- Bitmapset * matching_ecs ;
1135
+ Bitmapset * matching_ecs ;
1136
1136
int i ;
1137
1137
1138
1138
/* If inner rel is a child, extra setup work is needed */
@@ -2209,21 +2209,29 @@ match_eclasses_to_foreign_key_col(PlannerInfo *root,
2209
2209
2210
2210
/*
2211
2211
* add_child_rel_equivalences
2212
- * Search for EC members that reference the parent_rel , and
2212
+ * Search for EC members that reference the root parent of child_rel , and
2213
2213
* add transformed members referencing the child_rel.
2214
2214
*
2215
2215
* Note that this function won't be called at all unless we have at least some
2216
2216
* reason to believe that the EC members it generates will be useful.
2217
2217
*
2218
2218
* parent_rel and child_rel could be derived from appinfo, but since the
2219
2219
* caller has already computed them, we might as well just pass them in.
2220
+ *
2221
+ * The passed-in AppendRelInfo is not used when the parent_rel is not a
2222
+ * top-level baserel, since it shows the mapping from the parent_rel but
2223
+ * we need to translate EC expressions that refer to the top-level parent.
2224
+ * Using it is faster than using adjust_appendrel_attrs_multilevel(), though,
2225
+ * so we prefer it when we can.
2220
2226
*/
2221
2227
void
2222
2228
add_child_rel_equivalences (PlannerInfo * root ,
2223
2229
AppendRelInfo * appinfo ,
2224
2230
RelOptInfo * parent_rel ,
2225
2231
RelOptInfo * child_rel )
2226
2232
{
2233
+ Relids top_parent_relids = child_rel -> top_parent_relids ;
2234
+ Relids child_relids = child_rel -> relids ;
2227
2235
int i ;
2228
2236
2229
2237
/*
@@ -2248,7 +2256,7 @@ add_child_rel_equivalences(PlannerInfo *root,
2248
2256
continue ;
2249
2257
2250
2258
/* Sanity check eclass_indexes only contain ECs for parent_rel */
2251
- Assert (bms_is_subset (child_rel -> top_parent_relids , cur_ec -> ec_relids ));
2259
+ Assert (bms_is_subset (top_parent_relids , cur_ec -> ec_relids ));
2252
2260
2253
2261
/*
2254
2262
* We don't use foreach() here because there's no point in scanning
@@ -2268,13 +2276,14 @@ add_child_rel_equivalences(PlannerInfo *root,
2268
2276
* already-transformed child members. Otherwise, if some original
2269
2277
* member expression references more than one appendrel, we'd get
2270
2278
* an O(N^2) explosion of useless derived expressions for
2271
- * combinations of children.
2279
+ * combinations of children. (But add_child_join_rel_equivalences
2280
+ * may add targeted combinations for partitionwise-join purposes.)
2272
2281
*/
2273
2282
if (cur_em -> em_is_child )
2274
2283
continue ; /* ignore children here */
2275
2284
2276
2285
/* Does this member reference child's topmost parent rel? */
2277
- if (bms_overlap (cur_em -> em_relids , child_rel -> top_parent_relids ))
2286
+ if (bms_overlap (cur_em -> em_relids , top_parent_relids ))
2278
2287
{
2279
2288
/* Yes, generate transformed child version */
2280
2289
Expr * child_expr ;
@@ -2295,8 +2304,8 @@ add_child_rel_equivalences(PlannerInfo *root,
2295
2304
child_expr = (Expr * )
2296
2305
adjust_appendrel_attrs_multilevel (root ,
2297
2306
(Node * ) cur_em -> em_expr ,
2298
- child_rel -> relids ,
2299
- child_rel -> top_parent_relids );
2307
+ child_relids ,
2308
+ top_parent_relids );
2300
2309
}
2301
2310
2302
2311
/*
@@ -2306,21 +2315,20 @@ add_child_rel_equivalences(PlannerInfo *root,
2306
2315
* don't want the child member to be marked as constant.
2307
2316
*/
2308
2317
new_relids = bms_difference (cur_em -> em_relids ,
2309
- child_rel -> top_parent_relids );
2310
- new_relids = bms_add_members (new_relids , child_rel -> relids );
2318
+ top_parent_relids );
2319
+ new_relids = bms_add_members (new_relids , child_relids );
2311
2320
2312
2321
/*
2313
2322
* And likewise for nullable_relids. Note this code assumes
2314
2323
* parent and child relids are singletons.
2315
2324
*/
2316
2325
new_nullable_relids = cur_em -> em_nullable_relids ;
2317
- if (bms_overlap (new_nullable_relids ,
2318
- child_rel -> top_parent_relids ))
2326
+ if (bms_overlap (new_nullable_relids , top_parent_relids ))
2319
2327
{
2320
2328
new_nullable_relids = bms_difference (new_nullable_relids ,
2321
- child_rel -> top_parent_relids );
2329
+ top_parent_relids );
2322
2330
new_nullable_relids = bms_add_members (new_nullable_relids ,
2323
- child_rel -> relids );
2331
+ child_relids );
2324
2332
}
2325
2333
2326
2334
(void ) add_eq_member (cur_ec , child_expr ,
@@ -2334,6 +2342,133 @@ add_child_rel_equivalences(PlannerInfo *root,
2334
2342
}
2335
2343
}
2336
2344
2345
+ /*
2346
+ * add_child_join_rel_equivalences
2347
+ * Like add_child_rel_equivalences(), but for joinrels
2348
+ *
2349
+ * Here we find the ECs relevant to the top parent joinrel and add transformed
2350
+ * member expressions that refer to this child joinrel.
2351
+ *
2352
+ * Note that this function won't be called at all unless we have at least some
2353
+ * reason to believe that the EC members it generates will be useful.
2354
+ */
2355
+ void
2356
+ add_child_join_rel_equivalences (PlannerInfo * root ,
2357
+ int nappinfos , AppendRelInfo * * appinfos ,
2358
+ RelOptInfo * parent_joinrel ,
2359
+ RelOptInfo * child_joinrel )
2360
+ {
2361
+ Relids top_parent_relids = child_joinrel -> top_parent_relids ;
2362
+ Relids child_relids = child_joinrel -> relids ;
2363
+ Bitmapset * matching_ecs ;
2364
+ int i ;
2365
+
2366
+ Assert (IS_JOIN_REL (child_joinrel ) && IS_JOIN_REL (parent_joinrel ));
2367
+
2368
+ /* We need consider only ECs that mention the parent joinrel */
2369
+ matching_ecs = get_eclass_indexes_for_relids (root , top_parent_relids );
2370
+
2371
+ i = -1 ;
2372
+ while ((i = bms_next_member (matching_ecs , i )) >= 0 )
2373
+ {
2374
+ EquivalenceClass * cur_ec = (EquivalenceClass * ) list_nth (root -> eq_classes , i );
2375
+ int num_members ;
2376
+
2377
+ /*
2378
+ * If this EC contains a volatile expression, then generating child
2379
+ * EMs would be downright dangerous, so skip it. We rely on a
2380
+ * volatile EC having only one EM.
2381
+ */
2382
+ if (cur_ec -> ec_has_volatile )
2383
+ continue ;
2384
+
2385
+ /* Sanity check on get_eclass_indexes_for_relids result */
2386
+ Assert (bms_overlap (top_parent_relids , cur_ec -> ec_relids ));
2387
+
2388
+ /*
2389
+ * We don't use foreach() here because there's no point in scanning
2390
+ * newly-added child members, so we can stop after the last
2391
+ * pre-existing EC member.
2392
+ */
2393
+ num_members = list_length (cur_ec -> ec_members );
2394
+ for (int pos = 0 ; pos < num_members ; pos ++ )
2395
+ {
2396
+ EquivalenceMember * cur_em = (EquivalenceMember * ) list_nth (cur_ec -> ec_members , pos );
2397
+
2398
+ if (cur_em -> em_is_const )
2399
+ continue ; /* ignore consts here */
2400
+
2401
+ /*
2402
+ * We consider only original EC members here, not
2403
+ * already-transformed child members.
2404
+ */
2405
+ if (cur_em -> em_is_child )
2406
+ continue ; /* ignore children here */
2407
+
2408
+ /*
2409
+ * We may ignore expressions that reference a single baserel,
2410
+ * because add_child_rel_equivalences should have handled them.
2411
+ */
2412
+ if (bms_membership (cur_em -> em_relids ) != BMS_MULTIPLE )
2413
+ continue ;
2414
+
2415
+ /* Does this member reference child's topmost parent rel? */
2416
+ if (bms_overlap (cur_em -> em_relids , top_parent_relids ))
2417
+ {
2418
+ /* Yes, generate transformed child version */
2419
+ Expr * child_expr ;
2420
+ Relids new_relids ;
2421
+ Relids new_nullable_relids ;
2422
+
2423
+ if (parent_joinrel -> reloptkind == RELOPT_JOINREL )
2424
+ {
2425
+ /* Simple single-level transformation */
2426
+ child_expr = (Expr * )
2427
+ adjust_appendrel_attrs (root ,
2428
+ (Node * ) cur_em -> em_expr ,
2429
+ nappinfos , appinfos );
2430
+ }
2431
+ else
2432
+ {
2433
+ /* Must do multi-level transformation */
2434
+ Assert (parent_joinrel -> reloptkind == RELOPT_OTHER_JOINREL );
2435
+ child_expr = (Expr * )
2436
+ adjust_appendrel_attrs_multilevel (root ,
2437
+ (Node * ) cur_em -> em_expr ,
2438
+ child_relids ,
2439
+ top_parent_relids );
2440
+ }
2441
+
2442
+ /*
2443
+ * Transform em_relids to match. Note we do *not* do
2444
+ * pull_varnos(child_expr) here, as for example the
2445
+ * transformation might have substituted a constant, but we
2446
+ * don't want the child member to be marked as constant.
2447
+ */
2448
+ new_relids = bms_difference (cur_em -> em_relids ,
2449
+ top_parent_relids );
2450
+ new_relids = bms_add_members (new_relids , child_relids );
2451
+
2452
+ /*
2453
+ * For nullable_relids, we must selectively replace parent
2454
+ * nullable relids with child ones.
2455
+ */
2456
+ new_nullable_relids = cur_em -> em_nullable_relids ;
2457
+ if (bms_overlap (new_nullable_relids , top_parent_relids ))
2458
+ new_nullable_relids =
2459
+ adjust_child_relids_multilevel (root ,
2460
+ new_nullable_relids ,
2461
+ child_relids ,
2462
+ top_parent_relids );
2463
+
2464
+ (void ) add_eq_member (cur_ec , child_expr ,
2465
+ new_relids , new_nullable_relids ,
2466
+ true, cur_em -> em_datatype );
2467
+ }
2468
+ }
2469
+ }
2470
+ }
2471
+
2337
2472
2338
2473
/*
2339
2474
* generate_implied_equalities_for_column
0 commit comments