Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit f622c54

Browse files
committed
Allow DECLARE CURSOR to take parameters from the portal in which it is
executed. Previously, the DECLARE would succeed but subsequent FETCHes would fail since the parameter values supplied to DECLARE were not propagated to the portal created for the cursor. In support of this, add type Oids to ParamListInfo entries, which seems like a good idea anyway since code that extracts a value can double-check that it got the type of value it was expecting. Oliver Jowett, with minor editorialization by Tom Lane.
1 parent 410b1df commit f622c54

File tree

18 files changed

+263
-115
lines changed

18 files changed

+263
-115
lines changed

src/backend/commands/portalcmds.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
*
1616
* IDENTIFICATION
17-
* $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.30 2004/07/31 00:45:31 tgl Exp $
17+
* $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.31 2004/08/02 01:30:40 tgl Exp $
1818
*
1919
*-------------------------------------------------------------------------
2020
*/
@@ -36,7 +36,7 @@
3636
* Execute SQL DECLARE CURSOR command.
3737
*/
3838
void
39-
PerformCursorOpen(DeclareCursorStmt *stmt)
39+
PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params)
4040
{
4141
List *rewritten;
4242
Query *query;
@@ -104,6 +104,17 @@ PerformCursorOpen(DeclareCursorStmt *stmt)
104104
list_make1(plan),
105105
PortalGetHeapMemory(portal));
106106

107+
/*
108+
* Also copy the outer portal's parameter list into the inner portal's
109+
* memory context. We want to pass down the parameter values in case
110+
* we had a command like
111+
* DECLARE c CURSOR FOR SELECT ... WHERE foo = $1
112+
* This will have been parsed using the outer parameter set and the
113+
* parameter value needs to be preserved for use when the cursor is
114+
* executed.
115+
*/
116+
params = copyParamList(params);
117+
107118
MemoryContextSwitchTo(oldContext);
108119

109120
/*
@@ -123,9 +134,9 @@ PerformCursorOpen(DeclareCursorStmt *stmt)
123134
}
124135

125136
/*
126-
* Start execution --- never any params for a cursor.
137+
* Start execution, inserting parameters if any.
127138
*/
128-
PortalStart(portal, NULL);
139+
PortalStart(portal, params);
129140

130141
Assert(portal->strategy == PORTAL_ONE_SELECT);
131142

src/backend/commands/prepare.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Copyright (c) 2002-2003, PostgreSQL Global Development Group
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.28 2004/06/11 01:08:38 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.29 2004/08/02 01:30:40 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -200,7 +200,7 @@ ExecuteQuery(ExecuteStmt *stmt, DestReceiver *dest, char *completionTag)
200200

201201
/*
202202
* Evaluates a list of parameters, using the given executor state. It
203-
* requires a list of the parameter values themselves, and a list of
203+
* requires a list of the parameter expressions themselves, and a list of
204204
* their types. It returns a filled-in ParamListInfo -- this can later
205205
* be passed to CreateQueryDesc(), which allows the executor to make use
206206
* of the parameters during query execution.
@@ -211,7 +211,7 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
211211
int nargs = list_length(argtypes);
212212
ParamListInfo paramLI;
213213
List *exprstates;
214-
ListCell *l;
214+
ListCell *le, *la;
215215
int i = 0;
216216

217217
/* Parser should have caught this error, but check for safety */
@@ -223,9 +223,9 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
223223
paramLI = (ParamListInfo)
224224
palloc0((nargs + 1) * sizeof(ParamListInfoData));
225225

226-
foreach(l, exprstates)
226+
forboth(le, exprstates, la, argtypes)
227227
{
228-
ExprState *n = lfirst(l);
228+
ExprState *n = lfirst(le);
229229
bool isNull;
230230

231231
paramLI[i].value = ExecEvalExprSwitchContext(n,
@@ -234,6 +234,7 @@ EvaluateParams(EState *estate, List *params, List *argtypes)
234234
NULL);
235235
paramLI[i].kind = PARAM_NUM;
236236
paramLI[i].id = i + 1;
237+
paramLI[i].ptype = lfirst_oid(la);
237238
paramLI[i].isnull = isNull;
238239

239240
i++;

src/backend/commands/schemacmds.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.21 2004/08/01 20:30:48 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.22 2004/08/02 01:30:40 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -168,7 +168,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
168168
/* schemas should contain only utility stmts */
169169
Assert(querytree->commandType == CMD_UTILITY);
170170
/* do this step */
171-
ProcessUtility(querytree->utilityStmt, None_Receiver, NULL);
171+
ProcessUtility(querytree->utilityStmt, NULL, None_Receiver, NULL);
172172
/* make sure later steps can see the object created here */
173173
CommandCounterIncrement();
174174
}

src/backend/executor/execQual.c

