1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-29 23:43:17 +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

@@ -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;

View File

@@ -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;

View File

@@ -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();