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