PostgreSQL Source Code  git master
plancache.h File Reference
#include "access/tupdesc.h"
#include "lib/ilist.h"
#include "nodes/params.h"
#include "tcop/cmdtag.h"
#include "utils/queryenvironment.h"
#include "utils/resowner.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
 
struct  CachedExpression
 

Macros

#define CACHEDPLANSOURCE_MAGIC   195726186
 
#define CACHEDPLAN_MAGIC   953717834
 
#define CACHEDEXPR_MAGIC   838275847
 

Typedefs

typedef struct CachedPlanSource CachedPlanSource
 
typedef struct CachedPlan CachedPlan
 
typedef struct CachedExpression CachedExpression
 

Enumerations

enum  PlanCacheMode { PLAN_CACHE_MODE_AUTO, PLAN_CACHE_MODE_FORCE_GENERIC_PLAN, PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN }
 

Functions

void InitPlanCache (void)
 
void ResetPlanCache (void)
 
CachedPlanSourceCreateCachedPlan (struct RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
 
CachedPlanSourceCreateOneShotCachedPlan (struct RawStmt *raw_parse_tree, const char *query_string, CommandTag 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, ResourceOwner owner, QueryEnvironment *queryEnv)
 
void ReleaseCachedPlan (CachedPlan *plan, ResourceOwner owner)
 
bool CachedPlanAllowsSimpleValidityCheck (CachedPlanSource *plansource, CachedPlan *plan, ResourceOwner owner)
 
bool CachedPlanIsSimplyValid (CachedPlanSource *plansource, CachedPlan *plan, ResourceOwner owner)
 
CachedExpressionGetCachedExpression (Node *expr)
 
void FreeCachedExpression (CachedExpression *cexpr)
 

Variables

int plan_cache_mode
 

Macro Definition Documentation

◆ CACHEDEXPR_MAGIC

#define CACHEDEXPR_MAGIC   838275847

◆ CACHEDPLAN_MAGIC

◆ CACHEDPLANSOURCE_MAGIC

Typedef Documentation

◆ CachedExpression

◆ CachedPlan

typedef struct CachedPlan CachedPlan

◆ CachedPlanSource

Enumeration Type Documentation

◆ PlanCacheMode

Enumerator
PLAN_CACHE_MODE_AUTO 
PLAN_CACHE_MODE_FORCE_GENERIC_PLAN 
PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN 

Definition at line 30 of file plancache.h.

Function Documentation

◆ CachedPlanAllowsSimpleValidityCheck()

bool CachedPlanAllowsSimpleValidityCheck ( CachedPlanSource plansource,
CachedPlan plan,
ResourceOwner  owner 
)

Definition at line 1310 of file plancache.c.

References Assert, CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CMD_UTILITY, PlannedStmt::commandType, Query::commandType, Query::cteList, CachedPlanSource::dependsOnRLS, CachedPlan::dependsOnRole, CachedPlanSource::gplan, Query::hasSubLinks, CachedPlanSource::is_oneshot, CachedPlan::is_oneshot, CachedPlan::is_valid, lfirst, lfirst_node, CachedPlanSource::magic, CachedPlan::magic, OverrideSearchPathMatchesCurrent(), CachedPlanSource::query_list, CachedPlan::refcount, ResourceOwnerEnlargePlanCacheRefs(), ResourceOwnerRememberPlanCacheRef(), PlannedStmt::rtable, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, CachedPlan::saved_xmin, CachedPlanSource::search_path, CachedPlan::stmt_list, and TransactionIdIsValid.

Referenced by exec_eval_simple_expr(), and exec_simple_check_plan().

1312 {
1313  ListCell *lc;
1314 
1315  /*
1316  * Sanity-check that the caller gave us a validated generic plan. Notice
1317  * that we *don't* assert plansource->is_valid as you might expect; that's
1318  * because it's possible that that's already false when GetCachedPlan
1319  * returns, e.g. because ResetPlanCache happened partway through. We
1320  * should accept the plan as long as plan->is_valid is true, and expect to
1321  * replan after the next CachedPlanIsSimplyValid call.
1322  */
1323  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1324  Assert(plan->magic == CACHEDPLAN_MAGIC);
1325  Assert(plan->is_valid);
1326  Assert(plan == plansource->gplan);
1327  Assert(plansource->search_path != NULL);
1329 
1330  /* We don't support oneshot plans here. */
1331  if (plansource->is_oneshot)
1332  return false;
1333  Assert(!plan->is_oneshot);
1334 
1335  /*
1336  * If the plan is dependent on RLS considerations, or it's transient,
1337  * reject. These things probably can't ever happen for table-free
1338  * queries, but for safety's sake let's check.
1339  */
1340  if (plansource->dependsOnRLS)
1341  return false;
1342  if (plan->dependsOnRole)
1343  return false;
1344  if (TransactionIdIsValid(plan->saved_xmin))
1345  return false;
1346 
1347  /*
1348  * Reject if AcquirePlannerLocks would have anything to do. This is
1349  * simplistic, but there's no need to inquire any more carefully; indeed,
1350  * for current callers it shouldn't even be possible to hit any of these
1351  * checks.
1352  */
1353  foreach(lc, plansource->query_list)
1354  {
1355  Query *query = lfirst_node(Query, lc);
1356 
1357  if (query->commandType == CMD_UTILITY)
1358  return false;
1359  if (query->rtable || query->cteList || query->hasSubLinks)
1360  return false;
1361  }
1362 
1363  /*
1364  * Reject if AcquireExecutorLocks would have anything to do. This is
1365  * probably unnecessary given the previous check, but let's be safe.
1366  */
1367  foreach(lc, plan->stmt_list)
1368  {
1369  PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
1370  ListCell *lc2;
1371 
1372  if (plannedstmt->commandType == CMD_UTILITY)
1373  return false;
1374 
1375  /*
1376  * We have to grovel through the rtable because it's likely to contain
1377  * an RTE_RESULT relation, rather than being totally empty.
1378  */
1379  foreach(lc2, plannedstmt->rtable)
1380  {
1381  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
1382 
1383  if (rte->rtekind == RTE_RELATION)
1384  return false;
1385  }
1386  }
1387 
1388  /*
1389  * Okay, it's simple. Note that what we've primarily established here is
1390  * that no locks need be taken before checking the plan's is_valid flag.
1391  */
1392 
1393  /* Bump refcount if requested. */
1394  if (owner)
1395  {
1397  plan->refcount++;
1398  ResourceOwnerRememberPlanCacheRef(owner, plan);
1399  }
1400 
1401  return true;
1402 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:41
bool is_valid
Definition: plancache.h:153
int refcount
Definition: plancache.h:159
void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1161
bool dependsOnRole
Definition: plancache.h:155
void ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
Definition: resowner.c:1150
struct CachedPlan * gplan
Definition: plancache.h:121
List * rtable
Definition: parsenodes.h:147
#define lfirst_node(type, lc)
Definition: pg_list.h:172
CmdType commandType
Definition: plannodes.h:46
CmdType commandType
Definition: parsenodes.h:120
bool OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
Definition: namespace.c:3464
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
List * rtable
Definition: plannodes.h:66
bool is_oneshot
Definition: plancache.h:151
RTEKind rtekind
Definition: parsenodes.h:995
List * cteList
Definition: parsenodes.h:145
bool hasSubLinks
Definition: parsenodes.h:136
List * query_list
Definition: plancache.h:111
List * stmt_list
Definition: plancache.h:150
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40
#define TransactionIdIsValid(xid)
Definition: transam.h:41
TransactionId saved_xmin
Definition: plancache.h:156
struct OverrideSearchPath * search_path
Definition: plancache.h:114

◆ CachedPlanGetTargetList()

List* CachedPlanGetTargetList ( CachedPlanSource plansource,
QueryEnvironment queryEnv 
)

Definition at line 1612 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().

1614 {
1615  Query *pstmt;
1616 
1617  /* Assert caller is doing things in a sane order */
1618  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1619  Assert(plansource->is_complete);
1620 
1621  /*
1622  * No work needed if statement doesn't return tuples (we assume this
1623  * feature cannot be changed by an invalidation)
1624  */
1625  if (plansource->resultDesc == NULL)
1626  return NIL;
1627 
1628  /* Make sure the querytree list is valid and we have parse-time locks */
1629  RevalidateCachedQuery(plansource, queryEnv);
1630 
1631  /* Get the primary statement and find out what it returns */
1632  pstmt = QueryListGetPrimaryStmt(plansource->query_list);
1633 
1634  return FetchStatementTargetList((Node *) pstmt);
1635 }
#define NIL
Definition: pg_list.h:65
Definition: nodes.h:539
TupleDesc resultDesc
Definition: plancache.h:108
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:345
static Query * QueryListGetPrimaryStmt(List *stmts)
Definition: plancache.c:1725
static List * RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:555
#define Assert(condition)
Definition: c.h:804
List * query_list
Definition: plancache.h:111
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40

◆ CachedPlanIsSimplyValid()

bool CachedPlanIsSimplyValid ( CachedPlanSource plansource,
CachedPlan plan,
ResourceOwner  owner 
)

Definition at line 1425 of file plancache.c.

References Assert, CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::gplan, CachedPlanSource::is_valid, CachedPlan::is_valid, CachedPlanSource::magic, CachedPlan::magic, OverrideSearchPathMatchesCurrent(), CachedPlan::refcount, ResourceOwnerEnlargePlanCacheRefs(), ResourceOwnerRememberPlanCacheRef(), and CachedPlanSource::search_path.

Referenced by exec_eval_simple_expr().

1427 {
1428  /*
1429  * Careful here: since the caller doesn't necessarily hold a refcount on
1430  * the plan to start with, it's possible that "plan" is a dangling
1431  * pointer. Don't dereference it until we've verified that it still
1432  * matches the plansource's gplan (which is either valid or NULL).
1433  */
1434  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1435 
1436  /*
1437  * Has cache invalidation fired on this plan? We can check this right
1438  * away since there are no locks that we'd need to acquire first. Note
1439  * that here we *do* check plansource->is_valid, so as to force plan
1440  * rebuild if that's become false.
1441  */
1442  if (!plansource->is_valid || plan != plansource->gplan || !plan->is_valid)
1443  return false;
1444 
1445  Assert(plan->magic == CACHEDPLAN_MAGIC);
1446 
1447  /* Is the search_path still the same as when we made it? */
1448  Assert(plansource->search_path != NULL);
1450  return false;
1451 
1452  /* It's still good. Bump refcount if requested. */
1453  if (owner)
1454  {
1456  plan->refcount++;
1457  ResourceOwnerRememberPlanCacheRef(owner, plan);
1458  }
1459 
1460  return true;
1461 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:41
bool is_valid
Definition: plancache.h:153
int refcount
Definition: plancache.h:159
void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1161
void ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
Definition: resowner.c:1150
struct CachedPlan * gplan
Definition: plancache.h:121
bool OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
Definition: namespace.c:3464
#define Assert(condition)
Definition: c.h:804
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40
struct OverrideSearchPath * search_path
Definition: plancache.h:114

◆ CachedPlanIsValid()

bool CachedPlanIsValid ( CachedPlanSource plansource)

Definition at line 1599 of file plancache.c.

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

Referenced by SPI_plan_is_valid().

1600 {
1601  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1602  return plansource->is_valid;
1603 }
#define Assert(condition)
Definition: c.h:804
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40

◆ CachedPlanSetParentContext()

void CachedPlanSetParentContext ( CachedPlanSource plansource,
MemoryContext  newcontext 
)

Definition at line 1470 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().

1472 {
1473  /* Assert caller is doing things in a sane order */
1474  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1475  Assert(plansource->is_complete);
1476 
1477  /* These seem worth real tests, though */
1478  if (plansource->is_saved)
1479  elog(ERROR, "cannot move a saved cached plan to another context");
1480  if (plansource->is_oneshot)
1481  elog(ERROR, "cannot move a one-shot cached plan to another context");
1482 
1483  /* OK, let the caller keep the plan where he wishes */
1484  MemoryContextSetParent(plansource->context, newcontext);
1485 
1486  /*
1487  * The query_context needs no special handling, since it's a child of
1488  * plansource->context. But if there's a generic plan, it should be
1489  * maintained as a sibling of plansource->context.
1490  */
1491  if (plansource->gplan)
1492  {
1493  Assert(plansource->gplan->magic == CACHEDPLAN_MAGIC);
1494  MemoryContextSetParent(plansource->gplan->context, newcontext);
1495  }
1496 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:41
MemoryContext context
Definition: plancache.h:109
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:361
MemoryContext context
Definition: plancache.h:160
struct CachedPlan * gplan
Definition: plancache.h:121
#define ERROR
Definition: elog.h:46
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40

◆ CompleteCachedPlan()

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 338 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().

347 {
348  MemoryContext source_context = plansource->context;
350 
351  /* Assert caller is doing things in a sane order */
352  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
353  Assert(!plansource->is_complete);
354 
355  /*
356  * If caller supplied a querytree_context, reparent it underneath the
357  * CachedPlanSource's context; otherwise, create a suitable context and
358  * copy the querytree_list into it. But no data copying should be done
359  * for one-shot plans; for those, assume the passed querytree_list is
360  * sufficiently long-lived.
361  */
362  if (plansource->is_oneshot)
363  {
364  querytree_context = CurrentMemoryContext;
365  }
366  else if (querytree_context != NULL)
367  {
368  MemoryContextSetParent(querytree_context, source_context);
369  MemoryContextSwitchTo(querytree_context);
370  }
371  else
372  {
373  /* Again, it's a good bet the querytree_context can be small */
374  querytree_context = AllocSetContextCreate(source_context,
375  "CachedPlanQuery",
377  MemoryContextSwitchTo(querytree_context);
378  querytree_list = copyObject(querytree_list);
379  }
380 
381  plansource->query_context = querytree_context;
382  plansource->query_list = querytree_list;
383 
384  if (!plansource->is_oneshot && !IsTransactionStmtPlan(plansource))
385  {
386  /*
387  * Use the planner machinery to extract dependencies. Data is saved
388  * in query_context. (We assume that not a lot of extra cruft is
389  * created by this call.) We can skip this for one-shot plans, and
390  * transaction control commands have no such dependencies anyway.
391  */
392  extract_query_dependencies((Node *) querytree_list,
393  &plansource->relationOids,
394  &plansource->invalItems,
395  &plansource->dependsOnRLS);
396 
397  /* Update RLS info as well. */
398  plansource->rewriteRoleId = GetUserId();
399  plansource->rewriteRowSecurity = row_security;
400 
401  /*
402  * Also save the current search_path in the query_context. (This
403  * should not generate much extra cruft either, since almost certainly
404  * the path is already valid.) Again, we don't really need this for
405  * one-shot plans; and we *must* skip this for transaction control
406  * commands, because this could result in catalog accesses.
407  */
408  plansource->search_path = GetOverrideSearchPath(querytree_context);
409  }
410 
411  /*
412  * Save the final parameter types (or other parameter specification data)
413  * into the source_context, as well as our other parameters. Also save
414  * the result tuple descriptor.
415  */
416  MemoryContextSwitchTo(source_context);
417 
418  if (num_params > 0)
419  {
420  plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
421  memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
422  }
423  else
424  plansource->param_types = NULL;
425  plansource->num_params = num_params;
426  plansource->parserSetup = parserSetup;
427  plansource->parserSetupArg = parserSetupArg;
428  plansource->cursor_options = cursor_options;
429  plansource->fixed_result = fixed_result;
430  plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
431 
432  MemoryContextSwitchTo(oldcxt);
433 
434  plansource->is_complete = true;
435  plansource->is_valid = true;
436 }
MemoryContext context
Definition: plancache.h:109
bool rewriteRowSecurity
Definition: plancache.h:118
#define AllocSetContextCreate
Definition: memutils.h:173
Oid GetUserId(void)
Definition: miscinit.c:478
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:361
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:539
unsigned int Oid
Definition: postgres_ext.h:31
TupleDesc resultDesc
Definition: plancache.h:108
List * invalItems
Definition: plancache.h:113
OverrideSearchPath * GetOverrideSearchPath(MemoryContext context)
Definition: namespace.c:3405
List * relationOids
Definition: plancache.h:112
void * parserSetupArg
Definition: plancache.h:105
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
ParserSetupHook parserSetup
Definition: plancache.h:104
bool row_security
Definition: guc.c:569
#define Assert(condition)
Definition: c.h:804
void extract_query_dependencies(Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
Definition: setrefs.c:3030
void * palloc(Size size)
Definition: mcxt.c:1062
MemoryContext query_context
Definition: plancache.h:116
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:212
List * query_list
Definition: plancache.h:111
#define IsTransactionStmtPlan(plansource)
Definition: plancache.c:82
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40
#define copyObject(obj)
Definition: nodes.h:655
static TupleDesc PlanCacheComputeResultDesc(List *stmt_list)
Definition: plancache.c:1912
struct OverrideSearchPath * search_path
Definition: plancache.h:114

◆ CopyCachedPlan()

CachedPlanSource* CopyCachedPlan ( CachedPlanSource plansource)

Definition at line 1508 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, MemoryContextSetIdentifier(), MemoryContextSwitchTo(), CachedPlanSource::num_custom_plans, CachedPlanSource::num_generic_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().

1509 {
1510  CachedPlanSource *newsource;
1511  MemoryContext source_context;
1512  MemoryContext querytree_context;
1513  MemoryContext oldcxt;
1514 
1515  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1516  Assert(plansource->is_complete);
1517 
1518  /*
1519  * One-shot plans can't be copied, because we haven't taken care that
1520  * parsing/planning didn't scribble on the raw parse tree or querytrees.
1521  */
1522  if (plansource->is_oneshot)
1523  elog(ERROR, "cannot copy a one-shot cached plan");
1524 
1526  "CachedPlanSource",
1528 
1529  oldcxt = MemoryContextSwitchTo(source_context);
1530 
1531  newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1532  newsource->magic = CACHEDPLANSOURCE_MAGIC;
1533  newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
1534  newsource->query_string = pstrdup(plansource->query_string);
1535  MemoryContextSetIdentifier(source_context, newsource->query_string);
1536  newsource->commandTag = plansource->commandTag;
1537  if (plansource->num_params > 0)
1538  {
1539  newsource->param_types = (Oid *)
1540  palloc(plansource->num_params * sizeof(Oid));
1541  memcpy(newsource->param_types, plansource->param_types,
1542  plansource->num_params * sizeof(Oid));
1543  }
1544  else
1545  newsource->param_types = NULL;
1546  newsource->num_params = plansource->num_params;
1547  newsource->parserSetup = plansource->parserSetup;
1548  newsource->parserSetupArg = plansource->parserSetupArg;
1549  newsource->cursor_options = plansource->cursor_options;
1550  newsource->fixed_result = plansource->fixed_result;
1551  if (plansource->resultDesc)
1552  newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
1553  else
1554  newsource->resultDesc = NULL;
1555  newsource->context = source_context;
1556 
1557  querytree_context = AllocSetContextCreate(source_context,
1558  "CachedPlanQuery",
1560  MemoryContextSwitchTo(querytree_context);
1561  newsource->query_list = copyObject(plansource->query_list);
1562  newsource->relationOids = copyObject(plansource->relationOids);
1563  newsource->invalItems = copyObject(plansource->invalItems);
1564  if (plansource->search_path)
1565  newsource->search_path = CopyOverrideSearchPath(plansource->search_path);
1566  newsource->query_context = querytree_context;
1567  newsource->rewriteRoleId = plansource->rewriteRoleId;
1568  newsource->rewriteRowSecurity = plansource->rewriteRowSecurity;
1569  newsource->dependsOnRLS = plansource->dependsOnRLS;
1570 
1571  newsource->gplan = NULL;
1572 
1573  newsource->is_oneshot = false;
1574  newsource->is_complete = true;
1575  newsource->is_saved = false;
1576  newsource->is_valid = plansource->is_valid;
1577  newsource->generation = plansource->generation;
1578 
1579  /* We may as well copy any acquired cost knowledge */
1580  newsource->generic_cost = plansource->generic_cost;
1581  newsource->total_custom_cost = plansource->total_custom_cost;
1582  newsource->num_generic_plans = plansource->num_generic_plans;
1583  newsource->num_custom_plans = plansource->num_custom_plans;
1584 
1585  MemoryContextSwitchTo(oldcxt);
1586 
1587  return newsource;
1588 }
MemoryContext context
Definition: plancache.h:109
bool rewriteRowSecurity
Definition: plancache.h:118
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define AllocSetContextCreate
Definition: memutils.h:173
char * pstrdup(const char *in)
Definition: mcxt.c:1299
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
double total_custom_cost
Definition: plancache.h:132
struct CachedPlan * gplan
Definition: plancache.h:121
int64 num_custom_plans
Definition: plancache.h:133
TupleDesc resultDesc
Definition: plancache.h:108
#define ERROR
Definition: elog.h:46
OverrideSearchPath * CopyOverrideSearchPath(OverrideSearchPath *path)
Definition: namespace.c:3442
List * invalItems
Definition: plancache.h:113
List * relationOids
Definition: plancache.h:112
void * parserSetupArg
Definition: plancache.h:105
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
ParserSetupHook parserSetup
Definition: plancache.h:104
void * palloc0(Size size)
Definition: mcxt.c:1093
int64 num_generic_plans
Definition: plancache.h:134
double generic_cost
Definition: plancache.h:131
#define Assert(condition)
Definition: c.h:804
const char * query_string
Definition: plancache.h:100
CommandTag commandTag
Definition: plancache.h:101
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:336
struct RawStmt * raw_parse_tree
Definition: plancache.h:99
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
MemoryContext query_context
Definition: plancache.h:116
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:212
List * query_list
Definition: plancache.h:111
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40
#define copyObject(obj)
Definition: nodes.h:655
struct OverrideSearchPath * search_path
Definition: plancache.h:114

◆ CreateCachedPlan()

CachedPlanSource* CreateCachedPlan ( struct RawStmt raw_parse_tree,
const char *  query_string,
CommandTag  commandTag 
)

Definition at line 164 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, MemoryContextSetIdentifier(), MemoryContextSwitchTo(), NIL, CachedPlanSource::num_custom_plans, CachedPlanSource::num_generic_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().

167 {
168  CachedPlanSource *plansource;
169  MemoryContext source_context;
170  MemoryContext oldcxt;
171 
172  Assert(query_string != NULL); /* required as of 8.4 */
173 
174  /*
175  * Make a dedicated memory context for the CachedPlanSource and its
176  * permanent subsidiary data. It's probably not going to be large, but
177  * just in case, allow it to grow large. Initially it's a child of the
178  * caller's context (which we assume to be transient), so that it will be
179  * cleaned up on error.
180  */
182  "CachedPlanSource",
184 
185  /*
186  * Create and fill the CachedPlanSource struct within the new context.
187  * Most fields are just left empty for the moment.
188  */
189  oldcxt = MemoryContextSwitchTo(source_context);
190 
191  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
192  plansource->magic = CACHEDPLANSOURCE_MAGIC;
193  plansource->raw_parse_tree = copyObject(raw_parse_tree);
194  plansource->query_string = pstrdup(query_string);
195  MemoryContextSetIdentifier(source_context, plansource->query_string);
196  plansource->commandTag = commandTag;
197  plansource->param_types = NULL;
198  plansource->num_params = 0;
199  plansource->parserSetup = NULL;
200  plansource->parserSetupArg = NULL;
201  plansource->cursor_options = 0;
202  plansource->fixed_result = false;
203  plansource->resultDesc = NULL;
204  plansource->context = source_context;
205  plansource->query_list = NIL;
206  plansource->relationOids = NIL;
207  plansource->invalItems = NIL;
208  plansource->search_path = NULL;
209  plansource->query_context = NULL;
210  plansource->rewriteRoleId = InvalidOid;
211  plansource->rewriteRowSecurity = false;
212  plansource->dependsOnRLS = false;
213  plansource->gplan = NULL;
214  plansource->is_oneshot = false;
215  plansource->is_complete = false;
216  plansource->is_saved = false;
217  plansource->is_valid = false;
218  plansource->generation = 0;
219  plansource->generic_cost = -1;
220  plansource->total_custom_cost = 0;
221  plansource->num_generic_plans = 0;
222  plansource->num_custom_plans = 0;
223 
224  MemoryContextSwitchTo(oldcxt);
225 
226  return plansource;
227 }
MemoryContext context
Definition: plancache.h:109
#define NIL
Definition: pg_list.h:65
bool rewriteRowSecurity
Definition: plancache.h:118
#define AllocSetContextCreate
Definition: memutils.h:173
char * pstrdup(const char *in)
Definition: mcxt.c:1299
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
double total_custom_cost
Definition: plancache.h:132
struct CachedPlan * gplan
Definition: plancache.h:121
int64 num_custom_plans
Definition: plancache.h:133
TupleDesc resultDesc
Definition: plancache.h:108
List * invalItems
Definition: plancache.h:113
List * relationOids
Definition: plancache.h:112
void * parserSetupArg
Definition: plancache.h:105
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
ParserSetupHook parserSetup
Definition: plancache.h:104
void * palloc0(Size size)
Definition: mcxt.c:1093
int64 num_generic_plans
Definition: plancache.h:134
#define InvalidOid
Definition: postgres_ext.h:36
double generic_cost
Definition: plancache.h:131
#define Assert(condition)
Definition: c.h:804
const char * query_string
Definition: plancache.h:100
CommandTag commandTag
Definition: plancache.h:101
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:336
struct RawStmt * raw_parse_tree
Definition: plancache.h:99
MemoryContext query_context
Definition: plancache.h:116
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:212
List * query_list
Definition: plancache.h:111
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40
#define copyObject(obj)
Definition: nodes.h:655
struct OverrideSearchPath * search_path
Definition: plancache.h:114

◆ CreateOneShotCachedPlan()

CachedPlanSource* CreateOneShotCachedPlan ( struct RawStmt raw_parse_tree,
const char *  query_string,
CommandTag  commandTag 
)

Definition at line 248 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, NIL, CachedPlanSource::num_custom_plans, CachedPlanSource::num_generic_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().

251 {
252  CachedPlanSource *plansource;
253 
254  Assert(query_string != NULL); /* required as of 8.4 */
255 
256  /*
257  * Create and fill the CachedPlanSource struct within the caller's memory
258  * context. Most fields are just left empty for the moment.
259  */
260  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
261  plansource->magic = CACHEDPLANSOURCE_MAGIC;
262  plansource->raw_parse_tree = raw_parse_tree;
263  plansource->query_string = query_string;
264  plansource->commandTag = commandTag;
265  plansource->param_types = NULL;
266  plansource->num_params = 0;
267  plansource->parserSetup = NULL;
268  plansource->parserSetupArg = NULL;
269  plansource->cursor_options = 0;
270  plansource->fixed_result = false;
271  plansource->resultDesc = NULL;
272  plansource->context = CurrentMemoryContext;
273  plansource->query_list = NIL;
274  plansource->relationOids = NIL;
275  plansource->invalItems = NIL;
276  plansource->search_path = NULL;
277  plansource->query_context = NULL;
278  plansource->rewriteRoleId = InvalidOid;
279  plansource->rewriteRowSecurity = false;
280  plansource->dependsOnRLS = false;
281  plansource->gplan = NULL;
282  plansource->is_oneshot = true;
283  plansource->is_complete = false;
284  plansource->is_saved = false;
285  plansource->is_valid = false;
286  plansource->generation = 0;
287  plansource->generic_cost = -1;
288  plansource->total_custom_cost = 0;
289  plansource->num_generic_plans = 0;
290  plansource->num_custom_plans = 0;
291 
292  return plansource;
293 }
MemoryContext context
Definition: plancache.h:109
#define NIL
Definition: pg_list.h:65
bool rewriteRowSecurity
Definition: plancache.h:118
double total_custom_cost
Definition: plancache.h:132
struct CachedPlan * gplan
Definition: plancache.h:121
int64 num_custom_plans
Definition: plancache.h:133
TupleDesc resultDesc
Definition: plancache.h:108
List * invalItems
Definition: plancache.h:113
List * relationOids
Definition: plancache.h:112
void * parserSetupArg
Definition: plancache.h:105
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
ParserSetupHook parserSetup
Definition: plancache.h:104
void * palloc0(Size size)
Definition: mcxt.c:1093
int64 num_generic_plans
Definition: plancache.h:134
#define InvalidOid
Definition: postgres_ext.h:36
double generic_cost
Definition: plancache.h:131
#define Assert(condition)
Definition: c.h:804
const char * query_string
Definition: plancache.h:100
CommandTag commandTag
Definition: plancache.h:101
struct RawStmt * raw_parse_tree
Definition: plancache.h:99
MemoryContext query_context
Definition: plancache.h:116
List * query_list
Definition: plancache.h:111
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40
struct OverrideSearchPath * search_path
Definition: plancache.h:114

◆ DropCachedPlan()

void DropCachedPlan ( CachedPlanSource plansource)

Definition at line 498 of file plancache.c.

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

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

499 {
500  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
501 
502  /* If it's been saved, remove it from the list */
503  if (plansource->is_saved)
504  {
505  dlist_delete(&plansource->node);
506  plansource->is_saved = false;
507  }
508 
509  /* Decrement generic CachedPlan's refcount and drop if no longer needed */
510  ReleaseGenericPlan(plansource);
511 
512  /* Mark it no longer valid */
513  plansource->magic = 0;
514 
515  /*
516  * Remove the CachedPlanSource and all subsidiary data (including the
517  * query_context if any). But if it's a one-shot we can't free anything.
518  */
519  if (!plansource->is_oneshot)
520  MemoryContextDelete(plansource->context);
521 }
MemoryContext context
Definition: plancache.h:109
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:527
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
#define Assert(condition)
Definition: c.h:804
dlist_node node
Definition: plancache.h:129
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40

◆ FreeCachedExpression()

void FreeCachedExpression ( CachedExpression cexpr)

Definition at line 1706 of file plancache.c.

References Assert, CACHEDEXPR_MAGIC, CachedExpression::context, dlist_delete(), CachedExpression::magic, MemoryContextDelete(), and CachedExpression::node.

Referenced by get_cast_hashentry().

1707 {
1708  /* Sanity check */
1709  Assert(cexpr->magic == CACHEDEXPR_MAGIC);
1710  /* Unlink from global list */
1711  dlist_delete(&cexpr->node);
1712  /* Free all storage associated with CachedExpression */
1713  MemoryContextDelete(cexpr->context);
1714 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
MemoryContext context
Definition: plancache.h:183
#define CACHEDEXPR_MAGIC
Definition: plancache.h:42
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
#define Assert(condition)
Definition: c.h:804
dlist_node node
Definition: plancache.h:184

◆ GetCachedExpression()

CachedExpression* GetCachedExpression ( Node expr)

Definition at line 1649 of file plancache.c.

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, CACHEDEXPR_MAGIC, CacheMemoryContext, CachedExpression::context, copyObject, CurrentMemoryContext, dlist_push_tail(), CachedExpression::expr, expression_planner_with_deps(), CachedExpression::invalItems, CachedExpression::is_valid, CachedExpression::magic, MemoryContextSetParent(), MemoryContextSwitchTo(), CachedExpression::node, palloc(), and CachedExpression::relationOids.

Referenced by get_cast_hashentry().

1650 {
1651  CachedExpression *cexpr;
1652  List *relationOids;
1653  List *invalItems;
1654  MemoryContext cexpr_context;
1655  MemoryContext oldcxt;
1656 
1657  /*
1658  * Pass the expression through the planner, and collect dependencies.
1659  * Everything built here is leaked in the caller's context; that's
1660  * intentional to minimize the size of the permanent data structure.
1661  */
1662  expr = (Node *) expression_planner_with_deps((Expr *) expr,
1663  &relationOids,
1664  &invalItems);
1665 
1666  /*
1667  * Make a private memory context, and copy what we need into that. To
1668  * avoid leaking a long-lived context if we fail while copying data, we
1669  * initially make the context under the caller's context.
1670  */
1672  "CachedExpression",
1674 
1675  oldcxt = MemoryContextSwitchTo(cexpr_context);
1676 
1677  cexpr = (CachedExpression *) palloc(sizeof(CachedExpression));
1678  cexpr->magic = CACHEDEXPR_MAGIC;
1679  cexpr->expr = copyObject(expr);
1680  cexpr->is_valid = true;
1681  cexpr->relationOids = copyObject(relationOids);
1682  cexpr->invalItems = copyObject(invalItems);
1683  cexpr->context = cexpr_context;
1684 
1685  MemoryContextSwitchTo(oldcxt);
1686 
1687  /*
1688  * Reparent the expr's memory context under CacheMemoryContext so that it
1689  * will live indefinitely.
1690  */
1692 
1693  /*
1694  * Add the entry to the global list of cached expressions.
1695  */
1697 
1698  return cexpr;
1699 }
#define AllocSetContextCreate
Definition: memutils.h:173
MemoryContext context
Definition: plancache.h:183
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:361
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:205
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:317
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Definition: nodes.h:539
static dlist_head cached_expression_list
Definition: plancache.c:97
List * relationOids
Definition: plancache.h:181
List * invalItems
Definition: plancache.h:182
#define CACHEDEXPR_MAGIC
Definition: plancache.h:42
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
dlist_node node
Definition: plancache.h:184
Expr * expression_planner_with_deps(Expr *expr, List **relationOids, List **invalItems)
Definition: planner.c:5680
void * palloc(Size size)
Definition: mcxt.c:1062
#define copyObject(obj)
Definition: nodes.h:655
Definition: pg_list.h:50
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ GetCachedPlan()

CachedPlan* GetCachedPlan ( CachedPlanSource plansource,
ParamListInfo  boundParams,
ResourceOwner  owner,
QueryEnvironment queryEnv 
)

Definition at line 1142 of file plancache.c.

References Assert, BuildCachedPlan(), cached_plan_cost(), CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CacheMemoryContext, CheckCachedPlan(), choose_custom_plan(), CachedPlanSource::context, CachedPlan::context, 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, CachedPlanSource::num_generic_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().

1144 {
1145  CachedPlan *plan = NULL;
1146  List *qlist;
1147  bool customplan;
1148 
1149  /* Assert caller is doing things in a sane order */
1150  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1151  Assert(plansource->is_complete);
1152  /* This seems worth a real test, though */
1153  if (owner && !plansource->is_saved)
1154  elog(ERROR, "cannot apply ResourceOwner to non-saved cached plan");
1155 
1156  /* Make sure the querytree list is valid and we have parse-time locks */
1157  qlist = RevalidateCachedQuery(plansource, queryEnv);
1158 
1159  /* Decide whether to use a custom plan */
1160  customplan = choose_custom_plan(plansource, boundParams);
1161 
1162  if (!customplan)
1163  {
1164  if (CheckCachedPlan(plansource))
1165  {
1166  /* We want a generic plan, and we already have a valid one */
1167  plan = plansource->gplan;
1168  Assert(plan->magic == CACHEDPLAN_MAGIC);
1169  }
1170  else
1171  {
1172  /* Build a new generic plan */
1173  plan = BuildCachedPlan(plansource, qlist, NULL, queryEnv);
1174  /* Just make real sure plansource->gplan is clear */
1175  ReleaseGenericPlan(plansource);
1176  /* Link the new generic plan into the plansource */
1177  plansource->gplan = plan;
1178  plan->refcount++;
1179  /* Immediately reparent into appropriate context */
1180  if (plansource->is_saved)
1181  {
1182  /* saved plans all live under CacheMemoryContext */
1184  plan->is_saved = true;
1185  }
1186  else
1187  {
1188  /* otherwise, it should be a sibling of the plansource */
1190  MemoryContextGetParent(plansource->context));
1191  }
1192  /* Update generic_cost whenever we make a new generic plan */
1193  plansource->generic_cost = cached_plan_cost(plan, false);
1194 
1195  /*
1196  * If, based on the now-known value of generic_cost, we'd not have
1197  * chosen to use a generic plan, then forget it and make a custom
1198  * plan. This is a bit of a wart but is necessary to avoid a
1199  * glitch in behavior when the custom plans are consistently big
1200  * winners; at some point we'll experiment with a generic plan and
1201  * find it's a loser, but we don't want to actually execute that
1202  * plan.
1203  */
1204  customplan = choose_custom_plan(plansource, boundParams);
1205 
1206  /*
1207  * If we choose to plan again, we need to re-copy the query_list,
1208  * since the planner probably scribbled on it. We can force
1209  * BuildCachedPlan to do that by passing NIL.
1210  */
1211  qlist = NIL;
1212  }
1213  }
1214 
1215  if (customplan)
1216  {
1217  /* Build a custom plan */
1218  plan = BuildCachedPlan(plansource, qlist, boundParams, queryEnv);
1219  /* Accumulate total costs of custom plans */
1220  plansource->total_custom_cost += cached_plan_cost(plan, true);
1221 
1222  plansource->num_custom_plans++;
1223  }
1224  else
1225  {
1226  plansource->num_generic_plans++;
1227  }
1228 
1229  Assert(plan != NULL);
1230 
1231  /* Flag the plan as in use by caller */
1232  if (owner)
1234  plan->refcount++;
1235  if (owner)
1236  ResourceOwnerRememberPlanCacheRef(owner, plan);
1237 
1238  /*
1239  * Saved plans should be under CacheMemoryContext so they will not go away
1240  * until their reference count goes to zero. In the generic-plan cases we
1241  * already took care of that, but for a custom plan, do it as soon as we
1242  * have created a reference-counted link.
1243  */
1244  if (customplan && plansource->is_saved)
1245  {
1247  plan->is_saved = true;
1248  }
1249 
1250  return plan;
1251 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:41
MemoryContext context
Definition: plancache.h:109
static CachedPlan * BuildCachedPlan(CachedPlanSource *plansource, List *qlist, ParamListInfo boundParams, QueryEnvironment *queryEnv)
Definition: plancache.c:879
#define NIL
Definition: pg_list.h:65
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:527
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:446
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:361
int refcount
Definition: plancache.h:159
void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1161
void ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
Definition: resowner.c:1150
MemoryContext context
Definition: plancache.h:160
double total_custom_cost
Definition: plancache.h:132
struct CachedPlan * gplan
Definition: plancache.h:121
int64 num_custom_plans
Definition: plancache.h:133
#define ERROR
Definition: elog.h:46
static List * RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:555
bool is_saved
Definition: plancache.h:152
int64 num_generic_plans
Definition: plancache.h:134
double generic_cost
Definition: plancache.h:131
#define Assert(condition)
Definition: c.h:804
static bool CheckCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:795
#define elog(elevel,...)
Definition: elog.h:232
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40
Definition: pg_list.h:50
static bool choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams)
Definition: plancache.c:1020
MemoryContext CacheMemoryContext
Definition: mcxt.c:51
static double cached_plan_cost(CachedPlan *plan, bool include_planner)
Definition: plancache.c:1077

◆ InitPlanCache()

void InitPlanCache ( void  )

Definition at line 127 of file plancache.c.

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

Referenced by InitPostgres().

128 {
137 }
static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:2032
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1477
static void PlanCacheRelCallback(Datum arg, Oid relid)
Definition: plancache.c:1948
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1435
uintptr_t Datum
Definition: postgres.h:411
static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:2141

◆ ReleaseCachedPlan()

void ReleaseCachedPlan ( CachedPlan plan,
ResourceOwner  owner 
)

Definition at line 1265 of file plancache.c.

References Assert, CACHEDPLAN_MAGIC, CachedPlan::context, 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(), ResourceOwnerReleaseAllPlanCacheRefs(), ResourceOwnerReleaseInternal(), and SPI_cursor_open_internal().

1266 {
1267  Assert(plan->magic == CACHEDPLAN_MAGIC);
1268  if (owner)
1269  {
1270  Assert(plan->is_saved);
1271  ResourceOwnerForgetPlanCacheRef(owner, plan);
1272  }
1273  Assert(plan->refcount > 0);
1274  plan->refcount--;
1275  if (plan->refcount == 0)
1276  {
1277  /* Mark it no longer valid */
1278  plan->magic = 0;
1279 
1280  /* One-shot plans do not own their context, so we can't free them */
1281  if (!plan->is_oneshot)
1283  }
1284 }
#define CACHEDPLAN_MAGIC
Definition: plancache.h:41
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
int refcount
Definition: plancache.h:159
MemoryContext context
Definition: plancache.h:160
void ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1170
bool is_saved
Definition: plancache.h:152
#define Assert(condition)
Definition: c.h:804
bool is_oneshot
Definition: plancache.h:151

◆ ResetPlanCache()

void ResetPlanCache ( void  )

Definition at line 2150 of file plancache.c.

References Assert, CACHEDEXPR_MAGIC, CACHEDPLANSOURCE_MAGIC, CMD_UTILITY, Query::commandType, dlist_iter::cur, dlist_container, dlist_foreach, CachedPlanSource::gplan, CachedPlanSource::is_valid, CachedPlan::is_valid, CachedExpression::is_valid, IsTransactionStmtPlan, lfirst_node, CachedPlanSource::magic, CachedExpression::magic, CachedPlanSource::query_list, UtilityContainsQuery(), and Query::utilityStmt.

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

2151 {
2152  dlist_iter iter;
2153 
2155  {
2157  node, iter.cur);
2158  ListCell *lc;
2159 
2160  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
2161 
2162  /* No work if it's already invalidated */
2163  if (!plansource->is_valid)
2164  continue;
2165 
2166  /*
2167  * We *must not* mark transaction control statements as invalid,
2168  * particularly not ROLLBACK, because they may need to be executed in
2169  * aborted transactions when we can't revalidate them (cf bug #5269).
2170  */
2171  if (IsTransactionStmtPlan(plansource))
2172  continue;
2173 
2174  /*
2175  * In general there is no point in invalidating utility statements
2176  * since they have no plans anyway. So invalidate it only if it
2177  * contains at least one non-utility statement, or contains a utility
2178  * statement that contains a pre-analyzed query (which could have
2179  * dependencies.)
2180  */
2181  foreach(lc, plansource->query_list)
2182  {
2183  Query *query = lfirst_node(Query, lc);
2184 
2185  if (query->commandType != CMD_UTILITY ||
2187  {
2188  /* non-utility statement, so invalidate */
2189  plansource->is_valid = false;
2190  if (plansource->gplan)
2191  plansource->gplan->is_valid = false;
2192  /* no need to look further */
2193  break;
2194  }
2195  }
2196  }
2197 
2198  /* Likewise invalidate cached expressions */
2200  {
2202  node, iter.cur);
2203 
2204  Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2205 
2206  cexpr->is_valid = false;
2207  }
2208 }
bool is_valid
Definition: plancache.h:153
#define dlist_foreach(iter, lhead)
Definition: ilist.h:526
Node * utilityStmt
Definition: parsenodes.h:128
static dlist_head cached_expression_list
Definition: plancache.c:97
struct CachedPlan * gplan
Definition: plancache.h:121
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:2135
#define dlist_container(type, membername, ptr)
Definition: ilist.h:496
#define lfirst_node(type, lc)
Definition: pg_list.h:172
#define CACHEDEXPR_MAGIC
Definition: plancache.h:42
static dlist_head saved_plan_list
Definition: plancache.c:92
dlist_node * cur
Definition: ilist.h:161
CmdType commandType
Definition: parsenodes.h:120
#define Assert(condition)
Definition: c.h:804
List * query_list
Definition: plancache.h:111
#define IsTransactionStmtPlan(plansource)
Definition: plancache.c:82
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40

◆ SaveCachedPlan()

void SaveCachedPlan ( CachedPlanSource plansource)

Definition at line 454 of file plancache.c.

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

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

455 {
456  /* Assert caller is doing things in a sane order */
457  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
458  Assert(plansource->is_complete);
459  Assert(!plansource->is_saved);
460 
461  /* This seems worth a real test, though */
462  if (plansource->is_oneshot)
463  elog(ERROR, "cannot save one-shot cached plan");
464 
465  /*
466  * In typical use, this function would be called before generating any
467  * plans from the CachedPlanSource. If there is a generic plan, moving it
468  * into CacheMemoryContext would be pretty risky since it's unclear
469  * whether the caller has taken suitable care with making references
470  * long-lived. Best thing to do seems to be to discard the plan.
471  */
472  ReleaseGenericPlan(plansource);
473 
474  /*
475  * Reparent the source memory context under CacheMemoryContext so that it
476  * will live indefinitely. The query_context follows along since it's
477  * already a child of the other one.
478  */
480 
481  /*
482  * Add the entry to the global list of cached plans.
483  */
484  dlist_push_tail(&saved_plan_list, &plansource->node);
485 
486  plansource->is_saved = true;
487 }
MemoryContext context
Definition: plancache.h:109
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:527
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:361
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:317
#define ERROR
Definition: elog.h:46
static dlist_head saved_plan_list
Definition: plancache.c:92
#define Assert(condition)
Definition: c.h:804
dlist_node node
Definition: plancache.h:129
#define elog(elevel,...)
Definition: elog.h:232
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

Variable Documentation

◆ plan_cache_mode

int plan_cache_mode

Definition at line 119 of file plancache.c.

Referenced by choose_custom_plan().