@@ -169,7 +169,8 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels)
169
169
/*
170
170
* Except for the topmost scan/join rel, consider gathering
171
171
* partial paths. We'll do the same for the topmost scan/join rel
172
- * once we know the final targetlist (see grouping_planner).
172
+ * once we know the final targetlist (see grouping_planner's and
173
+ * its call to apply_scanjoin_target_to_paths).
173
174
*/
174
175
if (!bms_equal (rel -> relids , root -> all_query_rels ))
175
176
generate_useful_gather_paths (root , rel , false);
@@ -178,7 +179,7 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels)
178
179
set_cheapest (rel );
179
180
180
181
#ifdef OPTIMIZER_DEBUG
181
- debug_print_rel ( root , rel );
182
+ pprint ( rel );
182
183
#endif
183
184
}
184
185
}
@@ -258,6 +259,8 @@ join_search_one_level(PlannerInfo *root, int level)
258
259
if (old_rel -> joininfo != NIL || old_rel -> has_eclass_joins ||
259
260
has_join_restriction (root , old_rel ))
260
261
{
262
+ int first_rel ;
263
+
261
264
/*
262
265
* There are join clauses or join order restrictions relevant to
263
266
* this rel, so consider joins between this rel and (only) those
@@ -271,24 +274,12 @@ join_search_one_level(PlannerInfo *root, int level)
271
274
* to each initial rel they don't already include but have a join
272
275
* clause or restriction with.
273
276
*/
274
- List * other_rels_list ;
275
- ListCell * other_rels ;
276
-
277
277
if (level == 2 ) /* consider remaining initial rels */
278
- {
279
- other_rels_list = joinrels [level - 1 ];
280
- other_rels = lnext (other_rels_list , r );
281
- }
282
- else /* consider all initial rels */
283
- {
284
- other_rels_list = joinrels [1 ];
285
- other_rels = list_head (other_rels_list );
286
- }
278
+ first_rel = foreach_current_index (r ) + 1 ;
279
+ else
280
+ first_rel = 0 ;
287
281
288
- make_rels_by_clause_joins (root ,
289
- old_rel ,
290
- other_rels_list ,
291
- other_rels );
282
+ make_rels_by_clause_joins (root , old_rel , joinrels [1 ], first_rel );
292
283
}
293
284
else
294
285
{
@@ -332,8 +323,7 @@ join_search_one_level(PlannerInfo *root, int level)
332
323
foreach (r , joinrels [k ])
333
324
{
334
325
RelOptInfo * old_rel = (RelOptInfo * ) lfirst (r );
335
- List * other_rels_list ;
336
- ListCell * other_rels ;
326
+ int first_rel ;
337
327
ListCell * r2 ;
338
328
339
329
/*
@@ -345,19 +335,12 @@ join_search_one_level(PlannerInfo *root, int level)
345
335
!has_join_restriction (root , old_rel ))
346
336
continue ;
347
337
348
- if (k == other_level )
349
- {
350
- /* only consider remaining rels */
351
- other_rels_list = joinrels [k ];
352
- other_rels = lnext (other_rels_list , r );
353
- }
338
+ if (k == other_level ) /* only consider remaining rels */
339
+ first_rel = foreach_current_index (r ) + 1 ;
354
340
else
355
- {
356
- other_rels_list = joinrels [other_level ];
357
- other_rels = list_head (other_rels_list );
358
- }
341
+ first_rel = 0 ;
359
342
360
- for_each_cell (r2 , other_rels_list , other_rels )
343
+ for_each_from (r2 , joinrels [ other_level ], first_rel )
361
344
{
362
345
RelOptInfo * new_rel = (RelOptInfo * ) lfirst (r2 );
363
346
@@ -452,22 +435,21 @@ join_search_one_level(PlannerInfo *root, int level)
452
435
* automatically ensures that each new joinrel is only added to the list once.
453
436
*
454
437
* 'old_rel' is the relation entry for the relation to be joined
455
- * 'other_rels_list': a list containing the other
456
- * rels to be considered for joining
457
- * 'other_rels': the first cell to be considered
438
+ * 'other_rels': a list containing the other rels to be considered for joining
439
+ * 'first_rel_idx': the first rel to be considered in 'other_rels'
458
440
*
459
441
* Currently, this is only used with initial rels in other_rels, but it
460
442
* will work for joining to joinrels too.
461
443
*/
462
444
static void
463
445
make_rels_by_clause_joins (PlannerInfo * root ,
464
446
RelOptInfo * old_rel ,
465
- List * other_rels_list ,
466
- ListCell * other_rels )
447
+ List * other_rels ,
448
+ int first_rel_idx )
467
449
{
468
450
ListCell * l ;
469
451
470
- for_each_cell (l , other_rels_list , other_rels )
452
+ for_each_from (l , other_rels , first_rel_idx )
471
453
{
472
454
RelOptInfo * other_rel = (RelOptInfo * ) lfirst (l );
473
455
@@ -942,6 +924,9 @@ restriction_is_constant_false(List *restrictlist,
942
924
* Construct the SpecialJoinInfo for a child-join by translating
943
925
* SpecialJoinInfo for the join between parents. left_relids and right_relids
944
926
* are the relids of left and right side of the join respectively.
927
+ *
928
+ * If translations are added to or removed from this function, consider
929
+ * updating free_child_join_sjinfo() accordingly.
945
930
*/
946
931
static SpecialJoinInfo *
947
932
build_child_join_sjinfo (PlannerInfo * root , SpecialJoinInfo * parent_sjinfo ,
@@ -953,6 +938,14 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
953
938
AppendRelInfo * * right_appinfos ;
954
939
int right_nappinfos ;
955
940
941
+ /* Dummy SpecialJoinInfos can be created without any translation. */
942
+ if (parent_sjinfo -> jointype == JOIN_INNER )
943
+ {
944
+ Assert (parent_sjinfo -> ojrelid == 0 );
945
+ init_dummy_sjinfo (sjinfo , left_relids , right_relids );
946
+ return sjinfo ;
947
+ }
948
+
956
949
memcpy (sjinfo , parent_sjinfo , sizeof (SpecialJoinInfo ));
957
950
left_appinfos = find_appinfos_by_relids (root , left_relids ,
958
951
& left_nappinfos );
@@ -1260,7 +1253,6 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
1260
1253
SpecialJoinInfo * child_sjinfo ;
1261
1254
List * child_restrictlist ;
1262
1255
RelOptInfo * child_joinrel ;
1263
- Relids child_joinrelids ;
1264
1256
AppendRelInfo * * appinfos ;
1265
1257
int nappinfos ;
1266
1258
@@ -1357,13 +1349,11 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
1357
1349
child_rel1 -> relids ,
1358
1350
child_rel2 -> relids );
1359
1351
1360
- /* Build correct join relids for child join */
1361
- child_joinrelids = bms_union (child_rel1 -> relids , child_rel2 -> relids );
1362
- child_joinrelids = add_outer_joins_to_relids (root , child_joinrelids ,
1363
- child_sjinfo , NULL );
1364
-
1365
1352
/* Find the AppendRelInfo structures */
1366
- appinfos = find_appinfos_by_relids (root , child_joinrelids , & nappinfos );
1353
+ appinfos = find_appinfos_by_relids (root ,
1354
+ bms_union (child_rel1 -> relids ,
1355
+ child_rel2 -> relids ),
1356
+ & nappinfos );
1367
1357
1368
1358
/*
1369
1359
* Construct restrictions applicable to the child join from those
@@ -1373,8 +1363,8 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
1373
1363
(List * ) adjust_appendrel_attrs (root ,
1374
1364
(Node * ) parent_restrictlist ,
1375
1365
nappinfos , appinfos );
1376
- pfree (appinfos );
1377
1366
1367
+ /* Find or construct the child join's RelOptInfo */
1378
1368
child_joinrel = joinrel -> part_rels [cnt_parts ];
1379
1369
if (!child_joinrel )
1380
1370
{
@@ -1387,10 +1377,49 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
1387
1377
child_joinrel -> relids );
1388
1378
}
1389
1379
1390
- Assert (bms_equal (child_joinrel -> relids , child_joinrelids ));
1380
+ /* Assert we got the right one */
1381
+ Assert (bms_equal (child_joinrel -> relids ,
1382
+ adjust_child_relids (joinrel -> relids ,
1383
+ nappinfos , appinfos )));
1391
1384
1385
+ /* And make paths for the child join */
1392
1386
populate_joinrel_with_paths (root , child_rel1 , child_rel2 ,
1393
1387
child_joinrel , child_sjinfo ,
1394
1388
child_restrictlist );
1389
+
1390
+ pfree (appinfos );
1391
+ free_child_join_sjinfo (child_sjinfo );
1392
+ }
1393
+ }
1394
+
1395
+
1396
+ /*
1397
+ * free_child_join_sjinfo
1398
+ * Free memory consumed by a SpecialJoinInfo created by
1399
+ * build_child_join_sjinfo()
1400
+ *
1401
+ * Only members that are translated copies of their counterpart in the parent
1402
+ * SpecialJoinInfo are freed here.
1403
+ */
1404
+ static void
1405
+ free_child_join_sjinfo (SpecialJoinInfo * sjinfo )
1406
+ {
1407
+ /*
1408
+ * Dummy SpecialJoinInfos of inner joins do not have any translated fields
1409
+ * and hence no fields that to be freed.
1410
+ */
1411
+ if (sjinfo -> jointype != JOIN_INNER )
1412
+ {
1413
+ bms_free (sjinfo -> min_lefthand );
1414
+ bms_free (sjinfo -> min_righthand );
1415
+ bms_free (sjinfo -> syn_lefthand );
1416
+ bms_free (sjinfo -> syn_righthand );
1417
+
1418
+ /*
1419
+ * semi_rhs_exprs may in principle be freed, but a simple pfree() does
1420
+ * not suffice, so we leave it alone.
1421
+ */
1395
1422
}
1423
+
1424
+ pfree (sjinfo );
1396
1425
}
0 commit comments