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.
@@ -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
@@ -2553,36 +2556,38 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
2553
2556
}
2554
2557
2555
2558
/*
2556
- * Add expression steps deforming the ExprState 's inner/outer/scan slots
2557
- * as much as required by the expression.
2559
+ * Add expression steps performing setup that 's needed before any of the
2560
+ * main execution of the expression.
2558
2561
*/
2559
2562
static void
2560
- ExecInitExprSlots (ExprState * state , Node * node )
2563
+ ExecCreateExprSetupSteps (ExprState * state , Node * node )
2561
2564
{
2562
- LastAttnumInfo info = {0 , 0 , 0 };
2565
+ ExprSetupInfo info = {0 , 0 , 0 , NIL };
2563
2566
2564
- /*
2565
- * Figure out which attributes we're going to need.
2566
- */
2567
- get_last_attnums_walker (node , & info );
2567
+ /* Prescan to find out what we need. */
2568
+ expr_setup_walker (node , & info );
2568
2569
2569
- ExecPushExprSlots (state , & info );
2570
+ /* And generate those steps. */
2571
+ ExecPushExprSetupSteps (state , & info );
2570
2572
}
2571
2573
2572
2574
/*
2573
- * Add steps deforming the ExprState's inner/out/scan slots as much as
2574
- * indicated by info. This is useful when building an ExprState covering more
2575
- * than one expression.
2575
+ * Add steps performing expression setup as indicated by "info".
2576
+ * This is useful when building an ExprState covering more than one expression.
2576
2577
*/
2577
2578
static void
2578
- ExecPushExprSlots (ExprState * state , LastAttnumInfo * info )
2579
+ ExecPushExprSetupSteps (ExprState * state , ExprSetupInfo * info )
2579
2580
{
2580
2581
ExprEvalStep scratch = {0 };
2582
+ ListCell * lc ;
2581
2583
2582
2584
scratch .resvalue = NULL ;
2583
2585
scratch .resnull = NULL ;
2584
2586
2585
- /* Emit steps as needed */
2587
+ /*
2588
+ * Add steps deforming the ExprState's inner/outer/scan slots as much as
2589
+ * required by any Vars appearing in the expression.
2590
+ */
2586
2591
if (info -> last_inner > 0 )
2587
2592
{
2588
2593
scratch .opcode = EEOP_INNER_FETCHSOME ;
@@ -2613,13 +2618,48 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
2613
2618
if (ExecComputeSlotInfo (state , & scratch ))
2614
2619
ExprEvalPushStep (state , & scratch );
2615
2620
}
2621
+
2622
+ /*
2623
+ * Add steps to execute any MULTIEXPR SubPlans appearing in the
2624
+ * expression. We need to evaluate these before any of the Params
2625
+ * referencing their outputs are used, but after we've prepared for any
2626
+ * Var references they may contain. (There cannot be cross-references
2627
+ * between MULTIEXPR SubPlans, so we needn't worry about their order.)
2628
+ */
2629
+ foreach (lc , info -> multiexpr_subplans )
2630
+ {
2631
+ SubPlan * subplan = (SubPlan * ) lfirst (lc );
2632
+ SubPlanState * sstate ;
2633
+
2634
+ Assert (subplan -> subLinkType == MULTIEXPR_SUBLINK );
2635
+
2636
+ /* This should match what ExecInitExprRec does for other SubPlans: */
2637
+
2638
+ if (!state -> parent )
2639
+ elog (ERROR , "SubPlan found with no parent plan" );
2640
+
2641
+ sstate = ExecInitSubPlan (subplan , state -> parent );
2642
+
2643
+ /* add SubPlanState nodes to state->parent->subPlan */
2644
+ state -> parent -> subPlan = lappend (state -> parent -> subPlan ,
2645
+ sstate );
2646
+
2647
+ scratch .opcode = EEOP_SUBPLAN ;
2648
+ scratch .d .subplan .sstate = sstate ;
2649
+
2650
+ /* The result can be ignored, but we better put it somewhere */
2651
+ scratch .resvalue = & state -> resvalue ;
2652
+ scratch .resnull = & state -> resnull ;
2653
+
2654
+ ExprEvalPushStep (state , & scratch );
2655
+ }
2616
2656
}
2617
2657
2618
2658
/*
2619
- * get_last_attnums_walker : expression walker for ExecInitExprSlots
2659
+ * expr_setup_walker : expression walker for ExecCreateExprSetupSteps
2620
2660
*/
2621
2661
static bool
2622
- get_last_attnums_walker (Node * node , LastAttnumInfo * info )
2662
+ expr_setup_walker (Node * node , ExprSetupInfo * info )
2623
2663
{
2624
2664
if (node == NULL )
2625
2665
return false;
@@ -2647,6 +2687,16 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2647
2687
return false;
2648
2688
}
2649
2689
2690
+ /* Collect all MULTIEXPR SubPlans, too */
2691
+ if (IsA (node , SubPlan ))
2692
+ {
2693
+ SubPlan * subplan = (SubPlan * ) node ;
2694
+
2695
+ if (subplan -> subLinkType == MULTIEXPR_SUBLINK )
2696
+ info -> multiexpr_subplans = lappend (info -> multiexpr_subplans ,
2697
+ subplan );
2698
+ }
2699
+
2650
2700
/*
2651
2701
* Don't examine the arguments or filters of Aggrefs or WindowFuncs,
2652
2702
* because those do not represent expressions to be evaluated within the
@@ -2659,7 +2709,7 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
2659
2709
return false;
2660
2710
if (IsA (node , GroupingFunc ))
2661
2711
return false;
2662
- return expression_tree_walker (node , get_last_attnums_walker ,
2712
+ return expression_tree_walker (node , expr_setup_walker ,
2663
2713
(void * ) info );
2664
2714
}
2665
2715
@@ -3278,7 +3328,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
3278
3328
PlanState * parent = & aggstate -> ss .ps ;
3279
3329
ExprEvalStep scratch = {0 };
3280
3330
bool isCombine = DO_AGGSPLIT_COMBINE (aggstate -> aggsplit );
3281
- LastAttnumInfo deform = {0 , 0 , 0 };
3331
+ ExprSetupInfo deform = {0 , 0 , 0 , NIL };
3282
3332
3283
3333
state -> expr = (Expr * ) aggstate ;
3284
3334
state -> parent = parent ;
@@ -3294,18 +3344,18 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
3294
3344
{
3295
3345
AggStatePerTrans pertrans = & aggstate -> pertrans [transno ];
3296
3346
3297
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggdirectargs ,
3298
- & deform );
3299
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> args ,
3300
- & deform );
3301
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggorder ,
3302
- & deform );
3303
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggdistinct ,
3304
- & deform );
3305
- get_last_attnums_walker ((Node * ) pertrans -> aggref -> aggfilter ,
3306
- & deform );
3347
+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggdirectargs ,
3348
+ & deform );
3349
+ expr_setup_walker ((Node * ) pertrans -> aggref -> args ,
3350
+ & deform );
3351
+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggorder ,
3352
+ & deform );
3353
+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggdistinct ,
3354
+ & deform );
3355
+ expr_setup_walker ((Node * ) pertrans -> aggref -> aggfilter ,
3356
+ & deform );
3307
3357
}
3308
- ExecPushExprSlots (state , & deform );
3358
+ ExecPushExprSetupSteps (state , & deform );
3309
3359
3310
3360
/*
3311
3361
* Emit instructions for each transition value / grouping set combination.
0 commit comments