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 @@
* 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 = &paramLI->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;
paramInfo = lookupParam(econtext->ecxt_param_list_info,
thisParamKind,
expression->paramname,
thisParamId,
false);
Assert(paramInfo->ptype == expression->paramtype);
*isNull = paramInfo->isnull;
return paramInfo->value;
ParamListInfo paramInfo = econtext->ecxt_param_list_info;
Assert(expression->paramkind == PARAM_EXTERN);
if (paramInfo &&
thisParamId > 0 && thisParamId <= paramInfo->numParams)
{
ParamExternData *prm = &paramInfo->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 = &paramLI->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 = &paramLI->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],
&paramTypLen, &paramTypByVal);
paramLI[k].value = datumCopy(Values[k],
paramTypByVal, paramTypLen);
get_typlenbyval(prm->ptype, &paramTypLen, &paramTypByVal);
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 = &paramLI->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);
}
......
/*-------------------------------------------------------------------------
*
* 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;
/* 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);
}
ParamExternData *prm = &retval->params[i];
int16 typLen;
bool typByVal;
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;
Assert(paramInfo->ptype == param->paramtype);
get_typlenbyval(param->paramtype, &typLen, &typByVal);
return (Node *) makeConst(param->paramtype,
(int) typLen,
paramInfo->value,
paramInfo->isnull,
typByVal);
ParamExternData *prm = &PlannerBoundParamList->params[param->paramid - 1];
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
/*-------------------------------------------------------------------------
*
* 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;
for (i = 0; i < expr->nparams; i++)
{
ParamExternData *prm = &paramLI->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],
&paramLI[i].ptype,
&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.
......
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