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