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