4848#include "utils/typcache.h"
4949
5050
51- typedef struct LastAttnumInfo
51+ typedef struct ExprSetupInfo
5252{
53+ /* Highest attribute numbers fetched from inner/outer/scan tuple slots: */
5354AttrNumber last_inner ;
5455AttrNumber last_outer ;
5556AttrNumber last_scan ;
56- }LastAttnumInfo ;
57+ /* MULTIEXPR SubPlan nodes appearing in the expression: */
58+ List * multiexpr_subplans ;
59+ }ExprSetupInfo ;
5760
5861static void ExecReadyExpr (ExprState * state );
5962static void ExecInitExprRec (Expr * node ,ExprState * state ,
6063Datum * resv ,bool * resnull );
6164static void ExecInitFunc (ExprEvalStep * scratch ,Expr * node ,List * args ,
6265Oid funcid ,Oid inputcollid ,
6366ExprState * state );
64- static void ExecInitExprSlots (ExprState * state ,Node * node );
65- static void ExecPushExprSlots (ExprState * state ,LastAttnumInfo * info );
66- static bool get_last_attnums_walker (Node * node ,LastAttnumInfo * info );
67+ static void ExecCreateExprSetupSteps (ExprState * state ,Node * node );
68+ static void ExecPushExprSetupSteps (ExprState * state ,ExprSetupInfo * info );
69+ static bool expr_setup_walker (Node * node ,ExprSetupInfo * info );
6770static void ExecComputeSlotInfo (ExprState * state ,ExprEvalStep * op );
6871static void ExecInitWholeRowVar (ExprEvalStep * scratch ,Var * variable ,
6972ExprState * state );
@@ -132,8 +135,8 @@ ExecInitExpr(Expr *node, PlanState *parent)
132135state -> parent = parent ;
133136state -> ext_params = NULL ;
134137
135- /* InsertEEOP_*_FETCHSOME steps as needed */
136- ExecInitExprSlots (state , (Node * )node );
138+ /* Insertsetup steps as needed */
139+ ExecCreateExprSetupSteps (state , (Node * )node );
137140
138141/* Compile the expression proper */
139142ExecInitExprRec (node ,state ,& state -> resvalue ,& state -> resnull );
@@ -169,8 +172,8 @@ ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
169172state -> parent = NULL ;
170173state -> ext_params = ext_params ;
171174
172- /* InsertEEOP_*_FETCHSOME steps as needed */
173- ExecInitExprSlots (state , (Node * )node );
175+ /* Insertsetup steps as needed */
176+ ExecCreateExprSetupSteps (state , (Node * )node );
174177
175178/* Compile the expression proper */
176179ExecInitExprRec (node ,state ,& state -> resvalue ,& state -> resnull );
@@ -224,8 +227,8 @@ ExecInitQual(List *qual, PlanState *parent)
224227/* mark expression as to be used with ExecQual() */
225228state -> flags = EEO_FLAG_IS_QUAL ;
226229
227- /* InsertEEOP_*_FETCHSOME steps as needed */
228- ExecInitExprSlots (state , (Node * )qual );
230+ /* Insertsetup steps as needed */
231+ ExecCreateExprSetupSteps (state , (Node * )qual );
229232
230233/*
231234 * ExecQual() needs to return false for an expression returning NULL. That
@@ -394,8 +397,8 @@ ExecBuildProjectionInfoExt(List *targetList,
394397
395398state -> resultslot = slot ;
396399
397- /* InsertEEOP_*_FETCHSOME steps as needed */
398- ExecInitExprSlots (state , (Node * )targetList );
400+ /* Insertsetup steps as needed */
401+ ExecCreateExprSetupSteps (state , (Node * )targetList );
399402
400403/* Now compile each tlist column */
401404foreach (lc ,targetList )
@@ -1117,6 +1120,21 @@ ExecInitExprRec(Expr *node, ExprState *state,
11171120SubPlan * subplan = (SubPlan * )node ;
11181121SubPlanState * sstate ;
11191122
1123+ /*
1124+ * Real execution of a MULTIEXPR SubPlan has already been
1125+ * done. What we have to do here is return a dummy NULL record
1126+ * value in case this targetlist element is assigned
1127+ * someplace.
1128+ */
1129+ if (subplan -> subLinkType == MULTIEXPR_SUBLINK )
1130+ {
1131+ scratch .opcode = EEOP_CONST ;
1132+ scratch .d .constval .value = (Datum )0 ;
1133+ scratch .d .constval .isnull = true;
1134+ ExprEvalPushStep (state ,& scratch );
1135+ break ;
1136+ }
1137+
11201138if (!state -> parent )
11211139elog (ERROR ,"SubPlan found with no parent plan" );
11221140
@@ -2285,36 +2303,38 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
22852303}
22862304
22872305/*
2288- * Add expression stepsdeforming the ExprState 'sinner/outer/scan slots
2289- *as much as required by the expression.
2306+ * Add expression stepsperforming setup that 'sneeded before any of the
2307+ *main execution of the expression.
22902308 */
22912309static void
2292- ExecInitExprSlots (ExprState * state ,Node * node )
2310+ ExecCreateExprSetupSteps (ExprState * state ,Node * node )
22932311{
2294- LastAttnumInfo info = {0 ,0 ,0 };
2312+ ExprSetupInfo info = {0 ,0 ,0 , NIL };
22952313
2296- /*
2297- * Figure out which attributes we're going to need.
2298- */
2299- get_last_attnums_walker (node ,& info );
2314+ /* Prescan to find out what we need. */
2315+ expr_setup_walker (node ,& info );
23002316
2301- ExecPushExprSlots (state ,& info );
2317+ /* And generate those steps. */
2318+ ExecPushExprSetupSteps (state ,& info );
23022319}
23032320
23042321/*
2305- * Add steps deforming the ExprState's inner/out/scan slots as much as
2306- * indicated by info. This is useful when building an ExprState covering more
2307- * than one expression.
2322+ * Add steps performing expression setup as indicated by "info".
2323+ * This is useful when building an ExprState covering more than one expression.
23082324 */
23092325static void
2310- ExecPushExprSlots (ExprState * state ,LastAttnumInfo * info )
2326+ ExecPushExprSetupSteps (ExprState * state ,ExprSetupInfo * info )
23112327{
23122328ExprEvalStep scratch = {0 };
2329+ ListCell * lc ;
23132330
23142331scratch .resvalue = NULL ;
23152332scratch .resnull = NULL ;
23162333
2317- /* Emit steps as needed */
2334+ /*
2335+ * Add steps deforming the ExprState's inner/outer/scan slots as much as
2336+ * required by any Vars appearing in the expression.
2337+ */
23182338if (info -> last_inner > 0 )
23192339{
23202340scratch .opcode = EEOP_INNER_FETCHSOME ;
@@ -2345,13 +2365,48 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
23452365ExecComputeSlotInfo (state ,& scratch );
23462366ExprEvalPushStep (state ,& scratch );
23472367}
2368+
2369+ /*
2370+ * Add steps to execute any MULTIEXPR SubPlans appearing in the
2371+ * expression. We need to evaluate these before any of the Params
2372+ * referencing their outputs are used, but after we've prepared for any
2373+ * Var references they may contain. (There cannot be cross-references
2374+ * between MULTIEXPR SubPlans, so we needn't worry about their order.)
2375+ */
2376+ foreach (lc ,info -> multiexpr_subplans )
2377+ {
2378+ SubPlan * subplan = (SubPlan * )lfirst (lc );
2379+ SubPlanState * sstate ;
2380+
2381+ Assert (subplan -> subLinkType == MULTIEXPR_SUBLINK );
2382+
2383+ /* This should match what ExecInitExprRec does for other SubPlans: */
2384+
2385+ if (!state -> parent )
2386+ elog (ERROR ,"SubPlan found with no parent plan" );
2387+
2388+ sstate = ExecInitSubPlan (subplan ,state -> parent );
2389+
2390+ /* add SubPlanState nodes to state->parent->subPlan */
2391+ state -> parent -> subPlan = lappend (state -> parent -> subPlan ,
2392+ sstate );
2393+
2394+ scratch .opcode = EEOP_SUBPLAN ;
2395+ scratch .d .subplan .sstate = sstate ;
2396+
2397+ /* The result can be ignored, but we better put it somewhere */
2398+ scratch .resvalue = & state -> resvalue ;
2399+ scratch .resnull = & state -> resnull ;
2400+
2401+ ExprEvalPushStep (state ,& scratch );
2402+ }
23482403}
23492404
23502405/*
2351- *get_last_attnums_walker : expression walker forExecInitExprSlots
2406+ *expr_setup_walker : expression walker forExecCreateExprSetupSteps
23522407 */
23532408static bool
2354- get_last_attnums_walker (Node * node ,LastAttnumInfo * info )
2409+ expr_setup_walker (Node * node ,ExprSetupInfo * info )
23552410{
23562411if (node == NULL )
23572412return false;
@@ -2379,6 +2434,16 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
23792434return false;
23802435}
23812436
2437+ /* Collect all MULTIEXPR SubPlans, too */
2438+ if (IsA (node ,SubPlan ))
2439+ {
2440+ SubPlan * subplan = (SubPlan * )node ;
2441+
2442+ if (subplan -> subLinkType == MULTIEXPR_SUBLINK )
2443+ info -> multiexpr_subplans = lappend (info -> multiexpr_subplans ,
2444+ subplan );
2445+ }
2446+
23822447/*
23832448 * Don't examine the arguments or filters of Aggrefs or WindowFuncs,
23842449 * because those do not represent expressions to be evaluated within the
@@ -2391,7 +2456,7 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
23912456return false;
23922457if (IsA (node ,GroupingFunc ))
23932458return false;
2394- return expression_tree_walker (node ,get_last_attnums_walker ,
2459+ return expression_tree_walker (node ,expr_setup_walker ,
23952460 (void * )info );
23962461}
23972462
@@ -2968,7 +3033,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
29683033int transno = 0 ;
29693034int setoff = 0 ;
29703035bool isCombine = DO_AGGSPLIT_COMBINE (aggstate -> aggsplit );
2971- LastAttnumInfo deform = {0 ,0 ,0 };
3036+ ExprSetupInfo deform = {0 ,0 ,0 , NIL };
29723037
29733038state -> expr = (Expr * )aggstate ;
29743039state -> parent = parent ;
@@ -2984,18 +3049,18 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
29843049{
29853050AggStatePerTrans pertrans = & aggstate -> pertrans [transno ];
29863051
2987- get_last_attnums_walker ((Node * )pertrans -> aggref -> aggdirectargs ,
2988- & deform );
2989- get_last_attnums_walker ((Node * )pertrans -> aggref -> args ,
2990- & deform );
2991- get_last_attnums_walker ((Node * )pertrans -> aggref -> aggorder ,
2992- & deform );
2993- get_last_attnums_walker ((Node * )pertrans -> aggref -> aggdistinct ,
2994- & deform );
2995- get_last_attnums_walker ((Node * )pertrans -> aggref -> aggfilter ,
2996- & deform );
3052+ expr_setup_walker ((Node * )pertrans -> aggref -> aggdirectargs ,
3053+ & deform );
3054+ expr_setup_walker ((Node * )pertrans -> aggref -> args ,
3055+ & deform );
3056+ expr_setup_walker ((Node * )pertrans -> aggref -> aggorder ,
3057+ & deform );
3058+ expr_setup_walker ((Node * )pertrans -> aggref -> aggdistinct ,
3059+ & deform );
3060+ expr_setup_walker ((Node * )pertrans -> aggref -> aggfilter ,
3061+ & deform );
29973062}
2998- ExecPushExprSlots (state ,& deform );
3063+ ExecPushExprSetupSteps (state ,& deform );
29993064
30003065/*
30013066 * Emit instructions for each transition value / grouping set combination.