diff options
| author | Tom Lane | 2007-03-15 23:12:07 +0000 |
|---|---|---|
| committer | Tom Lane | 2007-03-15 23:12:07 +0000 |
| commit | 95f6d2d20921b7c2dbec29bf2706fd9448208aa6 (patch) | |
| tree | 21dcb36f9df60546d82d547a7855605be73a771c /src/backend/utils | |
| parent | d3ff180163a0c88d7a05e0c865f649e5d8bcd6e1 (diff) | |
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.)
Diffstat (limited to 'src/backend/utils')
| -rw-r--r-- | src/backend/utils/adt/ri_triggers.c | 58 | ||||
| -rw-r--r-- | src/backend/utils/adt/ruleutils.c | 10 | ||||
| -rw-r--r-- | src/backend/utils/adt/xml.c | 6 | ||||
| -rw-r--r-- | src/backend/utils/cache/plancache.c | 24 |
4 files changed, 48 insertions, 50 deletions
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 4ba2bb7a98f..72200ced9dc 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -8,16 +8,14 @@ * across query and transaction boundaries, in fact they live as long as * the backend does. This works because the hashtable structures * themselves are allocated by dynahash.c in its permanent DynaHashCxt, - * and the parse/plan node trees they point to are copied into - * TopMemoryContext using SPI_saveplan(). This is pretty ugly, since there - * is no way to free a no-longer-needed plan tree, but then again we don't - * yet have any bookkeeping that would allow us to detect that a plan isn't - * needed anymore. Improve it someday. + * and the SPI plans they point to are saved using SPI_saveplan(). + * There is not currently any provision for throwing away a no-longer-needed + * plan --- consider improving this someday. * * * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.91 2007/02/14 01:58:57 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.92 2007/03/15 23:12:06 tgl Exp $ * * ---------- */ @@ -35,7 +33,7 @@ #include "catalog/pg_constraint.h" #include "catalog/pg_operator.h" #include "commands/trigger.h" -#include "executor/spi_priv.h" +#include "executor/spi.h" #include "parser/parse_coerce.h" #include "parser/parse_relation.h" #include "miscadmin.h" @@ -135,7 +133,7 @@ typedef struct RI_QueryKey typedef struct RI_QueryHashEntry { RI_QueryKey key; - void *plan; + SPIPlanPtr plan; } RI_QueryHashEntry; @@ -206,18 +204,18 @@ static bool ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, const RI_ConstraintInfo *riinfo); static void ri_InitHashTables(void); -static void *ri_FetchPreparedPlan(RI_QueryKey *key); -static void ri_HashPreparedPlan(RI_QueryKey *key, void *plan); +static SPIPlanPtr ri_FetchPreparedPlan(RI_QueryKey *key); +static void ri_HashPreparedPlan(RI_QueryKey *key, SPIPlanPtr plan); static RI_CompareHashEntry *ri_HashCompareOp(Oid eq_opr, Oid typeid); static void ri_CheckTrigger(FunctionCallInfo fcinfo, const char *funcname, int tgkind); static void ri_FetchConstraintInfo(RI_ConstraintInfo *riinfo, Trigger *trigger, Relation trig_rel, bool rel_is_pk); -static void *ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes, +static SPIPlanPtr ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes, RI_QueryKey *qkey, Relation fk_rel, Relation pk_rel, bool cache_plan); -static bool ri_PerformCheck(RI_QueryKey *qkey, void *qplan, +static bool ri_PerformCheck(RI_QueryKey *qkey, SPIPlanPtr qplan, Relation fk_rel, Relation pk_rel, HeapTuple old_tuple, HeapTuple new_tuple, bool detectNewRows, @@ -248,7 +246,7 @@ RI_FKey_check(PG_FUNCTION_ARGS) HeapTuple old_row; Buffer new_row_buf; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; int i; /* @@ -542,7 +540,7 @@ ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, HeapTuple old_row, const RI_ConstraintInfo *riinfo) { - void *qplan; + SPIPlanPtr qplan; RI_QueryKey qkey; int i; bool result; @@ -678,7 +676,7 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS) Relation pk_rel; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; int i; /* @@ -855,7 +853,7 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS) HeapTuple new_row; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; int i; /* @@ -1040,7 +1038,7 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS) Relation pk_rel; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; int i; /* @@ -1203,7 +1201,7 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS) HeapTuple new_row; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; int i; int j; @@ -1397,7 +1395,7 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS) Relation pk_rel; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; int i; /* @@ -1569,7 +1567,7 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS) HeapTuple new_row; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; int i; /* @@ -1744,7 +1742,7 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS) Relation pk_rel; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; int i; /* @@ -1916,7 +1914,7 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS) HeapTuple new_row; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; int i; bool use_cached_query; @@ -2130,7 +2128,7 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS) Relation pk_rel; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; /* * Check that this is a valid trigger call on the right time and event. @@ -2313,7 +2311,7 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS) HeapTuple new_row; HeapTuple old_row; RI_QueryKey qkey; - void *qplan; + SPIPlanPtr qplan; /* * Check that this is a valid trigger call on the right time and event. @@ -2637,7 +2635,7 @@ RI_Initial_Check(Trigger *trigger, Relation fk_rel, Relation pk_rel) int old_work_mem; char workmembuf[32]; int spi_result; - void *qplan; + SPIPlanPtr qplan; /* * Check to make sure current user has enough permissions to do the test @@ -3165,12 +3163,12 @@ ri_FetchConstraintInfo(RI_ConstraintInfo *riinfo, * If cache_plan is true, the plan is saved into our plan hashtable * so that we don't need to plan it again. */ -static void * +static SPIPlanPtr ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes, RI_QueryKey *qkey, Relation fk_rel, Relation pk_rel, bool cache_plan) { - void *qplan; + SPIPlanPtr qplan; Relation query_rel; Oid save_uid; @@ -3212,7 +3210,7 @@ ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes, * Perform a query to enforce an RI restriction */ static bool -ri_PerformCheck(RI_QueryKey *qkey, void *qplan, +ri_PerformCheck(RI_QueryKey *qkey, SPIPlanPtr qplan, Relation fk_rel, Relation pk_rel, HeapTuple old_tuple, HeapTuple new_tuple, bool detectNewRows, @@ -3576,7 +3574,7 @@ ri_InitHashTables(void) * and saved SPI execution plans. Return the plan if found or NULL. * ---------- */ -static void * +static SPIPlanPtr ri_FetchPreparedPlan(RI_QueryKey *key) { RI_QueryHashEntry *entry; @@ -3606,7 +3604,7 @@ ri_FetchPreparedPlan(RI_QueryKey *key) * ---------- */ static void -ri_HashPreparedPlan(RI_QueryKey *key, void *plan) +ri_HashPreparedPlan(RI_QueryKey *key, SPIPlanPtr plan) { RI_QueryHashEntry *entry; bool found; diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index f17061738a4..9ec0aa56f0a 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.252 2007/02/27 23:48:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.253 2007/03/15 23:12:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -105,9 +105,9 @@ typedef struct * Global data * ---------- */ -static void *plan_getrulebyoid = NULL; +static SPIPlanPtr plan_getrulebyoid = NULL; static char *query_getrulebyoid = "SELECT * FROM pg_catalog.pg_rewrite WHERE oid = $1"; -static void *plan_getviewrule = NULL; +static SPIPlanPtr plan_getviewrule = NULL; static char *query_getviewrule = "SELECT * FROM pg_catalog.pg_rewrite WHERE ev_class = $1 AND rulename = $2"; @@ -250,7 +250,7 @@ pg_get_ruledef_worker(Oid ruleoid, int prettyFlags) if (plan_getrulebyoid == NULL) { Oid argtypes[1]; - void *plan; + SPIPlanPtr plan; argtypes[0] = OIDOID; plan = SPI_prepare(query_getrulebyoid, 1, argtypes); @@ -380,7 +380,7 @@ pg_get_viewdef_worker(Oid viewoid, int prettyFlags) if (plan_getviewrule == NULL) { Oid argtypes[2]; - void *plan; + SPIPlanPtr plan; argtypes[0] = OIDOID; argtypes[1] = NAMEOID; diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 921fe1d9f50..fa82837fd0c 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.34 2007/03/03 19:32:55 neilc Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.35 2007/03/15 23:12:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1800,7 +1800,7 @@ query_to_xmlschema(PG_FUNCTION_ARGS) const char *targetns = _textout(PG_GETARG_TEXT_P(3)); const char *result; - void *plan; + SPIPlanPtr plan; Portal portal; SPI_connect(); @@ -1871,7 +1871,7 @@ query_to_xml_and_xmlschema(PG_FUNCTION_ARGS) const char *targetns = _textout(PG_GETARG_TEXT_P(3)); const char *xmlschema; - void *plan; + SPIPlanPtr plan; Portal portal; SPI_connect(); diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index 95ed49818cb..61a576d35d9 100644 --- a/src/backend/utils/cache/plancache.c +++ b/src/backend/utils/cache/plancache.c @@ -33,7 +33,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.1 2007/03/13 00:33:42 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.2 2007/03/15 23:12:06 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -77,7 +77,6 @@ static void ScanQueryForRelids(Query *parsetree, void *arg); static bool ScanQueryWalker(Node *node, ScanQueryWalkerContext *context); static bool rowmark_member(List *rowMarks, int rt_index); -static TupleDesc ComputeResultDesc(List *stmt_list); static void PlanCacheCallback(Datum arg, Oid relid); static void InvalRelid(Oid relid, LOCKMODE lockmode, InvalRelidContext *context); @@ -153,7 +152,7 @@ CreateCachedPlan(Node *raw_parse_tree, plansource->fully_planned = fully_planned; plansource->fixed_result = fixed_result; plansource->generation = 0; /* StoreCachedPlan will increment */ - plansource->resultDesc = ComputeResultDesc(stmt_list); + plansource->resultDesc = PlanCacheComputeResultDesc(stmt_list); plansource->plan = NULL; plansource->context = source_context; plansource->orig_plan = NULL; @@ -225,7 +224,7 @@ FastCreateCachedPlan(Node *raw_parse_tree, plansource->fully_planned = fully_planned; plansource->fixed_result = fixed_result; plansource->generation = 0; /* StoreCachedPlan will increment */ - plansource->resultDesc = ComputeResultDesc(stmt_list); + plansource->resultDesc = PlanCacheComputeResultDesc(stmt_list); plansource->plan = NULL; plansource->context = context; plansource->orig_plan = NULL; @@ -271,12 +270,13 @@ StoreCachedPlan(CachedPlanSource *plansource, { /* * Make a dedicated memory context for the CachedPlan and its - * subsidiary data. + * subsidiary data. It's probably not going to be large, but + * just in case, use the default maxsize parameter. */ plan_context = AllocSetContextCreate(CacheMemoryContext, "CachedPlan", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_SMALL_MINSIZE, + ALLOCSET_SMALL_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* @@ -445,7 +445,7 @@ RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner) * Check or update the result tupdesc. XXX should we use a weaker * condition than equalTupleDescs() here? */ - resultDesc = ComputeResultDesc(slist); + resultDesc = PlanCacheComputeResultDesc(slist); if (resultDesc == NULL && plansource->resultDesc == NULL) { /* OK, doesn't return tuples */ @@ -718,14 +718,14 @@ rowmark_member(List *rowMarks, int rt_index) } /* - * ComputeResultDesc: given a list of either fully-planned statements or - * Queries, determine the result tupledesc it will produce. Returns NULL + * PlanCacheComputeResultDesc: given a list of either fully-planned statements + * or Queries, determine the result tupledesc it will produce. Returns NULL * if the execution will not return tuples. * * Note: the result is created or copied into current memory context. */ -static TupleDesc -ComputeResultDesc(List *stmt_list) +TupleDesc +PlanCacheComputeResultDesc(List *stmt_list) { Node *node; Query *query; |
