diff --git a/src/pl/plpython/plpy_cursorobject.c b/src/pl/plpython/plpy_cursorobject.c
index 6108384c9a..bb3fa8a390 100644
--- a/src/pl/plpython/plpy_cursorobject.c
+++ b/src/pl/plpython/plpy_cursorobject.c
@@ -140,7 +140,6 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
 {
 	PLyCursorObject *cursor;
 	volatile int nargs;
-	int			i;
 	PLyPlanObject *plan;
 	PLyExecutionContext *exec_ctx = PLy_current_execution_context();
 	volatile MemoryContext oldcontext;
@@ -199,13 +198,30 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
 	PG_TRY();
 	{
 		Portal		portal;
+		MemoryContext tmpcontext;
+		Datum	   *volatile values;
 		char	   *volatile nulls;
 		volatile int j;
 
+		/*
+		 * Converted arguments and associated cruft will be in this context,
+		 * which is local to our subtransaction.
+		 */
+		tmpcontext = AllocSetContextCreate(CurTransactionContext,
+										   "PL/Python temporary context",
+										   ALLOCSET_SMALL_SIZES);
+		MemoryContextSwitchTo(tmpcontext);
+
 		if (nargs > 0)
-			nulls = palloc(nargs * sizeof(char));
+		{
+			values = (Datum *) palloc(nargs * sizeof(Datum));
+			nulls = (char *) palloc(nargs * sizeof(char));
+		}
 		else
+		{
+			values = NULL;
 			nulls = NULL;
+		}
 
 		for (j = 0; j < nargs; j++)
 		{
@@ -217,7 +233,7 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
 			{
 				bool		isnull;
 
-				plan->values[j] = PLy_output_convert(arg, elem, &isnull);
+				values[j] = PLy_output_convert(arg, elem, &isnull);
 				nulls[j] = isnull ? 'n' : ' ';
 			}
 			PG_FINALLY(2);
@@ -227,7 +243,9 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
 			PG_END_TRY(2);
 		}
 
-		portal = SPI_cursor_open(NULL, plan->plan, plan->values, nulls,
+		MemoryContextSwitchTo(oldcontext);
+
+		portal = SPI_cursor_open(NULL, plan->plan, values, nulls,
 								 exec_ctx->curr_proc->fn_readonly);
 		if (portal == NULL)
 			elog(ERROR, "SPI_cursor_open() failed: %s",
@@ -237,40 +255,18 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
 
 		PinPortal(portal);
 
+		MemoryContextDelete(tmpcontext);
 		PLy_spi_subtransaction_commit(oldcontext, oldowner);
 	}
 	PG_CATCH();
 	{
-		int			k;
-
-		/* cleanup plan->values array */
-		for (k = 0; k < nargs; k++)
-		{
-			if (!plan->args[k].typbyval &&
-				(plan->values[k] != PointerGetDatum(NULL)))
-			{
-				pfree(DatumGetPointer(plan->values[k]));
-				plan->values[k] = PointerGetDatum(NULL);
-			}
-		}
-
 		Py_DECREF(cursor);
-
+		/* Subtransaction abort will remove the tmpcontext */
 		PLy_spi_subtransaction_abort(oldcontext, oldowner);
 		return NULL;
 	}
 	PG_END_TRY();
 
-	for (i = 0; i < nargs; i++)
-	{
-		if (!plan->args[i].typbyval &&
-			(plan->values[i] != PointerGetDatum(NULL)))
-		{
-			pfree(DatumGetPointer(plan->values[i]));
-			plan->values[i] = PointerGetDatum(NULL);
-		}
-	}
-
 	Assert(cursor->portalname != NULL);
 	return (PyObject *) cursor;
 }
diff --git a/src/pl/plpython/plpy_planobject.c b/src/pl/plpython/plpy_planobject.c
index bbef889329..9427674d2f 100644
--- a/src/pl/plpython/plpy_planobject.c
+++ b/src/pl/plpython/plpy_planobject.c
@@ -54,7 +54,6 @@ PLy_plan_new(void)
 	ob->plan = NULL;
 	ob->nargs = 0;
 	ob->types = NULL;
-	ob->values = NULL;
 	ob->args = NULL;
 	ob->mcxt = NULL;
 
diff --git a/src/pl/plpython/plpy_planobject.h b/src/pl/plpython/plpy_planobject.h
index 729effb163..a6b34fae19 100644
--- a/src/pl/plpython/plpy_planobject.h
+++ b/src/pl/plpython/plpy_planobject.h
@@ -15,7 +15,6 @@ typedef struct PLyPlanObject
 	SPIPlanPtr	plan;
 	int			nargs;
 	Oid		   *types;
-	Datum	   *values;
 	PLyObToDatum *args;
 	MemoryContext mcxt;
 } PLyPlanObject;
diff --git a/src/pl/plpython/plpy_spi.c b/src/pl/plpython/plpy_spi.c
index bcbd07b70a..77fbfd6c86 100644
--- a/src/pl/plpython/plpy_spi.c
+++ b/src/pl/plpython/plpy_spi.c
@@ -66,7 +66,6 @@ PLy_spi_prepare(PyObject *self, PyObject *args)
 
 	plan->nargs = nargs;
 	plan->types = nargs ? palloc0(sizeof(Oid) * nargs) : NULL;
-	plan->values = nargs ? palloc0(sizeof(Datum) * nargs) : NULL;
 	plan->args = nargs ? palloc0(sizeof(PLyObToDatum) * nargs) : NULL;
 
 	MemoryContextSwitchTo(oldcontext);
@@ -172,8 +171,7 @@ PyObject *
 PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
 {
 	volatile int nargs;
-	int			i,
-				rv;
+	int			rv;
 	PLyPlanObject *plan;
 	volatile MemoryContext oldcontext;
 	volatile ResourceOwner oldowner;
@@ -219,13 +217,30 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
 	PG_TRY();
 	{
 		PLyExecutionContext *exec_ctx = PLy_current_execution_context();
+		MemoryContext tmpcontext;
+		Datum	   *volatile values;
 		char	   *volatile nulls;
 		volatile int j;
 
+		/*
+		 * Converted arguments and associated cruft will be in this context,
+		 * which is local to our subtransaction.
+		 */
+		tmpcontext = AllocSetContextCreate(CurTransactionContext,
+										   "PL/Python temporary context",
+										   ALLOCSET_SMALL_SIZES);
+		MemoryContextSwitchTo(tmpcontext);
+
 		if (nargs > 0)
-			nulls = palloc(nargs * sizeof(char));
+		{
+			values = (Datum *) palloc(nargs * sizeof(Datum));
+			nulls = (char *) palloc(nargs * sizeof(char));
+		}
 		else
+		{
+			values = NULL;
 			nulls = NULL;
+		}
 
 		for (j = 0; j < nargs; j++)
 		{
@@ -237,7 +252,7 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
 			{
 				bool		isnull;
 
-				plan->values[j] = PLy_output_convert(arg, elem, &isnull);
+				values[j] = PLy_output_convert(arg, elem, &isnull);
 				nulls[j] = isnull ? 'n' : ' ';
 			}
 			PG_FINALLY(2);
@@ -247,47 +262,23 @@ PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
 			PG_END_TRY(2);
 		}
 
-		rv = SPI_execute_plan(plan->plan, plan->values, nulls,
+		MemoryContextSwitchTo(oldcontext);
+
+		rv = SPI_execute_plan(plan->plan, values, nulls,
 							  exec_ctx->curr_proc->fn_readonly, limit);
 		ret = PLy_spi_execute_fetch_result(SPI_tuptable, SPI_processed, rv);
 
-		if (nargs > 0)
-			pfree(nulls);
-
+		MemoryContextDelete(tmpcontext);
 		PLy_spi_subtransaction_commit(oldcontext, oldowner);
 	}
 	PG_CATCH();
 	{
-		int			k;
-
-		/*
-		 * cleanup plan->values array
-		 */
-		for (k = 0; k < nargs; k++)
-		{
-			if (!plan->args[k].typbyval &&
-				(plan->values[k] != PointerGetDatum(NULL)))
-			{
-				pfree(DatumGetPointer(plan->values[k]));
-				plan->values[k] = PointerGetDatum(NULL);
-			}
-		}
-
+		/* Subtransaction abort will remove the tmpcontext */
 		PLy_spi_subtransaction_abort(oldcontext, oldowner);
 		return NULL;
 	}
 	PG_END_TRY();
 
-	for (i = 0; i < nargs; i++)
-	{
-		if (!plan->args[i].typbyval &&
-			(plan->values[i] != PointerGetDatum(NULL)))
-		{
-			pfree(DatumGetPointer(plan->values[i]));
-			plan->values[i] = PointerGetDatum(NULL);
-		}
-	}
-
 	if (rv < 0)
 	{
 		PLy_exception_set(PLy_exc_spi_error,