Lines changed: 12 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.164 2004/06/09 19:08:14 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.165 2004/08/02 01:30:41 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -589,56 +589,18 @@ ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
589589
else
590590
{
591591
/*
592-
* All other parameter types must be sought in
593-
* ecxt_param_list_info. NOTE: The last entry in the param array
594-
* is always an entry with kind == PARAM_INVALID.
592+
* All other parameter types must be sought in ecxt_param_list_info.
595593
*/
596-
ParamListInfo paramList = econtext->ecxt_param_list_info;
597-
char *thisParamName = expression->paramname;
598-
bool matchFound = false;
599-
600-
if (paramList != NULL)
601-
{
602-
while (paramList->kind != PARAM_INVALID && !matchFound)
603-
{
604-
if (thisParamKind == paramList->kind)
605-
{
606-
switch (thisParamKind)
607-
{
608-
case PARAM_NAMED:
609-
if (strcmp(paramList->name, thisParamName) == 0)
610-
matchFound = true;
611-
break;
612-
case PARAM_NUM:
613-
if (paramList->id == thisParamId)
614-
matchFound = true;
615-
break;
616-
default:
617-
elog(ERROR, "unrecognized paramkind: %d",
618-
thisParamKind);
619-
}
620-
}
621-
if (!matchFound)
622-
paramList++;
623-
} /* while */
624-
} /* if */
625-
626-
if (!matchFound)
627-
{
628-
if (thisParamKind == PARAM_NAMED)
629-
ereport(ERROR,
630-
(errcode(ERRCODE_UNDEFINED_OBJECT),
631-
errmsg("no value found for parameter \"%s\"",
632-
thisParamName)));
633-
else
634-
ereport(ERROR,
635-
(errcode(ERRCODE_UNDEFINED_OBJECT),
636-
errmsg("no value found for parameter %d",
637-
thisParamId)));
638-
}
639-
640-
*isNull = paramList->isnull;
641-
return paramList->value;
594+
ParamListInfo paramInfo;
595+
596+
paramInfo = lookupParam(econtext->ecxt_param_list_info,
597+
thisParamKind,
598+
expression->paramname,
599+
thisParamId,
600+
false);
601+
Assert(paramInfo->ptype == expression->paramtype);
602+
*isNull = paramInfo->isnull;
603+
return paramInfo->value;
642604
}
643605
}
644606

src/backend/executor/functions.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.83 2004/07/15 13:51:38 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.84 2004/08/02 01:30:41 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -58,6 +58,7 @@ typedef struct local_es
5858
*/
5959
typedef struct
6060
{
61+
Oid *argtypes; /* resolved types of arguments */
6162
Oid rettype; /* actual return type */
6263
int typlen; /* length of the return type */
6364
bool typbyval; /* true if return type is pass by value */
@@ -223,6 +224,7 @@ init_sql_fcache(FmgrInfo *finfo)
223224
}
224225
else
225226
argOidVect = NULL;
227+
fcache->argtypes = argOidVect;
226228

227229
tmp = SysCacheGetAttr(PROCOID,
228230
procedureTuple,
@@ -283,7 +285,8 @@ postquel_getnext(execution_state *es)
283285

284286
if (es->qd->operation == CMD_UTILITY)
285287
{
286-
ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->dest, NULL);
288+
ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->params,
289+
es->qd->dest, NULL);
287290
return NULL;
288291
}
289292

@@ -332,6 +335,7 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
332335
{
333336
paramLI[i].kind = PARAM_NUM;
334337
paramLI[i].id = i + 1;
338+
paramLI[i].ptype = fcache->argtypes[i];
335339
paramLI[i].value = fcinfo->arg[i];
336340
paramLI[i].isnull = fcinfo->argnull[i];
337341
}

src/backend/executor/spi.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.122 2004/07/31 20:55:41 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.123 2004/08/02 01:30:41 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -820,6 +820,7 @@ SPI_cursor_open(const char *name, void *plan, Datum *Values, const char *Nulls)
820820
{
821821
paramLI[k].kind = PARAM_NUM;
822822
paramLI[k].id = k + 1;
823+
paramLI[k].ptype = spiplan->argtypes[k];
823824
paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
824825
if (paramLI[k].isnull)
825826
{
@@ -1251,7 +1252,7 @@ _SPI_execute(const char *src, int tcount, _SPI_plan *plan)
12511252
res = SPI_OK_UTILITY;
12521253
if (plan == NULL)
12531254
{
1254-
ProcessUtility(queryTree->utilityStmt, dest, NULL);
1255+
ProcessUtility(queryTree->utilityStmt, NULL, dest, NULL);
12551256
CommandCounterIncrement();
12561257
}
12571258
}
@@ -1319,6 +1320,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
13191320
{
13201321
paramLI[k].kind = PARAM_NUM;
13211322
paramLI[k].id = k + 1;
1323+
paramLI[k].ptype = plan->argtypes[k];
13221324
paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
13231325
paramLI[k].value = Values[k];
13241326
}
@@ -1366,7 +1368,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, const char *Nulls,
13661368
dest = CreateDestReceiver(queryTree->canSetTag ? SPI : None, NULL);
13671369
if (queryTree->commandType == CMD_UTILITY)
13681370
{
1369-
ProcessUtility(queryTree->utilityStmt, dest, NULL);
1371+
ProcessUtility(queryTree->utilityStmt, paramLI, dest, NULL);
13701372
res = SPI_OK_UTILITY;
13711373
CommandCounterIncrement();
13721374
}

src/backend/nodes/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Makefile for backend/nodes
55
#
66
# IDENTIFICATION
7-
# $PostgreSQL: pgsql/src/backend/nodes/Makefile,v 1.16 2004/01/07 18:43:36 neilc Exp $
7+
# $PostgreSQL: pgsql/src/backend/nodes/Makefile,v 1.17 2004/08/02 01:30:42 tgl Exp $
88
#
99
#-------------------------------------------------------------------------
1010

@@ -14,7 +14,7 @@ include $(top_builddir)/src/Makefile.global
1414

1515
OBJS = nodeFuncs.o nodes.o list.o bitmapset.o \
1616
copyfuncs.o equalfuncs.o makefuncs.o \
17-
outfuncs.o readfuncs.o print.o read.o value.o
17+
outfuncs.o readfuncs.o print.o read.o params.o value.o
1818

1919
all: SUBSYS.o
2020

0 commit comments

Comments
 (0)