1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-27 07:42:10 +03:00

Make use of plancache module for SPI plans. In particular, since plpgsql

uses SPI plans, this finally fixes the ancient gotcha that you can't
drop and recreate a temp table used by a plpgsql function.

Along the way, clean up SPI's API a little bit by declaring SPI plan
pointers as "SPIPlanPtr" instead of "void *".  This is cosmetic but
helps to forestall simple programming mistakes.  (I have changed some
but not all of the callers to match; there are still some "void *"'s
in contrib and the PL's.  This is intentional so that we can see if
anyone's compiler complains about it.)
This commit is contained in:
Tom Lane
2007-03-15 23:12:07 +00:00
parent d3ff180163
commit 95f6d2d209
16 changed files with 654 additions and 285 deletions

View File

@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/spi_priv.h,v 1.27 2007/02/20 17:32:17 tgl Exp $
* $PostgreSQL: pgsql/src/include/executor/spi_priv.h,v 1.28 2007/03/15 23:12:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,6 +16,8 @@
#include "executor/spi.h"
#define _SPI_PLAN_MAGIC 569278163
typedef struct
{
/* current results */
@@ -25,29 +27,46 @@ typedef struct
MemoryContext procCxt; /* procedure context */
MemoryContext execCxt; /* executor context */
MemoryContext savedcxt;
MemoryContext savedcxt; /* context of SPI_connect's caller */
SubTransactionId connectSubid; /* ID of connecting subtransaction */
} _SPI_connection;
typedef struct
/*
* SPI plans have two states: saved or unsaved.
*
* For an unsaved plan, the _SPI_plan struct and all its subsidiary data are in
* a dedicated memory context identified by plancxt. An unsaved plan is good
* at most for the current transaction, since the locks that protect it from
* schema changes will be lost at end of transaction. Hence the plancxt is
* always a transient one.
*
* For a saved plan, the _SPI_plan struct and the argument type array are in
* the plancxt (which can be really small). All the other subsidiary state
* is in plancache entries identified by plancache_list (note: the list cells
* themselves are in plancxt). We rely on plancache.c to keep the cache
* entries up-to-date as needed. The plancxt is a child of CacheMemoryContext
* since it should persist until explicitly destroyed.
*
* To avoid redundant coding, the representation of unsaved plans matches
* that of saved plans, ie, plancache_list is a list of CachedPlanSource
* structs which in turn point to CachedPlan structs. However, in an unsaved
* plan all these structs are just created by spi.c and are not known to
* plancache.c. We don't try very hard to make all their fields valid,
* only the ones spi.c actually uses.
*
* Note: if the original query string contained only whitespace and comments,
* the plancache_list will be NIL and so there is no place to store the
* query string. We don't care about that, but we do care about the
* argument type array, which is why it's seemingly-redundantly stored.
*/
typedef struct _SPI_plan
{
/* Context containing _SPI_plan itself as well as subsidiary data */
MemoryContext plancxt;
/* Original query string (used for error reporting) */
const char *query;
/*
* List of List of PlannedStmts and utility stmts; one sublist per
* original parsetree
*/
List *stmt_list_list;
/* Argument types, if a prepared plan */
int nargs;
Oid *argtypes;
int magic; /* should equal _SPI_PLAN_MAGIC */
bool saved; /* saved or unsaved plan? */
List *plancache_list; /* one CachedPlanSource per parsetree */
MemoryContext plancxt; /* Context containing _SPI_plan and data */
int nargs; /* number of plan arguments */
Oid *argtypes; /* Argument types (NULL if nargs is 0) */
} _SPI_plan;
#define _SPI_CPLAN_CURCXT 0
#define _SPI_CPLAN_PROCXT 1
#define _SPI_CPLAN_TOPCXT 2
#endif /* SPI_PRIV_H */