PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 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 (struct RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
 
CachedPlanSourceCreateCachedPlanForQuery (struct Query *analyzed_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 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.

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

1450{
1451 ListCell *lc;
1452
1453 /*
1454 * Sanity-check that the caller gave us a validated generic plan. Notice
1455 * that we *don't* assert plansource->is_valid as you might expect; that's
1456 * because it's possible that that's already false when GetCachedPlan
1457 * returns, e.g. because ResetPlanCache happened partway through. We
1458 * should accept the plan as long as plan->is_valid is true, and expect to
1459 * replan after the next CachedPlanIsSimplyValid call.
1460 */
1461 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1462 Assert(plan->magic == CACHEDPLAN_MAGIC);
1463 Assert(plan->is_valid);
1464 Assert(plan == plansource->gplan);
1465 Assert(plansource->search_path != NULL);
1467
1468 /* We don't support oneshot plans here. */
1469 if (plansource->is_oneshot)
1470 return false;
1471 Assert(!plan->is_oneshot);
1472
1473 /*
1474 * If the plan is dependent on RLS considerations, or it's transient,
1475 * reject. These things probably can't ever happen for table-free
1476 * queries, but for safety's sake let's check.
1477 */
1478 if (plansource->dependsOnRLS)
1479 return false;
1480 if (plan->dependsOnRole)
1481 return false;
1482 if (TransactionIdIsValid(plan->saved_xmin))
1483 return false;
1484
1485 /*
1486 * Reject if AcquirePlannerLocks would have anything to do. This is
1487 * simplistic, but there's no need to inquire any more carefully; indeed,
1488 * for current callers it shouldn't even be possible to hit any of these
1489 * checks.
1490 */
1491 foreach(lc, plansource->query_list)
1492 {
1493 Query *query = lfirst_node(Query, lc);
1494
1495 if (query->commandType == CMD_UTILITY)
1496 return false;
1497 if (query->rtable || query->cteList || query->hasSubLinks)
1498 return false;
1499 }
1500
1501 /*
1502 * Reject if AcquireExecutorLocks would have anything to do. This is
1503 * probably unnecessary given the previous check, but let's be safe.
1504 */
1505 foreach(lc, plan->stmt_list)
1506 {
1507 PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
1508 ListCell *lc2;
1509
1510 if (plannedstmt->commandType == CMD_UTILITY)
1511 return false;
1512
1513 /*
1514 * We have to grovel through the rtable because it's likely to contain
1515 * an RTE_RESULT relation, rather than being totally empty.
1516 */
1517 foreach(lc2, plannedstmt->rtable)
1518 {
1519 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
1520
1521 if (rte->rtekind == RTE_RELATION)
1522 return false;
1523 }
1524 }
1525
1526 /*
1527 * Okay, it's simple. Note that what we've primarily established here is
1528 * that no locks need be taken before checking the plan's is_valid flag.
1529 */
1530
1531 /* Bump refcount if requested. */
1532 if (owner)
1533 {
1534 ResourceOwnerEnlarge(owner);
1535 plan->refcount++;
1537 }
1538
1539 return true;
1540}
Assert(PointerIsAligned(start, uint64))
bool SearchPathMatchesCurrentEnvironment(SearchPathMatcher *path)
Definition: namespace.c:3911
@ CMD_UTILITY
Definition: nodes.h:276
@ RTE_RELATION
Definition: parsenodes.h:1026
#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:452
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:53
List * rtable
Definition: plannodes.h:91
List * cteList
Definition: parsenodes.h:168
List * rtable
Definition: parsenodes.h:170
CmdType commandType
Definition: parsenodes.h:121
RTEKind rtekind
Definition: parsenodes.h:1061
#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 1755 of file plancache.c.

1757{
1758 Query *pstmt;
1759
1760 /* Assert caller is doing things in a sane order */
1761 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1762 Assert(plansource->is_complete);
1763
1764 /*
1765 * No work needed if statement doesn't return tuples (we assume this
1766 * feature cannot be changed by an invalidation)
1767 */
1768 if (plansource->resultDesc == NULL)
1769 return NIL;
1770
1771 /* Make sure the querytree list is valid and we have parse-time locks */
1772 RevalidateCachedQuery(plansource, queryEnv);
1773
1774 /* Get the primary statement and find out what it returns */
1775 pstmt = QueryListGetPrimaryStmt(plansource->query_list);
1776
1777 return FetchStatementTargetList((Node *) pstmt);
1778}
#define NIL
Definition: pg_list.h:68
static List * RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:667
static Query * QueryListGetPrimaryStmt(List *stmts)
Definition: plancache.c:1868
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:349
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 1563 of file plancache.c.

1565{
1566 /*
1567 * Careful here: since the caller doesn't necessarily hold a refcount on
1568 * the plan to start with, it's possible that "plan" is a dangling
1569 * pointer. Don't dereference it until we've verified that it still
1570 * matches the plansource's gplan (which is either valid or NULL).
1571 */
1572 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1573
1574 /*
1575 * Has cache invalidation fired on this plan? We can check this right
1576 * away since there are no locks that we'd need to acquire first. Note
1577 * that here we *do* check plansource->is_valid, so as to force plan
1578 * rebuild if that's become false.
1579 */
1580 if (!plansource->is_valid ||
1581 plan == NULL || plan != plansource->gplan ||
1582 !plan->is_valid)
1583 return false;
1584
1585 Assert(plan->magic == CACHEDPLAN_MAGIC);
1586
1587 /* Is the search_path still the same as when we made it? */
1588 Assert(plansource->search_path != NULL);
1590 return false;
1591
1592 /* It's still good. Bump refcount if requested. */
1593 if (owner)
1594 {
1595 ResourceOwnerEnlarge(owner);
1596 plan->refcount++;
1598 }
1599
1600 return true;
1601}

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

1743{
1744 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1745 return plansource->is_valid;
1746}

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

1612{
1613 /* Assert caller is doing things in a sane order */
1614 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1615 Assert(plansource->is_complete);
1616
1617 /* These seem worth real tests, though */
1618 if (plansource->is_saved)
1619 elog(ERROR, "cannot move a saved cached plan to another context");
1620 if (plansource->is_oneshot)
1621 elog(ERROR, "cannot move a one-shot cached plan to another context");
1622
1623 /* OK, let the caller keep the plan where he wishes */
1624 MemoryContextSetParent(plansource->context, newcontext);
1625
1626 /*
1627 * The query_context needs no special handling, since it's a child of
1628 * plansource->context. But if there's a generic plan, it should be
1629 * maintained as a sibling of plansource->context.
1630 */
1631 if (plansource->gplan)
1632 {
1633 Assert(plansource->gplan->magic == CACHEDPLAN_MAGIC);
1634 MemoryContextSetParent(plansource->gplan->context, newcontext);
1635 }
1636}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:637
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. Also save
467 * the result tuple descriptor.
468 */
469 MemoryContextSwitchTo(source_context);
470
471 if (num_params > 0)
472 {
473 plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
474 memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
475 }
476 else
477 plansource->param_types = NULL;
478 plansource->num_params = num_params;
479 plansource->parserSetup = parserSetup;
480 plansource->parserSetupArg = parserSetupArg;
481 plansource->cursor_options = cursor_options;
482 plansource->fixed_result = fixed_result;
483 plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
484
485 MemoryContextSwitchTo(oldcxt);
486
487 plansource->is_complete = true;
488 plansource->is_valid = true;
489}
bool row_security
Definition: guc_tables.c:527
void * palloc(Size size)
Definition: mcxt.c:1321
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:177
Oid GetUserId(void)
Definition: miscinit.c:520
SearchPathMatcher * GetSearchPathMatcher(MemoryContext context)
Definition: namespace.c:3852
#define copyObject(obj)
Definition: nodes.h:230
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static bool StmtPlanRequiresRevalidation(CachedPlanSource *plansource)
Definition: plancache.c:625
static TupleDesc PlanCacheComputeResultDesc(List *stmt_list)
Definition: plancache.c:2062
unsigned int Oid
Definition: postgres_ext.h:30
void extract_query_dependencies(Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
Definition: setrefs.c:3631
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

References ALLOCSET_START_SMALL_SIZES, AllocSetContextCreate, Assert(), CACHEDPLANSOURCE_MAGIC, CachedPlanSource::context, copyObject, 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 1648 of file plancache.c.

1649{
1650 CachedPlanSource *newsource;
1651 MemoryContext source_context;
1652 MemoryContext querytree_context;
1653 MemoryContext oldcxt;
1654
1655 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1656 Assert(plansource->is_complete);
1657
1658 /*
1659 * One-shot plans can't be copied, because we haven't taken care that
1660 * parsing/planning didn't scribble on the raw parse tree or querytrees.
1661 */
1662 if (plansource->is_oneshot)
1663 elog(ERROR, "cannot copy a one-shot cached plan");
1664
1666 "CachedPlanSource",
1668
1669 oldcxt = MemoryContextSwitchTo(source_context);
1670
1671 newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1672 newsource->magic = CACHEDPLANSOURCE_MAGIC;
1673 newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
1674 newsource->analyzed_parse_tree = copyObject(plansource->analyzed_parse_tree);
1675 newsource->query_string = pstrdup(plansource->query_string);
1676 MemoryContextSetIdentifier(source_context, newsource->query_string);
1677 newsource->commandTag = plansource->commandTag;
1678 if (plansource->num_params > 0)
1679 {
1680 newsource->param_types = (Oid *)
1681 palloc(plansource->num_params * sizeof(Oid));
1682 memcpy(newsource->param_types, plansource->param_types,
1683 plansource->num_params * sizeof(Oid));
1684 }
1685 else
1686 newsource->param_types = NULL;
1687 newsource->num_params = plansource->num_params;
1688 newsource->parserSetup = plansource->parserSetup;
1689 newsource->parserSetupArg = plansource->parserSetupArg;
1690 newsource->postRewrite = plansource->postRewrite;
1691 newsource->postRewriteArg = plansource->postRewriteArg;
1692 newsource->cursor_options = plansource->cursor_options;
1693 newsource->fixed_result = plansource->fixed_result;
1694 if (plansource->resultDesc)
1695 newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
1696 else
1697 newsource->resultDesc = NULL;
1698 newsource->context = source_context;
1699
1700 querytree_context = AllocSetContextCreate(source_context,
1701 "CachedPlanQuery",
1703 MemoryContextSwitchTo(querytree_context);
1704 newsource->query_list = copyObject(plansource->query_list);
1705 newsource->relationOids = copyObject(plansource->relationOids);
1706 newsource->invalItems = copyObject(plansource->invalItems);
1707 if (plansource->search_path)
1708 newsource->search_path = CopySearchPathMatcher(plansource->search_path);
1709 newsource->query_context = querytree_context;
1710 newsource->rewriteRoleId = plansource->rewriteRoleId;
1711 newsource->rewriteRowSecurity = plansource->rewriteRowSecurity;
1712 newsource->dependsOnRLS = plansource->dependsOnRLS;
1713
1714 newsource->gplan = NULL;
1715
1716 newsource->is_oneshot = false;
1717 newsource->is_complete = true;
1718 newsource->is_saved = false;
1719 newsource->is_valid = plansource->is_valid;
1720 newsource->generation = plansource->generation;
1721
1722 /* We may as well copy any acquired cost knowledge */
1723 newsource->generic_cost = plansource->generic_cost;
1724 newsource->total_custom_cost = plansource->total_custom_cost;
1725 newsource->num_generic_plans = plansource->num_generic_plans;
1726 newsource->num_custom_plans = plansource->num_custom_plans;
1727
1728 MemoryContextSwitchTo(oldcxt);
1729
1730 return newsource;
1731}
char * pstrdup(const char *in)
Definition: mcxt.c:1703
void * palloc0(Size size)
Definition: mcxt.c:1351
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:612
SearchPathMatcher * CopySearchPathMatcher(SearchPathMatcher *path)
Definition: namespace.c:3889
PostRewriteHook postRewrite
Definition: plancache.h:116
struct Query * analyzed_parse_tree
Definition: plancache.h:109
CommandTag commandTag
Definition: plancache.h:111
double total_custom_cost
Definition: plancache.h:144
const char * query_string
Definition: plancache.h:110
struct RawStmt * raw_parse_tree
Definition: plancache.h:108
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
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:245

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 ( struct 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:35

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 ( struct 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 ( struct 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 574 of file plancache.c.

575{
576 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
577
578 /* If it's been saved, remove it from the list */
579 if (plansource->is_saved)
580 {
581 dlist_delete(&plansource->node);
582 plansource->is_saved = false;
583 }
584
585 /* Decrement generic CachedPlan's refcount and drop if no longer needed */
586 ReleaseGenericPlan(plansource);
587
588 /* Mark it no longer valid */
589 plansource->magic = 0;
590
591 /*
592 * Remove the CachedPlanSource and all subsidiary data (including the
593 * query_context if any). But if it's a one-shot we can't free anything.
594 */
595 if (!plansource->is_oneshot)
596 MemoryContextDelete(plansource->context);
597}
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:603
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 1849 of file plancache.c.

1850{
1851 /* Sanity check */
1852 Assert(cexpr->magic == CACHEDEXPR_MAGIC);
1853 /* Unlink from global list */
1854 dlist_delete(&cexpr->node);
1855 /* Free all storage associated with CachedExpression */
1857}
#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 1792 of file plancache.c.

1793{
1794 CachedExpression *cexpr;
1795 List *relationOids;
1796 List *invalItems;
1797 MemoryContext cexpr_context;
1798 MemoryContext oldcxt;
1799
1800 /*
1801 * Pass the expression through the planner, and collect dependencies.
1802 * Everything built here is leaked in the caller's context; that's
1803 * intentional to minimize the size of the permanent data structure.
1804 */
1805 expr = (Node *) expression_planner_with_deps((Expr *) expr,
1806 &relationOids,
1807 &invalItems);
1808
1809 /*
1810 * Make a private memory context, and copy what we need into that. To
1811 * avoid leaking a long-lived context if we fail while copying data, we
1812 * initially make the context under the caller's context.
1813 */
1815 "CachedExpression",
1817
1818 oldcxt = MemoryContextSwitchTo(cexpr_context);
1819
1820 cexpr = (CachedExpression *) palloc(sizeof(CachedExpression));
1821 cexpr->magic = CACHEDEXPR_MAGIC;
1822 cexpr->expr = copyObject(expr);
1823 cexpr->is_valid = true;
1824 cexpr->relationOids = copyObject(relationOids);
1825 cexpr->invalItems = copyObject(invalItems);
1826 cexpr->context = cexpr_context;
1827
1828 MemoryContextSwitchTo(oldcxt);
1829
1830 /*
1831 * Reparent the expr's memory context under CacheMemoryContext so that it
1832 * will live indefinitely.
1833 */
1835
1836 /*
1837 * Add the entry to the global list of cached expressions.
1838 */
1840
1841 return cexpr;
1842}
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
#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:6718
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 1280 of file plancache.c.

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

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, CachedPlanSource::magic, MemoryContextGetParent(), MemoryContextSetParent(), NIL, CachedPlanSource::num_custom_plans, CachedPlanSource::num_generic_plans, plan, 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:2291
static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:2182
static void PlanCacheRelCallback(Datum arg, Oid relid)
Definition: plancache.c:2098
uintptr_t Datum
Definition: postgres.h:69

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

Referenced by InitPostgres().

◆ ReleaseAllPlanCacheRefsInOwner()

void ReleaseAllPlanCacheRefsInOwner ( ResourceOwner  owner)

Definition at line 2347 of file plancache.c.

2348{
2350}
static const ResourceOwnerDesc planref_resowner_desc
Definition: plancache.c:115
void ResourceOwnerReleaseAllOfKind(ResourceOwner owner, const ResourceOwnerDesc *kind)
Definition: resowner.c:818

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

1404{
1405 Assert(plan->magic == CACHEDPLAN_MAGIC);
1406 if (owner)
1407 {
1408 Assert(plan->is_saved);
1410 }
1411 Assert(plan->refcount > 0);
1412 plan->refcount--;
1413 if (plan->refcount == 0)
1414 {
1415 /* Mark it no longer valid */
1416 plan->magic = 0;
1417
1418 /* One-shot plans do not own their context, so we can't free them */
1419 if (!plan->is_oneshot)
1420 MemoryContextDelete(plan->context);
1421 }
1422}
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 2300 of file plancache.c.

2301{
2302 dlist_iter iter;
2303
2305 {
2307 node, iter.cur);
2308
2309 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
2310
2311 /* No work if it's already invalidated */
2312 if (!plansource->is_valid)
2313 continue;
2314
2315 /*
2316 * We *must not* mark transaction control statements as invalid,
2317 * particularly not ROLLBACK, because they may need to be executed in
2318 * aborted transactions when we can't revalidate them (cf bug #5269).
2319 * In general there's no point in invalidating statements for which a
2320 * new parse analysis/rewrite/plan cycle would certainly give the same
2321 * results.
2322 */
2323 if (!StmtPlanRequiresRevalidation(plansource))
2324 continue;
2325
2326 plansource->is_valid = false;
2327 if (plansource->gplan)
2328 plansource->gplan->is_valid = false;
2329 }
2330
2331 /* Likewise invalidate cached expressions */
2333 {
2335 node, iter.cur);
2336
2337 Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2338
2339 cexpr->is_valid = false;
2340 }
2341}
#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 530 of file plancache.c.

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

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

508{
509 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
510 plansource->postRewrite = postRewrite;
511 plansource->postRewriteArg = postRewriteArg;
512}

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