1 /*-------------------------------------------------------------------------
2  *
3  * plancache.h
4  *	  Plan cache definitions.
5  *
6  * See plancache.c for comments.
7  *
8  * Portions Copyright (c) 1996-2021, 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 "tcop/cmdtag.h"
22 #include "utils/queryenvironment.h"
23 #include "utils/resowner.h"
24 
25 
26 /* Forward declaration, to avoid including parsenodes.h here */
27 struct RawStmt;
28 
29 /* possible values for plan_cache_mode */
30 typedef enum
31 {
32 	PLAN_CACHE_MODE_AUTO,
33 	PLAN_CACHE_MODE_FORCE_GENERIC_PLAN,
34 	PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN
35 }			PlanCacheMode;
36 
37 /* GUC parameter */
38 extern int	plan_cache_mode;
39 
40 #define CACHEDPLANSOURCE_MAGIC		195726186
41 #define CACHEDPLAN_MAGIC			953717834
42 #define CACHEDEXPR_MAGIC			838275847
43 
44 /*
45  * CachedPlanSource (which might better have been called CachedQuery)
46  * represents a SQL query that we expect to use multiple times.  It stores
47  * the query source text, the raw parse tree, and the analyzed-and-rewritten
48  * query tree, as well as adjunct data.  Cache invalidation can happen as a
49  * result of DDL affecting objects used by the query.  In that case we discard
50  * the analyzed-and-rewritten query tree, and rebuild it when next needed.
51  *
52  * An actual execution plan, represented by CachedPlan, is derived from the
53  * CachedPlanSource when we need to execute the query.  The plan could be
54  * either generic (usable with any set of plan parameters) or custom (for a
55  * specific set of parameters).  plancache.c contains the logic that decides
56  * which way to do it for any particular execution.  If we are using a generic
57  * cached plan then it is meant to be re-used across multiple executions, so
58  * callers must always treat CachedPlans as read-only.
59  *
60  * Once successfully built and "saved", CachedPlanSources typically live
61  * for the life of the backend, although they can be dropped explicitly.
62  * CachedPlans are reference-counted and go away automatically when the last
63  * reference is dropped.  A CachedPlan can outlive the CachedPlanSource it
64  * was created from.
65  *
66  * An "unsaved" CachedPlanSource can be used for generating plans, but it
67  * lives in transient storage and will not be updated in response to sinval
68  * events.
69  *
70  * CachedPlans made from saved CachedPlanSources are likewise in permanent
71  * storage, so to avoid memory leaks, the reference-counted references to them
72  * must be held in permanent data structures or ResourceOwners.  CachedPlans
73  * made from unsaved CachedPlanSources are in children of the caller's
74  * memory context, so references to them should not be longer-lived than
75  * 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 the
79  * struct itself, the query source text and the raw parse tree, and another
80  * context that holds the rewritten query tree and associated data.  This
81  * 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 queries
84  * 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 case
86  * there are no separate memory contexts: the CachedPlanSource struct and
87  * all subsidiary data live in the caller's CurrentMemoryContext, and there
88  * is no way to free memory short of clearing that entire context.  A oneshot
89  * 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 (before
94  * rewriting) was an empty string.
95  */
96 typedef struct CachedPlanSource
97 {
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 parsing
115 											 * 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 CachedPlanSource
140  * (if any), and any active plan executions, so the plan can be discarded
141  * exactly when refcount goes to zero.  Both the struct itself and the
142  * 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 CachedPlan
145  * so no freeing is possible.)
146  */
147 typedef struct CachedPlan
148 {
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 TransactionXmin
157 								 * 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 form
165  * of standalone scalar expressions.  While such expressions are not usually
166  * subject to cache invalidation events, that can happen, for example because
167  * of replacement of a SQL function that was inlined into the expression.
168  * The plancache takes care of storing the expression tree and marking it
169  * invalid if a cache invalidation occurs, but the caller must notice the
170  * !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 not
173  * need to replan for the life of the session.
174  */
175 typedef struct CachedExpression
176 {
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 
188 extern void InitPlanCache(void);
189 extern void ResetPlanCache(void);
190 
191 extern CachedPlanSource *CreateCachedPlan(struct RawStmt *raw_parse_tree,
192 										  const char *query_string,
193 										  CommandTag commandTag);
194 extern CachedPlanSource *CreateOneShotCachedPlan(struct RawStmt *raw_parse_tree,
195 												 const char *query_string,
196 												 CommandTag commandTag);
197 extern 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 
207 extern void SaveCachedPlan(CachedPlanSource *plansource);
208 extern void DropCachedPlan(CachedPlanSource *plansource);
209 
210 extern void CachedPlanSetParentContext(CachedPlanSource *plansource,
211 									   MemoryContext newcontext);
212 
213 extern CachedPlanSource *CopyCachedPlan(CachedPlanSource *plansource);
214 
215 extern bool CachedPlanIsValid(CachedPlanSource *plansource);
216 
217 extern List *CachedPlanGetTargetList(CachedPlanSource *plansource,
218 									 QueryEnvironment *queryEnv);
219 
220 extern CachedPlan *GetCachedPlan(CachedPlanSource *plansource,
221 								 ParamListInfo boundParams,
222 								 ResourceOwner owner,
223 								 QueryEnvironment *queryEnv);
224 extern void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner);
225 
226 extern bool CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource,
227 												CachedPlan *plan,
228 												ResourceOwner owner);
229 extern bool CachedPlanIsSimplyValid(CachedPlanSource *plansource,
230 									CachedPlan *plan,
231 									ResourceOwner owner);
232 
233 extern CachedExpression *GetCachedExpression(Node *expr);
234 extern void FreeCachedExpression(CachedExpression *cexpr);
235 
236 #endif							/* PLANCACHE_H */
237