|
46 | 46 | #include "commands/matview.h"
|
47 | 47 | #include "commands/trigger.h"
|
48 | 48 | #include "executor/execdebug.h"
|
| 49 | +#include "executor/nodeSubplan.h" |
49 | 50 | #include "foreign/fdwapi.h"
|
50 | 51 | #include "mb/pg_wchar.h"
|
51 | 52 | #include "miscadmin.h"
|
@@ -1727,8 +1728,8 @@ ExecutePlan(EState *estate,
|
1727 | 1728 | if (TupIsNull(slot))
|
1728 | 1729 | {
|
1729 | 1730 | /*
|
1730 |
| - * If we know we won't need to back up, we can release |
1731 |
| - * resources at this point. |
| 1731 | + * If we know we won't need to back up, we can release resources |
| 1732 | + * at this point. |
1732 | 1733 | */
|
1733 | 1734 | if (!(estate->es_top_eflags & EXEC_FLAG_BACKWARD))
|
1734 | 1735 | (void) ExecShutdownNode(planstate);
|
@@ -1778,8 +1779,8 @@ ExecutePlan(EState *estate,
|
1778 | 1779 | if (numberTuples && numberTuples == current_tuple_count)
|
1779 | 1780 | {
|
1780 | 1781 | /*
|
1781 |
| - * If we know we won't need to back up, we can release |
1782 |
| - * resources at this point. |
| 1782 | + * If we know we won't need to back up, we can release resources |
| 1783 | + * at this point. |
1783 | 1784 | */
|
1784 | 1785 | if (!(estate->es_top_eflags & EXEC_FLAG_BACKWARD))
|
1785 | 1786 | (void) ExecShutdownNode(planstate);
|
@@ -3078,6 +3079,14 @@ EvalPlanQualBegin(EPQState *epqstate, EState *parentestate)
|
3078 | 3079 | {
|
3079 | 3080 | int i;
|
3080 | 3081 |
|
| 3082 | + /* |
| 3083 | + * Force evaluation of any InitPlan outputs that could be needed |
| 3084 | + * by the subplan, just in case they got reset since |
| 3085 | + * EvalPlanQualStart (see comments therein). |
| 3086 | + */ |
| 3087 | + ExecSetParamPlanMulti(planstate->plan->extParam, |
| 3088 | + GetPerTupleExprContext(parentestate)); |
| 3089 | + |
3081 | 3090 | i = list_length(parentestate->es_plannedstmt->paramExecTypes);
|
3082 | 3091 |
|
3083 | 3092 | while (--i >= 0)
|
@@ -3170,9 +3179,32 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
|
3170 | 3179 | {
|
3171 | 3180 | int i;
|
3172 | 3181 |
|
| 3182 | + /* |
| 3183 | + * Force evaluation of any InitPlan outputs that could be needed by |
| 3184 | + * the subplan. (With more complexity, maybe we could postpone this |
| 3185 | + * till the subplan actually demands them, but it doesn't seem worth |
| 3186 | + * the trouble; this is a corner case already, since usually the |
| 3187 | + * InitPlans would have been evaluated before reaching EvalPlanQual.) |
| 3188 | + * |
| 3189 | + * This will not touch output params of InitPlans that occur somewhere |
| 3190 | + * within the subplan tree, only those that are attached to the |
| 3191 | + * ModifyTable node or above it and are referenced within the subplan. |
| 3192 | + * That's OK though, because the planner would only attach such |
| 3193 | + * InitPlans to a lower-level SubqueryScan node, and EPQ execution |
| 3194 | + * will not descend into a SubqueryScan. |
| 3195 | + * |
| 3196 | + * The EState's per-output-tuple econtext is sufficiently short-lived |
| 3197 | + * for this, since it should get reset before there is any chance of |
| 3198 | + * doing EvalPlanQual again. |
| 3199 | + */ |
| 3200 | + ExecSetParamPlanMulti(planTree->extParam, |
| 3201 | + GetPerTupleExprContext(parentestate)); |
| 3202 | + |
| 3203 | + /* now make the internal param workspace ... */ |
3173 | 3204 | i = list_length(parentestate->es_plannedstmt->paramExecTypes);
|
3174 | 3205 | estate->es_param_exec_vals = (ParamExecData *)
|
3175 | 3206 | palloc0(i * sizeof(ParamExecData));
|
| 3207 | + /* ... and copy down all values, whether really needed or not */ |
3176 | 3208 | while (--i >= 0)
|
3177 | 3209 | {
|
3178 | 3210 | /* copy value if any, but not execPlan link */
|
|
0 commit comments