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.
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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
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 = ¶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 */
}
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* 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
{
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;
{
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;
* 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 $
*
*-------------------------------------------------------------------------
*/
COPY_SCALAR_FIELD(paramkind);
COPY_SCALAR_FIELD(paramid);
- COPY_STRING_FIELD(paramname);
COPY_SCALAR_FIELD(paramtype);
return newnode;
* 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 $
*
*-------------------------------------------------------------------------
*/
_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;
}
*
*
* 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*
{
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 $
*
*-------------------------------------------------------------------------
*/
/*
- * Copy a ParamList.
+ * Copy a ParamListInfo structure.
*
* The result is allocated in CurrentMemoryContext.
*/
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;
-}
*
*
* 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
{
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();
* 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 $
*
*-------------------------------------------------------------------------
*/
retval = makeNode(Param);
retval->paramkind = PARAM_EXEC;
- retval->paramid = (AttrNumber) i;
+ retval->paramid = i;
retval->paramtype = var->vartype;
return retval;
retval = makeNode(Param);
retval->paramkind = PARAM_EXEC;
- retval->paramid = (AttrNumber) i;
+ retval->paramid = i;
retval->paramtype = agg->aggtype;
return retval;
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));
{
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);
}
*
*
* 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
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) */
{
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
{
Param *param = (Param *) node;
- if (param->paramkind == PARAM_NUM)
+ if (param->paramkind == PARAM_EXTERN)
{
int paramno = param->paramid;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
return result;
}
if (inputTypeId == UNKNOWNOID && IsA(node, Param) &&
- ((Param *) node)->paramkind == PARAM_NUM &&
+ ((Param *) node)->paramkind == PARAM_EXTERN &&
pstate != NULL && pstate->p_variableparams)
{
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
}
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;
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);
*
*
* 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
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)
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);
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)
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
* 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"
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:
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
/* 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;
/* 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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
/* ----------------
* 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
* 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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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 = ¶mLI->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],
- ¶mLI[i].ptype,
- ¶mLI[i].value, ¶mLI[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.