Skip to content

Commit 12957de

Browse files
committed
Refactor set_rel_consider_parallel routine in pg_compat
1 parent 26a6d6c commit 12957de

File tree

1 file changed

+19
-152
lines changed

1 file changed

+19
-152
lines changed

src/compat/pg_compat.c

Lines changed: 19 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -325,11 +325,17 @@ set_dummy_rel_pathlist(RelOptInfo *rel)
325325
* If this relation could possibly be scanned from within a worker, then set
326326
* its consider_parallel flag.
327327
*/
328-
#if PG_VERSION_NUM >= 100000
329328
void
330329
set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
331330
RangeTblEntry *rte)
332331
{
332+
#if PG_VERSION_NUM >= 100000
333+
#define is_parallel_safe_compat(root, exprs) is_parallel_safe((root), (exprs))
334+
#elif PG_VERSION_NUM >= 90500
335+
#define is_parallel_safe_compat(root, exprs) \
336+
(!has_parallel_hazard((exprs), false))
337+
#endif
338+
333339
/*
334340
* The flag has previously been initialized to false, so we can just
335341
* return if it becomes clear that we can't safely set it.
@@ -340,7 +346,8 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
340346
Assert(root->glob->parallelModeOK);
341347

342348
/* This should only be called for baserels and appendrel children. */
343-
Assert(IS_SIMPLE_REL(rel));
349+
Assert(rel->reloptkind == RELOPT_BASEREL ||
350+
rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
344351

345352
/* Assorted checks based on rtekind. */
346353
switch (rte->rtekind)
@@ -370,7 +377,8 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
370377

371378
if (proparallel != PROPARALLEL_SAFE)
372379
return;
373-
if (!is_parallel_safe(root, (Node *) rte->tablesample->args))
380+
if (!is_parallel_safe_compat(
381+
root, (Node *) rte->tablesample->args))
374382
return;
375383
}
376384

@@ -423,17 +431,19 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
423431

424432
case RTE_FUNCTION:
425433
/* Check for parallel-restricted functions. */
426-
if (!is_parallel_safe(root, (Node *) rte->functions))
434+
if (!is_parallel_safe_compat(root, (Node *) rte->functions))
427435
return;
428436
break;
429437

438+
#if PG_VERSION_NUM >= 100000
430439
case RTE_TABLEFUNC:
431440
/* not parallel safe */
432441
return;
442+
#endif
433443

434444
case RTE_VALUES:
435445
/* Check for parallel-restricted functions. */
436-
if (!is_parallel_safe(root, (Node *) rte->values_lists))
446+
if (!is_parallel_safe_compat(root, (Node *) rte->values_lists))
437447
return;
438448
break;
439449

@@ -448,12 +458,14 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
448458
*/
449459
return;
450460

461+
#if PG_VERSION_NUM >= 100000
451462
case RTE_NAMEDTUPLESTORE:
452463
/*
453464
* tuplestore cannot be shared, at least without more
454465
* infrastructure to support that.
455466
*/
456467
return;
468+
#endif
457469
}
458470

