Improve comments for trivial_subqueryscan().

This function can be called from mark_async_capable_plan(), a helper
function for create_append_plan(), before set_subqueryscan_references(),
to determine the triviality of a SubqueryScan that is a child of an
Append plan node, which is done before doing finalize_plan() on the
SubqueryScan (if necessary) and set_plan_references() on the subplan,
unlike when called from set_subqueryscan_references().  The reason why
this is safe wouldn't be that obvious, so add comments explaining this.

Follow-up for commit c2bb02bc2.

Reviewed by Zhihong Yu.

Discussion: https://postgr.es/m/CAPmGK17%2BGiJBthC6va7%2B9n6t75e-M1N0U18YB2G1B%2BE5OdrNTA%40mail.gmail.com
This commit is contained in:
Etsuro Fujita 2022-06-09 19:30:00 +09:00
parent e77de23fbb
commit 4a8a5dd7f5

View File

@ -1349,8 +1349,23 @@ set_subqueryscan_references(PlannerInfo *root,
* We can delete it if it has no qual to check and the targetlist just * We can delete it if it has no qual to check and the targetlist just
* regurgitates the output of the child plan. * regurgitates the output of the child plan.
* *
* This might be called repeatedly on a SubqueryScan node, so we cache the * This can be called from mark_async_capable_plan(), a helper function for
* result in the SubqueryScan node to avoid repeated computation. * create_append_plan(), before set_subqueryscan_references(), to determine
* triviality of a SubqueryScan that is a child of an Append node. So we
* cache the result in the SubqueryScan node to avoid repeated computation.
*
* Note: when called from mark_async_capable_plan(), we determine the result
* before running finalize_plan() on the SubqueryScan node (if needed) and
* set_plan_references() on the subplan tree, but this would be safe, because
* 1) finalize_plan() doesn't modify the tlist or quals for the SubqueryScan
* node (or that for any plan node in the subplan tree), and
* 2) set_plan_references() modifies the tlist for every plan node in the
* subplan tree, but keeps const/resjunk columns as const/resjunk ones and
* preserves the length and order of the tlist, and
* 3) set_plan_references() might delete the topmost plan node like an Append
* or MergeAppend from the subplan tree and pull up the child plan node,
* but in that case, the tlist for the child plan node exactly matches the
* parent.
*/ */
bool bool
trivial_subqueryscan(SubqueryScan *plan) trivial_subqueryscan(SubqueryScan *plan)
@ -1359,7 +1374,7 @@ trivial_subqueryscan(SubqueryScan *plan)
ListCell *lp, ListCell *lp,
*lc; *lc;
/* We might have detected this already (see mark_async_capable_plan) */ /* We might have detected this already; in which case reuse the result */
if (plan->scanstatus == SUBQUERY_SCAN_TRIVIAL) if (plan->scanstatus == SUBQUERY_SCAN_TRIVIAL)
return true; return true;
if (plan->scanstatus == SUBQUERY_SCAN_NONTRIVIAL) if (plan->scanstatus == SUBQUERY_SCAN_NONTRIVIAL)