]> granicus.if.org Git - postgresql/blob - src/include/utils/plancache.h
Fix initialization of fake LSN for unlogged relations
[postgresql] / src / include / utils / plancache.h
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 */