459471
/*
@@ -465,164 +477,19 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
465477
* outer join clauses work correctly. It would likely break equivalence
466478
* classes, too.
467479
*/
468-
if (!is_parallel_safe(root, (Node *) rel->baserestrictinfo))
469-
return;
470-
471-
/*
472-
* Likewise, if the relation's outputs are not parallel-safe, give up.
473-
* (Usually, they're just Vars, but sometimes they're not.)
474-
*/
475-
if (!is_parallel_safe(root, (Node *) rel->reltarget->exprs))
476-
return;
477-
478-
/* We have a winner. */
479-
rel->consider_parallel = true;
480-
}
481-
#elif PG_VERSION_NUM >= 90600
482-
void
483-
set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
484-
RangeTblEntry *rte)
485-
{
486-
/*
487-
* The flag has previously been initialized to false, so we can just
488-
* return if it becomes clear that we can't safely set it.
489-
*/
490-
Assert(!rel->consider_parallel);
491-
492-
/* Don't call this if parallelism is disallowed for the entire query. */
493-
Assert(root->glob->parallelModeOK);
494-
495-
/* This should only be called for baserels and appendrel children. */
496-
Assert(rel->reloptkind == RELOPT_BASEREL ||
497-
rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
498-
499-
/* Assorted checks based on rtekind. */
500-
switch (rte->rtekind)
501-
{
502-
case RTE_RELATION:
503-
504-
/*
505-
* Currently, parallel workers can't access the leader's temporary
506-
* tables. We could possibly relax this if the wrote all of its
507-
* local buffers at the start of the query and made no changes
508-
* thereafter (maybe we could allow hint bit changes), and if we
509-
* taught the workers to read them. Writing a large number of
510-
* temporary buffers could be expensive, though, and we don't have
511-
* the rest of the necessary infrastructure right now anyway. So
512-
* for now, bail out if we see a temporary table.
513-
*/
514-
if (get_rel_persistence(rte->relid) == RELPERSISTENCE_TEMP)
515-
return;
516-
517-
/*
518-
* Table sampling can be pushed down to workers if the sample
519-
* function and its arguments are safe.
520-
*/
521-
if (rte->tablesample != NULL)
522-
{
523-
char proparallel = func_parallel(rte->tablesample->tsmhandler);
524-
525-
if (proparallel != PROPARALLEL_SAFE)
526-
return;
527-
if (has_parallel_hazard((Node *) rte->tablesample->args,
528-
false))
529-
return;
530-
}
531-
532-
/*
533-
* Ask FDWs whether they can support performing a ForeignScan
534-
* within a worker. Most often, the answer will be no. For
535-
* example, if the nature of the FDW is such that it opens a TCP
536-
* connection with a remote server, each parallel worker would end
537-
* up with a separate connection, and these connections might not
538-
* be appropriately coordinated between workers and the leader.
539-
*/
540-
if (rte->relkind == RELKIND_FOREIGN_TABLE)
541-
{
542-
Assert(rel->fdwroutine);
543-
if (!rel->fdwroutine->IsForeignScanParallelSafe)
544-
return;
545-
if (!rel->fdwroutine->IsForeignScanParallelSafe(root, rel, rte))
546-
return;
547-
}
548-
549-
/*
550-
* There are additional considerations for appendrels, which we'll
551-
* deal with in set_append_rel_size and set_append_rel_pathlist.
552-
* For now, just set consider_parallel based on the rel's own
553-
* quals and targetlist.
554-
*/
555-
break;
556-
557-
case RTE_SUBQUERY:
558-
559-
/*
560-
* There's no intrinsic problem with scanning a subquery-in-FROM
561-
* (as distinct from a SubPlan or InitPlan) in a parallel worker.
562-
* If the subquery doesn't happen to have any parallel-safe paths,
563-
* then flagging it as consider_parallel won't change anything,
564-
* but that's true for plain tables, too. We must set
565-
* consider_parallel based on the rel's own quals and targetlist,
566-
* so that if a subquery path is parallel-safe but the quals and
567-
* projection we're sticking onto it are not, we correctly mark
568-
* the SubqueryScanPath as not parallel-safe. (Note that
569-
* set_subquery_pathlist() might push some of these quals down
570-
* into the subquery itself, but that doesn't change anything.)
571-
*/
572-
break;
573-
574-
case RTE_JOIN:
575-
/* Shouldn't happen; we're only considering baserels here. */
576-
Assert(false);
577-
return;
578-
579-
case RTE_FUNCTION:
580-
/* Check for parallel-restricted functions. */
581-
if (has_parallel_hazard((Node *) rte->functions, false))
582-
return;
583-
break;
584-
585-
case RTE_VALUES:
586-
/* Check for parallel-restricted functions. */
587-
if (has_parallel_hazard((Node *) rte->values_lists, false))
588-
return;
589-
break;
590-
591-
case RTE_CTE:
592-
593-
/*
594-
* CTE tuplestores aren't shared among parallel workers, so we
595-
* force all CTE scans to happen in the leader. Also, populating
596-
* the CTE would require executing a subplan that's not available
597-
* in the worker, might be parallel-restricted, and must get
598-
* executed only once.
599-
*/
600-
return;
601-
}
602-
603-
/*
604-
* If there's anything in baserestrictinfo that's parallel-restricted, we
605-
* give up on parallelizing access to this relation. We could consider
606-
* instead postponing application of the restricted quals until we're
607-
* above all the parallelism in the plan tree, but it's not clear that
608-
* that would be a win in very many cases, and it might be tricky to make
609-
* outer join clauses work correctly. It would likely break equivalence
610-
* classes, too.
611-
*/
612-
if (has_parallel_hazard((Node *) rel->baserestrictinfo, false))
480+
if (!is_parallel_safe_compat(root, (Node *) rel->baserestrictinfo))
613481
return;
614482

615483
/*
616484
* Likewise, if the relation's outputs are not parallel-safe, give up.
617485
* (Usually, they're just Vars, but sometimes they're not.)
618486
*/
619-
if (has_parallel_hazard((Node *) rel->reltarget->exprs, false))
487+
if (!is_parallel_safe_compat(root, (Node *) rel->reltarget->exprs))
620488
return;
621489

622490
/* We have a winner. */
623491
rel->consider_parallel = true;
624492
}
625-
#endif
626493

627494

628495
/*

0 commit comments

Comments
 (0)