aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache
diff options
context:
space:
mode:
authorKevin Grittner <kgrittn@postgresql.org>2017-03-31 23:17:18 -0500
committerKevin Grittner <kgrittn@postgresql.org>2017-03-31 23:17:18 -0500
commit18ce3a4ab22d2984f8540ab480979c851dae5338 (patch)
treeff63f19ee776dfe26c675abacb8558bb60c5b0b6 /src/backend/utils/cache
parent25dc142a49c60c3107480c487cd8444dc83f9bdf (diff)
downloadpostgresql-18ce3a4ab22d2984f8540ab480979c851dae5338.tar.gz
postgresql-18ce3a4ab22d2984f8540ab480979c851dae5338.zip
Add infrastructure to support EphemeralNamedRelation references.
A QueryEnvironment concept is added, which allows new types of objects to be passed into queries from parsing on through execution. At this point, the only thing implemented is a collection of EphemeralNamedRelation objects -- relations which can be referenced by name in queries, but do not exist in the catalogs. The only type of ENR implemented is NamedTuplestore, but provision is made to add more types fairly easily. An ENR can carry its own TupleDesc or reference a relation in the catalogs by relid. Although these features can be used without SPI, convenience functions are added to SPI so that ENRs can easily be used by code run through SPI. The initial use of all this is going to be transition tables in AFTER triggers, but that will be added to each PL as a separate commit. An incidental effect of this patch is to produce a more informative error message if an attempt is made to modify the contents of a CTE from a referencing DML statement. No tests previously covered that possibility, so one is added. Kevin Grittner and Thomas Munro Reviewed by Heikki Linnakangas, David Fetter, and Thomas Munro with valuable comments and suggestions from many others
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r--src/backend/utils/cache/plancache.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 043085d3a76..a116d5ed63e 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -88,10 +88,11 @@
static CachedPlanSource *first_saved_plan = NULL;
static void ReleaseGenericPlan(CachedPlanSource *plansource);
-static List *RevalidateCachedQuery(CachedPlanSource *plansource);
+static List *RevalidateCachedQuery(CachedPlanSource *plansource,
+ QueryEnvironment *queryEnv);
static bool CheckCachedPlan(CachedPlanSource *plansource);
static CachedPlan *BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
- ParamListInfo boundParams);
+ ParamListInfo boundParams, QueryEnvironment *queryEnv);
static bool choose_custom_plan(CachedPlanSource *plansource,
ParamListInfo boundParams);
static double cached_plan_cost(CachedPlan *plan, bool include_planner);
@@ -150,7 +151,8 @@ InitPlanCache(void)
CachedPlanSource *
CreateCachedPlan(RawStmt *raw_parse_tree,
const char *query_string,
- const char *commandTag)
+ const char *commandTag,
+ QueryEnvironment *queryEnv)
{
CachedPlanSource *plansource;
MemoryContext source_context;
@@ -553,7 +555,8 @@ ReleaseGenericPlan(CachedPlanSource *plansource)
* a tree copying step in a subsequent BuildCachedPlan call.)
*/
static List *
-RevalidateCachedQuery(CachedPlanSource *plansource)
+RevalidateCachedQuery(CachedPlanSource *plansource,
+ QueryEnvironment *queryEnv)
{
bool snapshot_set;
RawStmt *rawtree;
@@ -685,12 +688,14 @@ RevalidateCachedQuery(CachedPlanSource *plansource)
tlist = pg_analyze_and_rewrite_params(rawtree,
plansource->query_string,
plansource->parserSetup,
- plansource->parserSetupArg);
+ plansource->parserSetupArg,
+ queryEnv);
else
tlist = pg_analyze_and_rewrite(rawtree,
plansource->query_string,
plansource->param_types,
- plansource->num_params);
+ plansource->num_params,
+ queryEnv);
/* Release snapshot if we got one */
if (snapshot_set)
@@ -875,7 +880,7 @@ CheckCachedPlan(CachedPlanSource *plansource)
*/
static CachedPlan *
BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
- ParamListInfo boundParams)
+ ParamListInfo boundParams, QueryEnvironment *queryEnv)
{
CachedPlan *plan;
List *plist;
@@ -899,7 +904,7 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
* safety, let's treat it as real and redo the RevalidateCachedQuery call.
*/
if (!plansource->is_valid)
- qlist = RevalidateCachedQuery(plansource);
+ qlist = RevalidateCachedQuery(plansource, queryEnv);
/*
* If we don't already have a copy of the querytree list that can be
@@ -1129,7 +1134,7 @@ cached_plan_cost(CachedPlan *plan, bool include_planner)
*/
CachedPlan *
GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
- bool useResOwner)
+ bool useResOwner, QueryEnvironment *queryEnv)
{
CachedPlan *plan = NULL;
List *qlist;
@@ -1143,7 +1148,7 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
elog(ERROR, "cannot apply ResourceOwner to non-saved cached plan");
/* Make sure the querytree list is valid and we have parse-time locks */
- qlist = RevalidateCachedQuery(plansource);
+ qlist = RevalidateCachedQuery(plansource, queryEnv);
/* Decide whether to use a custom plan */
customplan = choose_custom_plan(plansource, boundParams);
@@ -1159,7 +1164,7 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
else
{
/* Build a new generic plan */
- plan = BuildCachedPlan(plansource, qlist, NULL);
+ plan = BuildCachedPlan(plansource, qlist, NULL, queryEnv);
/* Just make real sure plansource->gplan is clear */
ReleaseGenericPlan(plansource);
/* Link the new generic plan into the plansource */
@@ -1204,7 +1209,7 @@ GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
if (customplan)
{
/* Build a custom plan */
- plan = BuildCachedPlan(plansource, qlist, boundParams);
+ plan = BuildCachedPlan(plansource, qlist, boundParams, queryEnv);
/* Accumulate total costs of custom plans, but 'ware overflow */
if (plansource->num_custom_plans < INT_MAX)
{
@@ -1418,7 +1423,8 @@ CachedPlanIsValid(CachedPlanSource *plansource)
* within the cached plan, and may disappear next time the plan is updated.
*/
List *
-CachedPlanGetTargetList(CachedPlanSource *plansource)
+CachedPlanGetTargetList(CachedPlanSource *plansource,
+ QueryEnvironment *queryEnv)
{
Query *pstmt;
@@ -1434,7 +1440,7 @@ CachedPlanGetTargetList(CachedPlanSource *plansource)
return NIL;
/* Make sure the querytree list is valid and we have parse-time locks */
- RevalidateCachedQuery(plansource);
+ RevalidateCachedQuery(plansource, queryEnv);
/* Get the primary statement and find out what it returns */
pstmt = QueryListGetPrimaryStmt(plansource->query_list);