diff options
Diffstat (limited to 'src/backend/optimizer/plan/setrefs.c')
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index bf4c722c028..7519723081d 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -115,7 +115,6 @@ static Plan *set_indexonlyscan_references(PlannerInfo *root, static Plan *set_subqueryscan_references(PlannerInfo *root, SubqueryScan *plan, int rtoffset); -static bool trivial_subqueryscan(SubqueryScan *plan); static Plan *clean_up_removed_plan_level(Plan *parent, Plan *child); static void set_foreignscan_references(PlannerInfo *root, ForeignScan *fscan, @@ -1319,14 +1318,26 @@ set_subqueryscan_references(PlannerInfo *root, * * We can delete it if it has no qual to check and the targetlist just * regurgitates the output of the child plan. + * + * This might be called repeatedly on a SubqueryScan node, so we cache the + * result in the SubqueryScan node to avoid repeated computation. */ -static bool +bool trivial_subqueryscan(SubqueryScan *plan) { int attrno; ListCell *lp, *lc; + /* We might have detected this already (see mark_async_capable_plan) */ + if (plan->scanstatus == SUBQUERY_SCAN_TRIVIAL) + return true; + if (plan->scanstatus == SUBQUERY_SCAN_NONTRIVIAL) + return false; + Assert(plan->scanstatus == SUBQUERY_SCAN_UNKNOWN); + /* Initially, mark the SubqueryScan as non-deletable from the plan tree */ + plan->scanstatus = SUBQUERY_SCAN_NONTRIVIAL; + if (plan->scan.plan.qual != NIL) return false; @@ -1368,6 +1379,9 @@ trivial_subqueryscan(SubqueryScan *plan) attrno++; } + /* Re-mark the SubqueryScan as deletable from the plan tree */ + plan->scanstatus = SUBQUERY_SCAN_TRIVIAL; + return true; } |