52
52
#include "utils/typcache.h"
53
53
54
54
55
- typedef struct LastAttnumInfo
55
+ typedef struct ExprSetupInfo
56
56
{
57
+ /* Highest attribute numbers fetched from inner/outer/scan tuple slots: */
57
58
AttrNumber last_inner ;
58
59
AttrNumber last_outer ;
59
60
AttrNumber last_scan ;
60
- } LastAttnumInfo ;
61
+ /* MULTIEXPR SubPlan nodes appearing in the expression: */
62
+ List * multiexpr_subplans ;
63
+ } ExprSetupInfo ;
61
64
62
65
static void ExecReadyExpr (ExprState * state );
63
66
static void ExecInitExprRec (Expr * node , ExprState * state ,
64
67
Datum * resv , bool * resnull );
65
68
static void ExecInitFunc (ExprEvalStep * scratch , Expr * node , List * args ,
66
69
Oid funcid , Oid inputcollid ,
67
70
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 );
71
74
static bool ExecComputeSlotInfo (ExprState * state , ExprEvalStep * op );
72
75
static void ExecInitWholeRowVar (ExprEvalStep * scratch , Var * variable ,
73
76
ExprState * state );
@@ -136,8 +139,8 @@ ExecInitExpr(Expr *node, PlanState *parent)
136
139
state -> parent = parent ;
137
140
state -> ext_params = NULL ;
138
141
139
- /* Insert EEOP_*_FETCHSOME steps as needed */
140
- ExecInitExprSlots (state , (Node * ) node );
142
+ /* Insert setup steps as needed */
143
+ ExecCreateExprSetupSteps (state , (Node * ) node );
141
144
142
145
/* Compile the expression proper */
143
146
ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
@@ -173,8 +176,8 @@ ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
173
176
state -> parent = NULL ;
174
177
state -> ext_params = ext_params ;
175
178
176
- /* Insert EEOP_*_FETCHSOME steps as needed */
177
- ExecInitExprSlots (state , (Node * ) node );
179
+ /* Insert setup steps as needed */
180
+ ExecCreateExprSetupSteps (state , (Node * ) node );
178
181
179
182
/* Compile the expression proper */
180
183
ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
@@ -228,8 +231,8 @@ ExecInitQual(List *qual, PlanState *parent)
228
231
/* mark expression as to be used with ExecQual() */
229
232
state -> flags = EEO_FLAG_IS_QUAL ;
230
233
231
- /* Insert EEOP_*_FETCHSOME steps as needed */
232
- ExecInitExprSlots (state , (Node * ) qual );
234
+ /* Insert setup steps as needed */
235
+ ExecCreateExprSetupSteps (state , (Node * ) qual );
233
236
234
237
/*
235
238
* ExecQual() needs to return false for an expression returning NULL. That
@@ -372,8 +375,8 @@ ExecBuildProjectionInfo(List *targetList,
372
375
373
376
state -> resultslot = slot ;
374
377
375
- /* Insert EEOP_*_FETCHSOME steps as needed */
376
- ExecInitExprSlots (state , (Node * ) targetList );
378
+ /* Insert setup steps as needed */
379
+ ExecCreateExprSetupSteps (state , (Node * ) targetList );
377
380
378
381
/* Now compile each tlist column */
379
382
foreach (lc , targetList )
@@ -524,7 +527,7 @@ ExecBuildUpdateProjection(List *targetList,
524
527
int nAssignableCols ;
525
528
bool sawJunk ;
526
529
Bitmapset * assignedCols ;
527
- LastAttnumInfo deform = {0 , 0 , 0 };
530
+ ExprSetupInfo deform = {0 , 0 , 0 , NIL };
528
531
ExprEvalStep scratch = {0 };
529
532
int outerattnum ;
530
533
ListCell * lc ,
@@ -603,17 +606,18 @@ ExecBuildUpdateProjection(List *targetList,
603
606
* number of columns of the "outer" tuple.
604
607
*/
605
608
if (evalTargetList )
606
- get_last_attnums_walker ((Node * ) targetList , & deform );
609
+ expr_setup_walker ((Node * ) targetList , & deform );
607
610
else
608
611
deform .last_outer = nAssignableCols ;
609
612
610
- ExecPushExprSlots (state , & deform );
613
+ ExecPushExprSetupSteps (state , & deform );
611
614
612
615
/*
613
616
* Now generate code to evaluate the tlist's assignable expressions or
614
617
* fetch them from the outer tuple, incidentally validating that they'll
615
618
* 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.
617
621
*/
618
622
outerattnum = 0 ;
619
623
forboth (lc , targetList , lc2 , targetColnos )
@@ -676,22 +680,6 @@ ExecBuildUpdateProjection(List *targetList,
676
680
outerattnum ++ ;
677
681
}
678
682
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
-
695
683
/*
696
684
* Now generate code to copy over any old columns that were not assigned
697
685
* to, and to ensure that dropped columns are set to NULL.
@@ -1402,6 +1390,21 @@ ExecInitExprRec(Expr *node, ExprState *state,
1402
1390
SubPlan * subplan = (SubPlan * ) node ;
1403
1391
SubPlanState * sstate ;
1404
1392
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
+
1405
1408
if (!state -> parent )
1406
1409
elog (ERROR , "SubPlan found with no parent plan" );
1407
1410
@@ -2542,36 +2545,38 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2542
2545
}
2543
2546
2544
2547
/*
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.
2547
2550
*/
2548
2551
static void
2549
- ExecInitExprSlots (ExprState * state , Node * node )
2552
+ ExecCreateExprSetupSteps (ExprState * state , Node * node )
2550
2553
{
2551
- LastAttnumInfo info = {0 , 0 , 0 };
2554
+ ExprSetupInfo info = {0 , 0 , 0 , NIL };
2552
2555
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 );
2557
2558
2558
- ExecPushExprSlots (state , & info );
2559
+ /* And generate those steps. */
2560
+ ExecPushExprSetupSteps (state , & info );
2559
2561
}
2560
2562
2561
2563
/*
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.
2565
2566
*/
2566
2567
static void
2567
- ExecPushExprSlots (ExprState * state , LastAttnumInfo * info )
2568
+ ExecPushExprSetupSteps (ExprState * state , ExprSetupInfo * info )
2568
2569
{
2569
2570
ExprEvalStep scratch = {0 };
2571
+ ListCell * lc ;
2570
2572
2571
2573
scratch .resvalue = NULL ;
2572
2574
scratch .resnull = NULL ;
2573
2575
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
+ */
2575
2580
if (info -> last_inner > 0 )
2576
2581
{
2577
2582
scratch .opcode = EEOP_INNER_FETCHSOME ;
@@ -2602,13 +2607,48 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
2602
2607
if (ExecComputeSlotInfo (state , & scratch ))
2603
2608
ExprEvalPushStep (state , & scratch );
2604
2609
}
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
+ }
2605
2645
}
2606
2646
2607
2647
/*
2608
- * get_last_attnums_walker : expression walker for ExecInitExprSlots
2648
+ * expr_setup_walker : expression walker for ExecCreateExprSetupSteps
2609
2649
*/
2610
2650
static bool
2611
- get_last_attnums_walker (Node * node , LastAttnumInfo * info )
2651
+ expr_setup_walker (Node * node , ExprSetupInfo * info )
2612
2652
{
2613
2653
if (node == NULL )
2614
2654
return false;
@@ -2636,6 +2676,16 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2636
2676
return false;
2637
2677
}
2638
2678
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
+
2639
2689
/*
2640
2690
* Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2641
2691
* because those do not represent expressions to be evaluated within the
@@ -2648,7 +2698,7 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2648
2698
return false;
2649
2699
if (IsA (node , GroupingFunc ))
2650
2700
return false;
2651
- return expression_tree_walker (node , get_last_attnums_walker ,
2701
+ return expression_tree_walker (node , expr_setup_walker ,
2652
2702
(void * ) info );
2653
2703
}
2654
2704
@@ -3267,7 +3317,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
3267
3317
PlanState * parent = & aggstate -> ss .ps ;
3268
3318
ExprEvalStep scratch = {0 };
3269
3319
bool isCombine = DO_AGGSPLIT_COMBINE (aggstate -> aggsplit );
3270
- LastAttnumInfo deform = {0 , 0 , 0 };
3320
+ ExprSetupInfo deform = {0 , 0 , 0 , NIL };
3271
3321
3272
3322
state -> expr = (Expr * ) aggstate ;
3273
3323
state -> parent = parent ;
@@ -3283,18 +3333,18 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
3283
3333
{
3284
3334
AggStatePerTrans pertrans = & aggstate -> pertrans [transno ];
3285
3335
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 );
3296
3346
}
3297
- ExecPushExprSlots (state , & deform );
3347
+ ExecPushExprSetupSteps (state , & deform );
3298
3348
3299
3349
/*
3300
3350
* Emit instructions for each transition value / grouping set combination.
0 commit comments