ExecSerializePlan(Plan *plan, EState *estate)
{
PlannedStmt *pstmt;
- ListCell *tlist;
+ ListCell *lc;
/* We can't scribble on the original plan, so make a copy. */
plan = copyObject(plan);
* accordingly. This is sort of a hack; there might be better ways to do
* this...
*/
- foreach(tlist, plan->targetlist)
+ foreach(lc, plan->targetlist)
{
- TargetEntry *tle = (TargetEntry *) lfirst(tlist);
+ TargetEntry *tle = lfirst_node(TargetEntry, lc);
tle->resjunk = false;
}
pstmt->rtable = estate->es_range_table;
pstmt->resultRelations = NIL;
pstmt->nonleafResultRelations = NIL;
- pstmt->subplans = estate->es_plannedstmt->subplans;
+
+ /*
+ * Transfer only parallel-safe subplans, leaving a NULL "hole" in the list
+ * for unsafe ones (so that the list indexes of the safe ones are
+ * preserved). This positively ensures that the worker won't try to run,
+ * or even do ExecInitNode on, an unsafe subplan. That's important to
+ * protect, eg, non-parallel-aware FDWs from getting into trouble.
+ */
+ pstmt->subplans = NIL;
+ foreach(lc, estate->es_plannedstmt->subplans)
+ {
+ Plan *subplan = (Plan *) lfirst(lc);
+
+ if (subplan && !subplan->parallel_safe)
+ subplan = NULL;
+ pstmt->subplans = lappend(pstmt->subplans, subplan);
+ }
+
pstmt->rewindPlanIDs = NULL;
pstmt->rowMarks = NIL;
pstmt->relationOids = NIL;
/* rtable indexes of non-leaf target relations for INSERT/UPDATE/DELETE */
List *nonleafResultRelations;
- List *subplans; /* Plan trees for SubPlan expressions */
+ List *subplans; /* Plan trees for SubPlan expressions; note
+ * that some could be NULL */
Bitmapset *rewindPlanIDs; /* indices of subplans that require REWIND */