LCOV - code coverage report
Current view: top level - src/include/utils - plancache.h (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 4 4 100.0 %
Date: 2025-02-22 07:14:56 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * plancache.h
       4             :  *    Plan cache definitions.
       5             :  *
       6             :  * See plancache.c for comments.
       7             :  *
       8             :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
       9             :  * Portions Copyright (c) 1994, Regents of the University of California
      10             :  *
      11             :  * src/include/utils/plancache.h
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #ifndef PLANCACHE_H
      16             : #define PLANCACHE_H
      17             : 
      18             : #include "access/tupdesc.h"
      19             : #include "lib/ilist.h"
      20             : #include "nodes/params.h"
      21             : #include "nodes/parsenodes.h"
      22             : #include "nodes/plannodes.h"
      23             : #include "tcop/cmdtag.h"
      24             : #include "utils/queryenvironment.h"
      25             : #include "utils/resowner.h"
      26             : 
      27             : 
      28             : /* Forward declaration, to avoid including parsenodes.h here */
      29             : struct RawStmt;
      30             : 
      31             : /* possible values for plan_cache_mode */
      32             : typedef enum
      33             : {
      34             :     PLAN_CACHE_MODE_AUTO,
      35             :     PLAN_CACHE_MODE_FORCE_GENERIC_PLAN,
      36             :     PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN,
      37             : }           PlanCacheMode;
      38             : 
      39             : /* GUC parameter */
      40             : extern PGDLLIMPORT int plan_cache_mode;
      41             : 
      42             : #define CACHEDPLANSOURCE_MAGIC      195726186
      43             : #define CACHEDPLAN_MAGIC            953717834
      44             : #define CACHEDEXPR_MAGIC            838275847
      45             : 
      46             : /*
      47             :  * CachedPlanSource (which might better have been called CachedQuery)
      48             :  * represents a SQL query that we expect to use multiple times.  It stores
      49             :  * the query source text, the raw parse tree, and the analyzed-and-rewritten
      50             :  * query tree, as well as adjunct data.  Cache invalidation can happen as a
      51             :  * result of DDL affecting objects used by the query.  In that case we discard
      52             :  * the analyzed-and-rewritten query tree, and rebuild it when next needed.
      53             :  *
      54             :  * An actual execution plan, represented by CachedPlan, is derived from the
      55             :  * CachedPlanSource when we need to execute the query.  The plan could be
      56             :  * either generic (usable with any set of plan parameters) or custom (for a
      57             :  * specific set of parameters).  plancache.c contains the logic that decides
      58             :  * which way to do it for any particular execution.  If we are using a generic
      59             :  * cached plan then it is meant to be re-used across multiple executions, so
      60             :  * callers must always treat CachedPlans as read-only.
      61             :  *
      62             :  * Once successfully built and "saved", CachedPlanSources typically live
      63             :  * for the life of the backend, although they can be dropped explicitly.
      64             :  * CachedPlans are reference-counted and go away automatically when the last
      65             :  * reference is dropped.  A CachedPlan can outlive the CachedPlanSource it
      66             :  * was created from.
      67             :  *
      68             :  * An "unsaved" CachedPlanSource can be used for generating plans, but it
      69             :  * lives in transient storage and will not be updated in response to sinval
      70             :  * events.
      71             :  *
      72             :  * CachedPlans made from saved CachedPlanSources are likewise in permanent
      73             :  * storage, so to avoid memory leaks, the reference-counted references to them
      74             :  * must be held in permanent data structures or ResourceOwners.  CachedPlans
      75             :  * made from unsaved CachedPlanSources are in children of the caller's
      76             :  * memory context, so references to them should not be longer-lived than
      77             :  * that context.  (Reference counting is somewhat pro forma in that case,
      78             :  * though it may be useful if the CachedPlan can be discarded early.)
      79             :  *
      80             :  * A CachedPlanSource has two associated memory contexts: one that holds the
      81             :  * struct itself, the query source text and the raw parse tree, and another
      82             :  * context that holds the rewritten query tree and associated data.  This
      83             :  * allows the query tree to be discarded easily when it is invalidated.
      84             :  *
      85             :  * Some callers wish to use the CachedPlan API even with one-shot queries
      86             :  * that have no reason to be saved at all.  We therefore support a "oneshot"
      87             :  * variant that does no data copying or invalidation checking.  In this case
      88             :  * there are no separate memory contexts: the CachedPlanSource struct and
      89             :  * all subsidiary data live in the caller's CurrentMemoryContext, and there
      90             :  * is no way to free memory short of clearing that entire context.  A oneshot
      91             :  * plan is always treated as unsaved.
      92             :  *
      93             :  * Note: the string referenced by commandTag is not subsidiary storage;
      94             :  * it is assumed to be a compile-time-constant string.  As with portals,
      95             :  * commandTag shall be NULL if and only if the original query string (before
      96             :  * rewriting) was an empty string.
      97             :  */
      98             : typedef struct CachedPlanSource
      99             : {
     100             :     int         magic;          /* should equal CACHEDPLANSOURCE_MAGIC */
     101             :     struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */
     102             :     const char *query_string;   /* source text of query */
     103             :     CommandTag  commandTag;     /* 'nuff said */
     104             :     Oid        *param_types;    /* array of parameter type OIDs, or NULL */
     105             :     int         num_params;     /* length of param_types array */
     106             :     ParserSetupHook parserSetup;    /* alternative parameter spec method */
     107             :     void       *parserSetupArg;
     108             :     int         cursor_options; /* cursor options used for planning */
     109             :     bool        fixed_result;   /* disallow change in result tupdesc? */
     110             :     TupleDesc   resultDesc;     /* result type; NULL = doesn't return tuples */
     111             :     MemoryContext context;      /* memory context holding all above */
     112             :     /* These fields describe the current analyzed-and-rewritten query tree: */
     113             :     List       *query_list;     /* list of Query nodes, or NIL if not valid */
     114             :     List       *relationOids;   /* OIDs of relations the queries depend on */
     115             :     List       *invalItems;     /* other dependencies, as PlanInvalItems */
     116             :     struct SearchPathMatcher *search_path;  /* search_path used for parsing
     117             :                                              * and planning */
     118             :     MemoryContext query_context;    /* context holding the above, or NULL */
     119             :     Oid         rewriteRoleId;  /* Role ID we did rewriting for */
     120             :     bool        rewriteRowSecurity; /* row_security used during rewrite */
     121             :     bool        dependsOnRLS;   /* is rewritten query specific to the above? */
     122             :     /* If we have a generic plan, this is a reference-counted link to it: */
     123             :     struct CachedPlan *gplan;   /* generic plan, or NULL if not valid */
     124             :     /* Some state flags: */
     125             :     bool        is_oneshot;     /* is it a "oneshot" plan? */
     126             :     bool        is_complete;    /* has CompleteCachedPlan been done? */
     127             :     bool        is_saved;       /* has CachedPlanSource been "saved"? */
     128             :     bool        is_valid;       /* is the query_list currently valid? */
     129             :     int         generation;     /* increments each time we create a plan */
     130             :     /* If CachedPlanSource has been saved, it is a member of a global list */
     131             :     dlist_node  node;           /* list link, if is_saved */
     132             :     /* State kept to help decide whether to use custom or generic plans: */
     133             :     double      generic_cost;   /* cost of generic plan, or -1 if not known */
     134             :     double      total_custom_cost;  /* total cost of custom plans so far */
     135             :     int64       num_custom_plans;   /* # of custom plans included in total */
     136             :     int64       num_generic_plans;  /* # of generic plans */
     137             : } CachedPlanSource;
     138             : 
     139             : /*
     140             :  * CachedPlan represents an execution plan derived from a CachedPlanSource.
     141             :  * The reference count includes both the link from the parent CachedPlanSource
     142             :  * (if any), and any active plan executions, so the plan can be discarded
     143             :  * exactly when refcount goes to zero.  Both the struct itself and the
     144             :  * subsidiary data, except the PlannedStmts in stmt_list live in the context
     145             :  * denoted by the context field; the PlannedStmts live in the context denoted
     146             :  * by stmt_context.  Separate contexts makes it easy to free a no-longer-needed
     147             :  * cached plan. (However, if is_oneshot is true, the context does not belong
     148             :  * solely to the CachedPlan so no freeing is possible.)
     149             :  */
     150             : typedef struct CachedPlan
     151             : {
     152             :     int         magic;          /* should equal CACHEDPLAN_MAGIC */
     153             :     List       *stmt_list;      /* list of PlannedStmts */
     154             :     bool        is_oneshot;     /* is it a "oneshot" plan? */
     155             :     bool        is_saved;       /* is CachedPlan in a long-lived context? */
     156             :     bool        is_reused;      /* is it a reused generic plan? */
     157             :     bool        is_valid;       /* is the stmt_list currently valid? */
     158             :     Oid         planRoleId;     /* Role ID the plan was created for */
     159             :     bool        dependsOnRole;  /* is plan specific to that role? */
     160             :     TransactionId saved_xmin;   /* if valid, replan when TransactionXmin
     161             :                                  * changes from this value */
     162             :     int         generation;     /* parent's generation number for this plan */
     163             :     int         refcount;       /* count of live references to this struct */
     164             :     MemoryContext context;      /* context containing this CachedPlan */
     165             :     MemoryContext stmt_context; /* context containing the PlannedStmts in
     166             :                                  * stmt_list, but not the List itself which is
     167             :                                  * in the above context; NULL if is_oneshot is
     168             :                                  * true. */
     169             : } CachedPlan;
     170             : 
     171             : /*
     172             :  * CachedExpression is a low-overhead mechanism for caching the planned form
     173             :  * of standalone scalar expressions.  While such expressions are not usually
     174             :  * subject to cache invalidation events, that can happen, for example because
     175             :  * of replacement of a SQL function that was inlined into the expression.
     176             :  * The plancache takes care of storing the expression tree and marking it
     177             :  * invalid if a cache invalidation occurs, but the caller must notice the
     178             :  * !is_valid status and discard the obsolete expression without reusing it.
     179             :  * We do not store the original parse tree, only the planned expression;
     180             :  * this is an optimization based on the assumption that we usually will not
     181             :  * need to replan for the life of the session.
     182             :  */
     183             : typedef struct CachedExpression
     184             : {
     185             :     int         magic;          /* should equal CACHEDEXPR_MAGIC */
     186             :     Node       *expr;           /* planned form of expression */
     187             :     bool        is_valid;       /* is the expression still valid? */
     188             :     /* remaining fields should be treated as private to plancache.c: */
     189             :     List       *relationOids;   /* OIDs of relations the expr depends on */
     190             :     List       *invalItems;     /* other dependencies, as PlanInvalItems */
     191             :     MemoryContext context;      /* context containing this CachedExpression */
     192             :     dlist_node  node;           /* link in global list of CachedExpressions */
     193             : } CachedExpression;
     194             : 
     195             : 
     196             : extern void InitPlanCache(void);
     197             : extern void ResetPlanCache(void);
     198             : 
     199             : extern void ReleaseAllPlanCacheRefsInOwner(ResourceOwner owner);
     200             : 
     201             : extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree,
     202             :                                           const char *query_string,
     203             :                                           CommandTag commandTag);
     204             : extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree,
     205             :                                                  const char *query_string,
     206             :                                                  CommandTag commandTag);
     207             : extern void CompleteCachedPlan(CachedPlanSource *plansource,
     208             :                                List *querytree_list,
     209             :                                MemoryContext querytree_context,
     210             :                                Oid *param_types,
     211             :                                int num_params,
     212             :                                ParserSetupHook parserSetup,
     213             :                                void *parserSetupArg,
     214             :                                int cursor_options,
     215             :                                bool fixed_result);
     216             : 
     217             : extern void SaveCachedPlan(CachedPlanSource *plansource);
     218             : extern void DropCachedPlan(CachedPlanSource *plansource);
     219             : 
     220             : extern void CachedPlanSetParentContext(CachedPlanSource *plansource,
     221             :                                        MemoryContext newcontext);
     222             : 
     223             : extern CachedPlanSource *CopyCachedPlan(CachedPlanSource *plansource);
     224             : 
     225             : extern bool CachedPlanIsValid(CachedPlanSource *plansource);
     226             : 
     227             : extern List *CachedPlanGetTargetList(CachedPlanSource *plansource,
     228             :                                      QueryEnvironment *queryEnv);
     229             : 
     230             : extern CachedPlan *GetCachedPlan(CachedPlanSource *plansource,
     231             :                                  ParamListInfo boundParams,
     232             :                                  ResourceOwner owner,
     233             :                                  QueryEnvironment *queryEnv);
     234             : extern PlannedStmt *UpdateCachedPlan(CachedPlanSource *plansource,
     235             :                                      int query_index,
     236             :                                      QueryEnvironment *queryEnv);
     237             : 
     238             : extern void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner);
     239             : 
     240             : extern bool CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource,
     241             :                                                 CachedPlan *plan,
     242             :                                                 ResourceOwner owner);
     243             : extern bool CachedPlanIsSimplyValid(CachedPlanSource *plansource,
     244             :                                     CachedPlan *plan,
     245             :                                     ResourceOwner owner);
     246             : 
     247             : extern CachedExpression *GetCachedExpression(Node *expr);
     248             : extern void FreeCachedExpression(CachedExpression *cexpr);
     249             : 
     250             : /*
     251             :  * CachedPlanRequiresLocking: should the executor acquire additional locks?
     252             :  *
     253             :  * If the plan is a saved generic plan, the executor must acquire locks for
     254             :  * relations that are not covered by AcquireExecutorLocks(), such as partitions
     255             :  * that are subject to initial runtime pruning.
     256             :  */
     257             : static inline bool
     258         290 : CachedPlanRequiresLocking(CachedPlan *cplan)
     259             : {
     260         290 :     return !cplan->is_oneshot && cplan->is_reused;
     261             : }
     262             : 
     263             : /*
     264             :  * CachedPlanValid
     265             :  *      Returns whether a cached generic plan is still valid.
     266             :  *
     267             :  * Invoked by the executor to check if the plan has not been invalidated after
     268             :  * taking locks during the initialization of the plan.
     269             :  */
     270             : static inline bool
     271      359658 : CachedPlanValid(CachedPlan *cplan)
     272             : {
     273      359658 :     return cplan->is_valid;
     274             : }
     275             : 
     276             : #endif                          /* PLANCACHE_H */

Generated by: LCOV version 1.14