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 Query Query
 
typedef struct RawStmt RawStmt
 
typedef void(* PostRewriteHook) (List *querytree_list, void *arg)
 
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)
 
void ReleaseAllPlanCacheRefsInOwner (ResourceOwner owner)
 
CachedPlanSourceCreateCachedPlan (RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
 
CachedPlanSourceCreateCachedPlanForQuery (Query *analyzed_parse_tree, const char *query_string, CommandTag commandTag)
 
CachedPlanSourceCreateOneShotCachedPlan (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 SetPostRewriteHook (CachedPlanSource *plansource, PostRewriteHook postRewrite, void *postRewriteArg)
 
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

PGDLLIMPORT int plan_cache_mode
 

Macro Definition Documentation

◆ CACHEDEXPR_MAGIC

#define CACHEDEXPR_MAGIC   838275847

Definition at line 46 of file plancache.h.

◆ CACHEDPLAN_MAGIC

#define CACHEDPLAN_MAGIC   953717834

Definition at line 45 of file plancache.h.

◆ CACHEDPLANSOURCE_MAGIC

#define CACHEDPLANSOURCE_MAGIC   195726186

Definition at line 44 of file plancache.h.

Typedef Documentation

◆ CachedExpression

◆ CachedPlan

typedef struct CachedPlan CachedPlan

◆ CachedPlanSource

◆ PostRewriteHook

typedef void(* PostRewriteHook) (List *querytree_list, void *arg)

Definition at line 42 of file plancache.h.

◆ Query

typedef struct Query Query

Definition at line 27 of file plancache.h.

◆ RawStmt

typedef struct RawStmt RawStmt

Definition at line 28 of file plancache.h.

Enumeration Type Documentation

◆ PlanCacheMode

Enumerator
PLAN_CACHE_MODE_AUTO 
PLAN_CACHE_MODE_FORCE_GENERIC_PLAN 
PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN 

Definition at line 31 of file plancache.h.

32{
PlanCacheMode
Definition: plancache.h:32
@ PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN
Definition: plancache.h:35
@ PLAN_CACHE_MODE_FORCE_GENERIC_PLAN
Definition: plancache.h:34
@ PLAN_CACHE_MODE_AUTO
Definition: plancache.h:33

Function Documentation

◆ CachedPlanAllowsSimpleValidityCheck()

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

Definition at line 1471 of file plancache.c.

1473{
1474 ListCell *lc;
1475
1476 /*
1477 * Sanity-check that the caller gave us a validated generic plan. Notice
1478 * that we *don't* assert plansource->is_valid as you might expect; that's
1479 * because it's possible that that's already false when GetCachedPlan
1480 * returns, e.g. because ResetPlanCache happened partway through. We
1481 * should accept the plan as long as plan->is_valid is true, and expect to
1482 * replan after the next CachedPlanIsSimplyValid call.
1483 */
1484 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1485 Assert(plan->magic == CACHEDPLAN_MAGIC);
1486 Assert(plan->is_valid);
1487 Assert(plan == plansource->gplan);
1488 Assert(plansource->search_path != NULL);
1490
1491 /* We don't support oneshot plans here. */
1492 if (plansource->is_oneshot)
1493 return false;
1494 Assert(!plan->is_oneshot);
1495
1496 /*
1497 * If the plan is dependent on RLS considerations, or it's transient,
1498 * reject. These things probably can't ever happen for table-free
1499 * queries, but for safety's sake let's check.
1500 */
1501 if (plansource->dependsOnRLS)
1502 return false;
1503 if (plan->dependsOnRole)
1504 return false;
1505 if (TransactionIdIsValid(plan->saved_xmin))
1506 return false;
1507
1508 /*
1509 * Reject if AcquirePlannerLocks would have anything to do. This is
1510 * simplistic, but there's no need to inquire any more carefully; indeed,
1511 * for current callers it shouldn't even be possible to hit any of these
1512 * checks.
1513 */
1514 foreach(lc, plansource->query_list)
1515 {
1516 Query *query = lfirst_node(Query, lc);
1517
1518 if (query->commandType == CMD_UTILITY)
1519 return false;
1520 if (query->rtable || query->cteList || query->hasSubLinks)
1521 return false;
1522 }
1523
1524 /*
1525 * Reject if AcquireExecutorLocks would have anything to do. This is
1526 * probably unnecessary given the previous check, but let's be safe.
1527 */
1528 foreach(lc, plan->stmt_list)
1529 {
1530 PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
1531 ListCell *lc2;
1532
1533 if (plannedstmt->commandType == CMD_UTILITY)
1534 return false;
1535
1536 /*
1537 * We have to grovel through the rtable because it's likely to contain
1538 * an RTE_RESULT relation, rather than being totally empty.
1539 */
1540 foreach(lc2, plannedstmt->rtable)
1541 {
1542 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
1543
1544 if (rte->rtekind == RTE_RELATION)
1545 return false;
1546 }
1547 }
1548
1549 /*
1550 * Okay, it's simple. Note that what we've primarily established here is
1551 * that no locks need be taken before checking the plan's is_valid flag.
1552 */
1553
1554 /* Bump refcount if requested. */
1555 if (owner)
1556 {
1557 ResourceOwnerEnlarge(owner);
1558 plan->refcount++;
1560 }
1561
1562 return true;
1563}
Assert(PointerIsAligned(start, uint64))
bool SearchPathMatchesCurrentEnvironment(SearchPathMatcher *path)
Definition: namespace.c:3981
@ CMD_UTILITY
Definition: nodes.h:280
@ RTE_RELATION
Definition: parsenodes.h:1043
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define plan(x)
Definition: pg_regress.c:161
static void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: plancache.c:126
#define CACHEDPLAN_MAGIC
Definition: plancache.h:45
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:44
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:449
struct CachedPlan * gplan
Definition: plancache.h:133
struct SearchPathMatcher * search_path
Definition: plancache.h:126
List * query_list
Definition: plancache.h:123
CmdType commandType
Definition: plannodes.h:68
List * rtable
Definition: plannodes.h:109
List * cteList
Definition: parsenodes.h:173
List * rtable
Definition: parsenodes.h:175
CmdType commandType
Definition: parsenodes.h:121
RTEKind rtekind
Definition: parsenodes.h:1078
#define TransactionIdIsValid(xid)
Definition: transam.h:41

References Assert(), CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CMD_UTILITY, Query::commandType, PlannedStmt::commandType, Query::cteList, CachedPlanSource::dependsOnRLS, CachedPlanSource::gplan, CachedPlanSource::is_oneshot, lfirst, lfirst_node, CachedPlanSource::magic, plan, CachedPlanSource::query_list, ResourceOwnerEnlarge(), ResourceOwnerRememberPlanCacheRef(), Query::rtable, PlannedStmt::rtable, RTE_RELATION, RangeTblEntry::rtekind, CachedPlanSource::search_path, SearchPathMatchesCurrentEnvironment(), and TransactionIdIsValid.

Referenced by exec_eval_simple_expr(), and exec_simple_check_plan().

◆ CachedPlanGetTargetList()

List * CachedPlanGetTargetList ( CachedPlanSource plansource,
QueryEnvironment queryEnv 
)

Definition at line 1778 of file plancache.c.

1780{
1781 Query *pstmt;
1782
1783 /* Assert caller is doing things in a sane order */
1784 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1785 Assert(plansource->is_complete);
1786
1787 /*
1788 * No work needed if statement doesn't return tuples (we assume this
1789 * feature cannot be changed by an invalidation)
1790 */
1791 if (plansource->resultDesc == NULL)
1792 return NIL;
1793
1794 /* Make sure the querytree list is valid and we have parse-time locks */
1795 RevalidateCachedQuery(plansource, queryEnv);
1796
1797 /* Get the primary statement and find out what it returns */
1798 pstmt = QueryListGetPrimaryStmt(plansource->query_list);
1799
1800 return FetchStatementTargetList((Node *) pstmt);
1801}
#define NIL
Definition: pg_list.h:68
static List * RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:682
static Query * QueryListGetPrimaryStmt(List *stmts)
Definition: plancache.c:1891
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:344
TupleDesc resultDesc
Definition: plancache.h:120
Definition: nodes.h:135

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

◆ CachedPlanIsSimplyValid()

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

Definition at line 1586 of file plancache.c.

1588{
1589 /*
1590 * Careful here: since the caller doesn't necessarily hold a refcount on
1591 * the plan to start with, it's possible that "plan" is a dangling
1592 * pointer. Don't dereference it until we've verified that it still
1593 * matches the plansource's gplan (which is either valid or NULL).
1594 */
1595 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1596
1597 /*
1598 * Has cache invalidation fired on this plan? We can check this right
1599 * away since there are no locks that we'd need to acquire first. Note
1600 * that here we *do* check plansource->is_valid, so as to force plan
1601 * rebuild if that's become false.
1602 */
1603 if (!plansource->is_valid ||
1604 plan == NULL || plan != plansource->gplan ||
1605 !plan->is_valid)
1606 return false;
1607
1608 Assert(plan->magic == CACHEDPLAN_MAGIC);
1609
1610 /* Is the search_path still the same as when we made it? */
1611 Assert(plansource->search_path != NULL);
1613 return false;
1614
1615 /* It's still good. Bump refcount if requested. */
1616 if (owner)
1617 {
1618 ResourceOwnerEnlarge(owner);
1619 plan->refcount++;
1621 }
1622
1623 return true;
1624}

References Assert(), CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CachedPlanSource::gplan, CachedPlanSource::is_valid, CachedPlanSource::magic, plan, ResourceOwnerEnlarge(), ResourceOwnerRememberPlanCacheRef(), CachedPlanSource::search_path, and SearchPathMatchesCurrentEnvironment().

Referenced by exec_eval_simple_expr().

◆ CachedPlanIsValid()

bool CachedPlanIsValid ( CachedPlanSource plansource)

Definition at line 1765 of file plancache.c.

1766{
1767 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1768 return plansource->is_valid;
1769}

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

Referenced by SPI_plan_is_valid().

◆ CachedPlanSetParentContext()

void CachedPlanSetParentContext ( CachedPlanSource plansource,
MemoryContext  newcontext 
)

Definition at line 1633 of file plancache.c.

1635{
1636 /* Assert caller is doing things in a sane order */
1637 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1638 Assert(plansource->is_complete);
1639
1640 /* These seem worth real tests, though */
1641 if (plansource->is_saved)
1642 elog(ERROR, "cannot move a saved cached plan to another context");
1643 if (plansource->is_oneshot)
1644 elog(ERROR, "cannot move a one-shot cached plan to another context");
1645
1646 /* OK, let the caller keep the plan where he wishes */
1647 MemoryContextSetParent(plansource->context, newcontext);
1648
1649 /*
1650 * The query_context needs no special handling, since it's a child of
1651 * plansource->context. But if there's a generic plan, it should be
1652 * maintained as a sibling of plansource->context.
1653 */
1654 if (plansource->gplan)
1655 {
1656 Assert(plansource->gplan->magic == CACHEDPLAN_MAGIC);
1657 MemoryContextSetParent(plansource->gplan->context, newcontext);
1658 }
1659}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:683
MemoryContext context
Definition: plancache.h:121
MemoryContext context
Definition: plancache.h:172

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

◆ 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 391 of file plancache.c.

400{
401 MemoryContext source_context = plansource->context;
403
404 /* Assert caller is doing things in a sane order */
405 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
406 Assert(!plansource->is_complete);
407
408 /*
409 * If caller supplied a querytree_context, reparent it underneath the
410 * CachedPlanSource's context; otherwise, create a suitable context and
411 * copy the querytree_list into it. But no data copying should be done
412 * for one-shot plans; for those, assume the passed querytree_list is
413 * sufficiently long-lived.
414 */
415 if (plansource->is_oneshot)
416 {
417 querytree_context = CurrentMemoryContext;
418 }
419 else if (querytree_context != NULL)
420 {
421 MemoryContextSetParent(querytree_context, source_context);
422 MemoryContextSwitchTo(querytree_context);
423 }
424 else
425 {
426 /* Again, it's a good bet the querytree_context can be small */
427 querytree_context = AllocSetContextCreate(source_context,
428 "CachedPlanQuery",
430 MemoryContextSwitchTo(querytree_context);
431 querytree_list = copyObject(querytree_list);
432 }
433
434 plansource->query_context = querytree_context;
435 plansource->query_list = querytree_list;
436
437 if (!plansource->is_oneshot && StmtPlanRequiresRevalidation(plansource))
438 {
439 /*
440 * Use the planner machinery to extract dependencies. Data is saved
441 * in query_context. (We assume that not a lot of extra cruft is
442 * created by this call.) We can skip this for one-shot plans, and
443 * plans not needing revalidation have no such dependencies anyway.
444 */
445 extract_query_dependencies((Node *) querytree_list,
446 &plansource->relationOids,
447 &plansource->invalItems,
448 &plansource->dependsOnRLS);
449
450 /* Update RLS info as well. */
451 plansource->rewriteRoleId = GetUserId();
452 plansource->rewriteRowSecurity = row_security;
453
454 /*
455 * Also save the current search_path in the query_context. (This
456 * should not generate much extra cruft either, since almost certainly
457 * the path is already valid.) Again, we don't really need this for
458 * one-shot plans; and we *must* skip this for transaction control
459 * commands, because this could result in catalog accesses.
460 */
461 plansource->search_path = GetSearchPathMatcher(querytree_context);
462 }
463
464 /*
465 * Save the final parameter types (or other parameter specification data)
466 * into the source_context, as well as our other parameters.
467 */
468 MemoryContextSwitchTo(source_context);
469
470 if (num_params > 0)
471 {
472 plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
473 memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
474 }
475 else
476 plansource->param_types = NULL;
477 plansource->num_params = num_params;
478 plansource->parserSetup = parserSetup;
479 plansource->parserSetupArg = parserSetupArg;
480 plansource->cursor_options = cursor_options;
481 plansource->fixed_result = fixed_result;
482
483 /*
484 * Also save the result tuple descriptor. PlanCacheComputeResultDesc may
485 * leak some cruft; normally we just accept that to save a copy step, but
486 * in USE_VALGRIND mode be tidy by running it in the caller's context.
487 */
488#ifdef USE_VALGRIND
489 MemoryContextSwitchTo(oldcxt);
490 plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
491 if (plansource->resultDesc)
492 {
493 MemoryContextSwitchTo(source_context);
494 plansource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
495 MemoryContextSwitchTo(oldcxt);
496 }
497#else
498 plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
499 MemoryContextSwitchTo(oldcxt);
500#endif
501
502 plansource->is_complete = true;
503 plansource->is_valid = true;
504}
bool row_security
Definition: guc_tables.c:528
void * palloc(Size size)
Definition: mcxt.c:1365
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:177
Oid GetUserId(void)
Definition: miscinit.c:469
SearchPathMatcher * GetSearchPathMatcher(MemoryContext context)
Definition: namespace.c:3922
#define copyObject(obj)
Definition: nodes.h:232
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static bool StmtPlanRequiresRevalidation(CachedPlanSource *plansource)
Definition: plancache.c:640
static TupleDesc PlanCacheComputeResultDesc(List *stmt_list)
Definition: plancache.c:2085
unsigned int Oid
Definition: postgres_ext.h:32
void extract_query_dependencies(Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
Definition: setrefs.c:3656
MemoryContext query_context
Definition: plancache.h:128
List * invalItems
Definition: plancache.h:125
ParserSetupHook parserSetup
Definition: plancache.h:114
bool rewriteRowSecurity
Definition: plancache.h:130
List * relationOids
Definition: plancache.h:124
void * parserSetupArg
Definition: plancache.h:115
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:252

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate, Assert(), CACHEDPLANSOURCE_MAGIC, CachedPlanSource::context, copyObject, CreateTupleDescCopy(), CurrentMemoryContext, CachedPlanSource::cursor_options, CachedPlanSource::dependsOnRLS, extract_query_dependencies(), CachedPlanSource::fixed_result, GetSearchPathMatcher(), GetUserId(), CachedPlanSource::invalItems, CachedPlanSource::is_complete, CachedPlanSource::is_oneshot, CachedPlanSource::is_valid, 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, CachedPlanSource::search_path, and StmtPlanRequiresRevalidation().

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

◆ CopyCachedPlan()

CachedPlanSource * CopyCachedPlan ( CachedPlanSource plansource)

Definition at line 1671 of file plancache.c.

1672{
1673 CachedPlanSource *newsource;
1674 MemoryContext source_context;
1675 MemoryContext querytree_context;
1676 MemoryContext oldcxt;
1677
1678 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1679 Assert(plansource->is_complete);
1680
1681 /*
1682 * One-shot plans can't be copied, because we haven't taken care that
1683 * parsing/planning didn't scribble on the raw parse tree or querytrees.
1684 */
1685 if (plansource->is_oneshot)
1686 elog(ERROR, "cannot copy a one-shot cached plan");
1687
1689 "CachedPlanSource",
1691
1692 oldcxt = MemoryContextSwitchTo(source_context);
1693
1694 newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1695 newsource->magic = CACHEDPLANSOURCE_MAGIC;
1696 newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
1697 newsource->analyzed_parse_tree = copyObject(plansource->analyzed_parse_tree);
1698 newsource->query_string = pstrdup(plansource->query_string);
1699 MemoryContextSetIdentifier(source_context, newsource->query_string);
1700 newsource->commandTag = plansource->commandTag;
1701 if (plansource->num_params > 0)
1702 {
1703 newsource->param_types = (Oid *)
1704 palloc(plansource->num_params * sizeof(Oid));
1705 memcpy(newsource->param_types, plansource->param_types,
1706 plansource->num_params * sizeof(Oid));
1707 }
1708 else
1709 newsource->param_types = NULL;
1710 newsource->num_params = plansource->num_params;
1711 newsource->parserSetup = plansource->parserSetup;
1712 newsource->parserSetupArg = plansource->parserSetupArg;
1713 newsource->postRewrite = plansource->postRewrite;
1714 newsource->postRewriteArg = plansource->postRewriteArg;
1715 newsource->cursor_options = plansource->cursor_options;
1716 newsource->fixed_result = plansource->fixed_result;
1717 if (plansource->resultDesc)
1718 newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
1719 else
1720 newsource->resultDesc = NULL;
1721 newsource->context = source_context;
1722
1723 querytree_context = AllocSetContextCreate(source_context,
1724 "CachedPlanQuery",
1726 MemoryContextSwitchTo(querytree_context);
1727 newsource->query_list = copyObject(plansource->query_list);
1728 newsource->relationOids = copyObject(plansource->relationOids);
1729 newsource->invalItems = copyObject(plansource->invalItems);
1730 if (plansource->search_path)
1731 newsource->search_path = CopySearchPathMatcher(plansource->search_path);
1732 newsource->query_context = querytree_context;
1733 newsource->rewriteRoleId = plansource->rewriteRoleId;
1734 newsource->rewriteRowSecurity = plansource->rewriteRowSecurity;
1735 newsource->dependsOnRLS = plansource->dependsOnRLS;
1736
1737 newsource->gplan = NULL;
1738
1739 newsource->is_oneshot = false;
1740 newsource->is_complete = true;
1741 newsource->is_saved = false;
1742 newsource->is_valid = plansource->is_valid;
1743 newsource->generation = plansource->generation;
1744
1745 /* We may as well copy any acquired cost knowledge */
1746 newsource->generic_cost = plansource->generic_cost;
1747 newsource->total_custom_cost = plansource->total_custom_cost;
1748 newsource->num_generic_plans = plansource->num_generic_plans;
1749 newsource->num_custom_plans = plansource->num_custom_plans;
1750
1751 MemoryContextSwitchTo(oldcxt);
1752
1753 return newsource;
1754}
char * pstrdup(const char *in)
Definition: mcxt.c:1759
void * palloc0(Size size)
Definition: mcxt.c:1395
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:658
SearchPathMatcher * CopySearchPathMatcher(SearchPathMatcher *path)
Definition: namespace.c:3959
PostRewriteHook postRewrite
Definition: plancache.h:116
Query * analyzed_parse_tree
Definition: plancache.h:109
RawStmt * raw_parse_tree
Definition: plancache.h:108
CommandTag commandTag
Definition: plancache.h:111
double total_custom_cost
Definition: plancache.h:144
const char * query_string
Definition: plancache.h:110
int64 num_custom_plans
Definition: plancache.h:145
int64 num_generic_plans
Definition: plancache.h:146
void * postRewriteArg
Definition: plancache.h:117
double generic_cost
Definition: plancache.h:143

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate, CachedPlanSource::analyzed_parse_tree, Assert(), CACHEDPLANSOURCE_MAGIC, CachedPlanSource::commandTag, CachedPlanSource::context, copyObject, CopySearchPathMatcher(), 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, CachedPlanSource::postRewrite, CachedPlanSource::postRewriteArg, 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().

◆ CreateCachedPlan()

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

Definition at line 183 of file plancache.c.

186{
187 CachedPlanSource *plansource;
188 MemoryContext source_context;
189 MemoryContext oldcxt;
190
191 Assert(query_string != NULL); /* required as of 8.4 */
192
193 /*
194 * Make a dedicated memory context for the CachedPlanSource and its
195 * permanent subsidiary data. It's probably not going to be large, but
196 * just in case, allow it to grow large. Initially it's a child of the
197 * caller's context (which we assume to be transient), so that it will be
198 * cleaned up on error.
199 */
201 "CachedPlanSource",
203
204 /*
205 * Create and fill the CachedPlanSource struct within the new context.
206 * Most fields are just left empty for the moment.
207 */
208 oldcxt = MemoryContextSwitchTo(source_context);
209
210 plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
211 plansource->magic = CACHEDPLANSOURCE_MAGIC;
212 plansource->raw_parse_tree = copyObject(raw_parse_tree);
213 plansource->analyzed_parse_tree = NULL;
214 plansource->query_string = pstrdup(query_string);
215 MemoryContextSetIdentifier(source_context, plansource->query_string);
216 plansource->commandTag = commandTag;
217 plansource->param_types = NULL;
218 plansource->num_params = 0;
219 plansource->parserSetup = NULL;
220 plansource->parserSetupArg = NULL;
221 plansource->postRewrite = NULL;
222 plansource->postRewriteArg = NULL;
223 plansource->cursor_options = 0;
224 plansource->fixed_result = false;
225 plansource->resultDesc = NULL;
226 plansource->context = source_context;
227 plansource->query_list = NIL;
228 plansource->relationOids = NIL;
229 plansource->invalItems = NIL;
230 plansource->search_path = NULL;
231 plansource->query_context = NULL;
232 plansource->rewriteRoleId = InvalidOid;
233 plansource->rewriteRowSecurity = false;
234 plansource->dependsOnRLS = false;
235 plansource->gplan = NULL;
236 plansource->is_oneshot = false;
237 plansource->is_complete = false;
238 plansource->is_saved = false;
239 plansource->is_valid = false;
240 plansource->generation = 0;
241 plansource->generic_cost = -1;
242 plansource->total_custom_cost = 0;
243 plansource->num_generic_plans = 0;
244 plansource->num_custom_plans = 0;
245
246 MemoryContextSwitchTo(oldcxt);
247
248 return plansource;
249}
#define InvalidOid
Definition: postgres_ext.h:37

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate, CachedPlanSource::analyzed_parse_tree, 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, CachedPlanSource::postRewrite, CachedPlanSource::postRewriteArg, 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(), CreateCachedPlanForQuery(), exec_parse_message(), prepare_next_query(), and PrepareQuery().

◆ CreateCachedPlanForQuery()

CachedPlanSource * CreateCachedPlanForQuery ( Query analyzed_parse_tree,
const char *  query_string,
CommandTag  commandTag 
)

Definition at line 263 of file plancache.c.

266{
267 CachedPlanSource *plansource;
268 MemoryContext oldcxt;
269
270 /* Rather than duplicating CreateCachedPlan, just do this: */
271 plansource = CreateCachedPlan(NULL, query_string, commandTag);
272 oldcxt = MemoryContextSwitchTo(plansource->context);
273 plansource->analyzed_parse_tree = copyObject(analyzed_parse_tree);
274 MemoryContextSwitchTo(oldcxt);
275
276 return plansource;
277}
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
Definition: plancache.c:183

References CachedPlanSource::analyzed_parse_tree, CachedPlanSource::context, copyObject, CreateCachedPlan(), and MemoryContextSwitchTo().

Referenced by prepare_next_query().

◆ CreateOneShotCachedPlan()

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

Definition at line 298 of file plancache.c.

301{
302 CachedPlanSource *plansource;
303
304 Assert(query_string != NULL); /* required as of 8.4 */
305
306 /*
307 * Create and fill the CachedPlanSource struct within the caller's memory
308 * context. Most fields are just left empty for the moment.
309 */
310 plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
311 plansource->magic = CACHEDPLANSOURCE_MAGIC;
312 plansource->raw_parse_tree = raw_parse_tree;
313 plansource->analyzed_parse_tree = NULL;
314 plansource->query_string = query_string;
315 plansource->commandTag = commandTag;
316 plansource->param_types = NULL;
317 plansource->num_params = 0;
318 plansource->parserSetup = NULL;
319 plansource->parserSetupArg = NULL;
320 plansource->postRewrite = NULL;
321 plansource->postRewriteArg = NULL;
322 plansource->cursor_options = 0;
323 plansource->fixed_result = false;
324 plansource->resultDesc = NULL;
325 plansource->context = CurrentMemoryContext;
326 plansource->query_list = NIL;
327 plansource->relationOids = NIL;
328 plansource->invalItems = NIL;
329 plansource->search_path = NULL;
330 plansource->query_context = NULL;
331 plansource->rewriteRoleId = InvalidOid;
332 plansource->rewriteRowSecurity = false;
333 plansource->dependsOnRLS = false;
334 plansource->gplan = NULL;
335 plansource->is_oneshot = true;
336 plansource->is_complete = false;
337 plansource->is_saved = false;
338 plansource->is_valid = false;
339 plansource->generation = 0;
340 plansource->generic_cost = -1;
341 plansource->total_custom_cost = 0;
342 plansource->num_generic_plans = 0;
343 plansource->num_custom_plans = 0;
344
345 return plansource;
346}

References CachedPlanSource::analyzed_parse_tree, 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::postRewrite, CachedPlanSource::postRewriteArg, 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().

◆ DropCachedPlan()

void DropCachedPlan ( CachedPlanSource plansource)

Definition at line 589 of file plancache.c.

590{
591 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
592
593 /* If it's been saved, remove it from the list */
594 if (plansource->is_saved)
595 {
596 dlist_delete(&plansource->node);
597 plansource->is_saved = false;
598 }
599
600 /* Decrement generic CachedPlan's refcount and drop if no longer needed */
601 ReleaseGenericPlan(plansource);
602
603 /* Mark it no longer valid */
604 plansource->magic = 0;
605
606 /*
607 * Remove the CachedPlanSource and all subsidiary data (including the
608 * query_context if any). But if it's a one-shot we can't free anything.
609 */
610 if (!plansource->is_oneshot)
611 MemoryContextDelete(plansource->context);
612}
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:469
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:618
dlist_node node
Definition: plancache.h:141

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(), SPI_freeplan(), and sql_delete_callback().

◆ FreeCachedExpression()

void FreeCachedExpression ( CachedExpression cexpr)

Definition at line 1872 of file plancache.c.

1873{
1874 /* Sanity check */
1875 Assert(cexpr->magic == CACHEDEXPR_MAGIC);
1876 /* Unlink from global list */
1877 dlist_delete(&cexpr->node);
1878 /* Free all storage associated with CachedExpression */
1880}
#define CACHEDEXPR_MAGIC
Definition: plancache.h:46
MemoryContext context
Definition: plancache.h:195
dlist_node node
Definition: plancache.h:196

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

Referenced by get_cast_hashentry().

◆ GetCachedExpression()

CachedExpression * GetCachedExpression ( Node expr)

Definition at line 1815 of file plancache.c.

1816{
1817 CachedExpression *cexpr;
1818 List *relationOids;
1819 List *invalItems;
1820 MemoryContext cexpr_context;
1821 MemoryContext oldcxt;
1822
1823 /*
1824 * Pass the expression through the planner, and collect dependencies.
1825 * Everything built here is leaked in the caller's context; that's
1826 * intentional to minimize the size of the permanent data structure.
1827 */
1828 expr = (Node *) expression_planner_with_deps((Expr *) expr,
1829 &relationOids,
1830 &invalItems);
1831
1832 /*
1833 * Make a private memory context, and copy what we need into that. To
1834 * avoid leaking a long-lived context if we fail while copying data, we
1835 * initially make the context under the caller's context.
1836 */
1838 "CachedExpression",
1840
1841 oldcxt = MemoryContextSwitchTo(cexpr_context);
1842
1843 cexpr = (CachedExpression *) palloc(sizeof(CachedExpression));
1844 cexpr->magic = CACHEDEXPR_MAGIC;
1845 cexpr->expr = copyObject(expr);
1846 cexpr->is_valid = true;
1847 cexpr->relationOids = copyObject(relationOids);
1848 cexpr->invalItems = copyObject(invalItems);
1849 cexpr->context = cexpr_context;
1850
1851 MemoryContextSwitchTo(oldcxt);
1852
1853 /*
1854 * Reparent the expr's memory context under CacheMemoryContext so that it
1855 * will live indefinitely.
1856 */
1858
1859 /*
1860 * Add the entry to the global list of cached expressions.
1861 */
1863
1864 return cexpr;
1865}
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364
MemoryContext CacheMemoryContext
Definition: mcxt.c:169
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
static dlist_head cached_expression_list
Definition: plancache.c:89
Expr * expression_planner_with_deps(Expr *expr, List **relationOids, List **invalItems)
Definition: planner.c:6790
List * relationOids
Definition: plancache.h:193
List * invalItems
Definition: plancache.h:194
Definition: pg_list.h:54

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, cached_expression_list, 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().

◆ GetCachedPlan()

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

Definition at line 1295 of file plancache.c.

1297{
1298 CachedPlan *plan = NULL;
1299 List *qlist;
1300 bool customplan;
1301 ListCell *lc;
1302
1303 /* Assert caller is doing things in a sane order */
1304 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1305 Assert(plansource->is_complete);
1306 /* This seems worth a real test, though */
1307 if (owner && !plansource->is_saved)
1308 elog(ERROR, "cannot apply ResourceOwner to non-saved cached plan");
1309
1310 /* Make sure the querytree list is valid and we have parse-time locks */
1311 qlist = RevalidateCachedQuery(plansource, queryEnv);
1312
1313 /* Decide whether to use a custom plan */
1314 customplan = choose_custom_plan(plansource, boundParams);
1315
1316 if (!customplan)
1317 {
1318 if (CheckCachedPlan(plansource))
1319 {
1320 /* We want a generic plan, and we already have a valid one */
1321 plan = plansource->gplan;
1322 Assert(plan->magic == CACHEDPLAN_MAGIC);
1323 }
1324 else
1325 {
1326 /* Build a new generic plan */
1327 plan = BuildCachedPlan(plansource, qlist, NULL, queryEnv);
1328 /* Just make real sure plansource->gplan is clear */
1329 ReleaseGenericPlan(plansource);
1330 /* Link the new generic plan into the plansource */
1331 plansource->gplan = plan;
1332 plan->refcount++;
1333 /* Immediately reparent into appropriate context */
1334 if (plansource->is_saved)
1335 {
1336 /* saved plans all live under CacheMemoryContext */
1338 plan->is_saved = true;
1339 }
1340 else
1341 {
1342 /* otherwise, it should be a sibling of the plansource */
1344 MemoryContextGetParent(plansource->context));
1345 }
1346 /* Update generic_cost whenever we make a new generic plan */
1347 plansource->generic_cost = cached_plan_cost(plan, false);
1348
1349 /*
1350 * If, based on the now-known value of generic_cost, we'd not have
1351 * chosen to use a generic plan, then forget it and make a custom
1352 * plan. This is a bit of a wart but is necessary to avoid a
1353 * glitch in behavior when the custom plans are consistently big
1354 * winners; at some point we'll experiment with a generic plan and
1355 * find it's a loser, but we don't want to actually execute that
1356 * plan.
1357 */
1358 customplan = choose_custom_plan(plansource, boundParams);
1359
1360 /*
1361 * If we choose to plan again, we need to re-copy the query_list,
1362 * since the planner probably scribbled on it. We can force
1363 * BuildCachedPlan to do that by passing NIL.
1364 */
1365 qlist = NIL;
1366 }
1367 }
1368
1369 if (customplan)
1370 {
1371 /* Build a custom plan */
1372 plan = BuildCachedPlan(plansource, qlist, boundParams, queryEnv);
1373 /* Accumulate total costs of custom plans */
1374 plansource->total_custom_cost += cached_plan_cost(plan, true);
1375
1376 plansource->num_custom_plans++;
1377 }
1378 else
1379 {
1380 plansource->num_generic_plans++;
1381 }
1382
1383 Assert(plan != NULL);
1384
1385 /* Flag the plan as in use by caller */
1386 if (owner)
1387 ResourceOwnerEnlarge(owner);
1388 plan->refcount++;
1389 if (owner)
1391
1392 /*
1393 * Saved plans should be under CacheMemoryContext so they will not go away
1394 * until their reference count goes to zero. In the generic-plan cases we
1395 * already took care of that, but for a custom plan, do it as soon as we
1396 * have created a reference-counted link.
1397 */
1398 if (customplan && plansource->is_saved)
1399 {
1401 plan->is_saved = true;
1402 }
1403
1404 foreach(lc, plan->stmt_list)
1405 {
1406 PlannedStmt *pstmt = (PlannedStmt *) lfirst(lc);
1407
1409 }
1410
1411 return plan;
1412}
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:777
static bool choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams)
Definition: plancache.c:1173
static CachedPlan * BuildCachedPlan(CachedPlanSource *plansource, List *qlist, ParamListInfo boundParams, QueryEnvironment *queryEnv)
Definition: plancache.c:1034
static bool CheckCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:950
static double cached_plan_cost(CachedPlan *plan, bool include_planner)
Definition: plancache.c:1230
@ PLAN_STMT_CACHE_CUSTOM
Definition: plannodes.h:43
@ PLAN_STMT_CACHE_GENERIC
Definition: plannodes.h:42
PlannedStmtOrigin planOrigin
Definition: plannodes.h:77

References Assert(), BuildCachedPlan(), cached_plan_cost(), CACHEDPLAN_MAGIC, CACHEDPLANSOURCE_MAGIC, CacheMemoryContext, CheckCachedPlan(), choose_custom_plan(), CachedPlanSource::context, elog, ERROR, CachedPlanSource::generic_cost, CachedPlanSource::gplan, CachedPlanSource::is_complete, CachedPlanSource::is_saved, lfirst, CachedPlanSource::magic, MemoryContextGetParent(), MemoryContextSetParent(), NIL, CachedPlanSource::num_custom_plans, CachedPlanSource::num_generic_plans, plan, PLAN_STMT_CACHE_CUSTOM, PLAN_STMT_CACHE_GENERIC, PlannedStmt::planOrigin, ReleaseGenericPlan(), ResourceOwnerEnlarge(), ResourceOwnerRememberPlanCacheRef(), RevalidateCachedQuery(), and CachedPlanSource::total_custom_cost.

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

◆ InitPlanCache()

void InitPlanCache ( void  )

Definition at line 146 of file plancache.c.

147{
155 CacheRegisterSyscacheCallback(FOREIGNDATAWRAPPEROID, PlanCacheSysCallback, (Datum) 0);
156}
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1854
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1812
static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:2314
static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:2205
static void PlanCacheRelCallback(Datum arg, Oid relid)
Definition: plancache.c:2121
uint64_t Datum
Definition: postgres.h:70

References CacheRegisterRelcacheCallback(), CacheRegisterSyscacheCallback(), PlanCacheObjectCallback(), PlanCacheRelCallback(), and PlanCacheSysCallback().

Referenced by InitPostgres().

◆ ReleaseAllPlanCacheRefsInOwner()

void ReleaseAllPlanCacheRefsInOwner ( ResourceOwner  owner)

Definition at line 2370 of file plancache.c.

2371{
2373}
static const ResourceOwnerDesc planref_resowner_desc
Definition: plancache.c:115
void ResourceOwnerReleaseAllOfKind(ResourceOwner owner, const ResourceOwnerDesc *kind)
Definition: resowner.c:815

References planref_resowner_desc, and ResourceOwnerReleaseAllOfKind().

Referenced by plpgsql_call_handler(), plpgsql_inline_handler(), and plpgsql_xact_cb().

◆ ReleaseCachedPlan()

void ReleaseCachedPlan ( CachedPlan plan,
ResourceOwner  owner 
)

Definition at line 1426 of file plancache.c.

1427{
1428 Assert(plan->magic == CACHEDPLAN_MAGIC);
1429 if (owner)
1430 {
1431 Assert(plan->is_saved);
1433 }
1434 Assert(plan->refcount > 0);
1435 plan->refcount--;
1436 if (plan->refcount == 0)
1437 {
1438 /* Mark it no longer valid */
1439 plan->magic = 0;
1440
1441 /* One-shot plans do not own their context, so we can't free them */
1442 if (!plan->is_oneshot)
1443 MemoryContextDelete(plan->context);
1444 }
1445}
static void ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: plancache.c:131

References Assert(), CACHEDPLAN_MAGIC, MemoryContextDelete(), plan, and ResourceOwnerForgetPlanCacheRef().

Referenced by _SPI_execute_plan(), exec_eval_simple_expr(), exec_simple_check_plan(), ExplainExecuteQuery(), init_execution_state(), make_callstmt_target(), PortalReleaseCachedPlan(), ReleaseGenericPlan(), ResOwnerReleaseCachedPlan(), ShutdownSQLFunction(), and SPI_cursor_open_internal().

◆ ResetPlanCache()

void ResetPlanCache ( void  )

Definition at line 2323 of file plancache.c.

2324{
2325 dlist_iter iter;
2326
2328 {
2330 node, iter.cur);
2331
2332 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
2333
2334 /* No work if it's already invalidated */
2335 if (!plansource->is_valid)
2336 continue;
2337
2338 /*
2339 * We *must not* mark transaction control statements as invalid,
2340 * particularly not ROLLBACK, because they may need to be executed in
2341 * aborted transactions when we can't revalidate them (cf bug #5269).
2342 * In general there's no point in invalidating statements for which a
2343 * new parse analysis/rewrite/plan cycle would certainly give the same
2344 * results.
2345 */
2346 if (!StmtPlanRequiresRevalidation(plansource))
2347 continue;
2348
2349 plansource->is_valid = false;
2350 if (plansource->gplan)
2351 plansource->gplan->is_valid = false;
2352 }
2353
2354 /* Likewise invalidate cached expressions */
2356 {
2358 node, iter.cur);
2359
2360 Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2361
2362 cexpr->is_valid = false;
2363 }
2364}
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
static dlist_head saved_plan_list
Definition: plancache.c:84
bool is_valid
Definition: plancache.h:165
dlist_node * cur
Definition: ilist.h:179

References Assert(), cached_expression_list, CACHEDEXPR_MAGIC, CACHEDPLANSOURCE_MAGIC, dlist_iter::cur, dlist_container, dlist_foreach, CachedPlanSource::gplan, CachedPlanSource::is_valid, CachedPlan::is_valid, CachedExpression::is_valid, CachedPlanSource::magic, CachedExpression::magic, saved_plan_list, and StmtPlanRequiresRevalidation().

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

◆ SaveCachedPlan()

void SaveCachedPlan ( CachedPlanSource plansource)

Definition at line 545 of file plancache.c.

546{
547 /* Assert caller is doing things in a sane order */
548 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
549 Assert(plansource->is_complete);
550 Assert(!plansource->is_saved);
551
552 /* This seems worth a real test, though */
553 if (plansource->is_oneshot)
554 elog(ERROR, "cannot save one-shot cached plan");
555
556 /*
557 * In typical use, this function would be called before generating any
558 * plans from the CachedPlanSource. If there is a generic plan, moving it
559 * into CacheMemoryContext would be pretty risky since it's unclear
560 * whether the caller has taken suitable care with making references
561 * long-lived. Best thing to do seems to be to discard the plan.
562 */
563 ReleaseGenericPlan(plansource);
564
565 /*
566 * Reparent the source memory context under CacheMemoryContext so that it
567 * will live indefinitely. The query_context follows along since it's
568 * already a child of the other one.
569 */
571
572 /*
573 * Add the entry to the global list of cached plans.
574 */
575 dlist_push_tail(&saved_plan_list, &plansource->node);
576
577 plansource->is_saved = true;
578}

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, ReleaseGenericPlan(), and saved_plan_list.

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

◆ SetPostRewriteHook()

void SetPostRewriteHook ( CachedPlanSource plansource,
PostRewriteHook  postRewrite,
void *  postRewriteArg 
)

Definition at line 520 of file plancache.c.

523{
524 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
525 plansource->postRewrite = postRewrite;
526 plansource->postRewriteArg = postRewriteArg;
527}

References Assert(), CACHEDPLANSOURCE_MAGIC, CachedPlanSource::magic, CachedPlanSource::postRewrite, and CachedPlanSource::postRewriteArg.

Referenced by prepare_next_query().

Variable Documentation

◆ plan_cache_mode

PGDLLIMPORT int plan_cache_mode
extern

Definition at line 138 of file plancache.c.

Referenced by choose_custom_plan().