mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08: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:
parent
0606860a20
commit
2206b498d8
@ -10,7 +10,7 @@
|
||||
* Copyright (c) 2002-2006, PostgreSQL Global Development Group
|
||||
*
|
||||
* 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)
|
||||
elog(ERROR, "wrong number of arguments");
|
||||
|
||||
if (nargs == 0)
|
||||
return NULL;
|
||||
|
||||
exprstates = (List *) ExecPrepareExpr((Expr *) params, estate);
|
||||
|
||||
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;
|
||||
|
||||
forboth(le, exprstates, la, argtypes)
|
||||
{
|
||||
ExprState *n = lfirst(le);
|
||||
bool isNull;
|
||||
ParamExternData *prm = ¶mLI->params[i];
|
||||
|
||||
paramLI[i].value = ExecEvalExprSwitchContext(n,
|
||||
GetPerTupleExprContext(estate),
|
||||
&isNull,
|
||||
NULL);
|
||||
paramLI[i].kind = PARAM_NUM;
|
||||
paramLI[i].id = i + 1;
|
||||
paramLI[i].ptype = lfirst_oid(la);
|
||||
paramLI[i].isnull = isNull;
|
||||
prm->ptype = lfirst_oid(la);
|
||||
prm->value = ExecEvalExprSwitchContext(n,
|
||||
GetPerTupleExprContext(estate),
|
||||
&prm->isnull,
|
||||
NULL);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
paramLI[i].kind = PARAM_INVALID;
|
||||
|
||||
return paramLI;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
Param *expression = (Param *) exprstate->expr;
|
||||
int thisParamKind = expression->paramkind;
|
||||
AttrNumber thisParamId = expression->paramid;
|
||||
int thisParamId = expression->paramid;
|
||||
|
||||
if (isDone)
|
||||
*isDone = ExprSingleResult;
|
||||
|
||||
if (thisParamKind == PARAM_EXEC)
|
||||
if (expression->paramkind == PARAM_EXEC)
|
||||
{
|
||||
/*
|
||||
* PARAM_EXEC params (internal executor parameters) are stored in the
|
||||
@ -633,18 +632,27 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
|
||||
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,
|
||||
thisParamKind,
|
||||
expression->paramname,
|
||||
thisParamId,
|
||||
false);
|
||||
Assert(paramInfo->ptype == expression->paramtype);
|
||||
*isNull = paramInfo->isnull;
|
||||
return paramInfo->value;
|
||||
Assert(expression->paramkind == PARAM_EXTERN);
|
||||
if (paramInfo &&
|
||||
thisParamId > 0 && thisParamId <= paramInfo->numParams)
|
||||
{
|
||||
ParamExternData *prm = ¶mInfo->params[thisParamId - 1];
|
||||
|
||||
if (OidIsValid(prm->ptype))
|
||||
{
|
||||
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 @@
|
||||
*
|
||||
*
|
||||
* 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;
|
||||
|
||||
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++)
|
||||
{
|
||||
paramLI[i].kind = PARAM_NUM;
|
||||
paramLI[i].id = i + 1;
|
||||
paramLI[i].ptype = fcache->argtypes[i];
|
||||
paramLI[i].value = fcinfo->arg[i];
|
||||
paramLI[i].isnull = fcinfo->argnull[i];
|
||||
ParamExternData *prm = ¶mLI->params[i];
|
||||
|
||||
prm->value = fcinfo->arg[i];
|
||||
prm->isnull = fcinfo->argnull[i];
|
||||
prm->ptype = fcache->argtypes[i];
|
||||
}
|
||||
paramLI[nargs].kind = PARAM_INVALID;
|
||||
}
|
||||
else
|
||||
paramLI = NULL;
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 (spiplan->nargs > 0)
|
||||
{
|
||||
paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) *
|
||||
sizeof(ParamListInfoData));
|
||||
/* sizeof(ParamListInfoData) includes the first array element */
|
||||
paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
|
||||
(spiplan->nargs - 1) * sizeof(ParamExternData));
|
||||
paramLI->numParams = spiplan->nargs;
|
||||
|
||||
for (k = 0; k < spiplan->nargs; k++)
|
||||
{
|
||||
paramLI[k].kind = PARAM_NUM;
|
||||
paramLI[k].id = k + 1;
|
||||
paramLI[k].ptype = spiplan->argtypes[k];
|
||||
paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
|
||||
if (paramLI[k].isnull)
|
||||
ParamExternData *prm = ¶mLI->params[k];
|
||||
|
||||
prm->ptype = spiplan->argtypes[k];
|
||||
prm->isnull = (Nulls && Nulls[k] == 'n');
|
||||
if (prm->isnull)
|
||||
{
|
||||
/* nulls just copy */
|
||||
paramLI[k].value = Values[k];
|
||||
prm->value = Values[k];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -905,13 +907,11 @@ SPI_cursor_open(const char *name, void *plan,
|
||||
int16 paramTypLen;
|
||||
bool paramTypByVal;
|
||||
|
||||
get_typlenbyval(spiplan->argtypes[k],
|
||||
¶mTypLen, ¶mTypByVal);
|
||||
paramLI[k].value = datumCopy(Values[k],
|
||||
paramTypByVal, paramTypLen);
|
||||
get_typlenbyval(prm->ptype, ¶mTypLen, ¶mTypByVal);
|
||||
prm->value = datumCopy(Values[k],
|
||||
paramTypByVal, paramTypLen);
|
||||
}
|
||||
}
|
||||
paramLI[k].kind = PARAM_INVALID;
|
||||
}
|
||||
else
|
||||
paramLI = NULL;
|
||||
@ -1334,18 +1334,19 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
|
||||
{
|
||||
int k;
|
||||
|
||||
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 (k = 0; k < nargs; k++)
|
||||
{
|
||||
paramLI[k].kind = PARAM_NUM;
|
||||
paramLI[k].id = k + 1;
|
||||
paramLI[k].ptype = plan->argtypes[k];
|
||||
paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
|
||||
paramLI[k].value = Values[k];
|
||||
ParamExternData *prm = ¶mLI->params[k];
|
||||
|
||||
prm->value = Values[k];
|
||||
prm->isnull = (Nulls && Nulls[k] == 'n');
|
||||
prm->ptype = plan->argtypes[k];
|
||||
}
|
||||
paramLI[k].kind = PARAM_INVALID;
|
||||
}
|
||||
else
|
||||
paramLI = NULL;
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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(paramid);
|
||||
COPY_STRING_FIELD(paramname);
|
||||
COPY_SCALAR_FIELD(paramtype);
|
||||
|
||||
return newnode;
|
||||
|
@ -18,7 +18,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
COMPARE_SCALAR_FIELD(paramkind);
|
||||
COMPARE_SCALAR_FIELD(paramid);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* 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_INT_FIELD(paramkind);
|
||||
WRITE_ENUM_FIELD(paramkind, ParamKind);
|
||||
WRITE_INT_FIELD(paramid);
|
||||
WRITE_STRING_FIELD(paramname);
|
||||
WRITE_OID_FIELD(paramtype);
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* 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) 1994, Regents of the University of California
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
@ -28,97 +29,34 @@ ParamListInfo
|
||||
copyParamList(ParamListInfo from)
|
||||
{
|
||||
ParamListInfo retval;
|
||||
int i,
|
||||
size;
|
||||
Size size;
|
||||
int i;
|
||||
|
||||
if (from == NULL)
|
||||
if (from == NULL || from->numParams <= 0)
|
||||
return NULL;
|
||||
|
||||
size = 0;
|
||||
while (from[size].kind != PARAM_INVALID)
|
||||
size++;
|
||||
/* sizeof(ParamListInfoData) includes the first array element */
|
||||
size = sizeof(ParamListInfoData) +
|
||||
(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 */
|
||||
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;
|
||||
ParamExternData *prm = &retval->params[i];
|
||||
int16 typLen;
|
||||
bool typByVal;
|
||||
|
||||
/* copy value */
|
||||
retval[i].isnull = from[i].isnull;
|
||||
if (from[i].isnull)
|
||||
{
|
||||
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);
|
||||
}
|
||||
if (prm->isnull || !OidIsValid(prm->ptype))
|
||||
continue;
|
||||
get_typlenbyval(prm->ptype, &typLen, &typByVal);
|
||||
prm->value = datumCopy(prm->value, typByVal, typLen);
|
||||
}
|
||||
|
||||
retval[size].kind = PARAM_INVALID;
|
||||
|
||||
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 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* Path and Plan nodes do not have any readfuncs support, because we
|
||||
@ -318,9 +318,8 @@ _readParam(void)
|
||||
{
|
||||
READ_LOCALS(Param);
|
||||
|
||||
READ_INT_FIELD(paramkind);
|
||||
READ_ENUM_FIELD(paramkind, ParamKind);
|
||||
READ_INT_FIELD(paramid);
|
||||
READ_STRING_FIELD(paramname);
|
||||
READ_OID_FIELD(paramtype);
|
||||
|
||||
READ_DONE();
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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->paramkind = PARAM_EXEC;
|
||||
retval->paramid = (AttrNumber) i;
|
||||
retval->paramid = i;
|
||||
retval->paramtype = var->vartype;
|
||||
|
||||
return retval;
|
||||
@ -201,7 +201,7 @@ replace_outer_agg(Aggref *agg)
|
||||
|
||||
retval = makeNode(Param);
|
||||
retval->paramkind = PARAM_EXEC;
|
||||
retval->paramid = (AttrNumber) i;
|
||||
retval->paramid = i;
|
||||
retval->paramtype = agg->aggtype;
|
||||
|
||||
return retval;
|
||||
@ -222,7 +222,7 @@ generate_new_param(Oid paramtype, int32 paramtypmod)
|
||||
|
||||
retval = makeNode(Param);
|
||||
retval->paramkind = PARAM_EXEC;
|
||||
retval->paramid = (AttrNumber) list_length(PlannerParamList);
|
||||
retval->paramid = list_length(PlannerParamList);
|
||||
retval->paramtype = paramtype;
|
||||
|
||||
pitem = (PlannerParamItem *) palloc(sizeof(PlannerParamItem));
|
||||
@ -1211,7 +1211,7 @@ finalize_primnode(Node *node, finalize_primnode_context *context)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -1500,36 +1500,35 @@ eval_const_expressions_mutator(Node *node,
|
||||
Param *param = (Param *) node;
|
||||
|
||||
/* OK to try to substitute value? */
|
||||
if (context->estimate && param->paramkind != PARAM_EXEC &&
|
||||
if (context->estimate && param->paramkind == PARAM_EXTERN &&
|
||||
PlannerBoundParamList != NULL)
|
||||
{
|
||||
ParamListInfo paramInfo;
|
||||
|
||||
/* Search to see if we've been given a value for this Param */
|
||||
paramInfo = lookupParam(PlannerBoundParamList,
|
||||
param->paramkind,
|
||||
param->paramname,
|
||||
param->paramid,
|
||||
true);
|
||||
if (paramInfo)
|
||||
/* Look to see if we've been given a value for this Param */
|
||||
if (param->paramid > 0 &&
|
||||
param->paramid <= PlannerBoundParamList->numParams)
|
||||
{
|
||||
/*
|
||||
* 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;
|
||||
ParamExternData *prm = &PlannerBoundParamList->params[param->paramid - 1];
|
||||
|
||||
Assert(paramInfo->ptype == param->paramtype);
|
||||
get_typlenbyval(param->paramtype, &typLen, &typByVal);
|
||||
return (Node *) makeConst(param->paramtype,
|
||||
(int) typLen,
|
||||
paramInfo->value,
|
||||
paramInfo->isnull,
|
||||
typByVal);
|
||||
if (OidIsValid(prm->ptype))
|
||||
{
|
||||
/*
|
||||
* 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(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) */
|
||||
@ -2810,8 +2809,8 @@ substitute_actual_parameters_mutator(Node *node,
|
||||
{
|
||||
Param *param = (Param *) node;
|
||||
|
||||
if (param->paramkind != PARAM_NUM)
|
||||
elog(ERROR, "unexpected paramkind: %d", param->paramkind);
|
||||
if (param->paramkind != PARAM_EXTERN)
|
||||
elog(ERROR, "unexpected paramkind: %d", (int) param->paramkind);
|
||||
if (param->paramid <= 0 || param->paramid > context->nargs)
|
||||
elog(ERROR, "invalid paramid: %d", param->paramid);
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||
* 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;
|
||||
|
||||
if (param->paramkind == PARAM_NUM)
|
||||
if (param->paramkind == PARAM_EXTERN)
|
||||
{
|
||||
int paramno = param->paramid;
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
if (inputTypeId == UNKNOWNOID && IsA(node, Param) &&
|
||||
((Param *) node)->paramkind == PARAM_NUM &&
|
||||
((Param *) node)->paramkind == PARAM_EXTERN &&
|
||||
pstate != NULL && pstate->p_variableparams)
|
||||
{
|
||||
/*
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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->paramkind = PARAM_NUM;
|
||||
param->paramid = (AttrNumber) paramno;
|
||||
param->paramkind = PARAM_EXTERN;
|
||||
param->paramid = paramno;
|
||||
param->paramtype = toppstate->p_paramtypes[paramno - 1];
|
||||
|
||||
return (Node *) param;
|
||||
@ -1177,7 +1177,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
|
||||
param = makeNode(Param);
|
||||
param->paramkind = PARAM_SUBLINK;
|
||||
param->paramid = (AttrNumber) tent->resno;
|
||||
param->paramid = tent->resno;
|
||||
param->paramtype = exprType((Node *) tent->expr);
|
||||
|
||||
right_list = lappend(right_list, param);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* this is the "main" module of the postgres backend and
|
||||
@ -1479,8 +1479,10 @@ exec_bind_message(StringInfo input_message)
|
||||
|
||||
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
|
||||
|
||||
params = (ParamListInfo)
|
||||
palloc0((numParams + 1) * sizeof(ParamListInfoData));
|
||||
/* sizeof(ParamListInfoData) includes the first array element */
|
||||
params = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
|
||||
(numParams - 1) * sizeof(ParamExternData));
|
||||
params->numParams = numParams;
|
||||
|
||||
i = 0;
|
||||
foreach(l, pstmt->argtype_list)
|
||||
@ -1545,8 +1547,10 @@ exec_bind_message(StringInfo input_message)
|
||||
else
|
||||
pstring = pg_client_to_server(pbuf.data, plength);
|
||||
|
||||
params[i].value = OidInputFunctionCall(typinput, pstring,
|
||||
typioparam, -1);
|
||||
params->params[i].value = OidInputFunctionCall(typinput,
|
||||
pstring,
|
||||
typioparam,
|
||||
-1);
|
||||
/* Free result of encoding conversion, if any */
|
||||
if (pstring && pstring != pbuf.data)
|
||||
pfree(pstring);
|
||||
@ -1567,8 +1571,10 @@ exec_bind_message(StringInfo input_message)
|
||||
else
|
||||
bufptr = &pbuf;
|
||||
|
||||
params[i].value = OidReceiveFunctionCall(typreceive, bufptr,
|
||||
typioparam, -1);
|
||||
params->params[i].value = OidReceiveFunctionCall(typreceive,
|
||||
bufptr,
|
||||
typioparam,
|
||||
-1);
|
||||
|
||||
/* Trouble if it didn't eat the whole buffer */
|
||||
if (!isNull && pbuf.cursor != pbuf.len)
|
||||
@ -1589,16 +1595,12 @@ exec_bind_message(StringInfo input_message)
|
||||
if (!isNull)
|
||||
pbuf.data[plength] = csave;
|
||||
|
||||
params[i].kind = PARAM_NUM;
|
||||
params[i].id = i + 1;
|
||||
params[i].ptype = ptype;
|
||||
params[i].isnull = isNull;
|
||||
params->params[i].isnull = isNull;
|
||||
params->params[i].ptype = ptype;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
params[i].kind = PARAM_INVALID;
|
||||
|
||||
MemoryContextSwitchTo(oldContext);
|
||||
}
|
||||
else
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ruleutils.c - Functions to convert stored expressions/querytrees
|
||||
* 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"
|
||||
@ -3120,24 +3120,7 @@ get_rule_expr(Node *node, deparse_context *context,
|
||||
break;
|
||||
|
||||
case T_Param:
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
appendStringInfo(buf, "$%d", ((Param *) node)->paramid);
|
||||
break;
|
||||
|
||||
case T_Aggref:
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||
* 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 */
|
||||
#define CATALOG_VERSION_NO 200604051
|
||||
#define CATALOG_VERSION_NO 200604211
|
||||
|
||||
#endif
|
||||
|
@ -1,87 +1,47 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* 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) 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
|
||||
#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 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
|
||||
* 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)
|
||||
* name : the parameter name (valid if kind == PARAM_NAMED)
|
||||
* 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.
|
||||
* Although parameter numbers are normally consecutive, we allow
|
||||
* ptype == InvalidOid to signal an unused array entry.
|
||||
*
|
||||
* ParamListInfo is to be used as an array of ParamListInfoData
|
||||
* records. A dummy record with kind == PARAM_INVALID marks the end
|
||||
* of the array.
|
||||
* Although the data structure is really an array, not a list, we keep
|
||||
* the old typedef name to avoid unnecessary code changes.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
typedef struct ParamExternData
|
||||
{
|
||||
Datum value; /* parameter value */
|
||||
bool isnull; /* is it NULL? */
|
||||
Oid ptype; /* parameter's datatype, or 0 */
|
||||
} ParamExternData;
|
||||
|
||||
typedef struct ParamListInfoData
|
||||
{
|
||||
int kind;
|
||||
char *name;
|
||||
AttrNumber id;
|
||||
Oid ptype;
|
||||
bool isnull;
|
||||
Datum value;
|
||||
int numParams; /* number of ParamExternDatas following */
|
||||
ParamExternData params[1]; /* VARIABLE LENGTH ARRAY */
|
||||
} ParamListInfoData;
|
||||
|
||||
typedef ParamListInfoData *ParamListInfo;
|
||||
@ -114,8 +74,5 @@ typedef struct ParamExecData
|
||||
|
||||
/* Functions found in src/backend/nodes/params.c */
|
||||
extern ParamListInfo copyParamList(ParamListInfo from);
|
||||
extern ParamListInfo lookupParam(ParamListInfo paramList, int thisParamKind,
|
||||
const char *thisParamName, AttrNumber thisParamId,
|
||||
bool noError);
|
||||
|
||||
#endif /* PARAMS_H */
|
||||
|
@ -10,7 +10,7 @@
|
||||
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
|
||||
* 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
|
||||
* 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
|
||||
* like `$.salary' or `$.foobar'.
|
||||
* In this case field `paramname' must be a valid name.
|
||||
* PARAM_EXTERN: The parameter value is supplied from outside the plan.
|
||||
* Such parameters are numbered from 1 to n.
|
||||
*
|
||||
* 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_EXEC: The parameter is an internal executor parameter, used
|
||||
* for passing values into and out of sub-queries.
|
||||
* For historical reasons, such parameters are numbered from 0.
|
||||
* These numbers are independent of PARAM_EXTERN numbers.
|
||||
*
|
||||
* PARAM_SUBLINK: The parameter represents an output column of a SubLink
|
||||
* node's sub-select. The column number is contained in the
|
||||
@ -165,12 +162,18 @@ typedef struct Const
|
||||
* PARAM_EXEC during planning.)
|
||||
* ----------------
|
||||
*/
|
||||
typedef enum ParamKind
|
||||
{
|
||||
PARAM_EXTERN,
|
||||
PARAM_EXEC,
|
||||
PARAM_SUBLINK
|
||||
} ParamKind;
|
||||
|
||||
typedef struct Param
|
||||
{
|
||||
Expr xpr;
|
||||
int paramkind; /* kind of parameter. See above */
|
||||
AttrNumber paramid; /* numeric ID for parameter ("$1") */
|
||||
char *paramname; /* name for parameter ("$.foo") */
|
||||
ParamKind paramkind; /* kind of parameter. See above */
|
||||
int paramid; /* numeric ID for parameter */
|
||||
Oid paramtype; /* PG_TYPE OID of parameter's datatype */
|
||||
} Param;
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* than one active param list.
|
||||
*/
|
||||
paramLI = (ParamListInfo)
|
||||
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++)
|
||||
if (expr->nparams > 0)
|
||||
{
|
||||
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;
|
||||
paramLI[i].id = i + 1;
|
||||
exec_eval_datum(estate, datum, expr->plan_argtypes[i],
|
||||
¶mLI[i].ptype,
|
||||
¶mLI[i].value, ¶mLI[i].isnull);
|
||||
for (i = 0; i < expr->nparams; i++)
|
||||
{
|
||||
ParamExternData *prm = ¶mLI->params[i];
|
||||
PLpgSQL_datum *datum = estate->datums[expr->params[i]];
|
||||
|
||||
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.
|
||||
|
Loading…
Reference in New Issue
Block a user