aboutsummaryrefslogtreecommitdiff
path: root/src/pl/tcl/pltcl.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-09-16 00:42:53 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2011-09-16 00:43:52 -0400
commite6faf910d75027bdce7cd0f2033db4e912592bcc (patch)
treeb5fdc2340cc1cdf27dd473e23a09cb2953b5053c /src/pl/tcl/pltcl.c
parent09e98a3e170ecdeb25a0e1afe81bdbeeeaf21f48 (diff)
downloadpostgresql-e6faf910d75027bdce7cd0f2033db4e912592bcc.tar.gz
postgresql-e6faf910d75027bdce7cd0f2033db4e912592bcc.zip
Redesign the plancache mechanism for more flexibility and efficiency.
Rewrite plancache.c so that a "cached plan" (which is rather a misnomer at this point) can support generation of custom, parameter-value-dependent plans, and can make an intelligent choice between using custom plans and the traditional generic-plan approach. The specific choice algorithm implemented here can probably be improved in future, but this commit is all about getting the mechanism in place, not the policy. In addition, restructure the API to greatly reduce the amount of extraneous data copying needed. The main compromise needed to make that possible was to split the initial creation of a CachedPlanSource into two steps. It's worth noting in particular that SPI_saveplan is now deprecated in favor of SPI_keepplan, which accomplishes the same end result with zero data copying, and no need to then spend even more cycles throwing away the original SPIPlan. The risk of long-term memory leaks while manipulating SPIPlans has also been greatly reduced. Most of this improvement is based on use of the recently-added MemoryContextSetParent primitive.
Diffstat (limited to 'src/pl/tcl/pltcl.c')
-rw-r--r--src/pl/tcl/pltcl.c17
1 files changed, 6 insertions, 11 deletions
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index be8fe7a0f21..ecde90626bf 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -128,7 +128,7 @@ typedef struct pltcl_proc_desc
typedef struct pltcl_query_desc
{
char qname[20];
- void *plan;
+ SPIPlanPtr plan;
int nargs;
Oid *argtypes;
FmgrInfo *arginfuncs;
@@ -2024,7 +2024,7 @@ pltcl_process_SPI_result(Tcl_Interp *interp,
* pltcl_SPI_prepare() - Builtin support for prepared plans
* The Tcl command SPI_prepare
* always saves the plan using
- * SPI_saveplan and returns a key for
+ * SPI_keepplan and returns a key for
* access. There is no chance to prepare
* and not save the plan currently.
**********************************************************************/
@@ -2035,7 +2035,6 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
int nargs;
CONST84 char **args;
pltcl_query_desc *qdesc;
- void *plan;
int i;
Tcl_HashEntry *hashent;
int hashnew;
@@ -2103,22 +2102,18 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
* Prepare the plan and check for errors
************************************************************/
UTF_BEGIN;
- plan = SPI_prepare(UTF_U2E(argv[1]), nargs, qdesc->argtypes);
+ qdesc->plan = SPI_prepare(UTF_U2E(argv[1]), nargs, qdesc->argtypes);
UTF_END;
- if (plan == NULL)
+ if (qdesc->plan == NULL)
elog(ERROR, "SPI_prepare() failed");
/************************************************************
* Save the plan into permanent memory (right now it's in the
* SPI procCxt, which will go away at function end).
************************************************************/
- qdesc->plan = SPI_saveplan(plan);
- if (qdesc->plan == NULL)
- elog(ERROR, "SPI_saveplan() failed");
-
- /* Release the procCxt copy to avoid within-function memory leak */
- SPI_freeplan(plan);
+ if (SPI_keepplan(qdesc->plan))
+ elog(ERROR, "SPI_keepplan() failed");
pltcl_subtrans_commit(oldcontext, oldowner);
}