PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plancache.h File Reference
#include "access/tupdesc.h"
#include "nodes/params.h"
#include "utils/queryenvironment.h"
Include dependency graph for plancache.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  CachedPlanSource
 
struct  CachedPlan
 

Macros

#define CACHEDPLANSOURCE_MAGIC   195726186
 
#define CACHEDPLAN_MAGIC   953717834
 

Typedefs

typedef struct CachedPlanSource CachedPlanSource
 
typedef struct CachedPlan CachedPlan
 

Functions

void InitPlanCache (void)
 
void ResetPlanCache (void)
 
CachedPlanSourceCreateCachedPlan (struct RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
 
CachedPlanSourceCreateOneShotCachedPlan (struct RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
 
void CompleteCachedPlan (CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, Oid *param_types, int num_params, ParserSetupHook parserSetup, void *parserSetupArg, int cursor_options, bool fixed_result)
 
void SaveCachedPlan (CachedPlanSource *plansource)
 
void DropCachedPlan (CachedPlanSource *plansource)
 
void CachedPlanSetParentContext (CachedPlanSource *plansource, MemoryContext newcontext)
 
CachedPlanSourceCopyCachedPlan (CachedPlanSource *plansource)
 
bool CachedPlanIsValid (CachedPlanSource *plansource)
 
ListCachedPlanGetTargetList (CachedPlanSource *plansource, QueryEnvironment *queryEnv)
 
CachedPlanGetCachedPlan (CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner, QueryEnvironment *queryEnv)
 
void ReleaseCachedPlan (CachedPlan *plan, bool useResOwner)
 

Macro Definition Documentation

#define CACHEDPLAN_MAGIC   953717834

Typedef Documentation

Function Documentation

List* CachedPlanGetTargetList ( CachedPlanSource plansource,
QueryEnvironment queryEnv 
)

Definition at line 1425 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, FetchStatementTargetList(), CachedPlanSource::is_complete, CachedPlanSource::magic, NIL, CachedPlanSource::query_list, QueryListGetPrimaryStmt(), CachedPlanSource::resultDesc, and RevalidateCachedQuery().

Referenced by exec_describe_statement_message(), and FetchPreparedStatementTargetList().

1427 {
1428  Query *pstmt;
1429 
1430  /* Assert caller is doing things in a sane order */
1431  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1432  Assert(plansource->is_complete);
1433 
1434  /*
1435  * No work needed if statement doesn't return tuples (we assume this
1436  * feature cannot be changed by an invalidation)
1437  */
1438  if (plansource->resultDesc == NULL)
1439  return NIL;
1440 
1441  /* Make sure the querytree list is valid and we have parse-time locks */
1442  RevalidateCachedQuery(plansource, queryEnv);
1443 
1444  /* Get the primary statement and find out what it returns */
1445  pstmt = QueryListGetPrimaryStmt(plansource->query_list);
1446 
1447  return FetchStatementTargetList((Node *) pstmt);
1448 }
#define NIL
Definition: pg_list.h:69
Definition: nodes.h:509
TupleDesc resultDesc
Definition: plancache.h:92
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:360
static Query * QueryListGetPrimaryStmt(List *stmts)
Definition: plancache.c:1459
static List * RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:557
#define Assert(condition)
Definition: c.h:664
List * query_list
Definition: plancache.h:95
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
bool CachedPlanIsValid ( CachedPlanSource plansource)

Definition at line 1412 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::is_valid, and CachedPlanSource::magic.

Referenced by SPI_plan_is_valid().

1413 {
1414  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1415  return plansource->is_valid;
1416 }
#define Assert(condition)
Definition: c.h:664
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
void CachedPlanSetParentContext ( CachedPlanSource plansource,
MemoryContext  newcontext 
)

Definition at line 1284 of file plancache.c.

References Assert, CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::context, CachedPlan::context, elog, ERROR, CachedPlanSource::gplan, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::magic, CachedPlan::magic, and MemoryContextSetParent().

Referenced by _SPI_make_plan_non_temp().

1286 {
1287  /* Assert caller is doing things in a sane order */
1288  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1289  Assert(plansource->is_complete);
1290 
1291  /* These seem worth real tests, though */
1292  if (plansource->is_saved)
1293  elog(ERROR, "cannot move a saved cached plan to another context");
1294  if (plansource->is_oneshot)
1295  elog(ERROR, "cannot move a one-shot cached plan to another context");
1296 
1297  /* OK, let the caller keep the plan where he wishes */
1298  MemoryContextSetParent(plansource->context, newcontext);
1299 
1300  /*
1301  * The query_context needs no special handling, since it's a child of
1302  * plansource->context. But if there's a generic plan, it should be
1303  * maintained as a sibling of plansource->context.
1304  */
1305  if (plansource->gplan)
1306  {
1307  Assert(plansource->gplan->magic == CACHEDPLAN_MAGIC);
1308  MemoryContextSetParent(plansource->gplan->context, newcontext);
1309  }
1310 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:26
MemoryContext context
Definition: plancache.h:93
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
MemoryContext context
Definition: plancache.h:143
struct CachedPlan * gplan
Definition: plancache.h:105
#define ERROR
Definition: elog.h:43
#define Assert(condition)
Definition: c.h:664
#define elog
Definition: elog.h:219
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
void CompleteCachedPlan ( CachedPlanSource plansource,
List querytree_list,
MemoryContext  querytree_context,
Oid param_types,
int  num_params,
ParserSetupHook  parserSetup,
void *  parserSetupArg,
int  cursor_options,
bool  fixed_result 
)

Definition at line 325 of file plancache.c.

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate(), Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::context, copyObject, CurrentMemoryContext, CachedPlanSource::cursor_options, CachedPlanSource::dependsOnRLS, extract_query_dependencies(), CachedPlanSource::fixed_result, GetOverrideSearchPath(), GetUserId(), CachedPlanSource::invalItems, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_valid, IsTransactionStmtPlan, CachedPlanSource::magic, MemoryContextSetParent(), MemoryContextSwitchTo(), CachedPlanSource::num_params, palloc(), CachedPlanSource::param_types, CachedPlanSource::parserSetup, CachedPlanSource::parserSetupArg, PlanCacheComputeResultDesc(), CachedPlanSource::query_context, CachedPlanSource::query_list, CachedPlanSource::relationOids, CachedPlanSource::resultDesc, CachedPlanSource::rewriteRoleId, CachedPlanSource::rewriteRowSecurity, row_security, and CachedPlanSource::search_path.

Referenced by _SPI_execute_plan(), _SPI_prepare_plan(), exec_parse_message(), and PrepareQuery().

334 {
335  MemoryContext source_context = plansource->context;
337 
338  /* Assert caller is doing things in a sane order */
339  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
340  Assert(!plansource->is_complete);
341 
342  /*
343  * If caller supplied a querytree_context, reparent it underneath the
344  * CachedPlanSource's context; otherwise, create a suitable context and
345  * copy the querytree_list into it. But no data copying should be done
346  * for one-shot plans; for those, assume the passed querytree_list is
347  * sufficiently long-lived.
348  */
349  if (plansource->is_oneshot)
350  {
351  querytree_context = CurrentMemoryContext;
352  }
353  else if (querytree_context != NULL)
354  {
355  MemoryContextSetParent(querytree_context, source_context);
356  MemoryContextSwitchTo(querytree_context);
357  }
358  else
359  {
360  /* Again, it's a good bet the querytree_context can be small */
361  querytree_context = AllocSetContextCreate(source_context,
362  "CachedPlanQuery",
364  MemoryContextSwitchTo(querytree_context);
365  querytree_list = copyObject(querytree_list);
366  }
367 
368  plansource->query_context = querytree_context;
369  plansource->query_list = querytree_list;
370 
371  if (!plansource->is_oneshot && !IsTransactionStmtPlan(plansource))
372  {
373  /*
374  * Use the planner machinery to extract dependencies. Data is saved
375  * in query_context. (We assume that not a lot of extra cruft is
376  * created by this call.) We can skip this for one-shot plans, and
377  * transaction control commands have no such dependencies anyway.
378  */
379  extract_query_dependencies((Node *) querytree_list,
380  &plansource->relationOids,
381  &plansource->invalItems,
382  &plansource->dependsOnRLS);
383 
384  /* Update RLS info as well. */
385  plansource->rewriteRoleId = GetUserId();
386  plansource->rewriteRowSecurity = row_security;
387 
388  /*
389  * Also save the current search_path in the query_context. (This
390  * should not generate much extra cruft either, since almost certainly
391  * the path is already valid.) Again, we don't really need this for
392  * one-shot plans; and we *must* skip this for transaction control
393  * commands, because this could result in catalog accesses.
394  */
395  plansource->search_path = GetOverrideSearchPath(querytree_context);
396  }
397 
398  /*
399  * Save the final parameter types (or other parameter specification data)
400  * into the source_context, as well as our other parameters. Also save
401  * the result tuple descriptor.
402  */
403  MemoryContextSwitchTo(source_context);
404 
405  if (num_params > 0)
406  {
407  plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
408  memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
409  }
410  else
411  plansource->param_types = NULL;
412  plansource->num_params = num_params;
413  plansource->parserSetup = parserSetup;
414  plansource->parserSetupArg = parserSetupArg;
415  plansource->cursor_options = cursor_options;
416  plansource->fixed_result = fixed_result;
417  plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
418 
419  MemoryContextSwitchTo(oldcxt);
420 
421  plansource->is_complete = true;
422  plansource->is_valid = true;
423 }
MemoryContext context
Definition: plancache.h:93
bool rewriteRowSecurity
Definition: plancache.h:102
Oid GetUserId(void)
Definition: miscinit.c:284
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:509
unsigned int Oid
Definition: postgres_ext.h:31
TupleDesc resultDesc
Definition: plancache.h:92
List * invalItems
Definition: plancache.h:97
OverrideSearchPath * GetOverrideSearchPath(MemoryContext context)
Definition: namespace.c:3281
Oid * param_types
Definition: plancache.h:86
List * relationOids
Definition: plancache.h:96
void * parserSetupArg
Definition: plancache.h:89
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ParserSetupHook parserSetup
Definition: plancache.h:88
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
bool row_security
Definition: guc.c:446
#define Assert(condition)
Definition: c.h:664
void extract_query_dependencies(Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
Definition: setrefs.c:2534
void * palloc(Size size)
Definition: mcxt.c:848
MemoryContext query_context
Definition: plancache.h:100
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:182
List * query_list
Definition: plancache.h:95
#define IsTransactionStmtPlan(plansource)
Definition: plancache.c:78
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
#define copyObject(obj)
Definition: nodes.h:622
static TupleDesc PlanCacheComputeResultDesc(List *stmt_list)
Definition: plancache.c:1671
struct OverrideSearchPath * search_path
Definition: plancache.h:98
CachedPlanSource* CopyCachedPlan ( CachedPlanSource plansource)

Definition at line 1322 of file plancache.c.

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate(), Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::commandTag, CachedPlanSource::context, copyObject, CopyOverrideSearchPath(), CreateTupleDescCopy(), CurrentMemoryContext, CachedPlanSource::cursor_options, CachedPlanSource::dependsOnRLS, elog, ERROR, CachedPlanSource::fixed_result, CachedPlanSource::generation, CachedPlanSource::generic_cost, CachedPlanSource::gplan, CachedPlanSource::invalItems, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::is_valid, CachedPlanSource::magic, MemoryContextSwitchTo(), CachedPlanSource::next_saved, CachedPlanSource::num_custom_plans, CachedPlanSource::num_params, palloc(), palloc0(), CachedPlanSource::param_types, CachedPlanSource::parserSetup, CachedPlanSource::parserSetupArg, pstrdup(), CachedPlanSource::query_context, CachedPlanSource::query_list, CachedPlanSource::query_string, CachedPlanSource::raw_parse_tree, CachedPlanSource::relationOids, CachedPlanSource::resultDesc, CachedPlanSource::rewriteRoleId, CachedPlanSource::rewriteRowSecurity, CachedPlanSource::search_path, and CachedPlanSource::total_custom_cost.

Referenced by _SPI_save_plan().

1323 {
1324  CachedPlanSource *newsource;
1325  MemoryContext source_context;
1326  MemoryContext querytree_context;
1327  MemoryContext oldcxt;
1328 
1329  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1330  Assert(plansource->is_complete);
1331 
1332  /*
1333  * One-shot plans can't be copied, because we haven't taken care that
1334  * parsing/planning didn't scribble on the raw parse tree or querytrees.
1335  */
1336  if (plansource->is_oneshot)
1337  elog(ERROR, "cannot copy a one-shot cached plan");
1338 
1340  "CachedPlanSource",
1342 
1343  oldcxt = MemoryContextSwitchTo(source_context);
1344 
1345  newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1346  newsource->magic = CACHEDPLANSOURCE_MAGIC;
1347  newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
1348  newsource->query_string = pstrdup(plansource->query_string);
1349  newsource->commandTag = plansource->commandTag;
1350  if (plansource->num_params > 0)
1351  {
1352  newsource->param_types = (Oid *)
1353  palloc(plansource->num_params * sizeof(Oid));
1354  memcpy(newsource->param_types, plansource->param_types,
1355  plansource->num_params * sizeof(Oid));
1356  }
1357  else
1358  newsource->param_types = NULL;
1359  newsource->num_params = plansource->num_params;
1360  newsource->parserSetup = plansource->parserSetup;
1361  newsource->parserSetupArg = plansource->parserSetupArg;
1362  newsource->cursor_options = plansource->cursor_options;
1363  newsource->fixed_result = plansource->fixed_result;
1364  if (plansource->resultDesc)
1365  newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
1366  else
1367  newsource->resultDesc = NULL;
1368  newsource->context = source_context;
1369 
1370  querytree_context = AllocSetContextCreate(source_context,
1371  "CachedPlanQuery",
1373  MemoryContextSwitchTo(querytree_context);
1374  newsource->query_list = copyObject(plansource->query_list);
1375  newsource->relationOids = copyObject(plansource->relationOids);
1376  newsource->invalItems = copyObject(plansource->invalItems);
1377  if (plansource->search_path)
1378  newsource->search_path = CopyOverrideSearchPath(plansource->search_path);
1379  newsource->query_context = querytree_context;
1380  newsource->rewriteRoleId = plansource->rewriteRoleId;
1381  newsource->rewriteRowSecurity = plansource->rewriteRowSecurity;
1382  newsource->dependsOnRLS = plansource->dependsOnRLS;
1383 
1384  newsource->gplan = NULL;
1385 
1386  newsource->is_oneshot = false;
1387  newsource->is_complete = true;
1388  newsource->is_saved = false;
1389  newsource->is_valid = plansource->is_valid;
1390  newsource->generation = plansource->generation;
1391  newsource->next_saved = NULL;
1392 
1393  /* We may as well copy any acquired cost knowledge */
1394  newsource->generic_cost = plansource->generic_cost;
1395  newsource->total_custom_cost = plansource->total_custom_cost;
1396  newsource->num_custom_plans = plansource->num_custom_plans;
1397 
1398  MemoryContextSwitchTo(oldcxt);
1399 
1400  return newsource;
1401 }
MemoryContext context
Definition: plancache.h:93
bool rewriteRowSecurity
Definition: plancache.h:102
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:102
const char * commandTag
Definition: plancache.h:85
char * pstrdup(const char *in)
Definition: mcxt.c:1076
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
double total_custom_cost
Definition: plancache.h:116
struct CachedPlan * gplan
Definition: plancache.h:105
TupleDesc resultDesc
Definition: plancache.h:92
struct CachedPlanSource * next_saved
Definition: plancache.h:113
#define ERROR
Definition: elog.h:43
OverrideSearchPath * CopyOverrideSearchPath(OverrideSearchPath *path)
Definition: namespace.c:3317
List * invalItems
Definition: plancache.h:97
Oid * param_types
Definition: plancache.h:86
List * relationOids
Definition: plancache.h:96
void * parserSetupArg
Definition: plancache.h:89
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ParserSetupHook parserSetup
Definition: plancache.h:88
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:877
double generic_cost
Definition: plancache.h:115
#define Assert(condition)
Definition: c.h:664
const char * query_string
Definition: plancache.h:84
struct RawStmt * raw_parse_tree
Definition: plancache.h:83
void * palloc(Size size)
Definition: mcxt.c:848
MemoryContext query_context
Definition: plancache.h:100
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:182
List * query_list
Definition: plancache.h:95
#define elog
Definition: elog.h:219
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
#define copyObject(obj)
Definition: nodes.h:622
struct OverrideSearchPath * search_path
Definition: plancache.h:98
CachedPlanSource* CreateCachedPlan ( struct RawStmt raw_parse_tree,
const char *  query_string,
const char *  commandTag 
)

Definition at line 152 of file plancache.c.

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate(), Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::commandTag, CachedPlanSource::context, copyObject, CurrentMemoryContext, CachedPlanSource::cursor_options, CachedPlanSource::dependsOnRLS, CachedPlanSource::fixed_result, CachedPlanSource::generation, CachedPlanSource::generic_cost, CachedPlanSource::gplan, InvalidOid, CachedPlanSource::invalItems, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::is_valid, CachedPlanSource::magic, MemoryContextSwitchTo(), CachedPlanSource::next_saved, NIL, CachedPlanSource::num_custom_plans, CachedPlanSource::num_params, palloc0(), CachedPlanSource::param_types, CachedPlanSource::parserSetup, CachedPlanSource::parserSetupArg, pstrdup(), CachedPlanSource::query_context, CachedPlanSource::query_list, CachedPlanSource::query_string, CachedPlanSource::raw_parse_tree, CachedPlanSource::relationOids, CachedPlanSource::resultDesc, CachedPlanSource::rewriteRoleId, CachedPlanSource::rewriteRowSecurity, CachedPlanSource::search_path, and CachedPlanSource::total_custom_cost.

Referenced by _SPI_prepare_plan(), exec_parse_message(), and PrepareQuery().

155 {
156  CachedPlanSource *plansource;
157  MemoryContext source_context;
158  MemoryContext oldcxt;
159 
160  Assert(query_string != NULL); /* required as of 8.4 */
161 
162  /*
163  * Make a dedicated memory context for the CachedPlanSource and its
164  * permanent subsidiary data. It's probably not going to be large, but
165  * just in case, allow it to grow large. Initially it's a child of the
166  * caller's context (which we assume to be transient), so that it will be
167  * cleaned up on error.
168  */
170  "CachedPlanSource",
172 
173  /*
174  * Create and fill the CachedPlanSource struct within the new context.
175  * Most fields are just left empty for the moment.
176  */
177  oldcxt = MemoryContextSwitchTo(source_context);
178 
179  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
180  plansource->magic = CACHEDPLANSOURCE_MAGIC;
181  plansource->raw_parse_tree = copyObject(raw_parse_tree);
182  plansource->query_string = pstrdup(query_string);
183  plansource->commandTag = commandTag;
184  plansource->param_types = NULL;
185  plansource->num_params = 0;
186  plansource->parserSetup = NULL;
187  plansource->parserSetupArg = NULL;
188  plansource->cursor_options = 0;
189  plansource->fixed_result = false;
190  plansource->resultDesc = NULL;
191  plansource->context = source_context;
192  plansource->query_list = NIL;
193  plansource->relationOids = NIL;
194  plansource->invalItems = NIL;
195  plansource->search_path = NULL;
196  plansource->query_context = NULL;
197  plansource->rewriteRoleId = InvalidOid;
198  plansource->rewriteRowSecurity = false;
199  plansource->dependsOnRLS = false;
200  plansource->gplan = NULL;
201  plansource->is_oneshot = false;
202  plansource->is_complete = false;
203  plansource->is_saved = false;
204  plansource->is_valid = false;
205  plansource->generation = 0;
206  plansource->next_saved = NULL;
207  plansource->generic_cost = -1;
208  plansource->total_custom_cost = 0;
209  plansource->num_custom_plans = 0;
210 
211  MemoryContextSwitchTo(oldcxt);
212 
213  return plansource;
214 }
MemoryContext context
Definition: plancache.h:93
#define NIL
Definition: pg_list.h:69
bool rewriteRowSecurity
Definition: plancache.h:102
const char * commandTag
Definition: plancache.h:85
char * pstrdup(const char *in)
Definition: mcxt.c:1076
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
double total_custom_cost
Definition: plancache.h:116
struct CachedPlan * gplan
Definition: plancache.h:105
TupleDesc resultDesc
Definition: plancache.h:92
struct CachedPlanSource * next_saved
Definition: plancache.h:113
List * invalItems
Definition: plancache.h:97
Oid * param_types
Definition: plancache.h:86
List * relationOids
Definition: plancache.h:96
void * parserSetupArg
Definition: plancache.h:89
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ParserSetupHook parserSetup
Definition: plancache.h:88
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void * palloc0(Size size)
Definition: mcxt.c:877
#define InvalidOid
Definition: postgres_ext.h:36
double generic_cost
Definition: plancache.h:115
#define Assert(condition)
Definition: c.h:664
const char * query_string
Definition: plancache.h:84
struct RawStmt * raw_parse_tree
Definition: plancache.h:83
MemoryContext query_context
Definition: plancache.h:100
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:182
List * query_list
Definition: plancache.h:95
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
#define copyObject(obj)
Definition: nodes.h:622
struct OverrideSearchPath * search_path
Definition: plancache.h:98
CachedPlanSource* CreateOneShotCachedPlan ( struct RawStmt raw_parse_tree,
const char *  query_string,
const char *  commandTag 
)

Definition at line 235 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::commandTag, CachedPlanSource::context, CurrentMemoryContext, CachedPlanSource::cursor_options, CachedPlanSource::dependsOnRLS, CachedPlanSource::fixed_result, CachedPlanSource::generation, CachedPlanSource::generic_cost, CachedPlanSource::gplan, InvalidOid, CachedPlanSource::invalItems, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::is_valid, CachedPlanSource::magic, CachedPlanSource::next_saved, NIL, CachedPlanSource::num_custom_plans, CachedPlanSource::num_params, palloc0(), CachedPlanSource::param_types, CachedPlanSource::parserSetup, CachedPlanSource::parserSetupArg, CachedPlanSource::query_context, CachedPlanSource::query_list, CachedPlanSource::query_string, CachedPlanSource::raw_parse_tree, CachedPlanSource::relationOids, CachedPlanSource::resultDesc, CachedPlanSource::rewriteRoleId, CachedPlanSource::rewriteRowSecurity, CachedPlanSource::search_path, and CachedPlanSource::total_custom_cost.

Referenced by _SPI_prepare_oneshot_plan().

238 {
239  CachedPlanSource *plansource;
240 
241  Assert(query_string != NULL); /* required as of 8.4 */
242 
243  /*
244  * Create and fill the CachedPlanSource struct within the caller's memory
245  * context. Most fields are just left empty for the moment.
246  */
247  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
248  plansource->magic = CACHEDPLANSOURCE_MAGIC;
249  plansource->raw_parse_tree = raw_parse_tree;
250  plansource->query_string = query_string;
251  plansource->commandTag = commandTag;
252  plansource->param_types = NULL;
253  plansource->num_params = 0;
254  plansource->parserSetup = NULL;
255  plansource->parserSetupArg = NULL;
256  plansource->cursor_options = 0;
257  plansource->fixed_result = false;
258  plansource->resultDesc = NULL;
259  plansource->context = CurrentMemoryContext;
260  plansource->query_list = NIL;
261  plansource->relationOids = NIL;
262  plansource->invalItems = NIL;
263  plansource->search_path = NULL;
264  plansource->query_context = NULL;
265  plansource->rewriteRoleId = InvalidOid;
266  plansource->rewriteRowSecurity = false;
267  plansource->dependsOnRLS = false;
268  plansource->gplan = NULL;
269  plansource->is_oneshot = true;
270  plansource->is_complete = false;
271  plansource->is_saved = false;
272  plansource->is_valid = false;
273  plansource->generation = 0;
274  plansource->next_saved = NULL;
275  plansource->generic_cost = -1;
276  plansource->total_custom_cost = 0;
277  plansource->num_custom_plans = 0;
278 
279  return plansource;
280 }
MemoryContext context
Definition: plancache.h:93
#define NIL
Definition: pg_list.h:69
bool rewriteRowSecurity
Definition: plancache.h:102
const char * commandTag
Definition: plancache.h:85
double total_custom_cost
Definition: plancache.h:116
struct CachedPlan * gplan
Definition: plancache.h:105
TupleDesc resultDesc
Definition: plancache.h:92
struct CachedPlanSource * next_saved
Definition: plancache.h:113
List * invalItems
Definition: plancache.h:97
Oid * param_types
Definition: plancache.h:86
List * relationOids
Definition: plancache.h:96
void * parserSetupArg
Definition: plancache.h:89
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
ParserSetupHook parserSetup
Definition: plancache.h:88
void * palloc0(Size size)
Definition: mcxt.c:877
#define InvalidOid
Definition: postgres_ext.h:36
double generic_cost
Definition: plancache.h:115
#define Assert(condition)
Definition: c.h:664
const char * query_string
Definition: plancache.h:84
struct RawStmt * raw_parse_tree
Definition: plancache.h:83
MemoryContext query_context
Definition: plancache.h:100
List * query_list
Definition: plancache.h:95
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
struct OverrideSearchPath * search_path
Definition: plancache.h:98
void DropCachedPlan ( CachedPlanSource plansource)

Definition at line 486 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::context, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::magic, MemoryContextDelete(), CachedPlanSource::next_saved, and ReleaseGenericPlan().

Referenced by drop_unnamed_stmt(), DropAllPreparedStatements(), DropPreparedStatement(), and SPI_freeplan().

487 {
488  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
489 
490  /* If it's been saved, remove it from the list */
491  if (plansource->is_saved)
492  {
493  if (first_saved_plan == plansource)
494  first_saved_plan = plansource->next_saved;
495  else
496  {
497  CachedPlanSource *psrc;
498 
499  for (psrc = first_saved_plan; psrc; psrc = psrc->next_saved)
500  {
501  if (psrc->next_saved == plansource)
502  {
503  psrc->next_saved = plansource->next_saved;
504  break;
505  }
506  }
507  }
508  plansource->is_saved = false;
509  }
510 
511  /* Decrement generic CachePlan's refcount and drop if no longer needed */
512  ReleaseGenericPlan(plansource);
513 
514  /* Mark it no longer valid */
515  plansource->magic = 0;
516 
517  /*
518  * Remove the CachedPlanSource and all subsidiary data (including the
519  * query_context if any). But if it's a one-shot we can't free anything.
520  */
521  if (!plansource->is_oneshot)
522  MemoryContextDelete(plansource->context);
523 }
MemoryContext context
Definition: plancache.h:93
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:529
struct CachedPlanSource * next_saved
Definition: plancache.h:113
static CachedPlanSource * first_saved_plan
Definition: plancache.c:88
#define Assert(condition)
Definition: c.h:664
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
CachedPlan* GetCachedPlan ( CachedPlanSource plansource,
ParamListInfo  boundParams,
bool  useResOwner,
QueryEnvironment queryEnv 
)

Definition at line 1135 of file plancache.c.

References Assert, BuildCachedPlan(), cached_plan_cost(), CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CacheMemoryContext, CheckCachedPlan(), choose_custom_plan(), CachedPlanSource::context, CachedPlan::context, CurrentResourceOwner, elog, ERROR, CachedPlanSource::generic_cost, CachedPlanSource::gplan, CachedPlanSource::is_complete, CachedPlanSource::is_saved, CachedPlan::is_saved, CachedPlanSource::magic, CachedPlan::magic, MemoryContextGetParent(), MemoryContextSetParent(), NIL, CachedPlanSource::num_custom_plans, CachedPlan::refcount, ReleaseGenericPlan(), ResourceOwnerEnlargePlanCacheRefs(), ResourceOwnerRememberPlanCacheRef(), RevalidateCachedQuery(), and CachedPlanSource::total_custom_cost.

Referenced by _SPI_execute_plan(), exec_bind_message(), ExecuteQuery(), ExplainExecuteQuery(), SPI_cursor_open_internal(), and SPI_plan_get_cached_plan().

1137 {
1138  CachedPlan *plan = NULL;
1139  List *qlist;
1140  bool customplan;
1141 
1142  /* Assert caller is doing things in a sane order */
1143  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1144  Assert(plansource->is_complete);
1145  /* This seems worth a real test, though */
1146  if (useResOwner && !plansource->is_saved)
1147  elog(ERROR, "cannot apply ResourceOwner to non-saved cached plan");
1148 
1149  /* Make sure the querytree list is valid and we have parse-time locks */
1150  qlist = RevalidateCachedQuery(plansource, queryEnv);
1151 
1152  /* Decide whether to use a custom plan */
1153  customplan = choose_custom_plan(plansource, boundParams);
1154 
1155  if (!customplan)
1156  {
1157  if (CheckCachedPlan(plansource))
1158  {
1159  /* We want a generic plan, and we already have a valid one */
1160  plan = plansource->gplan;
1161  Assert(plan->magic == CACHEDPLAN_MAGIC);
1162  }
1163  else
1164  {
1165  /* Build a new generic plan */
1166  plan = BuildCachedPlan(plansource, qlist, NULL, queryEnv);
1167  /* Just make real sure plansource->gplan is clear */
1168  ReleaseGenericPlan(plansource);
1169  /* Link the new generic plan into the plansource */
1170  plansource->gplan = plan;
1171  plan->refcount++;
1172  /* Immediately reparent into appropriate context */
1173  if (plansource->is_saved)
1174  {
1175  /* saved plans all live under CacheMemoryContext */
1177  plan->is_saved = true;
1178  }
1179  else
1180  {
1181  /* otherwise, it should be a sibling of the plansource */
1183  MemoryContextGetParent(plansource->context));
1184  }
1185  /* Update generic_cost whenever we make a new generic plan */
1186  plansource->generic_cost = cached_plan_cost(plan, false);
1187 
1188  /*
1189  * If, based on the now-known value of generic_cost, we'd not have
1190  * chosen to use a generic plan, then forget it and make a custom
1191  * plan. This is a bit of a wart but is necessary to avoid a
1192  * glitch in behavior when the custom plans are consistently big
1193  * winners; at some point we'll experiment with a generic plan and
1194  * find it's a loser, but we don't want to actually execute that
1195  * plan.
1196  */
1197  customplan = choose_custom_plan(plansource, boundParams);
1198 
1199  /*
1200  * If we choose to plan again, we need to re-copy the query_list,
1201  * since the planner probably scribbled on it. We can force
1202  * BuildCachedPlan to do that by passing NIL.
1203  */
1204  qlist = NIL;
1205  }
1206  }
1207 
1208  if (customplan)
1209  {
1210  /* Build a custom plan */
1211  plan = BuildCachedPlan(plansource, qlist, boundParams, queryEnv);
1212  /* Accumulate total costs of custom plans, but 'ware overflow */
1213  if (plansource->num_custom_plans < INT_MAX)
1214  {
1215  plansource->total_custom_cost += cached_plan_cost(plan, true);
1216  plansource->num_custom_plans++;
1217  }
1218  }
1219 
1220  Assert(plan != NULL);
1221 
1222  /* Flag the plan as in use by caller */
1223  if (useResOwner)
1225  plan->refcount++;
1226  if (useResOwner)
1228 
1229  /*
1230  * Saved plans should be under CacheMemoryContext so they will not go away
1231  * until their reference count goes to zero. In the generic-plan cases we
1232  * already took care of that, but for a custom plan, do it as soon as we
1233  * have created a reference-counted link.
1234  */
1235  if (customplan && plansource->is_saved)
1236  {
1238  plan->is_saved = true;
1239  }
1240 
1241  return plan;
1242 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:26
MemoryContext context
Definition: plancache.h:93
static CachedPlan * BuildCachedPlan(CachedPlanSource *plansource, List *qlist, ParamListInfo boundParams, QueryEnvironment *queryEnv)
Definition: plancache.c:881
#define NIL
Definition: pg_list.h:69
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:529
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:402
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
int refcount
Definition: plancache.h:142
void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1064
void ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
Definition: resowner.c:1053
MemoryContext context
Definition: plancache.h:143
double total_custom_cost
Definition: plancache.h:116
struct CachedPlan * gplan
Definition: plancache.h:105
#define ERROR
Definition: elog.h:43
static List * RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:557
bool is_saved
Definition: plancache.h:135
double generic_cost
Definition: plancache.h:115
#define Assert(condition)
Definition: c.h:664
static bool CheckCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:797
#define elog
Definition: elog.h:219
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
Definition: pg_list.h:45
static bool choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams)
Definition: plancache.c:1019
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
static double cached_plan_cost(CachedPlan *plan, bool include_planner)
Definition: plancache.c:1070
void InitPlanCache ( void  )

Definition at line 116 of file plancache.c.

References AMOPOPID, CacheRegisterRelcacheCallback(), CacheRegisterSyscacheCallback(), FOREIGNDATAWRAPPEROID, FOREIGNSERVEROID, NAMESPACEOID, OPEROID, PlanCacheFuncCallback(), PlanCacheRelCallback(), PlanCacheSysCallback(), and PROCOID.

Referenced by InitPostgres().

117 {
125 }
static void PlanCacheFuncCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:1772
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1431
static void PlanCacheRelCallback(Datum arg, Oid relid)
Definition: plancache.c:1707
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1389
uintptr_t Datum
Definition: postgres.h:372
static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:1851
void ReleaseCachedPlan ( CachedPlan plan,
bool  useResOwner 
)

Definition at line 1256 of file plancache.c.

References Assert, CACHEDPLAN_MAGIC, CachedPlan::context, CurrentResourceOwner, CachedPlan::is_oneshot, CachedPlan::is_saved, CachedPlan::magic, MemoryContextDelete(), CachedPlan::refcount, and ResourceOwnerForgetPlanCacheRef().

Referenced by _SPI_execute_plan(), exec_eval_simple_expr(), exec_simple_check_plan(), ExplainExecuteQuery(), PortalReleaseCachedPlan(), ReleaseGenericPlan(), ResourceOwnerReleaseInternal(), and SPI_cursor_open_internal().

1257 {
1258  Assert(plan->magic == CACHEDPLAN_MAGIC);
1259  if (useResOwner)
1260  {
1261  Assert(plan->is_saved);
1263  }
1264  Assert(plan->refcount > 0);
1265  plan->refcount--;
1266  if (plan->refcount == 0)
1267  {
1268  /* Mark it no longer valid */
1269  plan->magic = 0;
1270 
1271  /* One-shot plans do not own their context, so we can't free them */
1272  if (!plan->is_oneshot)
1274  }
1275 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:26
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
int refcount
Definition: plancache.h:142
MemoryContext context
Definition: plancache.h:143
void ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1073
bool is_saved
Definition: plancache.h:135
#define Assert(condition)
Definition: c.h:664
bool is_oneshot
Definition: plancache.h:134
void ResetPlanCache ( void  )

Definition at line 1860 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, CMD_UTILITY, Query::commandType, CachedPlanSource::gplan, CachedPlanSource::is_valid, CachedPlan::is_valid, IsTransactionStmtPlan, lfirst_node, CachedPlanSource::magic, CachedPlanSource::next_saved, CachedPlanSource::query_list, UtilityContainsQuery(), and Query::utilityStmt.

Referenced by assign_session_replication_role(), DiscardAll(), DiscardCommand(), and PlanCacheSysCallback().

1861 {
1862  CachedPlanSource *plansource;
1863 
1864  for (plansource = first_saved_plan; plansource; plansource = plansource->next_saved)
1865  {
1866  ListCell *lc;
1867 
1868  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1869 
1870  /* No work if it's already invalidated */
1871  if (!plansource->is_valid)
1872  continue;
1873 
1874  /*
1875  * We *must not* mark transaction control statements as invalid,
1876  * particularly not ROLLBACK, because they may need to be executed in
1877  * aborted transactions when we can't revalidate them (cf bug #5269).
1878  */
1879  if (IsTransactionStmtPlan(plansource))
1880  continue;
1881 
1882  /*
1883  * In general there is no point in invalidating utility statements
1884  * since they have no plans anyway. So invalidate it only if it
1885  * contains at least one non-utility statement, or contains a utility
1886  * statement that contains a pre-analyzed query (which could have
1887  * dependencies.)
1888  */
1889  foreach(lc, plansource->query_list)
1890  {
1891  Query *query = lfirst_node(Query, lc);
1892 
1893  if (query->commandType != CMD_UTILITY ||
1895  {
1896  /* non-utility statement, so invalidate */
1897  plansource->is_valid = false;
1898  if (plansource->gplan)
1899  plansource->gplan->is_valid = false;
1900  /* no need to look further */
1901  break;
1902  }
1903  }
1904  }
1905 }
bool is_valid
Definition: plancache.h:136
Node * utilityStmt
Definition: parsenodes.h:118
struct CachedPlan * gplan
Definition: plancache.h:105
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:1856
struct CachedPlanSource * next_saved
Definition: plancache.h:113
#define lfirst_node(type, lc)
Definition: pg_list.h:109
static CachedPlanSource * first_saved_plan
Definition: plancache.c:88
CmdType commandType
Definition: parsenodes.h:110
#define Assert(condition)
Definition: c.h:664
List * query_list
Definition: plancache.h:95
#define IsTransactionStmtPlan(plansource)
Definition: plancache.c:78
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
void SaveCachedPlan ( CachedPlanSource plansource)

Definition at line 441 of file plancache.c.

References Assert, CACHEDPLANSOURCE_MAGIC, CacheMemoryContext, CachedPlanSource::context, elog, ERROR, first_saved_plan, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_saved, CachedPlanSource::magic, MemoryContextSetParent(), CachedPlanSource::next_saved, and ReleaseGenericPlan().

Referenced by _SPI_save_plan(), exec_parse_message(), SPI_keepplan(), and StorePreparedStatement().

442 {
443  /* Assert caller is doing things in a sane order */
444  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
445  Assert(plansource->is_complete);
446  Assert(!plansource->is_saved);
447 
448  /* This seems worth a real test, though */
449  if (plansource->is_oneshot)
450  elog(ERROR, "cannot save one-shot cached plan");
451 
452  /*
453  * In typical use, this function would be called before generating any
454  * plans from the CachedPlanSource. If there is a generic plan, moving it
455  * into CacheMemoryContext would be pretty risky since it's unclear
456  * whether the caller has taken suitable care with making references
457  * long-lived. Best thing to do seems to be to discard the plan.
458  */
459  ReleaseGenericPlan(plansource);
460 
461  /*
462  * Reparent the source memory context under CacheMemoryContext so that it
463  * will live indefinitely. The query_context follows along since it's
464  * already a child of the other one.
465  */
467 
468  /*
469  * Add the entry to the global list of cached plans.
470  */
471  plansource->next_saved = first_saved_plan;
472  first_saved_plan = plansource;
473 
474  plansource->is_saved = true;
475 }
MemoryContext context
Definition: plancache.h:93
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:529
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
struct CachedPlanSource * next_saved
Definition: plancache.h:113
#define ERROR
Definition: elog.h:43
static CachedPlanSource * first_saved_plan
Definition: plancache.c:88
#define Assert(condition)
Definition: c.h:664
#define elog
Definition: elog.h:219
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:25
MemoryContext CacheMemoryContext
Definition: mcxt.c:46