diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 493ff82775f..47f21316429 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -195,9 +195,14 @@ standard_ExecutorStart(QueryDesc *queryDesc, int eflags) */ estate->es_param_list_info = queryDesc->params; - if (queryDesc->plannedstmt->nParamExec > 0) + if (queryDesc->plannedstmt->paramExecTypes != NIL) + { + int nParamExec; + + nParamExec = list_length(queryDesc->plannedstmt->paramExecTypes); estate->es_param_exec_vals = (ParamExecData *) - palloc0(queryDesc->plannedstmt->nParamExec * sizeof(ParamExecData)); + palloc0(nParamExec * sizeof(ParamExecData)); + } estate->es_sourceText = queryDesc->sourceText; @@ -3032,9 +3037,11 @@ EvalPlanQualBegin(EPQState *epqstate, EState *parentestate) MemSet(estate->es_epqScanDone, 0, rtsize * sizeof(bool)); /* Recopy current values of parent parameters */ - if (parentestate->es_plannedstmt->nParamExec > 0) + if (parentestate->es_plannedstmt->paramExecTypes != NIL) { - int i = parentestate->es_plannedstmt->nParamExec; + int i; + + i = list_length(parentestate->es_plannedstmt->paramExecTypes); while (--i >= 0) { @@ -3122,10 +3129,11 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree) * already set from other parts of the parent's plan tree. */ estate->es_param_list_info = parentestate->es_param_list_info; - if (parentestate->es_plannedstmt->nParamExec > 0) + if (parentestate->es_plannedstmt->paramExecTypes != NIL) { - int i = parentestate->es_plannedstmt->nParamExec; + int i; + i = list_length(parentestate->es_plannedstmt->paramExecTypes); estate->es_param_exec_vals = (ParamExecData *) palloc0(i * sizeof(ParamExecData)); while (--i >= 0) diff --git a/src/backend/executor/execParallel.c b/src/backend/executor/execParallel.c index 1b477baecb8..fd7e7cbf3d3 100644 --- a/src/backend/executor/execParallel.c +++ b/src/backend/executor/execParallel.c @@ -195,7 +195,7 @@ ExecSerializePlan(Plan *plan, EState *estate) pstmt->rowMarks = NIL; pstmt->relationOids = NIL; pstmt->invalItems = NIL; /* workers can't replan anyway... */ - pstmt->nParamExec = estate->es_plannedstmt->nParamExec; + pstmt->paramExecTypes = estate->es_plannedstmt->paramExecTypes; pstmt->utilityStmt = NULL; pstmt->stmt_location = -1; pstmt->stmt_len = -1; diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index cadd253ef17..76e75459b46 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -97,7 +97,7 @@ _copyPlannedStmt(const PlannedStmt *from) COPY_NODE_FIELD(rowMarks); COPY_NODE_FIELD(relationOids); COPY_NODE_FIELD(invalItems); - COPY_SCALAR_FIELD(nParamExec); + COPY_NODE_FIELD(paramExecTypes); COPY_NODE_FIELD(utilityStmt); COPY_LOCATION_FIELD(stmt_location); COPY_LOCATION_FIELD(stmt_len); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 291d1eeb46f..dc35df9e4fe 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -282,7 +282,7 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node) WRITE_NODE_FIELD(rowMarks); WRITE_NODE_FIELD(relationOids); WRITE_NODE_FIELD(invalItems); - WRITE_INT_FIELD(nParamExec); + WRITE_NODE_FIELD(paramExecTypes); WRITE_NODE_FIELD(utilityStmt); WRITE_LOCATION_FIELD(stmt_location); WRITE_LOCATION_FIELD(stmt_len); @@ -2181,7 +2181,7 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node) WRITE_NODE_FIELD(rootResultRelations); WRITE_NODE_FIELD(relationOids); WRITE_NODE_FIELD(invalItems); - WRITE_INT_FIELD(nParamExec); + WRITE_NODE_FIELD(paramExecTypes); WRITE_UINT_FIELD(lastPHId); WRITE_UINT_FIELD(lastRowMarkId); WRITE_INT_FIELD(lastPlanNodeId); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 42c595dc039..593658dd8a8 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1480,7 +1480,7 @@ _readPlannedStmt(void) READ_NODE_FIELD(rowMarks); READ_NODE_FIELD(relationOids); READ_NODE_FIELD(invalItems); - READ_INT_FIELD(nParamExec); + READ_NODE_FIELD(paramExecTypes); READ_NODE_FIELD(utilityStmt); READ_LOCATION_FIELD(stmt_location); READ_LOCATION_FIELD(stmt_len); diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 9b7a8fd82c4..607f7cd2518 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -243,7 +243,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) glob->rootResultRelations = NIL; glob->relationOids = NIL; glob->invalItems = NIL; - glob->nParamExec = 0; + glob->paramExecTypes = NIL; glob->lastPHId = 0; glob->lastRowMarkId = 0; glob->lastPlanNodeId = 0; @@ -415,7 +415,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) * set_plan_references' tree traversal, but for now it has to be separate * because we need to visit subplans before not after main plan. */ - if (glob->nParamExec > 0) + if (glob->paramExecTypes != NIL) { Assert(list_length(glob->subplans) == list_length(glob->subroots)); forboth(lp, glob->subplans, lr, glob->subroots) @@ -466,7 +466,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) result->rowMarks = glob->finalrowmarks; result->relationOids = glob->relationOids; result->invalItems = glob->invalItems; - result->nParamExec = glob->nParamExec; + result->paramExecTypes = glob->paramExecTypes; /* utilityStmt should be null, but we might as well copy it */ result->utilityStmt = parse->utilityStmt; result->stmt_location = parse->stmt_location; diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 8f75fa98edc..2e3abeea3d0 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -131,7 +131,9 @@ assign_param_for_var(PlannerInfo *root, Var *var) pitem = makeNode(PlannerParamItem); pitem->item = (Node *) var; - pitem->paramId = root->glob->nParamExec++; + pitem->paramId = list_length(root->glob->paramExecTypes); + root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes, + var->vartype); root->plan_params = lappend(root->plan_params, pitem); @@ -234,7 +236,9 @@ assign_param_for_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv) pitem = makeNode(PlannerParamItem); pitem->item = (Node *) phv; - pitem->paramId = root->glob->nParamExec++; + pitem->paramId = list_length(root->glob->paramExecTypes); + root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes, + exprType((Node *) phv->phexpr)); root->plan_params = lappend(root->plan_params, pitem); @@ -323,7 +327,9 @@ replace_outer_agg(PlannerInfo *root, Aggref *agg) pitem = makeNode(PlannerParamItem); pitem->item = (Node *) agg; - pitem->paramId = root->glob->nParamExec++; + pitem->paramId = list_length(root->glob->paramExecTypes); + root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes, + agg->aggtype); root->plan_params = lappend(root->plan_params, pitem); @@ -348,6 +354,7 @@ replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp) Param *retval; PlannerParamItem *pitem; Index levelsup; + Oid ptype; Assert(grp->agglevelsup > 0 && grp->agglevelsup < root->query_level); @@ -362,17 +369,20 @@ replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp) grp = copyObject(grp); IncrementVarSublevelsUp((Node *) grp, -((int) grp->agglevelsup), 0); Assert(grp->agglevelsup == 0); + ptype = exprType((Node *) grp); pitem = makeNode(PlannerParamItem); pitem->item = (Node *) grp; - pitem->paramId = root->glob->nParamExec++; + pitem->paramId = list_length(root->glob->paramExecTypes); + root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes, + ptype); root->plan_params = lappend(root->plan_params, pitem); retval = makeNode(Param); retval->paramkind = PARAM_EXEC; retval->paramid = pitem->paramId; - retval->paramtype = exprType((Node *) grp); + retval->paramtype = ptype; retval->paramtypmod = -1; retval->paramcollid = InvalidOid; retval->location = grp->location; @@ -385,7 +395,8 @@ replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp) * * This is used to create Params representing subplan outputs. * We don't need to build a PlannerParamItem for such a Param, but we do - * need to record the PARAM_EXEC slot number as being allocated. + * need to make sure we record the type in paramExecTypes (otherwise, + * there won't be a slot allocated for it). */ static Param * generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod, @@ -395,7 +406,9 @@ generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod, retval = makeNode(Param); retval->paramkind = PARAM_EXEC; - retval->paramid = root->glob->nParamExec++; + retval->paramid = list_length(root->glob->paramExecTypes); + root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes, + paramtype); retval->paramtype = paramtype; retval->paramtypmod = paramtypmod; retval->paramcollid = paramcollation; @@ -415,7 +428,11 @@ generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod, int SS_assign_special_param(PlannerInfo *root) { - return root->glob->nParamExec++; + int paramId = list_length(root->glob->paramExecTypes); + + root->glob->paramExecTypes = lappend_oid(root->glob->paramExecTypes, + InvalidOid); + return paramId; } /* @@ -2098,7 +2115,7 @@ SS_identify_outer_params(PlannerInfo *root) * If no parameters have been assigned anywhere in the tree, we certainly * don't need to do anything here. */ - if (root->glob->nParamExec == 0) + if (root->glob->paramExecTypes == NIL) return; /* diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 30cdd3da4c5..66e098f488a 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -1095,7 +1095,7 @@ is_parallel_safe(PlannerInfo *root, Node *node) * in this expression. But otherwise we don't need to look. */ if (root->glob->maxParallelHazard == PROPARALLEL_SAFE && - root->glob->nParamExec == 0) + root->glob->paramExecTypes == NIL) return true; /* Else use max_parallel_hazard's search logic, but stop on RESTRICTED */ context.max_hazard = PROPARALLEL_SAFE; diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index dd74efa9a41..a127682b0e7 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -89,7 +89,7 @@ typedef struct PlannedStmt List *invalItems; /* other dependencies, as PlanInvalItems */ - int nParamExec; /* number of PARAM_EXEC Params used */ + List *paramExecTypes; /* type OIDs for PARAM_EXEC Params */ Node *utilityStmt; /* non-null if this is utility stmt */ diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 05fc9a3f485..9e68e65cc63 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -114,7 +114,7 @@ typedef struct PlannerGlobal List *invalItems; /* other dependencies, as PlanInvalItems */ - int nParamExec; /* number of PARAM_EXEC Params used */ + List *paramExecTypes; /* type OIDs for PARAM_EXEC Params */ Index lastPHId; /* highest PlaceHolderVar ID assigned */ @@ -2219,8 +2219,8 @@ typedef struct MinMaxAggInfo * from subplans (values that are setParam items for those subplans). These * IDs need not be tracked via PlannerParamItems, since we do not need any * duplicate-elimination nor later processing of the represented expressions. - * Instead, we just record the assignment of the slot number by incrementing - * root->glob->nParamExec. + * Instead, we just record the assignment of the slot number by appending to + * root->glob->paramExecTypes. */ typedef struct PlannerParamItem {