1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

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.
This commit is contained in:
Tom Lane
2006-04-22 01:26:01 +00:00
parent 0606860a20
commit 2206b498d8
20 changed files with 214 additions and 335 deletions

View File

@ -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)
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);
GetPerTupleExprContext(estate), prm->value = ExecEvalExprSwitchContext(n,
&isNull, GetPerTupleExprContext(estate),
NULL); &prm->isnull,
paramLI[i].kind = PARAM_NUM; NULL);
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;
} }

View File

@ -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,
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,
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 */
} }
} }

View File

@ -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,
{ {
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;

View File

@ -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,
/* 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,
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,
{ {
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;

View File

@ -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)
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;

View File

@ -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,23 +147,9 @@ static bool
_equalParam(Param *a, Param *b) _equalParam(Param *a, Param *b)
{ {
COMPARE_SCALAR_FIELD(paramkind); COMPARE_SCALAR_FIELD(paramkind);
COMPARE_SCALAR_FIELD(paramid);
COMPARE_SCALAR_FIELD(paramtype); 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);
break;
default:
elog(ERROR, "unrecognized paramkind: %d",
a->paramkind);
}
return true; return true;
} }

View File

@ -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)
{ {
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);
} }

View File

@ -1,13 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* 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 @@
/* /*
* Copy a ParamList. * Copy a ParamListInfo structure.
* *
* The result is allocated in CurrentMemoryContext. * The result is allocated in CurrentMemoryContext.
*/ */
@ -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)); retval = (ParamListInfo) palloc(size);
memcpy(retval, from, size);
for (i = 0; i < size; i++) /*
* Flat-copy is not good enough for pass-by-ref data values, so make
* a pass over the array to copy those.
*/
for (i = 0; i < retval->numParams; i++)
{ {
/* copy metadata */ ParamExternData *prm = &retval->params[i];
retval[i].kind = from[i].kind; int16 typLen;
if (from[i].kind == PARAM_NAMED) bool typByVal;
retval[i].name = pstrdup(from[i].name);
retval[i].id = from[i].id;
retval[i].ptype = from[i].ptype;
/* copy value */ if (prm->isnull || !OidIsValid(prm->ptype))
retval[i].isnull = from[i].isnull; continue;
if (from[i].isnull) get_typlenbyval(prm->ptype, &typLen, &typByVal);
{ prm->value = datumCopy(prm->value, typByVal, typLen);
retval[i].value = from[i].value; /* nulls just copy */
}
else
{
int16 typLen;
bool typByVal;
get_typlenbyval(from[i].ptype, &typLen, &typByVal);
retval[i].value = datumCopy(from[i].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;
}

View File

@ -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)
{ {
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();

View File

@ -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)
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)
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)
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)
{ {
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);
} }

View File

@ -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,36 +1500,35 @@ 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 &&
/* Search to see if we've been given a value for this Param */ param->paramid <= PlannerBoundParamList->numParams)
paramInfo = lookupParam(PlannerBoundParamList,
param->paramkind,
param->paramname,
param->paramid,
true);
if (paramInfo)
{ {
/* ParamExternData *prm = &PlannerBoundParamList->params[param->paramid - 1];
* Found it, so return a Const representing the param value.
* Note that we don't copy pass-by-ref datatypes, so the Const
* will only be valid as long as the bound parameter list
* exists. This is okay for intended uses of
* estimate_expression_value().
*/
int16 typLen;
bool typByVal;
Assert(paramInfo->ptype == param->paramtype); if (OidIsValid(prm->ptype))
get_typlenbyval(param->paramtype, &typLen, &typByVal); {
return (Node *) makeConst(param->paramtype, /*
(int) typLen, * Found it, so return a Const representing the param
paramInfo->value, * value. Note that we don't copy pass-by-ref datatypes,
paramInfo->isnull, * so the Const will only be valid as long as the bound
typByVal); * parameter list exists. This is okay for intended uses
* of estimate_expression_value().
*/
int16 typLen;
bool typByVal;
Assert(prm->ptype == param->paramtype);
get_typlenbyval(param->paramtype, &typLen, &typByVal);
return (Node *) makeConst(param->paramtype,
(int) typLen,
prm->value,
prm->isnull,
typByVal);
}
} }
} }
/* Not replaceable, so just copy the Param (no need to recurse) */ /* Not replaceable, so just copy the Param (no need to recurse) */
@ -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);

View File

@ -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,
{ {
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;

View File

@ -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,
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)
{ {
/* /*

View File

@ -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)
} }
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)
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);

View File

@ -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)
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)
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)
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)
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

View File

@ -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,
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:

View File

@ -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 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200604051 #define CATALOG_VERSION_NO 200604211
#endif #endif

View File

@ -1,87 +1,47 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* 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
/* 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 */

View File

@ -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
/* ---------------- /* ----------------
* 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
* 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;

View File

@ -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,
* 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.
*/ */
paramLI = (ParamListInfo) if (expr->nparams > 0)
MemoryContextAlloc(econtext->ecxt_per_tuple_memory,
(expr->nparams + 1) * sizeof(ParamListInfoData));
/*
* Put the parameter values into the parameter list entries.
*/
for (i = 0; i < expr->nparams; i++)
{ {
PLpgSQL_datum *datum = estate->datums[expr->params[i]]; /* sizeof(ParamListInfoData) includes the first array element */
paramLI = (ParamListInfo)
MemoryContextAlloc(econtext->ecxt_per_tuple_memory,
sizeof(ParamListInfoData) +
(expr->nparams - 1) * sizeof(ParamExternData));
paramLI->numParams = expr->nparams;
paramLI[i].kind = PARAM_NUM; for (i = 0; i < expr->nparams; i++)
paramLI[i].id = i + 1; {
exec_eval_datum(estate, datum, expr->plan_argtypes[i], ParamExternData *prm = &paramLI->params[i];
&paramLI[i].ptype, PLpgSQL_datum *datum = estate->datums[expr->params[i]];
&paramLI[i].value, &paramLI[i].isnull);
exec_eval_datum(estate, datum, expr->plan_argtypes[i],
&prm->ptype,
&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.