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