Commit 2206b498 authored by Tom Lane's avatar Tom Lane

Simplify ParamListInfo data structure to support only numbered parameters,

not named ones, and replace linear searches of the list with array indexing.
The named-parameter support has been dead code for many years anyway,
and recent profiling suggests that the searching was costing a noticeable
amount of performance for complex queries.
parent 0606860a
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Copyright (c) 2002-2006, PostgreSQL Global Development Group * Copyright (c) 2002-2006, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.49 2006/03/05 15:58:24 momjian Exp $ * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.50 2006/04/22 01:25:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -247,30 +247,30 @@ EvaluateParams(EState *estate, List *params, List *argtypes) ...@@ -247,30 +247,30 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
if (list_length(params) != nargs) if (list_length(params) != nargs)
elog(ERROR, "wrong number of arguments"); elog(ERROR, "wrong number of arguments");
if (nargs == 0)
return NULL;
exprstates = (List *) ExecPrepareExpr((Expr *) params, estate); exprstates = (List *) ExecPrepareExpr((Expr *) params, estate);
paramLI = (ParamListInfo) /* sizeof(ParamListInfoData) includes the first array element */
palloc0((nargs + 1) * sizeof(ParamListInfoData)); paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
(nargs - 1) * sizeof(ParamExternData));
paramLI->numParams = nargs;
forboth(le, exprstates, la, argtypes) forboth(le, exprstates, la, argtypes)
{ {
ExprState *n = lfirst(le); ExprState *n = lfirst(le);
bool isNull; ParamExternData *prm = &paramLI->params[i];
paramLI[i].value = ExecEvalExprSwitchContext(n, prm->ptype = lfirst_oid(la);
prm->value = ExecEvalExprSwitchContext(n,
GetPerTupleExprContext(estate), GetPerTupleExprContext(estate),
&isNull, &prm->isnull,
NULL); NULL);
paramLI[i].kind = PARAM_NUM;
paramLI[i].id = i + 1;
paramLI[i].ptype = lfirst_oid(la);
paramLI[i].isnull = isNull;
i++; i++;
} }
paramLI[i].kind = PARAM_INVALID;
return paramLI; return paramLI;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.189 2006/03/10 01:51:23 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.190 2006/04/22 01:25:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -605,13 +605,12 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext, ...@@ -605,13 +605,12 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone) bool *isNull, ExprDoneCond *isDone)
{ {
Param *expression = (Param *) exprstate->expr; Param *expression = (Param *) exprstate->expr;
int thisParamKind = expression->paramkind; int thisParamId = expression->paramid;
AttrNumber thisParamId = expression->paramid;
if (isDone) if (isDone)
*isDone = ExprSingleResult; *isDone = ExprSingleResult;
if (thisParamKind == PARAM_EXEC) if (expression->paramkind == PARAM_EXEC)
{ {
/* /*
* PARAM_EXEC params (internal executor parameters) are stored in the * PARAM_EXEC params (internal executor parameters) are stored in the
...@@ -633,18 +632,27 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext, ...@@ -633,18 +632,27 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
else else
{ {
/* /*
* All other parameter types must be sought in ecxt_param_list_info. * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
*/ */
ParamListInfo paramInfo; ParamListInfo paramInfo = econtext->ecxt_param_list_info;
paramInfo = lookupParam(econtext->ecxt_param_list_info, Assert(expression->paramkind == PARAM_EXTERN);
thisParamKind, if (paramInfo &&
expression->paramname, thisParamId > 0 && thisParamId <= paramInfo->numParams)
thisParamId, {
false); ParamExternData *prm = &paramInfo->params[thisParamId - 1];
Assert(paramInfo->ptype == expression->paramtype);
*isNull = paramInfo->isnull; if (OidIsValid(prm->ptype))
return paramInfo->value; {
Assert(prm->ptype == expression->paramtype);
*isNull = prm->isnull;
return prm->value;
}
}
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("no value found for parameter %d", thisParamId)));
return (Datum) 0; /* keep compiler quiet */
} }
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.101 2006/03/05 15:58:26 momjian Exp $ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.102 2006/04/22 01:25:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -431,17 +431,19 @@ postquel_sub_params(SQLFunctionCachePtr fcache, ...@@ -431,17 +431,19 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
{ {
int i; int i;
paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData)); /* sizeof(ParamListInfoData) includes the first array element */
paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
(nargs - 1) * sizeof(ParamExternData));
paramLI->numParams = nargs;
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)
{ {
paramLI[i].kind = PARAM_NUM; ParamExternData *prm = &paramLI->params[i];
paramLI[i].id = i + 1;
paramLI[i].ptype = fcache->argtypes[i]; prm->value = fcinfo->arg[i];
paramLI[i].value = fcinfo->arg[i]; prm->isnull = fcinfo->argnull[i];
paramLI[i].isnull = fcinfo->argnull[i]; prm->ptype = fcache->argtypes[i];
} }
paramLI[nargs].kind = PARAM_INVALID;
} }
else else
paramLI = NULL; paramLI = NULL;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.150 2006/04/04 19:35:34 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.151 2006/04/22 01:25:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -885,19 +885,21 @@ SPI_cursor_open(const char *name, void *plan, ...@@ -885,19 +885,21 @@ SPI_cursor_open(const char *name, void *plan,
/* If the plan has parameters, set them up */ /* If the plan has parameters, set them up */
if (spiplan->nargs > 0) if (spiplan->nargs > 0)
{ {
paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) * /* sizeof(ParamListInfoData) includes the first array element */
sizeof(ParamListInfoData)); paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
(spiplan->nargs - 1) * sizeof(ParamExternData));
paramLI->numParams = spiplan->nargs;
for (k = 0; k < spiplan->nargs; k++) for (k = 0; k < spiplan->nargs; k++)
{ {
paramLI[k].kind = PARAM_NUM; ParamExternData *prm = &paramLI->params[k];
paramLI[k].id = k + 1;
paramLI[k].ptype = spiplan->argtypes[k]; prm->ptype = spiplan->argtypes[k];
paramLI[k].isnull = (Nulls && Nulls[k] == 'n'); prm->isnull = (Nulls && Nulls[k] == 'n');
if (paramLI[k].isnull) if (prm->isnull)
{ {
/* nulls just copy */ /* nulls just copy */
paramLI[k].value = Values[k]; prm->value = Values[k];
} }
else else
{ {
...@@ -905,13 +907,11 @@ SPI_cursor_open(const char *name, void *plan, ...@@ -905,13 +907,11 @@ SPI_cursor_open(const char *name, void *plan,
int16 paramTypLen; int16 paramTypLen;
bool paramTypByVal; bool paramTypByVal;
get_typlenbyval(spiplan->argtypes[k], get_typlenbyval(prm->ptype, &paramTypLen, &paramTypByVal);
&paramTypLen, &paramTypByVal); prm->value = datumCopy(Values[k],
paramLI[k].value = datumCopy(Values[k],
paramTypByVal, paramTypLen); paramTypByVal, paramTypLen);
} }
} }
paramLI[k].kind = PARAM_INVALID;
} }
else else
paramLI = NULL; paramLI = NULL;
...@@ -1334,18 +1334,19 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls, ...@@ -1334,18 +1334,19 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
{ {
int k; int k;
paramLI = (ParamListInfo) /* sizeof(ParamListInfoData) includes the first array element */
palloc0((nargs + 1) * sizeof(ParamListInfoData)); paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
(nargs - 1) * sizeof(ParamExternData));
paramLI->numParams = nargs;
for (k = 0; k < nargs; k++) for (k = 0; k < nargs; k++)
{ {
paramLI[k].kind = PARAM_NUM; ParamExternData *prm = &paramLI->params[k];
paramLI[k].id = k + 1;
paramLI[k].ptype = plan->argtypes[k]; prm->value = Values[k];
paramLI[k].isnull = (Nulls && Nulls[k] == 'n'); prm->isnull = (Nulls && Nulls[k] == 'n');
paramLI[k].value = Values[k]; prm->ptype = plan->argtypes[k];
} }
paramLI[k].kind = PARAM_INVALID;
} }
else else
paramLI = NULL; paramLI = NULL;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.333 2006/04/15 17:45:34 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.334 2006/04/22 01:25:58 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -729,7 +729,6 @@ _copyParam(Param *from) ...@@ -729,7 +729,6 @@ _copyParam(Param *from)
COPY_SCALAR_FIELD(paramkind); COPY_SCALAR_FIELD(paramkind);
COPY_SCALAR_FIELD(paramid); COPY_SCALAR_FIELD(paramid);
COPY_STRING_FIELD(paramname);
COPY_SCALAR_FIELD(paramtype); COPY_SCALAR_FIELD(paramtype);
return newnode; return newnode;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.269 2006/04/15 17:45:34 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.270 2006/04/22 01:25:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -147,22 +147,8 @@ static bool ...@@ -147,22 +147,8 @@ static bool
_equalParam(Param *a, Param *b) _equalParam(Param *a, Param *b)
{ {
COMPARE_SCALAR_FIELD(paramkind); COMPARE_SCALAR_FIELD(paramkind);
COMPARE_SCALAR_FIELD(paramtype);
switch (a->paramkind)
{
case PARAM_NAMED:
COMPARE_STRING_FIELD(paramname);
break;
case PARAM_NUM:
case PARAM_EXEC:
case PARAM_SUBLINK:
COMPARE_SCALAR_FIELD(paramid); COMPARE_SCALAR_FIELD(paramid);
break; COMPARE_SCALAR_FIELD(paramtype);
default:
elog(ERROR, "unrecognized paramkind: %d",
a->paramkind);
}
return true; return true;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.272 2006/03/23 00:19:29 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.273 2006/04/22 01:25:59 tgl Exp $
* *
* NOTES * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -624,9 +624,8 @@ _outParam(StringInfo str, Param *node) ...@@ -624,9 +624,8 @@ _outParam(StringInfo str, Param *node)
{ {
WRITE_NODE_TYPE("PARAM"); WRITE_NODE_TYPE("PARAM");
WRITE_INT_FIELD(paramkind); WRITE_ENUM_FIELD(paramkind, ParamKind);
WRITE_INT_FIELD(paramid); WRITE_INT_FIELD(paramid);
WRITE_STRING_FIELD(paramname);
WRITE_OID_FIELD(paramtype); WRITE_OID_FIELD(paramtype);
} }
......
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* params.c * params.c
* Support functions for plan parameter lists. * Support for finding the values associated with Param nodes.
*
* *
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/params.c,v 1.5 2006/03/05 15:58:28 momjian Exp $ * $PostgreSQL: pgsql/src/backend/nodes/params.c,v 1.6 2006/04/22 01:25:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,7 +21,7 @@ ...@@ -20,7 +21,7 @@
/* /*
* Copy a ParamList. * Copy a ParamListInfo structure.
* *
* The result is allocated in CurrentMemoryContext. * The result is allocated in CurrentMemoryContext.
*/ */
...@@ -28,97 +29,34 @@ ParamListInfo ...@@ -28,97 +29,34 @@ ParamListInfo
copyParamList(ParamListInfo from) copyParamList(ParamListInfo from)
{ {
ParamListInfo retval; ParamListInfo retval;
int i, Size size;
size; int i;
if (from == NULL) if (from == NULL || from->numParams <= 0)
return NULL; return NULL;
size = 0; /* sizeof(ParamListInfoData) includes the first array element */
while (from[size].kind != PARAM_INVALID) size = sizeof(ParamListInfoData) +
size++; (from->numParams - 1) * sizeof(ParamExternData);
retval = (ParamListInfo) palloc0((size + 1) * sizeof(ParamListInfoData));
for (i = 0; i < size; i++) retval = (ParamListInfo) palloc(size);
{ memcpy(retval, from, size);
/* copy metadata */
retval[i].kind = from[i].kind;
if (from[i].kind == PARAM_NAMED)
retval[i].name = pstrdup(from[i].name);
retval[i].id = from[i].id;
retval[i].ptype = from[i].ptype;
/* copy value */ /*
retval[i].isnull = from[i].isnull; * Flat-copy is not good enough for pass-by-ref data values, so make
if (from[i].isnull) * a pass over the array to copy those.
{ */
retval[i].value = from[i].value; /* nulls just copy */ for (i = 0; i < retval->numParams; i++)
}
else
{ {
ParamExternData *prm = &retval->params[i];
int16 typLen; int16 typLen;
bool typByVal; bool typByVal;
get_typlenbyval(from[i].ptype, &typLen, &typByVal); if (prm->isnull || !OidIsValid(prm->ptype))
retval[i].value = datumCopy(from[i].value, typByVal, typLen); continue;
} get_typlenbyval(prm->ptype, &typLen, &typByVal);
prm->value = datumCopy(prm->value, typByVal, typLen);
} }
retval[size].kind = PARAM_INVALID;
return retval; return retval;
} }
/*
* Search a ParamList for a given parameter.
*
* On success, returns a pointer to the parameter's entry.
* On failure, returns NULL if noError is true, else ereports the error.
*/
ParamListInfo
lookupParam(ParamListInfo paramList, int thisParamKind,
const char *thisParamName, AttrNumber thisParamId,
bool noError)
{
if (paramList != NULL)
{
while (paramList->kind != PARAM_INVALID)
{
if (thisParamKind == paramList->kind)
{
switch (thisParamKind)
{
case PARAM_NAMED:
if (strcmp(paramList->name, thisParamName) == 0)
return paramList;
break;
case PARAM_NUM:
if (paramList->id == thisParamId)
return paramList;
break;
default:
elog(ERROR, "unrecognized paramkind: %d",
thisParamKind);
}
}
paramList++;
}
}
if (!noError)
{
if (thisParamKind == PARAM_NAMED)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("no value found for parameter \"%s\"",
thisParamName)));
else
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("no value found for parameter %d",
thisParamId)));
}
return NULL;
}
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.187 2006/03/16 00:31:55 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.188 2006/04/22 01:25:59 tgl Exp $
* *
* NOTES * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
...@@ -318,9 +318,8 @@ _readParam(void) ...@@ -318,9 +318,8 @@ _readParam(void)
{ {
READ_LOCALS(Param); READ_LOCALS(Param);
READ_INT_FIELD(paramkind); READ_ENUM_FIELD(paramkind, ParamKind);
READ_INT_FIELD(paramid); READ_INT_FIELD(paramid);
READ_STRING_FIELD(paramname);
READ_OID_FIELD(paramtype); READ_OID_FIELD(paramtype);
READ_DONE(); READ_DONE();
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.104 2006/03/05 15:58:30 momjian Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.105 2006/04/22 01:25:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -163,7 +163,7 @@ replace_outer_var(Var *var) ...@@ -163,7 +163,7 @@ replace_outer_var(Var *var)
retval = makeNode(Param); retval = makeNode(Param);
retval->paramkind = PARAM_EXEC; retval->paramkind = PARAM_EXEC;
retval->paramid = (AttrNumber) i; retval->paramid = i;
retval->paramtype = var->vartype; retval->paramtype = var->vartype;
return retval; return retval;
...@@ -201,7 +201,7 @@ replace_outer_agg(Aggref *agg) ...@@ -201,7 +201,7 @@ replace_outer_agg(Aggref *agg)
retval = makeNode(Param); retval = makeNode(Param);
retval->paramkind = PARAM_EXEC; retval->paramkind = PARAM_EXEC;
retval->paramid = (AttrNumber) i; retval->paramid = i;
retval->paramtype = agg->aggtype; retval->paramtype = agg->aggtype;
return retval; return retval;
...@@ -222,7 +222,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod) ...@@ -222,7 +222,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
retval = makeNode(Param); retval = makeNode(Param);
retval->paramkind = PARAM_EXEC; retval->paramkind = PARAM_EXEC;
retval->paramid = (AttrNumber) list_length(PlannerParamList); retval->paramid = list_length(PlannerParamList);
retval->paramtype = paramtype; retval->paramtype = paramtype;
pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem)); pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
...@@ -1211,7 +1211,7 @@ finalize_primnode(Node *node, finalize_primnode_context *context) ...@@ -1211,7 +1211,7 @@ finalize_primnode(Node *node, finalize_primnode_context *context)
{ {
if (((Param *) node)->paramkind == PARAM_EXEC) if (((Param *) node)->paramkind == PARAM_EXEC)
{ {
int paramid = (int) ((Param *) node)->paramid; int paramid = ((Param *) node)->paramid;
context->paramids = bms_add_member(context->paramids, paramid); context->paramids = bms_add_member(context->paramids, paramid);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.210 2006/03/14 22:48:19 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.211 2006/04/22 01:25:59 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -1500,38 +1500,37 @@ eval_const_expressions_mutator(Node *node, ...@@ -1500,38 +1500,37 @@ eval_const_expressions_mutator(Node *node,
Param *param = (Param *) node; Param *param = (Param *) node;
/* OK to try to substitute value? */ /* OK to try to substitute value? */
if (context->estimate && param->paramkind != PARAM_EXEC && if (context->estimate && param->paramkind == PARAM_EXTERN &&
PlannerBoundParamList != NULL) PlannerBoundParamList != NULL)
{ {
ParamListInfo paramInfo; /* Look to see if we've been given a value for this Param */
if (param->paramid > 0 &&
param->paramid <= PlannerBoundParamList->numParams)
{
ParamExternData *prm = &PlannerBoundParamList->params[param->paramid - 1];
/* Search to see if we've been given a value for this Param */ if (OidIsValid(prm->ptype))
paramInfo = lookupParam(PlannerBoundParamList,
param->paramkind,
param->paramname,
param->paramid,
true);
if (paramInfo)
{ {
/* /*
* Found it, so return a Const representing the param value. * Found it, so return a Const representing the param
* Note that we don't copy pass-by-ref datatypes, so the Const * value. Note that we don't copy pass-by-ref datatypes,
* will only be valid as long as the bound parameter list * so the Const will only be valid as long as the bound
* exists. This is okay for intended uses of * parameter list exists. This is okay for intended uses
* estimate_expression_value(). * of estimate_expression_value().
*/ */
int16 typLen; int16 typLen;
bool typByVal; bool typByVal;
Assert(paramInfo->ptype == param->paramtype); Assert(prm->ptype == param->paramtype);
get_typlenbyval(param->paramtype, &typLen, &typByVal); get_typlenbyval(param->paramtype, &typLen, &typByVal);
return (Node *) makeConst(param->paramtype, return (Node *) makeConst(param->paramtype,
(int) typLen, (int) typLen,
paramInfo->value, prm->value,
paramInfo->isnull, prm->isnull,
typByVal); typByVal);
} }
} }
}
/* Not replaceable, so just copy the Param (no need to recurse) */ /* Not replaceable, so just copy the Param (no need to recurse) */
return (Node *) copyObject(param); return (Node *) copyObject(param);
} }
...@@ -2810,8 +2809,8 @@ substitute_actual_parameters_mutator(Node *node, ...@@ -2810,8 +2809,8 @@ substitute_actual_parameters_mutator(Node *node,
{ {
Param *param = (Param *) node; Param *param = (Param *) node;
if (param->paramkind != PARAM_NUM) if (param->paramkind != PARAM_EXTERN)
elog(ERROR, "unexpected paramkind: %d", param->paramkind); elog(ERROR, "unexpected paramkind: %d", (int) param->paramkind);
if (param->paramid <= 0 || param->paramid > context->nargs) if (param->paramid <= 0 || param->paramid > context->nargs)
elog(ERROR, "invalid paramid: %d", param->paramid); elog(ERROR, "invalid paramid: %d", param->paramid);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.332 2006/03/23 00:19:29 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.333 2006/04/22 01:25:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -3205,7 +3205,7 @@ check_parameter_resolution_walker(Node *node, ...@@ -3205,7 +3205,7 @@ check_parameter_resolution_walker(Node *node,
{ {
Param *param = (Param *) node; Param *param = (Param *) node;
if (param->paramkind == PARAM_NUM) if (param->paramkind == PARAM_EXTERN)
{ {
int paramno = param->paramid; int paramno = param->paramid;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.137 2006/04/05 22:11:55 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_coerce.c,v 2.138 2006/04/22 01:25:59 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -210,7 +210,7 @@ coerce_type(ParseState *pstate, Node *node, ...@@ -210,7 +210,7 @@ coerce_type(ParseState *pstate, Node *node,
return result; return result;
} }
if (inputTypeId == UNKNOWNOID && IsA(node, Param) && if (inputTypeId == UNKNOWNOID && IsA(node, Param) &&
((Param *) node)->paramkind == PARAM_NUM && ((Param *) node)->paramkind == PARAM_EXTERN &&
pstate != NULL && pstate->p_variableparams) pstate != NULL && pstate->p_variableparams)
{ {
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.191 2006/03/14 22:48:21 tgl Exp $ * $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.192 2006/04/22 01:26:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -568,8 +568,8 @@ transformParamRef(ParseState *pstate, ParamRef *pref) ...@@ -568,8 +568,8 @@ transformParamRef(ParseState *pstate, ParamRef *pref)
} }
param = makeNode(Param); param = makeNode(Param);
param->paramkind = PARAM_NUM; param->paramkind = PARAM_EXTERN;
param->paramid = (AttrNumber) paramno; param->paramid = paramno;
param->paramtype = toppstate->p_paramtypes[paramno - 1]; param->paramtype = toppstate->p_paramtypes[paramno - 1];
return (Node *) param; return (Node *) param;
...@@ -1177,7 +1177,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink) ...@@ -1177,7 +1177,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
param = makeNode(Param); param = makeNode(Param);
param->paramkind = PARAM_SUBLINK; param->paramkind = PARAM_SUBLINK;
param->paramid = (AttrNumber) tent->resno; param->paramid = tent->resno;
param->paramtype = exprType((Node *) tent->expr); param->paramtype = exprType((Node *) tent->expr);
right_list = lappend(right_list, param); right_list = lappend(right_list, param);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.484 2006/04/18 00:52:23 momjian Exp $ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.485 2006/04/22 01:26:00 tgl Exp $
* *
* NOTES * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
...@@ -1479,8 +1479,10 @@ exec_bind_message(StringInfo input_message) ...@@ -1479,8 +1479,10 @@ exec_bind_message(StringInfo input_message)
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
params = (ParamListInfo) /* sizeof(ParamListInfoData) includes the first array element */
palloc0((numParams + 1) * sizeof(ParamListInfoData)); params = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
(numParams - 1) * sizeof(ParamExternData));
params->numParams = numParams;
i = 0; i = 0;
foreach(l, pstmt->argtype_list) foreach(l, pstmt->argtype_list)
...@@ -1545,8 +1547,10 @@ exec_bind_message(StringInfo input_message) ...@@ -1545,8 +1547,10 @@ exec_bind_message(StringInfo input_message)
else else
pstring = pg_client_to_server(pbuf.data, plength); pstring = pg_client_to_server(pbuf.data, plength);
params[i].value = OidInputFunctionCall(typinput, pstring, params->params[i].value = OidInputFunctionCall(typinput,
typioparam, -1); pstring,
typioparam,
-1);
/* Free result of encoding conversion, if any */ /* Free result of encoding conversion, if any */
if (pstring && pstring != pbuf.data) if (pstring && pstring != pbuf.data)
pfree(pstring); pfree(pstring);
...@@ -1567,8 +1571,10 @@ exec_bind_message(StringInfo input_message) ...@@ -1567,8 +1571,10 @@ exec_bind_message(StringInfo input_message)
else else
bufptr = &pbuf; bufptr = &pbuf;
params[i].value = OidReceiveFunctionCall(typreceive, bufptr, params->params[i].value = OidReceiveFunctionCall(typreceive,
typioparam, -1); bufptr,
typioparam,
-1);
/* Trouble if it didn't eat the whole buffer */ /* Trouble if it didn't eat the whole buffer */
if (!isNull && pbuf.cursor != pbuf.len) if (!isNull && pbuf.cursor != pbuf.len)
...@@ -1589,16 +1595,12 @@ exec_bind_message(StringInfo input_message) ...@@ -1589,16 +1595,12 @@ exec_bind_message(StringInfo input_message)
if (!isNull) if (!isNull)
pbuf.data[plength] = csave; pbuf.data[plength] = csave;
params[i].kind = PARAM_NUM; params->params[i].isnull = isNull;
params[i].id = i + 1; params->params[i].ptype = ptype;
params[i].ptype = ptype;
params[i].isnull = isNull;
i++; i++;
} }
params[i].kind = PARAM_INVALID;
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
} }
else else
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ruleutils.c - Functions to convert stored expressions/querytrees * ruleutils.c - Functions to convert stored expressions/querytrees
* back to source text * back to source text
* *
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.219 2006/04/08 18:49:52 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.220 2006/04/22 01:26:00 tgl Exp $
**********************************************************************/ **********************************************************************/
#include "postgres.h" #include "postgres.h"
...@@ -3120,24 +3120,7 @@ get_rule_expr(Node *node, deparse_context *context, ...@@ -3120,24 +3120,7 @@ get_rule_expr(Node *node, deparse_context *context,
break; break;
case T_Param: case T_Param:
{ appendStringInfo(buf, "$%d", ((Param *) node)->paramid);
Param *param = (Param *) node;
switch (param->paramkind)
{
case PARAM_NAMED:
appendStringInfo(buf, "$%s", param->paramname);
break;
case PARAM_NUM:
case PARAM_EXEC:
case PARAM_SUBLINK:
appendStringInfo(buf, "$%d", param->paramid);
break;
default:
appendStringInfo(buf, "(param)");
break;
}
}
break; break;
case T_Aggref: case T_Aggref:
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.322 2006/04/05 22:11:55 tgl Exp $ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.323 2006/04/22 01:26:01 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200604051 #define CATALOG_VERSION_NO 200604211
#endif #endif
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* params.h * params.h
* Declarations of stuff needed to handle parameterized plans. * Support for finding the values associated with Param nodes.
* *
* *
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/params.h,v 1.30 2006/03/05 15:58:56 momjian Exp $ * $PostgreSQL: pgsql/src/include/nodes/params.h,v 1.31 2006/04/22 01:26:01 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef PARAMS_H #ifndef PARAMS_H
#define PARAMS_H #define PARAMS_H
#include "access/attnum.h"
/* ----------------
* The following are the possible values for the 'paramkind'
* field of a Param node.
*
* PARAM_NAMED: The parameter has a name, i.e. something
* like `$.salary' or `$.foobar'.
* In this case field `paramname' must be a valid name.
*
* PARAM_NUM: The parameter has only a numeric identifier,
* i.e. something like `$1', `$2' etc.
* The number is contained in the `paramid' field.
*
* PARAM_EXEC: The parameter is an internal executor parameter.
* It has a number contained in the `paramid' field.
*
* PARAM_SUBLINK: The parameter represents an output column of a SubLink
* node's sub-select. The column number is contained in the
* `paramid' field. (This type of Param is converted to
* PARAM_EXEC during planning.)
*
* PARAM_INVALID should never appear in a Param node; it's used to mark
* the end of a ParamListInfo array.
*
* NOTE: As of PostgreSQL 7.3, named parameters aren't actually used and
* so the code that handles PARAM_NAMED cases is dead code. We leave it
* in place since it might be resurrected someday.
* ----------------
*/
#define PARAM_NAMED 11
#define PARAM_NUM 12
#define PARAM_EXEC 15
#define PARAM_SUBLINK 16
#define PARAM_INVALID 100
/* ---------------- /* ----------------
* ParamListInfo * ParamListInfo
* *
* ParamListInfo entries are used to pass parameters into the executor * ParamListInfo arrays are used to pass parameters into the executor
* for parameterized plans. Each entry in the array defines the value * for parameterized plans. Each entry in the array defines the value
* to be substituted for a PARAM_NAMED or PARAM_NUM parameter. * to be substituted for a PARAM_EXTERN parameter. The "paramid"
* of a PARAM_EXTERN Param can range from 1 to numParams.
* *
* kind : the kind of parameter (PARAM_NAMED or PARAM_NUM) * Although parameter numbers are normally consecutive, we allow
* name : the parameter name (valid if kind == PARAM_NAMED) * ptype == InvalidOid to signal an unused array entry.
* id : the parameter id (valid if kind == PARAM_NUM)
* ptype : the type of the parameter value
* isnull : true if the value is null (if so 'value' is undefined)
* value : the value that has to be substituted in the place
* of the parameter.
* *
* ParamListInfo is to be used as an array of ParamListInfoData * Although the data structure is really an array, not a list, we keep
* records. A dummy record with kind == PARAM_INVALID marks the end * the old typedef name to avoid unnecessary code changes.
* of the array.
* ---------------- * ----------------
*/ */
typedef struct ParamExternData
{
Datum value; /* parameter value */
bool isnull; /* is it NULL? */
Oid ptype; /* parameter's datatype, or 0 */
} ParamExternData;
typedef struct ParamListInfoData typedef struct ParamListInfoData
{ {
int kind; int numParams; /* number of ParamExternDatas following */
char *name; ParamExternData params[1]; /* VARIABLE LENGTH ARRAY */
AttrNumber id;
Oid ptype;
bool isnull;
Datum value;
} ParamListInfoData; } ParamListInfoData;
typedef ParamListInfoData *ParamListInfo; typedef ParamListInfoData *ParamListInfo;
...@@ -114,8 +74,5 @@ typedef struct ParamExecData ...@@ -114,8 +74,5 @@ typedef struct ParamExecData
/* Functions found in src/backend/nodes/params.c */ /* Functions found in src/backend/nodes/params.c */
extern ParamListInfo copyParamList(ParamListInfo from); extern ParamListInfo copyParamList(ParamListInfo from);
extern ParamListInfo lookupParam(ParamListInfo paramList, int thisParamKind,
const char *thisParamName, AttrNumber thisParamId,
bool noError);
#endif /* PARAMS_H */ #endif /* PARAMS_H */
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.112 2006/03/05 15:58:57 momjian Exp $ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.113 2006/04/22 01:26:01 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -146,18 +146,15 @@ typedef struct Const ...@@ -146,18 +146,15 @@ typedef struct Const
/* ---------------- /* ----------------
* Param * Param
* paramkind - specifies the kind of parameter. The possible values * paramkind - specifies the kind of parameter. The possible values
* for this field are specified in "params.h", and they are: * for this field are:
* *
* PARAM_NAMED: The parameter has a name, i.e. something * PARAM_EXTERN: The parameter value is supplied from outside the plan.
* like `$.salary' or `$.foobar'. * Such parameters are numbered from 1 to n.
* In this case field `paramname' must be a valid name.
* *
* PARAM_NUM: The parameter has only a numeric identifier, * PARAM_EXEC: The parameter is an internal executor parameter, used
* i.e. something like `$1', `$2' etc. * for passing values into and out of sub-queries.
* The number is contained in the `paramid' field. * For historical reasons, such parameters are numbered from 0.
* * These numbers are independent of PARAM_EXTERN numbers.
* PARAM_EXEC: The parameter is an internal executor parameter.
* It has a number contained in the `paramid' field.
* *
* PARAM_SUBLINK: The parameter represents an output column of a SubLink * PARAM_SUBLINK: The parameter represents an output column of a SubLink
* node's sub-select. The column number is contained in the * node's sub-select. The column number is contained in the
...@@ -165,12 +162,18 @@ typedef struct Const ...@@ -165,12 +162,18 @@ typedef struct Const
* PARAM_EXEC during planning.) * PARAM_EXEC during planning.)
* ---------------- * ----------------
*/ */
typedef enum ParamKind
{
PARAM_EXTERN,
PARAM_EXEC,
PARAM_SUBLINK
} ParamKind;
typedef struct Param typedef struct Param
{ {
Expr xpr; Expr xpr;
int paramkind; /* kind of parameter. See above */ ParamKind paramkind; /* kind of parameter. See above */
AttrNumber paramid; /* numeric ID for parameter ("$1") */ int paramid; /* numeric ID for parameter */
char *paramname; /* name for parameter ("$.foo") */
Oid paramtype; /* PG_TYPE OID of parameter's datatype */ Oid paramtype; /* PG_TYPE OID of parameter's datatype */
} Param; } Param;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.163 2006/04/04 19:35:37 tgl Exp $ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.164 2006/04/22 01:26:01 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -3786,24 +3786,27 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate, ...@@ -3786,24 +3786,27 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
* back for subscript evaluation, and so there can be a need to have more * back for subscript evaluation, and so there can be a need to have more
* than one active param list. * than one active param list.
*/ */
if (expr->nparams > 0)
{
/* sizeof(ParamListInfoData) includes the first array element */
paramLI = (ParamListInfo) paramLI = (ParamListInfo)
MemoryContextAlloc(econtext->ecxt_per_tuple_memory, MemoryContextAlloc(econtext->ecxt_per_tuple_memory,
(expr->nparams + 1) * sizeof(ParamListInfoData)); sizeof(ParamListInfoData) +
(expr->nparams - 1) * sizeof(ParamExternData));
paramLI->numParams = expr->nparams;
/*
* Put the parameter values into the parameter list entries.
*/
for (i = 0; i < expr->nparams; i++) for (i = 0; i < expr->nparams; i++)
{ {
ParamExternData *prm = &paramLI->params[i];
PLpgSQL_datum *datum = estate->datums[expr->params[i]]; PLpgSQL_datum *datum = estate->datums[expr->params[i]];
paramLI[i].kind = PARAM_NUM;
paramLI[i].id = i + 1;
exec_eval_datum(estate, datum, expr->plan_argtypes[i], exec_eval_datum(estate, datum, expr->plan_argtypes[i],
&paramLI[i].ptype, &prm->ptype,
&paramLI[i].value, &paramLI[i].isnull); &prm->value, &prm->isnull);
} }
paramLI[i].kind = PARAM_INVALID; }
else
paramLI = NULL;
/* /*
* Now we can safely make the econtext point to the param list. * Now we can safely make the econtext point to the param list.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment