| /*------------------------------------------------------------------------- |
| * |
| * plancache.h |
| * Plan cache definitions. |
| * |
| * See plancache.c for comments. |
| * |
| * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group |
| * Portions Copyright (c) 1994, Regents of the University of California |
| * |
| * src/include/utils/plancache.h |
| * |
| *------------------------------------------------------------------------- |
| */ |
| #ifndef PLANCACHE_H |
| #define PLANCACHE_H |
| |
| #include "access/tupdesc.h" |
| #include "lib/ilist.h" |
| #include "nodes/params.h" |
| #include "nodes/primnodes.h" |
| #include "tcop/cmdtag.h" |
| #include "utils/queryenvironment.h" |
| #include "utils/resowner.h" |
| |
| /* Forward declaration, to avoid including recursively */ |
| typedef struct ResourceOwnerData *ResourceOwner; |
| |
| /* Forward declaration, to avoid including parsenodes.h here */ |
| struct RawStmt; |
| |
| /* possible values for plan_cache_mode */ |
| typedef enum |
| { |
| PLAN_CACHE_MODE_AUTO, |
| PLAN_CACHE_MODE_FORCE_GENERIC_PLAN, |
| PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN |
| } PlanCacheMode; |
| |
| /* GUC parameter */ |
| extern PGDLLIMPORT int plan_cache_mode; |
| |
| #define CACHEDPLANSOURCE_MAGIC 195726186 |
| #define CACHEDPLAN_MAGIC 953717834 |
| #define CACHEDEXPR_MAGIC 838275847 |
| |
| /* |
| * CachedPlanSource (which might better have been called CachedQuery) |
| * represents a SQL query that we expect to use multiple times. It stores |
| * the query source text, the raw parse tree, and the analyzed-and-rewritten |
| * query tree, as well as adjunct data. Cache invalidation can happen as a |
| * result of DDL affecting objects used by the query. In that case we discard |
| * the analyzed-and-rewritten query tree, and rebuild it when next needed. |
| * |
| * An actual execution plan, represented by CachedPlan, is derived from the |
| * CachedPlanSource when we need to execute the query. The plan could be |
| * either generic (usable with any set of plan parameters) or custom (for a |
| * specific set of parameters). plancache.c contains the logic that decides |
| * which way to do it for any particular execution. If we are using a generic |
| * cached plan then it is meant to be re-used across multiple executions, so |
| * callers must always treat CachedPlans as read-only. |
| * |
| * Once successfully built and "saved", CachedPlanSources typically live |
| * for the life of the backend, although they can be dropped explicitly. |
| * CachedPlans are reference-counted and go away automatically when the last |
| * reference is dropped. A CachedPlan can outlive the CachedPlanSource it |
| * was created from. |
| * |
| * An "unsaved" CachedPlanSource can be used for generating plans, but it |
| * lives in transient storage and will not be updated in response to sinval |
| * events. |
| * |
| * CachedPlans made from saved CachedPlanSources are likewise in permanent |
| * storage, so to avoid memory leaks, the reference-counted references to them |
| * must be held in permanent data structures or ResourceOwners. CachedPlans |
| * made from unsaved CachedPlanSources are in children of the caller's |
| * memory context, so references to them should not be longer-lived than |
| * that context. (Reference counting is somewhat pro forma in that case, |
| * though it may be useful if the CachedPlan can be discarded early.) |
| * |
| * A CachedPlanSource has two associated memory contexts: one that holds the |
| * struct itself, the query source text and the raw parse tree, and another |
| * context that holds the rewritten query tree and associated data. This |
| * allows the query tree to be discarded easily when it is invalidated. |
| * |
| * Some callers wish to use the CachedPlan API even with one-shot queries |
| * that have no reason to be saved at all. We therefore support a "oneshot" |
| * variant that does no data copying or invalidation checking. In this case |
| * there are no separate memory contexts: the CachedPlanSource struct and |
| * all subsidiary data live in the caller's CurrentMemoryContext, and there |
| * is no way to free memory short of clearing that entire context. A oneshot |
| * plan is always treated as unsaved. |
| * |
| * Note: the string referenced by commandTag is not subsidiary storage; |
| * it is assumed to be a compile-time-constant string. As with portals, |
| * commandTag shall be NULL if and only if the original query string (before |
| * rewriting) was an empty string. |
| */ |
| typedef struct CachedPlanSource |
| { |
| int magic; /* should equal CACHEDPLANSOURCE_MAGIC */ |
| struct RawStmt *raw_parse_tree; /* output of raw_parser(), or NULL */ |
| const char *query_string; /* source text of query */ |
| CommandTag commandTag; /* command tag (a constant!), or NULL */ |
| NodeTag sourceTag; /* GPDB: Original statement NodeTag */ |
| Oid *param_types; /* array of parameter type OIDs, or NULL */ |
| int num_params; /* length of param_types array */ |
| ParserSetupHook parserSetup; /* alternative parameter spec method */ |
| void *parserSetupArg; |
| int cursor_options; /* cursor options used for planning */ |
| bool fixed_result; /* disallow change in result tupdesc? */ |
| TupleDesc resultDesc; /* result type; NULL = doesn't return tuples */ |
| MemoryContext context; /* memory context holding all above */ |
| /* These fields describe the current analyzed-and-rewritten query tree: */ |
| List *query_list; /* list of Query nodes, or NIL if not valid */ |
| List *relationOids; /* OIDs of relations the queries depend on */ |
| List *invalItems; /* other dependencies, as PlanInvalItems */ |
| struct OverrideSearchPath *search_path; /* search_path used for parsing |
| * and planning */ |
| MemoryContext query_context; /* context holding the above, or NULL */ |
| Oid rewriteRoleId; /* Role ID we did rewriting for */ |
| bool rewriteRowSecurity; /* row_security used during rewrite */ |
| bool dependsOnRLS; /* is rewritten query specific to the above? */ |
| /* If we have a generic plan, this is a reference-counted link to it: */ |
| struct CachedPlan *gplan; /* generic plan, or NULL if not valid */ |
| /* Some state flags: */ |
| bool is_oneshot; /* is it a "oneshot" plan? */ |
| bool is_complete; /* has CompleteCachedPlan been done? */ |
| bool is_saved; /* has CachedPlanSource been "saved"? */ |
| bool is_valid; /* is the query_list currently valid? */ |
| int generation; /* increments each time we create a plan */ |
| /* If CachedPlanSource has been saved, it is a member of a global list */ |
| dlist_node node; /* list link, if is_saved */ |
| /* State kept to help decide whether to use custom or generic plans: */ |
| double generic_cost; /* cost of generic plan, or -1 if not known */ |
| double total_custom_cost; /* total cost of custom plans so far */ |
| int64 num_custom_plans; /* # of custom plans included in total */ |
| int64 num_generic_plans; /* # of generic plans */ |
| } CachedPlanSource; |
| |
| /* |
| * CachedPlan represents an execution plan derived from a CachedPlanSource. |
| * The reference count includes both the link from the parent CachedPlanSource |
| * (if any), and any active plan executions, so the plan can be discarded |
| * exactly when refcount goes to zero. Both the struct itself and the |
| * subsidiary data live in the context denoted by the context field. |
| * This makes it easy to free a no-longer-needed cached plan. (However, |
| * if is_oneshot is true, the context does not belong solely to the CachedPlan |
| * so no freeing is possible.) |
| */ |
| typedef struct CachedPlan |
| { |
| int magic; /* should equal CACHEDPLAN_MAGIC */ |
| List *stmt_list; /* list of PlannedStmts */ |
| bool is_oneshot; /* is it a "oneshot" plan? */ |
| bool is_saved; /* is CachedPlan in a long-lived context? */ |
| bool is_valid; /* is the stmt_list currently valid? */ |
| Oid planRoleId; /* Role ID the plan was created for */ |
| bool dependsOnRole; /* is plan specific to that role? */ |
| TransactionId saved_xmin; /* if valid, replan when TransactionXmin |
| * changes from this value */ |
| int generation; /* parent's generation number for this plan */ |
| int refcount; /* count of live references to this struct */ |
| MemoryContext context; /* context containing this CachedPlan */ |
| } CachedPlan; |
| |
| /* |
| * CachedExpression is a low-overhead mechanism for caching the planned form |
| * of standalone scalar expressions. While such expressions are not usually |
| * subject to cache invalidation events, that can happen, for example because |
| * of replacement of a SQL function that was inlined into the expression. |
| * The plancache takes care of storing the expression tree and marking it |
| * invalid if a cache invalidation occurs, but the caller must notice the |
| * !is_valid status and discard the obsolete expression without reusing it. |
| * We do not store the original parse tree, only the planned expression; |
| * this is an optimization based on the assumption that we usually will not |
| * need to replan for the life of the session. |
| */ |
| typedef struct CachedExpression |
| { |
| int magic; /* should equal CACHEDEXPR_MAGIC */ |
| Node *expr; /* planned form of expression */ |
| bool is_valid; /* is the expression still valid? */ |
| /* remaining fields should be treated as private to plancache.c: */ |
| List *relationOids; /* OIDs of relations the expr depends on */ |
| List *invalItems; /* other dependencies, as PlanInvalItems */ |
| MemoryContext context; /* context containing this CachedExpression */ |
| dlist_node node; /* link in global list of CachedExpressions */ |
| } CachedExpression; |
| |
| |
| extern void InitPlanCache(void); |
| extern void ResetPlanCache(void); |
| |
| extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree, |
| const char *query_string, |
| CommandTag commandTag); |
| extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree, |
| const char *query_string, |
| CommandTag commandTag); |
| extern void CompleteCachedPlan(CachedPlanSource *plansource, |
| List *querytree_list, |
| MemoryContext querytree_context, |
| NodeTag sourceTag, |
| Oid *param_types, |
| int num_params, |
| ParserSetupHook parserSetup, |
| void *parserSetupArg, |
| int cursor_options, |
| bool fixed_result); |
| |
| extern void SaveCachedPlan(CachedPlanSource *plansource); |
| extern void DropCachedPlan(CachedPlanSource *plansource); |
| |
| extern void CachedPlanSetParentContext(CachedPlanSource *plansource, |
| MemoryContext newcontext); |
| |
| extern CachedPlanSource *CopyCachedPlan(CachedPlanSource *plansource); |
| |
| extern bool CachedPlanIsValid(CachedPlanSource *plansource); |
| |
| extern List *CachedPlanGetTargetList(CachedPlanSource *plansource, |
| QueryEnvironment *queryEnv); |
| |
| extern CachedPlan *GetCachedPlan(CachedPlanSource *plansource, |
| ParamListInfo boundParams, |
| ResourceOwner owner, |
| QueryEnvironment *queryEnv, |
| IntoClause *intoClause); |
| extern void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner); |
| |
| |
| extern bool CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource, |
| CachedPlan *plan, |
| ResourceOwner owner); |
| extern bool CachedPlanIsSimplyValid(CachedPlanSource *plansource, |
| CachedPlan *plan, |
| ResourceOwner owner); |
| |
| extern CachedExpression *GetCachedExpression(Node *expr); |
| extern void FreeCachedExpression(CachedExpression *cexpr); |
| |
| #endif /* PLANCACHE_H */ |