PostgreSQL Source Code git master
Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
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 CachedPlan  CachedPlan
 
 

Enumerations

 

Functions

void  InitPlanCache (void)
 
void  ResetPlanCache (void)
 
 
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)
 
 
 
bool  CachedPlanIsValid (CachedPlanSource *plansource)
 
 
CachedPlanGetCachedPlan (CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
 
 
 
 
 
 

Variables

 

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 ( CachedPlanSourceplansource,
CachedPlanplan,
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
bool dependsOnRLS
Definition: plancache.h:131
struct SearchPathMatcher * search_path
Definition: plancache.h:126
bool is_oneshot
Definition: plancache.h:135
List * query_list
Definition: plancache.h:123
CmdType commandType
Definition: plannodes.h:68
List * rtable
Definition: plannodes.h:109
Definition: parsenodes.h:118
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
Definition: pg_list.h:46

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 ( CachedPlanSourceplansource,
QueryEnvironmentqueryEnv 
)

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:349
TupleDesc resultDesc
Definition: plancache.h:120
bool is_complete
Definition: plancache.h:136
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 ( CachedPlanSourceplansource,
CachedPlanplan,
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 ( CachedPlanSourceplansource )

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 ( CachedPlanSourceplansource,
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
int magic
Definition: plancache.h:161

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 ( CachedPlanSourceplansource,
Listquerytree_list,
MemoryContext  querytree_context,
Oidparam_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:3637
Oid * param_types
Definition: plancache.h:112
bool fixed_result
Definition: plancache.h:119
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
int cursor_options
Definition: plancache.h:118
List * relationOids
Definition: plancache.h:124
Oid rewriteRoleId
Definition: plancache.h:129
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 ( CachedPlanSourceplansource )

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 ( RawStmtraw_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 ( Queryanalyzed_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 ( RawStmtraw_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 ( CachedPlanSourceplansource )

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

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

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:6746
List * relationOids
Definition: plancache.h:193
Node * expr
Definition: plancache.h:190
List * invalItems
Definition: plancache.h:194
Definition: primnodes.h:189
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 ( CachedPlanSourceplansource,
ParamListInfo  boundParams,
ResourceOwner  owner,
QueryEnvironmentqueryEnv 
)

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 ( CachedPlanplan,
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
Definition: ilist.h:178
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 ( CachedPlanSourceplansource )

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

AltStyle によって変換されたページ (->オリジナル) /