@ -69,6 +69,9 @@ static void ExecInitExprRec(Expr *node, ExprState *state,
static void ExecInitFunc ( ExprEvalStep * scratch , Expr * node , List * args ,
Oid funcid , Oid inputcollid ,
ExprState * state ) ;
static void ExecInitSubPlanExpr ( SubPlan * subplan ,
ExprState * state ,
Datum * resv , bool * resnull ) ;
static void ExecCreateExprSetupSteps ( ExprState * state , Node * node ) ;
static void ExecPushExprSetupSteps ( ExprState * state , ExprSetupInfo * info ) ;
static bool expr_setup_walker ( Node * node , ExprSetupInfo * info ) ;
@ -1406,7 +1409,6 @@ ExecInitExprRec(Expr *node, ExprState *state,
case T_SubPlan :
{
SubPlan * subplan = ( SubPlan * ) node ;
SubPlanState * sstate ;
/*
* Real execution of a MULTIEXPR SubPlan has already been
@ -1423,19 +1425,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
break ;
}
if ( ! state - > parent )
elog ( ERROR , " SubPlan found with no parent plan " ) ;
sstate = ExecInitSubPlan ( subplan , state - > parent ) ;
/* add SubPlanState nodes to state->parent->subPlan */
state - > parent - > subPlan = lappend ( state - > parent - > subPlan ,
sstate ) ;
scratch . opcode = EEOP_SUBPLAN ;
scratch . d . subplan . sstate = sstate ;
ExprEvalPushStep ( state , & scratch ) ;
ExecInitSubPlanExpr ( subplan , state , resv , resnull ) ;
break ;
}
@ -2715,6 +2705,70 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
}
}
/*
* Append the steps necessary for the evaluation of a SubPlan node to
* ExprState - > steps .
*
* subplan - SubPlan expression to evaluate
* state - ExprState to whose - > steps to append the necessary operations
* resv / resnull - where to store the result of the node into
*/
static void
ExecInitSubPlanExpr ( SubPlan * subplan ,
ExprState * state ,
Datum * resv , bool * resnull )
{
ExprEvalStep scratch = { 0 } ;
SubPlanState * sstate ;
ListCell * pvar ;
ListCell * l ;
if ( ! state - > parent )
elog ( ERROR , " SubPlan found with no parent plan " ) ;
/*
* Generate steps to evaluate input arguments for the subplan .
*
* We evaluate the argument expressions into ExprState ' s resvalue / resnull ,
* and then use PARAM_SET to update the parameter . We do that , instead of
* evaluating directly into the param , to avoid depending on the pointer
* value remaining stable / being included in the generated expression . No
* danger of conflicts with other uses of resvalue / resnull as storing and
* using the value always is in subsequent steps .
*
* Any calculation we have to do can be done in the parent econtext , since
* the Param values don ' t need to have per - query lifetime .
*/
Assert ( list_length ( subplan - > parParam ) = = list_length ( subplan - > args ) ) ;
forboth ( l , subplan - > parParam , pvar , subplan - > args )
{
int paramid = lfirst_int ( l ) ;
Expr * arg = ( Expr * ) lfirst ( pvar ) ;
ExecInitExprRec ( arg , state ,
& state - > resvalue , & state - > resnull ) ;
scratch . opcode = EEOP_PARAM_SET ;
scratch . d . param . paramid = paramid ;
/* paramtype's not actually used, but we might as well fill it */
scratch . d . param . paramtype = exprType ( ( Node * ) arg ) ;
ExprEvalPushStep ( state , & scratch ) ;
}
sstate = ExecInitSubPlan ( subplan , state - > parent ) ;
/* add SubPlanState nodes to state->parent->subPlan */
state - > parent - > subPlan = lappend ( state - > parent - > subPlan ,
sstate ) ;
scratch . opcode = EEOP_SUBPLAN ;
scratch . resvalue = resv ;
scratch . resnull = resnull ;
scratch . d . subplan . sstate = sstate ;
ExprEvalPushStep ( state , & scratch ) ;
}
/*
* Add expression steps performing setup that ' s needed before any of the
* main execution of the expression .
@ -2789,29 +2843,12 @@ ExecPushExprSetupSteps(ExprState *state, ExprSetupInfo *info)
foreach ( lc , info - > multiexpr_subplans )
{
SubPlan * subplan = ( SubPlan * ) lfirst ( lc ) ;
SubPlanState * sstate ;
Assert ( subplan - > subLinkType = = MULTIEXPR_SUBLINK ) ;
/* This should match what ExecInitExprRec does for other SubPlans: */
if ( ! state - > parent )
elog ( ERROR , " SubPlan found with no parent plan " ) ;
sstate = ExecInitSubPlan ( subplan , state - > parent ) ;
/* add SubPlanState nodes to state->parent->subPlan */
state - > parent - > subPlan = lappend ( state - > parent - > subPlan ,
sstate ) ;
scratch . opcode = EEOP_SUBPLAN ;
scratch . d . subplan . sstate = sstate ;
/* The result can be ignored, but we better put it somewhere */
scratch . resvalue = & state - > resvalue ;
scratch . resnull = & state - > resnull ;
ExprEvalPushStep ( state , & scratch ) ;
ExecInitSubPlanExpr ( subplan , state ,
& state - > resvalue , & state - > resnull ) ;
}
}