aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/spi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/spi.c')
-rw-r--r--src/backend/executor/spi.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 42187fe43ad..f7d41373b4a 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.192 2008/04/01 03:09:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.193 2008/04/02 18:31:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -918,6 +918,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
CachedPlanSource *plansource;
CachedPlan *cplan;
List *stmt_list;
+ char *query_string;
ParamListInfo paramLI;
Snapshot snapshot;
MemoryContext oldcontext;
@@ -968,10 +969,22 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
portal = CreatePortal(name, false, false);
}
+ /*
+ * Prepare to copy stuff into the portal's memory context. We do all this
+ * copying first, because it could possibly fail (out-of-memory) and we
+ * don't want a failure to occur between RevalidateCachedPlan and
+ * PortalDefineQuery; that would result in leaking our plancache refcount.
+ */
+ oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
+
+ /* Copy the plan's query string, if available, into the portal */
+ query_string = plansource->query_string;
+ if (query_string)
+ query_string = pstrdup(query_string);
+
/* If the plan has parameters, copy them into the portal */
if (plan->nargs > 0)
{
- oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
/* sizeof(ParamListInfoData) includes the first array element */
paramLI = (ParamListInfo) palloc(sizeof(ParamListInfoData) +
(plan->nargs - 1) *sizeof(ParamExternData));
@@ -1000,11 +1013,12 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
paramTypByVal, paramTypLen);
}
}
- MemoryContextSwitchTo(oldcontext);
}
else
paramLI = NULL;
+ MemoryContextSwitchTo(oldcontext);
+
if (plan->saved)
{
/* Replan if needed, and increment plan refcount for portal */
@@ -1025,7 +1039,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan,
*/
PortalDefineQuery(portal,
NULL, /* no statement name */
- plansource->query_string,
+ query_string,
plansource->commandTag,
stmt_list,
cplan);