5252#include "utils/typcache.h"
5353
5454
55- typedef struct LastAttnumInfo
55+ typedef struct ExprSetupInfo
5656{
57+ /* Highest attribute numbers fetched from inner/outer/scan tuple slots: */
5758 AttrNumber last_inner ;
5859 AttrNumber last_outer ;
5960 AttrNumber last_scan ;
60- } LastAttnumInfo ;
61+ /* MULTIEXPR SubPlan nodes appearing in the expression: */
62+ List * multiexpr_subplans ;
63+ } ExprSetupInfo ;
6164
6265static void ExecReadyExpr (ExprState * state );
6366static void ExecInitExprRec (Expr * node , ExprState * state ,
6467 Datum * resv , bool * resnull );
6568static void ExecInitFunc (ExprEvalStep * scratch , Expr * node , List * args ,
6669 Oid funcid , Oid inputcollid ,
6770 ExprState * state );
68- static void ExecInitExprSlots (ExprState * state , Node * node );
69- static void ExecPushExprSlots (ExprState * state , LastAttnumInfo * info );
70- static bool get_last_attnums_walker (Node * node , LastAttnumInfo * info );
71+ static void ExecCreateExprSetupSteps (ExprState * state , Node * node );
72+ static void ExecPushExprSetupSteps (ExprState * state , ExprSetupInfo * info );
73+ static bool expr_setup_walker (Node * node , ExprSetupInfo * info );
7174static bool ExecComputeSlotInfo (ExprState * state , ExprEvalStep * op );
7275static void ExecInitWholeRowVar (ExprEvalStep * scratch , Var * variable ,
7376 ExprState * state );
@@ -136,8 +139,8 @@ ExecInitExpr(Expr *node, PlanState *parent)
136139 state -> parent = parent ;
137140 state -> ext_params = NULL ;
138141
139- /* Insert EEOP_*_FETCHSOME steps as needed */
140- ExecInitExprSlots (state , (Node * ) node );
142+ /* Insert setup steps as needed */
143+ ExecCreateExprSetupSteps (state , (Node * ) node );
141144
142145 /* Compile the expression proper */
143146 ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
@@ -173,8 +176,8 @@ ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
173176 state -> parent = NULL ;
174177 state -> ext_params = ext_params ;
175178
176- /* Insert EEOP_*_FETCHSOME steps as needed */
177- ExecInitExprSlots (state , (Node * ) node );
179+ /* Insert setup steps as needed */
180+ ExecCreateExprSetupSteps (state , (Node * ) node );
178181
179182 /* Compile the expression proper */
180183 ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
@@ -228,8 +231,8 @@ ExecInitQual(List *qual, PlanState *parent)
228231 /* mark expression as to be used with ExecQual() */
229232 state -> flags = EEO_FLAG_IS_QUAL ;
230233
231- /* Insert EEOP_*_FETCHSOME steps as needed */
232- ExecInitExprSlots (state , (Node * ) qual );
234+ /* Insert setup steps as needed */
235+ ExecCreateExprSetupSteps (state , (Node * ) qual );
233236
234237 /*
235238 * ExecQual() needs to return false for an expression returning NULL. That
@@ -372,8 +375,8 @@ ExecBuildProjectionInfo(List *targetList,
372375
373376 state -> resultslot = slot ;
374377
375- /* Insert EEOP_*_FETCHSOME steps as needed */
376- ExecInitExprSlots (state , (Node * ) targetList );
378+ /* Insert setup steps as needed */
379+ ExecCreateExprSetupSteps (state , (Node * ) targetList );
377380
378381 /* Now compile each tlist column */
379382 foreach (lc , targetList )
@@ -524,7 +527,7 @@ ExecBuildUpdateProjection(List *targetList,
524527 int nAssignableCols ;
525528 bool sawJunk ;
526529 Bitmapset * assignedCols ;
527- LastAttnumInfo deform = {0 , 0 , 0 };
530+ ExprSetupInfo deform = {0 , 0 , 0 , NIL };
528531 ExprEvalStep scratch = {0 };
529532 int outerattnum ;
530533 ListCell * lc ,
@@ -603,17 +606,18 @@ ExecBuildUpdateProjection(List *targetList,
603606 * number of columns of the "outer" tuple.
604607 */
605608 if (evalTargetList )
606- get_last_attnums_walker ((Node * ) targetList , & deform );
609+ expr_setup_walker ((Node * ) targetList , & deform );
607610 else
608611 deform .last_outer = nAssignableCols ;
609612
610- ExecPushExprSlots (state , & deform );
613+ ExecPushExprSetupSteps (state , & deform );
611614
612615 /*
613616 * Now generate code to evaluate the tlist's assignable expressions or
614617 * fetch them from the outer tuple, incidentally validating that they'll
615618 * be of the right data type. The checks above ensure that the forboth()
616- * will iterate over exactly the non-junk columns.
619+ * will iterate over exactly the non-junk columns. Note that we don't
620+ * bother evaluating any remaining resjunk columns.
617621 */
618622 outerattnum = 0 ;
619623 forboth (lc , targetList , lc2 , targetColnos )
@@ -676,22 +680,6 @@ ExecBuildUpdateProjection(List *targetList,
676680 outerattnum ++ ;
677681 }
678682
679- /*
680- * If we're evaluating the tlist, must evaluate any resjunk columns too.
681- * (This matters for things like MULTIEXPR_SUBLINK SubPlans.)
682- */
683- if (evalTargetList )
684- {
685- for_each_cell (lc , targetList , lc )
686- {
687- TargetEntry * tle = lfirst_node (TargetEntry , lc );
688-
689- Assert (tle -> resjunk );
690- ExecInitExprRec (tle -> expr , state ,
691- & state -> resvalue , & state -> resnull );
692- }
693- }
694-
695683 /*
696684 * Now generate code to copy over any old columns that were not assigned
697685 * to, and to ensure that dropped columns are set to NULL.
@@ -1402,6 +1390,21 @@ ExecInitExprRec(Expr *node, ExprState *state,
14021390 SubPlan * subplan = (SubPlan * ) node ;
14031391 SubPlanState * sstate ;
14041392
1393+ /*
1394+ * Real execution of a MULTIEXPR SubPlan has already been
1395+ * done. What we have to do here is return a dummy NULL record
1396+ * value in case this targetlist element is assigned
1397+ * someplace.
1398+ */
1399+ if (subplan -> subLinkType == MULTIEXPR_SUBLINK )
1400+ {
1401+ scratch .opcode = EEOP_CONST ;
1402+ scratch .d .constval .value = (Datum ) 0 ;
1403+ scratch .d .constval .isnull = true;
1404+ ExprEvalPushStep (state , & scratch );
1405+ break ;
1406+ }
1407+
14051408 if (!state -> parent )
14061409 elog (ERROR , "SubPlan found with no parent plan" );
14071410
@@ -2542,36 +2545,38 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
25422545}
25432546
25442547/*
2545- * Add expression steps deforming the ExprState 's inner/outer/scan slots
2546- * as much as required by the expression.
2548+ * Add expression steps performing setup that 's needed before any of the
2549+ * main execution of the expression.
25472550 */
25482551static void
2549- ExecInitExprSlots (ExprState * state , Node * node )
2552+ ExecCreateExprSetupSteps (ExprState * state , Node * node )
25502553{
2551- LastAttnumInfo info = {0 , 0 , 0 };
2554+ ExprSetupInfo info = {0 , 0 , 0 , NIL };
25522555
2553- /*
2554- * Figure out which attributes we're going to need.
2555- */
2556- get_last_attnums_walker (node , & info );
2556+ /* Prescan to find out what we need. */
2557+ expr_setup_walker (node , & info );
25572558
2558- ExecPushExprSlots (state , & info );
2559+ /* And generate those steps. */
2560+ ExecPushExprSetupSteps (state , & info );
25592561}
25602562
25612563/*
2562- * Add steps deforming the ExprState's inner/out/scan slots as much as
2563- * indicated by info. This is useful when building an ExprState covering more
2564- * than one expression.
2564+ * Add steps performing expression setup as indicated by "info".
2565+ * This is useful when building an ExprState covering more than one expression.
25652566 */
25662567static void
2567- ExecPushExprSlots (ExprState * state , LastAttnumInfo * info )
2568+ ExecPushExprSetupSteps (ExprState * state , ExprSetupInfo * info )
25682569{
25692570 ExprEvalStep scratch = {0 };
2571+ ListCell * lc ;
25702572
25712573 scratch .resvalue = NULL ;
25722574 scratch .resnull = NULL ;
25732575
2574- /* Emit steps as needed */
2576+ /*
2577+ * Add steps deforming the ExprState's inner/outer/scan slots as much as
2578+ * required by any Vars appearing in the expression.
2579+ */
25752580 if (info -> last_inner > 0 )
25762581 {
25772582 scratch .opcode = EEOP_INNER_FETCHSOME ;
@@ -2602,13 +2607,48 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
26022607 if (ExecComputeSlotInfo (state , & scratch ))
26032608 ExprEvalPushStep (state , & scratch );
26042609 }
2610+
2611+ /*
2612+ * Add steps to execute any MULTIEXPR SubPlans appearing in the
2613+ * expression. We need to evaluate these before any of the Params
2614+ * referencing their outputs are used, but after we've prepared for any
2615+ * Var references they may contain. (There cannot be cross-references
2616+ * between MULTIEXPR SubPlans, so we needn't worry about their order.)
2617+ */
2618+ foreach (lc , info -> multiexpr_subplans )
2619+ {
2620+ SubPlan * subplan = (SubPlan * ) lfirst (lc );
2621+ SubPlanState * sstate ;
2622+
2623+ Assert (subplan -> subLinkType == MULTIEXPR_SUBLINK );
2624+
2625+ /* This should match what ExecInitExprRec does for other SubPlans: */
2626+
2627+ if (!state -> parent )
2628+ elog (ERROR , "SubPlan found with no parent plan" );
2629+
2630+ sstate = ExecInitSubPlan (subplan , state -> parent );
2631+
2632+ /* add SubPlanState nodes to state->parent->subPlan */
2633+ state -> parent -> subPlan = lappend (state -> parent -> subPlan ,
2634+ sstate );
2635+
2636+ scratch .opcode = EEOP_SUBPLAN ;
2637+ scratch .d .subplan .sstate = sstate ;
2638+
2639+ /* The result can be ignored, but we better put it somewhere */
2640+ scratch .resvalue = & state -> resvalue ;
2641+ scratch .resnull = & state -> resnull ;
2642+
2643+ ExprEvalPushStep (state , & scratch );
2644+ }
26052645}
26062646
26072647/*
2608- * get_last_attnums_walker : expression walker for ExecInitExprSlots
2648+ * expr_setup_walker : expression walker for ExecCreateExprSetupSteps
26092649 */
26102650static bool
2611- get_last_attnums_walker (Node * node , LastAttnumInfo * info )
2651+ expr_setup_walker (Node * node , ExprSetupInfo * info )
26122652{
26132653 if (node == NULL )
26142654 return false;
@@ -2636,6 +2676,16 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
26362676 return false;
26372677 }
26382678
2679+ /* Collect all MULTIEXPR SubPlans, too */
2680+ if (IsA (node , SubPlan ))
2681+ {
2682+ SubPlan * subplan = (SubPlan * ) node ;
2683+
2684+ if (subplan -> subLinkType == MULTIEXPR_SUBLINK )
2685+ info -> multiexpr_subplans = lappend (info -> multiexpr_subplans ,
2686+ subplan );
2687+ }
2688+
26392689 /*
26402690 * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
26412691 * because those do not represent expressions to be evaluated within the
@@ -2648,7 +2698,7 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
26482698 return false;
26492699 if (IsA (node , GroupingFunc ))
26502700 return false;
2651- return expression_tree_walker (node , get_last_attnums_walker ,
2701+ return expression_tree_walker (node , expr_setup_walker ,
26522702 (void * ) info );
26532703}
26542704
@@ -3267,7 +3317,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
32673317 PlanState * parent = & aggstate -> ss .ps ;
32683318 ExprEvalStep scratch = {0 };
32693319 bool isCombine = DO_AGGSPLIT_COMBINE (aggstate -> aggsplit );
3270- LastAttnumInfo deform = {0 , 0 , 0 };
3320+ ExprSetupInfo deform = {0 , 0 , 0 , NIL };
32713321
32723322 state -> expr = (Expr * ) aggstate ;
32733323 state -> parent = parent ;
@@ -3283,18 +3333,18 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
32833333 {
32843334 AggStatePerTrans pertrans = & aggstate -> pertrans [transno ];
32853335
3286- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggdirectargs ,
3287- & deform );
3288- get_last_attnums_walker ((Node * ) pertrans -> aggref -> args ,
3289- & deform );
3290- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggorder ,
3291- & deform );
3292- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggdistinct ,
3293- & deform );
3294- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggfilter ,
3295- & deform );
3336+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggdirectargs ,
3337+ & deform );
3338+ expr_setup_walker ((Node * ) pertrans -> aggref -> args ,
3339+ & deform );
3340+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggorder ,
3341+ & deform );
3342+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggdistinct ,
3343+ & deform );
3344+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggfilter ,
3345+ & deform );
32963346 }
3297- ExecPushExprSlots (state , & deform );
3347+ ExecPushExprSetupSteps (state , & deform );
32983348
32993349 /*
33003350 * Emit instructions for each transition value / grouping set combination.
0 commit comments