codekingpro/portable-devtools
115k
1/*-------------------------------------------------------------------------2 *3 * plancache.h4 * Plan cache definitions.5 *6 * See plancache.c for comments.7 *8 * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group9 * Portions Copyright (c) 1994, Regents of the University of California10 *11 * src/include/utils/plancache.h12 *13 *-------------------------------------------------------------------------14 */15#ifndef PLANCACHE_H16#define PLANCACHE_H17 18#include "access/tupdesc.h"19#include "lib/ilist.h"20#include "nodes/params.h"21#include "tcop/cmdtag.h"22#include "utils/queryenvironment.h"23#include "utils/resowner.h"24 25 26/* Forward declaration, to avoid including parsenodes.h here */27struct RawStmt;28 29/* possible values for plan_cache_mode */30typedef enum31{32 PLAN_CACHE_MODE_AUTO,33 PLAN_CACHE_MODE_FORCE_GENERIC_PLAN,34 PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN35} PlanCacheMode;36 37/* GUC parameter */38extern PGDLLIMPORT int plan_cache_mode;39 40#define CACHEDPLANSOURCE_MAGIC 19572618641#define CACHEDPLAN_MAGIC 95371783442#define CACHEDEXPR_MAGIC 83827584743 44/*45 * CachedPlanSource (which might better have been called CachedQuery)46 * represents a SQL query that we expect to use multiple times. It stores47 * the query source text, the raw parse tree, and the analyzed-and-rewritten48 * query tree, as well as adjunct data. Cache invalidation can happen as a49 * result of DDL affecting objects used by the query. In that case we discard50 * the analyzed-and-rewritten query tree, and rebuild it when next needed.51 *52 * An actual execution plan, represented by CachedPlan, is derived from the53 * CachedPlanSource when we need to execute the query. The plan could be54 * either generic (usable with any set of plan parameters) or custom (for a55 * specific set of parameters). plancache.c contains the logic that decides56 * which way to do it for any particular execution. If we are using a generic57 * cached plan then it is meant to be re-used across multiple executions, so58 * callers must always treat CachedPlans as read-only.59 *60 * Once successfully built and "saved", CachedPlanSources typically live61 * for the life of the backend, although they can be dropped explicitly.62 * CachedPlans are reference-counted and go away automatically when the last63 * reference is dropped. A CachedPlan can outlive the CachedPlanSource it64 * was created from.65 *66 * An "unsaved" CachedPlanSource can be used for generating plans, but it67 * lives in transient storage and will not be updated in response to sinval68 * events.69 *70 * CachedPlans made from saved CachedPlanSources are likewise in permanent71 * storage, so to avoid memory leaks, the reference-counted references to them72 * must be held in permanent data structures or ResourceOwners. CachedPlans73 * made from unsaved CachedPlanSources are in children of the caller's74 * memory context, so references to them should not be longer-lived than75 * that context. (Reference counting is somewhat pro forma in that case,76 * though it may be useful if the CachedPlan can be discarded early.)77 *78 * A CachedPlanSource has two associated memory contexts: one that holds the79 * struct itself, the query source text and the raw parse tree, and another80 * context that holds the rewritten query tree and associated data. This81 * allows the query tree to be discarded easily when it is invalidated.82 *83 * Some callers wish to use the CachedPlan API even with one-shot queries84 * that have no reason to be saved at all. We therefore support a "oneshot"85 * variant that does no data copying or invalidation checking. In this case86 * there are no separate memory contexts: the CachedPlanSource struct and87 * all subsidiary data live in the caller's CurrentMemoryContext, and there88 * is no way to free memory short of clearing that entire context. A oneshot89 * plan is always treated as unsaved.90 *91 * Note: the string referenced by commandTag is not subsidiary storage;92 * it is assumed to be a compile-time-constant string. As with portals,93 * commandTag shall be NULL if and only if the original query string (before94 * rewriting) was an empty string.95 */96typedef struct CachedPlanSource97{98 int magic; /* should equal CACHEDPLANSOURCE_MAGIC */99 struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */100 const char *query_string; /* source text of query */101 CommandTag commandTag; /* 'nuff said */102 Oid *param_types; /* array of parameter type OIDs, or NULL */103 int num_params; /* length of param_types array */104 ParserSetupHook parserSetup; /* alternative parameter spec method */105 void *parserSetupArg;106 int cursor_options; /* cursor options used for planning */107 bool fixed_result; /* disallow change in result tupdesc? */108 TupleDesc resultDesc; /* result type; NULL = doesn't return tuples */109 MemoryContext context; /* memory context holding all above */110 /* These fields describe the current analyzed-and-rewritten query tree: */111 List *query_list; /* list of Query nodes, or NIL if not valid */112 List *relationOids; /* OIDs of relations the queries depend on */113 List *invalItems; /* other dependencies, as PlanInvalItems */114 struct OverrideSearchPath *search_path; /* search_path used for parsing115 * and planning */116 MemoryContext query_context; /* context holding the above, or NULL */117 Oid rewriteRoleId; /* Role ID we did rewriting for */118 bool rewriteRowSecurity; /* row_security used during rewrite */119 bool dependsOnRLS; /* is rewritten query specific to the above? */120 /* If we have a generic plan, this is a reference-counted link to it: */121 struct CachedPlan *gplan; /* generic plan, or NULL if not valid */122 /* Some state flags: */123 bool is_oneshot; /* is it a "oneshot" plan? */124 bool is_complete; /* has CompleteCachedPlan been done? */125 bool is_saved; /* has CachedPlanSource been "saved"? */126 bool is_valid; /* is the query_list currently valid? */127 int generation; /* increments each time we create a plan */128 /* If CachedPlanSource has been saved, it is a member of a global list */129 dlist_node node; /* list link, if is_saved */130 /* State kept to help decide whether to use custom or generic plans: */131 double generic_cost; /* cost of generic plan, or -1 if not known */132 double total_custom_cost; /* total cost of custom plans so far */133 int64 num_custom_plans; /* # of custom plans included in total */134 int64 num_generic_plans; /* # of generic plans */135} CachedPlanSource;136 137/*138 * CachedPlan represents an execution plan derived from a CachedPlanSource.139 * The reference count includes both the link from the parent CachedPlanSource140 * (if any), and any active plan executions, so the plan can be discarded141 * exactly when refcount goes to zero. Both the struct itself and the142 * subsidiary data live in the context denoted by the context field.143 * This makes it easy to free a no-longer-needed cached plan. (However,144 * if is_oneshot is true, the context does not belong solely to the CachedPlan145 * so no freeing is possible.)146 */147typedef struct CachedPlan148{149 int magic; /* should equal CACHEDPLAN_MAGIC */150 List *stmt_list; /* list of PlannedStmts */151 bool is_oneshot; /* is it a "oneshot" plan? */152 bool is_saved; /* is CachedPlan in a long-lived context? */153 bool is_valid; /* is the stmt_list currently valid? */154 Oid planRoleId; /* Role ID the plan was created for */155 bool dependsOnRole; /* is plan specific to that role? */156 TransactionId saved_xmin; /* if valid, replan when TransactionXmin157 * changes from this value */158 int generation; /* parent's generation number for this plan */159 int refcount; /* count of live references to this struct */160 MemoryContext context; /* context containing this CachedPlan */161} CachedPlan;162 163/*164 * CachedExpression is a low-overhead mechanism for caching the planned form165 * of standalone scalar expressions. While such expressions are not usually166 * subject to cache invalidation events, that can happen, for example because167 * of replacement of a SQL function that was inlined into the expression.168 * The plancache takes care of storing the expression tree and marking it169 * invalid if a cache invalidation occurs, but the caller must notice the170 * !is_valid status and discard the obsolete expression without reusing it.171 * We do not store the original parse tree, only the planned expression;172 * this is an optimization based on the assumption that we usually will not173 * need to replan for the life of the session.174 */175typedef struct CachedExpression176{177 int magic; /* should equal CACHEDEXPR_MAGIC */178 Node *expr; /* planned form of expression */179 bool is_valid; /* is the expression still valid? */180 /* remaining fields should be treated as private to plancache.c: */181 List *relationOids; /* OIDs of relations the expr depends on */182 List *invalItems; /* other dependencies, as PlanInvalItems */183 MemoryContext context; /* context containing this CachedExpression */184 dlist_node node; /* link in global list of CachedExpressions */185} CachedExpression;186 187 188extern void InitPlanCache(void);189extern void ResetPlanCache(void);190 191extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree,192 const char *query_string,193 CommandTag commandTag);194extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree,195 const char *query_string,196 CommandTag commandTag);197extern void CompleteCachedPlan(CachedPlanSource *plansource,198 List *querytree_list,199 MemoryContext querytree_context,200 Oid *param_types,201 int num_params,202 ParserSetupHook parserSetup,203 void *parserSetupArg,204 int cursor_options,205 bool fixed_result);206 207extern void SaveCachedPlan(CachedPlanSource *plansource);208extern void DropCachedPlan(CachedPlanSource *plansource);209 210extern void CachedPlanSetParentContext(CachedPlanSource *plansource,211 MemoryContext newcontext);212 213extern CachedPlanSource *CopyCachedPlan(CachedPlanSource *plansource);214 215extern bool CachedPlanIsValid(CachedPlanSource *plansource);216 217extern List *CachedPlanGetTargetList(CachedPlanSource *plansource,218 QueryEnvironment *queryEnv);219 220extern CachedPlan *GetCachedPlan(CachedPlanSource *plansource,221 ParamListInfo boundParams,222 ResourceOwner owner,223 QueryEnvironment *queryEnv);224extern void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner);225 226extern bool CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource,227 CachedPlan *plan,228 ResourceOwner owner);229extern bool CachedPlanIsSimplyValid(CachedPlanSource *plansource,230 CachedPlan *plan,231 ResourceOwner owner);232 233extern CachedExpression *GetCachedExpression(Node *expr);234extern void FreeCachedExpression(CachedExpression *cexpr);235 236#endif /* PLANCACHE_H */237 