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 */ |
24 | struct RawStmt; |
25 | |
26 | /* possible values for plan_cache_mode */ |
27 | typedef 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 */ |
35 | extern 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 | */ |
93 | typedef 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 | */ |
143 | typedef 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 | */ |
171 | typedef 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 | |
184 | extern void InitPlanCache(void); |
185 | extern void ResetPlanCache(void); |
186 | |
187 | extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree, |
188 | const char *query_string, |
189 | const char *commandTag); |
190 | extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree, |
191 | const char *query_string, |
192 | const char *commandTag); |
193 | extern 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 | |
203 | extern void SaveCachedPlan(CachedPlanSource *plansource); |
204 | extern void DropCachedPlan(CachedPlanSource *plansource); |
205 | |
206 | extern void CachedPlanSetParentContext(CachedPlanSource *plansource, |
207 | MemoryContext newcontext); |
208 | |
209 | extern CachedPlanSource *CopyCachedPlan(CachedPlanSource *plansource); |
210 | |
211 | extern bool CachedPlanIsValid(CachedPlanSource *plansource); |
212 | |
213 | extern List *CachedPlanGetTargetList(CachedPlanSource *plansource, |
214 | QueryEnvironment *queryEnv); |
215 | |
216 | extern CachedPlan *GetCachedPlan(CachedPlanSource *plansource, |
217 | ParamListInfo boundParams, |
218 | bool useResOwner, |
219 | QueryEnvironment *queryEnv); |
220 | extern void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner); |
221 | |
222 | extern CachedExpression *GetCachedExpression(Node *expr); |
223 | extern void FreeCachedExpression(CachedExpression *cexpr); |
224 | |
225 | #endif /* PLANCACHE_H */ |
226 | |