@@ -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
329328void
330329set_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