mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
Track in the plan the types associated with PARAM_EXEC parameters.
Up until now, we only tracked the number of parameters, which was sufficient to allocate an array of Datums of the appropriate size, but not sufficient to, for example, know how to serialize a Datum stored in one of those slots. An upcoming patch wants to do that, so add this tracking to make it possible. Patch by me, reviewed by Tom Lane and Amit Kapila. Discussion: http://postgr.es/m/CA+TgmoYqpxDKn8koHdW8BEKk8FMUL0=e8m2Qe=M+r0UBjr3tuQ@mail.gmail.com
This commit is contained in:
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user