51
51
#include "utils/typcache.h"
52
52
53
53
54
- typedef struct LastAttnumInfo
54
+ typedef struct ExprSetupInfo
55
55
{
56
+ /* Highest attribute numbers fetched from inner/outer/scan tuple slots: */
56
57
AttrNumber last_inner ;
57
58
AttrNumber last_outer ;
58
59
AttrNumber last_scan ;
59
- } LastAttnumInfo ;
60
+ /* MULTIEXPR SubPlan nodes appearing in the expression: */
61
+ List * multiexpr_subplans ;
62
+ } ExprSetupInfo ;
60
63
61
64
static void ExecReadyExpr (ExprState * state );
62
65
static void ExecInitExprRec (Expr * node , ExprState * state ,
63
66
Datum * resv , bool * resnull );
64
67
static void ExecInitFunc (ExprEvalStep * scratch , Expr * node , List * args ,
65
68
Oid funcid , Oid inputcollid ,
66
69
ExprState * state );
67
- static void ExecInitExprSlots (ExprState * state , Node * node );
68
- static void ExecPushExprSlots (ExprState * state , LastAttnumInfo * info );
69
- static bool get_last_attnums_walker (Node * node , LastAttnumInfo * info );
70
+ static void ExecCreateExprSetupSteps (ExprState * state , Node * node );
71
+ static void ExecPushExprSetupSteps (ExprState * state , ExprSetupInfo * info );
72
+ static bool expr_setup_walker (Node * node , ExprSetupInfo * info );
70
73
static bool ExecComputeSlotInfo (ExprState * state , ExprEvalStep * op );
71
74
static void ExecInitWholeRowVar (ExprEvalStep * scratch , Var * variable ,
72
75
ExprState * state );
@@ -135,8 +138,8 @@ ExecInitExpr(Expr *node, PlanState *parent)
135
138
state -> parent = parent ;
136
139
state -> ext_params = NULL ;
137
140
138
- /* Insert EEOP_*_FETCHSOME steps as needed */
139
- ExecInitExprSlots (state , (Node * ) node );
141
+ /* Insert setup steps as needed */
142
+ ExecCreateExprSetupSteps (state , (Node * ) node );
140
143
141
144
/* Compile the expression proper */
142
145
ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
@@ -172,8 +175,8 @@ ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
172
175
state -> parent = NULL ;
173
176
state -> ext_params = ext_params ;
174
177
175
- /* Insert EEOP_*_FETCHSOME steps as needed */
176
- ExecInitExprSlots (state , (Node * ) node );
178
+ /* Insert setup steps as needed */
179
+ ExecCreateExprSetupSteps (state , (Node * ) node );
177
180
178
181
/* Compile the expression proper */
179
182
ExecInitExprRec (node , state , & state -> resvalue , & state -> resnull );
@@ -227,8 +230,8 @@ ExecInitQual(List *qual, PlanState *parent)
227
230
/* mark expression as to be used with ExecQual() */
228
231
state -> flags = EEO_FLAG_IS_QUAL ;
229
232
230
- /* Insert EEOP_*_FETCHSOME steps as needed */
231
- ExecInitExprSlots (state , (Node * ) qual );
233
+ /* Insert setup steps as needed */
234
+ ExecCreateExprSetupSteps (state , (Node * ) qual );
232
235
233
236
/*
234
237
* ExecQual() needs to return false for an expression returning NULL. That
@@ -371,8 +374,8 @@ ExecBuildProjectionInfo(List *targetList,
371
374
372
375
state -> resultslot = slot ;
373
376
374
- /* Insert EEOP_*_FETCHSOME steps as needed */
375
- ExecInitExprSlots (state , (Node * ) targetList );
377
+ /* Insert setup steps as needed */
378
+ ExecCreateExprSetupSteps (state , (Node * ) targetList );
376
379
377
380
/* Now compile each tlist column */
378
381
foreach (lc , targetList )
@@ -523,7 +526,7 @@ ExecBuildUpdateProjection(List *targetList,
523
526
int nAssignableCols ;
524
527
bool sawJunk ;
525
528
Bitmapset * assignedCols ;
526
- LastAttnumInfo deform = {0 , 0 , 0 };
529
+ ExprSetupInfo deform = {0 , 0 , 0 , NIL };
527
530
ExprEvalStep scratch = {0 };
528
531
int outerattnum ;
529
532
ListCell * lc ,
@@ -602,17 +605,18 @@ ExecBuildUpdateProjection(List *targetList,
602
605
* number of columns of the "outer" tuple.
603
606
*/
604
607
if (evalTargetList )
605
- get_last_attnums_walker ((Node * ) targetList , & deform );
608
+ expr_setup_walker ((Node * ) targetList , & deform );
606
609
else
607
610
deform .last_outer = nAssignableCols ;
608
611
609
- ExecPushExprSlots (state , & deform );
612
+ ExecPushExprSetupSteps (state , & deform );
610
613
611
614
/*
612
615
* Now generate code to evaluate the tlist's assignable expressions or
613
616
* fetch them from the outer tuple, incidentally validating that they'll
614
617
* be of the right data type. The checks above ensure that the forboth()
615
- * will iterate over exactly the non-junk columns.
618
+ * will iterate over exactly the non-junk columns. Note that we don't
619
+ * bother evaluating any remaining resjunk columns.
616
620
*/
617
621
outerattnum = 0 ;
618
622
forboth (lc , targetList , lc2 , targetColnos )
@@ -675,22 +679,6 @@ ExecBuildUpdateProjection(List *targetList,
675
679
outerattnum ++ ;
676
680
}
677
681
678
- /*
679
- * If we're evaluating the tlist, must evaluate any resjunk columns too.
680
- * (This matters for things like MULTIEXPR_SUBLINK SubPlans.)
681
- */
682
- if (evalTargetList )
683
- {
684
- for_each_cell (lc , targetList , lc )
685
- {
686
- TargetEntry * tle = lfirst_node (TargetEntry , lc );
687
-
688
- Assert (tle -> resjunk );
689
- ExecInitExprRec (tle -> expr , state ,
690
- & state -> resvalue , & state -> resnull );
691
- }
692
- }
693
-
694
682
/*
695
683
* Now generate code to copy over any old columns that were not assigned
696
684
* to, and to ensure that dropped columns are set to NULL.
@@ -1401,6 +1389,21 @@ ExecInitExprRec(Expr *node, ExprState *state,
1401
1389
SubPlan * subplan = (SubPlan * ) node ;
1402
1390
SubPlanState * sstate ;
1403
1391
1392
+ /*
1393
+ * Real execution of a MULTIEXPR SubPlan has already been
1394
+ * done. What we have to do here is return a dummy NULL record
1395
+ * value in case this targetlist element is assigned
1396
+ * someplace.
1397
+ */
1398
+ if (subplan -> subLinkType == MULTIEXPR_SUBLINK )
1399
+ {
1400
+ scratch .opcode = EEOP_CONST ;
1401
+ scratch .d .constval .value = (Datum ) 0 ;
1402
+ scratch .d .constval .isnull = true;
1403
+ ExprEvalPushStep (state , & scratch );
1404
+ break ;
1405
+ }
1406
+
1404
1407
if (!state -> parent )
1405
1408
elog (ERROR , "SubPlan found with no parent plan" );
1406
1409
@@ -2552,36 +2555,38 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2552
2555
}
2553
2556
2554
2557
/*
2555
- * Add expression steps deforming the ExprState 's inner/outer/scan slots
2556
- * as much as required by the expression.
2558
+ * Add expression steps performing setup that 's needed before any of the
2559
+ * main execution of the expression.
2557
2560
*/
2558
2561
static void
2559
- ExecInitExprSlots (ExprState * state , Node * node )
2562
+ ExecCreateExprSetupSteps (ExprState * state , Node * node )
2560
2563
{
2561
- LastAttnumInfo info = {0 , 0 , 0 };
2564
+ ExprSetupInfo info = {0 , 0 , 0 , NIL };
2562
2565
2563
- /*
2564
- * Figure out which attributes we're going to need.
2565
- */
2566
- get_last_attnums_walker (node , & info );
2566
+ /* Prescan to find out what we need. */
2567
+ expr_setup_walker (node , & info );
2567
2568
2568
- ExecPushExprSlots (state , & info );
2569
+ /* And generate those steps. */
2570
+ ExecPushExprSetupSteps (state , & info );
2569
2571
}
2570
2572
2571
2573
/*
2572
- * Add steps deforming the ExprState's inner/out/scan slots as much as
2573
- * indicated by info. This is useful when building an ExprState covering more
2574
- * than one expression.
2574
+ * Add steps performing expression setup as indicated by "info".
2575
+ * This is useful when building an ExprState covering more than one expression.
2575
2576
*/
2576
2577
static void
2577
- ExecPushExprSlots (ExprState * state , LastAttnumInfo * info )
2578
+ ExecPushExprSetupSteps (ExprState * state , ExprSetupInfo * info )
2578
2579
{
2579
2580
ExprEvalStep scratch = {0 };
2581
+ ListCell * lc ;
2580
2582
2581
2583
scratch .resvalue = NULL ;
2582
2584
scratch .resnull = NULL ;
2583
2585
2584
- /* Emit steps as needed */
2586
+ /*
2587
+ * Add steps deforming the ExprState's inner/outer/scan slots as much as
2588
+ * required by any Vars appearing in the expression.
2589
+ */
2585
2590
if (info -> last_inner > 0 )
2586
2591
{
2587
2592
scratch .opcode = EEOP_INNER_FETCHSOME ;
@@ -2612,13 +2617,48 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
2612
2617
if (ExecComputeSlotInfo (state , & scratch ))
2613
2618
ExprEvalPushStep (state , & scratch );
2614
2619
}
2620
+
2621
+ /*
2622
+ * Add steps to execute any MULTIEXPR SubPlans appearing in the
2623
+ * expression. We need to evaluate these before any of the Params
2624
+ * referencing their outputs are used, but after we've prepared for any
2625
+ * Var references they may contain. (There cannot be cross-references
2626
+ * between MULTIEXPR SubPlans, so we needn't worry about their order.)
2627
+ */
2628
+ foreach (lc , info -> multiexpr_subplans )
2629
+ {
2630
+ SubPlan * subplan = (SubPlan * ) lfirst (lc );
2631
+ SubPlanState * sstate ;
2632
+
2633
+ Assert (subplan -> subLinkType == MULTIEXPR_SUBLINK );
2634
+
2635
+ /* This should match what ExecInitExprRec does for other SubPlans: */
2636
+
2637
+ if (!state -> parent )
2638
+ elog (ERROR , "SubPlan found with no parent plan" );
2639
+
2640
+ sstate = ExecInitSubPlan (subplan , state -> parent );
2641
+
2642
+ /* add SubPlanState nodes to state->parent->subPlan */
2643
+ state -> parent -> subPlan = lappend (state -> parent -> subPlan ,
2644
+ sstate );
2645
+
2646
+ scratch .opcode = EEOP_SUBPLAN ;
2647
+ scratch .d .subplan .sstate = sstate ;
2648
+
2649
+ /* The result can be ignored, but we better put it somewhere */
2650
+ scratch .resvalue = & state -> resvalue ;
2651
+ scratch .resnull = & state -> resnull ;
2652
+
2653
+ ExprEvalPushStep (state , & scratch );
2654
+ }
2615
2655
}
2616
2656
2617
2657
/*
2618
- * get_last_attnums_walker : expression walker for ExecInitExprSlots
2658
+ * expr_setup_walker : expression walker for ExecCreateExprSetupSteps
2619
2659
*/
2620
2660
static bool
2621
- get_last_attnums_walker (Node * node , LastAttnumInfo * info )
2661
+ expr_setup_walker (Node * node , ExprSetupInfo * info )
2622
2662
{
2623
2663
if (node == NULL )
2624
2664
return false;
@@ -2646,6 +2686,16 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2646
2686
return false;
2647
2687
}
2648
2688
2689
+ /* Collect all MULTIEXPR SubPlans, too */
2690
+ if (IsA (node , SubPlan ))
2691
+ {
2692
+ SubPlan * subplan = (SubPlan * ) node ;
2693
+
2694
+ if (subplan -> subLinkType == MULTIEXPR_SUBLINK )
2695
+ info -> multiexpr_subplans = lappend (info -> multiexpr_subplans ,
2696
+ subplan );
2697
+ }
2698
+
2649
2699
/*
2650
2700
* Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2651
2701
* because those do not represent expressions to be evaluated within the
@@ -2658,7 +2708,7 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2658
2708
return false;
2659
2709
if (IsA (node , GroupingFunc ))
2660
2710
return false;
2661
- return expression_tree_walker (node , get_last_attnums_walker ,
2711
+ return expression_tree_walker (node , expr_setup_walker ,
2662
2712
(void * ) info );
2663
2713
}
2664
2714
@@ -3277,7 +3327,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
3277
3327
PlanState * parent = & aggstate -> ss .ps ;
3278
3328
ExprEvalStep scratch = {0 };
3279
3329
bool isCombine = DO_AGGSPLIT_COMBINE (aggstate -> aggsplit );
3280
- LastAttnumInfo deform = {0 , 0 , 0 };
3330
+ ExprSetupInfo deform = {0 , 0 , 0 , NIL };
3281
3331
3282
3332
state -> expr = (Expr * ) aggstate ;
3283
3333
state -> parent = parent ;
@@ -3293,18 +3343,18 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
3293
3343
{
3294
3344
AggStatePerTrans pertrans = & aggstate -> pertrans [transno ];
3295
3345
3296
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggdirectargs ,
3297
- & deform );
3298
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> args ,
3299
- & deform );
3300
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggorder ,
3301
- & deform );
3302
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggdistinct ,
3303
- & deform );
3304
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggfilter ,
3305
- & deform );
3346
+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggdirectargs ,
3347
+ & deform );
3348
+ expr_setup_walker ((Node * ) pertrans -> aggref -> args ,
3349
+ & deform );
3350
+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggorder ,
3351
+ & deform );
3352
+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggdistinct ,
3353
+ & deform );
3354
+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggfilter ,
3355
+ & deform );
3306
3356
}
3307
- ExecPushExprSlots (state , & deform );
3357
+ ExecPushExprSetupSteps (state , & deform );
3308
3358
3309
3359
/*
3310
3360
* Emit instructions for each transition value / grouping set combination.
0 commit comments