Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * plancache.c
4 : * Plan cache management.
5 : *
6 : * The plan cache manager has two principal responsibilities: deciding when
7 : * to use a generic plan versus a custom (parameter-value-specific) plan,
8 : * and tracking whether cached plans need to be invalidated because of schema
9 : * changes in the objects they depend on.
10 : *
11 : * The logic for choosing generic or custom plans is in choose_custom_plan,
12 : * which see for comments.
13 : *
14 : * Cache invalidation is driven off sinval events. Any CachedPlanSource
15 : * that matches the event is marked invalid, as is its generic CachedPlan
16 : * if it has one. When (and if) the next demand for a cached plan occurs,
17 : * parse analysis and rewrite is repeated to build a new valid query tree,
18 : * and then planning is performed as normal. We also force re-analysis and
19 : * re-planning if the active search_path is different from the previous time
20 : * or, if RLS is involved, if the user changes or the RLS environment changes.
21 : *
22 : * Note that if the sinval was a result of user DDL actions, parse analysis
23 : * could throw an error, for example if a column referenced by the query is
24 : * no longer present. Another possibility is for the query's output tupdesc
25 : * to change (for instance "SELECT *" might expand differently than before).
26 : * The creator of a cached plan can specify whether it is allowable for the
27 : * query to change output tupdesc on replan --- if so, it's up to the
28 : * caller to notice changes and cope with them.
29 : *
30 : * Currently, we track exactly the dependencies of plans on relations,
31 : * user-defined functions, and domains. On relcache invalidation events or
32 : * pg_proc or pg_type syscache invalidation events, we invalidate just those
33 : * plans that depend on the particular object being modified. (Note: this
34 : * scheme assumes that any table modification that requires replanning will
35 : * generate a relcache inval event.) We also watch for inval events on
36 : * certain other system catalogs, such as pg_namespace; but for them, our
37 : * response is just to invalidate all plans. We expect updates on those
38 : * catalogs to be infrequent enough that more-detailed tracking is not worth
39 : * the effort.
40 : *
41 : * In addition to full-fledged query plans, we provide a facility for
42 : * detecting invalidations of simple scalar expressions. This is fairly
43 : * bare-bones; it's the caller's responsibility to build a new expression
44 : * if the old one gets invalidated.
45 : *
46 : *
47 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
48 : * Portions Copyright (c) 1994, Regents of the University of California
49 : *
50 : * IDENTIFICATION
51 : * src/backend/utils/cache/plancache.c
52 : *
53 : *-------------------------------------------------------------------------
54 : */
55 : #include "postgres.h"
56 :
57 : #include <limits.h>
58 :
59 : #include "access/transam.h"
60 : #include "catalog/namespace.h"
61 : #include "executor/executor.h"
62 : #include "miscadmin.h"
63 : #include "nodes/nodeFuncs.h"
64 : #include "optimizer/optimizer.h"
65 : #include "parser/analyze.h"
66 : #include "parser/parsetree.h"
67 : #include "storage/lmgr.h"
68 : #include "tcop/pquery.h"
69 : #include "tcop/utility.h"
70 : #include "utils/inval.h"
71 : #include "utils/memutils.h"
72 : #include "utils/resowner.h"
73 : #include "utils/rls.h"
74 : #include "utils/snapmgr.h"
75 : #include "utils/syscache.h"
76 :
77 :
78 : /*
79 : * We must skip "overhead" operations that involve database access when the
80 : * cached plan's subject statement is a transaction control command or one
81 : * that requires a snapshot not to be set yet (such as SET or LOCK). More
82 : * generally, statements that do not require parse analysis/rewrite/plan
83 : * activity never need to be revalidated, so we can treat them all like that.
84 : * For the convenience of postgres.c, treat empty statements that way too.
85 : */
86 : #define StmtPlanRequiresRevalidation(plansource) \
87 : ((plansource)->raw_parse_tree != NULL && \
88 : stmt_requires_parse_analysis((plansource)->raw_parse_tree))
89 :
90 : /*
91 : * This is the head of the backend's list of "saved" CachedPlanSources (i.e.,
92 : * those that are in long-lived storage and are examined for sinval events).
93 : * We use a dlist instead of separate List cells so that we can guarantee
94 : * to save a CachedPlanSource without error.
95 : */
96 : static dlist_head saved_plan_list = DLIST_STATIC_INIT(saved_plan_list);
97 :
98 : /*
99 : * This is the head of the backend's list of CachedExpressions.
100 : */
101 : static dlist_head cached_expression_list = DLIST_STATIC_INIT(cached_expression_list);
102 :
103 : static void ReleaseGenericPlan(CachedPlanSource *plansource);
104 : static List *RevalidateCachedQuery(CachedPlanSource *plansource,
105 : QueryEnvironment *queryEnv);
106 : static bool CheckCachedPlan(CachedPlanSource *plansource);
107 : static CachedPlan *BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
108 : ParamListInfo boundParams, QueryEnvironment *queryEnv);
109 : static bool choose_custom_plan(CachedPlanSource *plansource,
110 : ParamListInfo boundParams);
111 : static double cached_plan_cost(CachedPlan *plan, bool include_planner);
112 : static Query *QueryListGetPrimaryStmt(List *stmts);
113 : static void AcquireExecutorLocks(List *stmt_list, bool acquire);
114 : static void AcquirePlannerLocks(List *stmt_list, bool acquire);
115 : static void ScanQueryForLocks(Query *parsetree, bool acquire);
116 : static bool ScanQueryWalker(Node *node, bool *acquire);
117 : static TupleDesc PlanCacheComputeResultDesc(List *stmt_list);
118 : static void PlanCacheRelCallback(Datum arg, Oid relid);
119 : static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue);
120 : static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue);
121 :
122 : /* ResourceOwner callbacks to track plancache references */
123 : static void ResOwnerReleaseCachedPlan(Datum res);
124 :
125 : static const ResourceOwnerDesc planref_resowner_desc =
126 : {
127 : .name = "plancache reference",
128 : .release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
129 : .release_priority = RELEASE_PRIO_PLANCACHE_REFS,
130 : .ReleaseResource = ResOwnerReleaseCachedPlan,
131 : .DebugPrint = NULL /* the default message is fine */
132 : };
133 :
134 : /* Convenience wrappers over ResourceOwnerRemember/Forget */
135 : static inline void
136 173232 : ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
137 : {
138 173232 : ResourceOwnerRemember(owner, PointerGetDatum(plan), &planref_resowner_desc);
139 173232 : }
140 : static inline void
141 96134 : ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
142 : {
143 96134 : ResourceOwnerForget(owner, PointerGetDatum(plan), &planref_resowner_desc);
144 96134 : }
145 :
146 :
147 : /* GUC parameter */
148 : int plan_cache_mode = PLAN_CACHE_MODE_AUTO;
149 :
150 : /*
151 : * InitPlanCache: initialize module during InitPostgres.
152 : *
153 : * All we need to do is hook into inval.c's callback lists.
154 : */
155 : void
156 24250 : InitPlanCache(void)
157 : {
158 24250 : CacheRegisterRelcacheCallback(PlanCacheRelCallback, (Datum) 0);
159 24250 : CacheRegisterSyscacheCallback(PROCOID, PlanCacheObjectCallback, (Datum) 0);
160 24250 : CacheRegisterSyscacheCallback(TYPEOID, PlanCacheObjectCallback, (Datum) 0);
161 24250 : CacheRegisterSyscacheCallback(NAMESPACEOID, PlanCacheSysCallback, (Datum) 0);
162 24250 : CacheRegisterSyscacheCallback(OPEROID, PlanCacheSysCallback, (Datum) 0);
163 24250 : CacheRegisterSyscacheCallback(AMOPOPID, PlanCacheSysCallback, (Datum) 0);
164 24250 : CacheRegisterSyscacheCallback(FOREIGNSERVEROID, PlanCacheSysCallback, (Datum) 0);
165 24250 : CacheRegisterSyscacheCallback(FOREIGNDATAWRAPPEROID, PlanCacheSysCallback, (Datum) 0);
166 24250 : }
167 :
168 : /*
169 : * CreateCachedPlan: initially create a plan cache entry.
170 : *
171 : * Creation of a cached plan is divided into two steps, CreateCachedPlan and
172 : * CompleteCachedPlan. CreateCachedPlan should be called after running the
173 : * query through raw_parser, but before doing parse analysis and rewrite;
174 : * CompleteCachedPlan is called after that. The reason for this arrangement
175 : * is that it can save one round of copying of the raw parse tree, since
176 : * the parser will normally scribble on the raw parse tree. Callers would
177 : * otherwise need to make an extra copy of the parse tree to ensure they
178 : * still had a clean copy to present at plan cache creation time.
179 : *
180 : * All arguments presented to CreateCachedPlan are copied into a memory
181 : * context created as a child of the call-time CurrentMemoryContext, which
182 : * should be a reasonably short-lived working context that will go away in
183 : * event of an error. This ensures that the cached plan data structure will
184 : * likewise disappear if an error occurs before we have fully constructed it.
185 : * Once constructed, the cached plan can be made longer-lived, if needed,
186 : * by calling SaveCachedPlan.
187 : *
188 : * raw_parse_tree: output of raw_parser(), or NULL if empty query
189 : * query_string: original query text
190 : * commandTag: command tag for query, or UNKNOWN if empty query
191 : */
192 : CachedPlanSource *
193 49590 : CreateCachedPlan(RawStmt *raw_parse_tree,
194 : const char *query_string,
195 : CommandTag commandTag)
196 : {
197 : CachedPlanSource *plansource;
198 : MemoryContext source_context;
199 : MemoryContext oldcxt;
200 :
201 : Assert(query_string != NULL); /* required as of 8.4 */
202 :
203 : /*
204 : * Make a dedicated memory context for the CachedPlanSource and its
205 : * permanent subsidiary data. It's probably not going to be large, but
206 : * just in case, allow it to grow large. Initially it's a child of the
207 : * caller's context (which we assume to be transient), so that it will be
208 : * cleaned up on error.
209 : */
210 49590 : source_context = AllocSetContextCreate(CurrentMemoryContext,
211 : "CachedPlanSource",
212 : ALLOCSET_START_SMALL_SIZES);
213 :
214 : /*
215 : * Create and fill the CachedPlanSource struct within the new context.
216 : * Most fields are just left empty for the moment.
217 : */
218 49590 : oldcxt = MemoryContextSwitchTo(source_context);
219 :
220 49590 : plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
221 49590 : plansource->magic = CACHEDPLANSOURCE_MAGIC;
222 49590 : plansource->raw_parse_tree = copyObject(raw_parse_tree);
223 49590 : plansource->query_string = pstrdup(query_string);
224 49590 : MemoryContextSetIdentifier(source_context, plansource->query_string);
225 49590 : plansource->commandTag = commandTag;
226 49590 : plansource->param_types = NULL;
227 49590 : plansource->num_params = 0;
228 49590 : plansource->parserSetup = NULL;
229 49590 : plansource->parserSetupArg = NULL;
230 49590 : plansource->cursor_options = 0;
231 49590 : plansource->fixed_result = false;
232 49590 : plansource->resultDesc = NULL;
233 49590 : plansource->context = source_context;
234 49590 : plansource->query_list = NIL;
235 49590 : plansource->relationOids = NIL;
236 49590 : plansource->invalItems = NIL;
237 49590 : plansource->search_path = NULL;
238 49590 : plansource->query_context = NULL;
239 49590 : plansource->rewriteRoleId = InvalidOid;
240 49590 : plansource->rewriteRowSecurity = false;
241 49590 : plansource->dependsOnRLS = false;
242 49590 : plansource->gplan = NULL;
243 49590 : plansource->is_oneshot = false;
244 49590 : plansource->is_complete = false;
245 49590 : plansource->is_saved = false;
246 49590 : plansource->is_valid = false;
247 49590 : plansource->generation = 0;
248 49590 : plansource->generic_cost = -1;
249 49590 : plansource->total_custom_cost = 0;
250 49590 : plansource->num_generic_plans = 0;
251 49590 : plansource->num_custom_plans = 0;
252 :
253 49590 : MemoryContextSwitchTo(oldcxt);
254 :
255 49590 : return plansource;
256 : }
257 :
258 : /*
259 : * CreateOneShotCachedPlan: initially create a one-shot plan cache entry.
260 : *
261 : * This variant of CreateCachedPlan creates a plan cache entry that is meant
262 : * to be used only once. No data copying occurs: all data structures remain
263 : * in the caller's memory context (which typically should get cleared after
264 : * completing execution). The CachedPlanSource struct itself is also created
265 : * in that context.
266 : *
267 : * A one-shot plan cannot be saved or copied, since we make no effort to
268 : * preserve the raw parse tree unmodified. There is also no support for
269 : * invalidation, so plan use must be completed in the current transaction,
270 : * and DDL that might invalidate the querytree_list must be avoided as well.
271 : *
272 : * raw_parse_tree: output of raw_parser(), or NULL if empty query
273 : * query_string: original query text
274 : * commandTag: command tag for query, or NULL if empty query
275 : */
276 : CachedPlanSource *
277 12322 : CreateOneShotCachedPlan(RawStmt *raw_parse_tree,
278 : const char *query_string,
279 : CommandTag commandTag)
280 : {
281 : CachedPlanSource *plansource;
282 :
283 : Assert(query_string != NULL); /* required as of 8.4 */
284 :
285 : /*
286 : * Create and fill the CachedPlanSource struct within the caller's memory
287 : * context. Most fields are just left empty for the moment.
288 : */
289 12322 : plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
290 12322 : plansource->magic = CACHEDPLANSOURCE_MAGIC;
291 12322 : plansource->raw_parse_tree = raw_parse_tree;
292 12322 : plansource->query_string = query_string;
293 12322 : plansource->commandTag = commandTag;
294 12322 : plansource->param_types = NULL;
295 12322 : plansource->num_params = 0;
296 12322 : plansource->parserSetup = NULL;
297 12322 : plansource->parserSetupArg = NULL;
298 12322 : plansource->cursor_options = 0;
299 12322 : plansource->fixed_result = false;
300 12322 : plansource->resultDesc = NULL;
301 12322 : plansource->context = CurrentMemoryContext;
302 12322 : plansource->query_list = NIL;
303 12322 : plansource->relationOids = NIL;
304 12322 : plansource->invalItems = NIL;
305 12322 : plansource->search_path = NULL;
306 12322 : plansource->query_context = NULL;
307 12322 : plansource->rewriteRoleId = InvalidOid;
308 12322 : plansource->rewriteRowSecurity = false;
309 12322 : plansource->dependsOnRLS = false;
310 12322 : plansource->gplan = NULL;
311 12322 : plansource->is_oneshot = true;
312 12322 : plansource->is_complete = false;
313 12322 : plansource->is_saved = false;
314 12322 : plansource->is_valid = false;
315 12322 : plansource->generation = 0;
316 12322 : plansource->generic_cost = -1;
317 12322 : plansource->total_custom_cost = 0;
318 12322 : plansource->num_generic_plans = 0;
319 12322 : plansource->num_custom_plans = 0;
320 :
321 12322 : return plansource;
322 : }
323 :
324 : /*
325 : * CompleteCachedPlan: second step of creating a plan cache entry.
326 : *
327 : * Pass in the analyzed-and-rewritten form of the query, as well as the
328 : * required subsidiary data about parameters and such. All passed values will
329 : * be copied into the CachedPlanSource's memory, except as specified below.
330 : * After this is called, GetCachedPlan can be called to obtain a plan, and
331 : * optionally the CachedPlanSource can be saved using SaveCachedPlan.
332 : *
333 : * If querytree_context is not NULL, the querytree_list must be stored in that
334 : * context (but the other parameters need not be). The querytree_list is not
335 : * copied, rather the given context is kept as the initial query_context of
336 : * the CachedPlanSource. (It should have been created as a child of the
337 : * caller's working memory context, but it will now be reparented to belong
338 : * to the CachedPlanSource.) The querytree_context is normally the context in
339 : * which the caller did raw parsing and parse analysis. This approach saves
340 : * one tree copying step compared to passing NULL, but leaves lots of extra
341 : * cruft in the query_context, namely whatever extraneous stuff parse analysis
342 : * created, as well as whatever went unused from the raw parse tree. Using
343 : * this option is a space-for-time tradeoff that is appropriate if the
344 : * CachedPlanSource is not expected to survive long.
345 : *
346 : * plancache.c cannot know how to copy the data referenced by parserSetupArg,
347 : * and it would often be inappropriate to do so anyway. When using that
348 : * option, it is caller's responsibility that the referenced data remains
349 : * valid for as long as the CachedPlanSource exists.
350 : *
351 : * If the CachedPlanSource is a "oneshot" plan, then no querytree copying
352 : * occurs at all, and querytree_context is ignored; it is caller's
353 : * responsibility that the passed querytree_list is sufficiently long-lived.
354 : *
355 : * plansource: structure returned by CreateCachedPlan
356 : * querytree_list: analyzed-and-rewritten form of query (list of Query nodes)
357 : * querytree_context: memory context containing querytree_list,
358 : * or NULL to copy querytree_list into a fresh context
359 : * param_types: array of fixed parameter type OIDs, or NULL if none
360 : * num_params: number of fixed parameters
361 : * parserSetup: alternate method for handling query parameters
362 : * parserSetupArg: data to pass to parserSetup
363 : * cursor_options: options bitmask to pass to planner
364 : * fixed_result: true to disallow future changes in query's result tupdesc
365 : */
366 : void
367 61786 : CompleteCachedPlan(CachedPlanSource *plansource,
368 : List *querytree_list,
369 : MemoryContext querytree_context,
370 : Oid *param_types,
371 : int num_params,
372 : ParserSetupHook parserSetup,
373 : void *parserSetupArg,
374 : int cursor_options,
375 : bool fixed_result)
376 : {
377 61786 : MemoryContext source_context = plansource->context;
378 61786 : MemoryContext oldcxt = CurrentMemoryContext;
379 :
380 : /* Assert caller is doing things in a sane order */
381 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
382 : Assert(!plansource->is_complete);
383 :
384 : /*
385 : * If caller supplied a querytree_context, reparent it underneath the
386 : * CachedPlanSource's context; otherwise, create a suitable context and
387 : * copy the querytree_list into it. But no data copying should be done
388 : * for one-shot plans; for those, assume the passed querytree_list is
389 : * sufficiently long-lived.
390 : */
391 61786 : if (plansource->is_oneshot)
392 : {
393 12306 : querytree_context = CurrentMemoryContext;
394 : }
395 49480 : else if (querytree_context != NULL)
396 : {
397 5738 : MemoryContextSetParent(querytree_context, source_context);
398 5738 : MemoryContextSwitchTo(querytree_context);
399 : }
400 : else
401 : {
402 : /* Again, it's a good bet the querytree_context can be small */
403 43742 : querytree_context = AllocSetContextCreate(source_context,
404 : "CachedPlanQuery",
405 : ALLOCSET_START_SMALL_SIZES);
406 43742 : MemoryContextSwitchTo(querytree_context);
407 43742 : querytree_list = copyObject(querytree_list);
408 : }
409 :
410 61786 : plansource->query_context = querytree_context;
411 61786 : plansource->query_list = querytree_list;
412 :
413 61786 : if (!plansource->is_oneshot && StmtPlanRequiresRevalidation(plansource))
414 : {
415 : /*
416 : * Use the planner machinery to extract dependencies. Data is saved
417 : * in query_context. (We assume that not a lot of extra cruft is
418 : * created by this call.) We can skip this for one-shot plans, and
419 : * plans not needing revalidation have no such dependencies anyway.
420 : */
421 48668 : extract_query_dependencies((Node *) querytree_list,
422 : &plansource->relationOids,
423 : &plansource->invalItems,
424 : &plansource->dependsOnRLS);
425 :
426 : /* Update RLS info as well. */
427 48668 : plansource->rewriteRoleId = GetUserId();
428 48668 : plansource->rewriteRowSecurity = row_security;
429 :
430 : /*
431 : * Also save the current search_path in the query_context. (This
432 : * should not generate much extra cruft either, since almost certainly
433 : * the path is already valid.) Again, we don't really need this for
434 : * one-shot plans; and we *must* skip this for transaction control
435 : * commands, because this could result in catalog accesses.
436 : */
437 48668 : plansource->search_path = GetSearchPathMatcher(querytree_context);
438 : }
439 :
440 : /*
441 : * Save the final parameter types (or other parameter specification data)
442 : * into the source_context, as well as our other parameters. Also save
443 : * the result tuple descriptor.
444 : */
445 61786 : MemoryContextSwitchTo(source_context);
446 :
447 61786 : if (num_params > 0)
448 : {
449 12814 : plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
450 12814 : memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
451 : }
452 : else
453 48972 : plansource->param_types = NULL;
454 61786 : plansource->num_params = num_params;
455 61786 : plansource->parserSetup = parserSetup;
456 61786 : plansource->parserSetupArg = parserSetupArg;
457 61786 : plansource->cursor_options = cursor_options;
458 61786 : plansource->fixed_result = fixed_result;
459 61786 : plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
460 :
461 61786 : MemoryContextSwitchTo(oldcxt);
462 :
463 61786 : plansource->is_complete = true;
464 61786 : plansource->is_valid = true;
465 61786 : }
466 :
467 : /*
468 : * SaveCachedPlan: save a cached plan permanently
469 : *
470 : * This function moves the cached plan underneath CacheMemoryContext (making
471 : * it live for the life of the backend, unless explicitly dropped), and adds
472 : * it to the list of cached plans that are checked for invalidation when an
473 : * sinval event occurs.
474 : *
475 : * This is guaranteed not to throw error, except for the caller-error case
476 : * of trying to save a one-shot plan. Callers typically depend on that
477 : * since this is called just before or just after adding a pointer to the
478 : * CachedPlanSource to some permanent data structure of their own. Up until
479 : * this is done, a CachedPlanSource is just transient data that will go away
480 : * automatically on transaction abort.
481 : */
482 : void
483 38954 : SaveCachedPlan(CachedPlanSource *plansource)
484 : {
485 : /* Assert caller is doing things in a sane order */
486 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
487 : Assert(plansource->is_complete);
488 : Assert(!plansource->is_saved);
489 :
490 : /* This seems worth a real test, though */
491 38954 : if (plansource->is_oneshot)
492 0 : elog(ERROR, "cannot save one-shot cached plan");
493 :
494 : /*
495 : * In typical use, this function would be called before generating any
496 : * plans from the CachedPlanSource. If there is a generic plan, moving it
497 : * into CacheMemoryContext would be pretty risky since it's unclear
498 : * whether the caller has taken suitable care with making references
499 : * long-lived. Best thing to do seems to be to discard the plan.
500 : */
501 38954 : ReleaseGenericPlan(plansource);
502 :
503 : /*
504 : * Reparent the source memory context under CacheMemoryContext so that it
505 : * will live indefinitely. The query_context follows along since it's
506 : * already a child of the other one.
507 : */
508 38954 : MemoryContextSetParent(plansource->context, CacheMemoryContext);
509 :
510 : /*
511 : * Add the entry to the global list of cached plans.
512 : */
513 38954 : dlist_push_tail(&saved_plan_list, &plansource->node);
514 :
515 38954 : plansource->is_saved = true;
516 38954 : }
517 :
518 : /*
519 : * DropCachedPlan: destroy a cached plan.
520 : *
521 : * Actually this only destroys the CachedPlanSource: any referenced CachedPlan
522 : * is released, but not destroyed until its refcount goes to zero. That
523 : * handles the situation where DropCachedPlan is called while the plan is
524 : * still in use.
525 : */
526 : void
527 14514 : DropCachedPlan(CachedPlanSource *plansource)
528 : {
529 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
530 :
531 : /* If it's been saved, remove it from the list */
532 14514 : if (plansource->is_saved)
533 : {
534 14324 : dlist_delete(&plansource->node);
535 14324 : plansource->is_saved = false;
536 : }
537 :
538 : /* Decrement generic CachedPlan's refcount and drop if no longer needed */
539 14514 : ReleaseGenericPlan(plansource);
540 :
541 : /* Mark it no longer valid */
542 14514 : plansource->magic = 0;
543 :
544 : /*
545 : * Remove the CachedPlanSource and all subsidiary data (including the
546 : * query_context if any). But if it's a one-shot we can't free anything.
547 : */
548 14514 : if (!plansource->is_oneshot)
549 14514 : MemoryContextDelete(plansource->context);
550 14514 : }
551 :
552 : /*
553 : * ReleaseGenericPlan: release a CachedPlanSource's generic plan, if any.
554 : */
555 : static void
556 99020 : ReleaseGenericPlan(CachedPlanSource *plansource)
557 : {
558 : /* Be paranoid about the possibility that ReleaseCachedPlan fails */
559 99020 : if (plansource->gplan)
560 : {
561 10574 : CachedPlan *plan = plansource->gplan;
562 :
563 : Assert(plan->magic == CACHEDPLAN_MAGIC);
564 10574 : plansource->gplan = NULL;
565 10574 : ReleaseCachedPlan(plan, NULL);
566 : }
567 99020 : }
568 :
569 : /*
570 : * RevalidateCachedQuery: ensure validity of analyzed-and-rewritten query tree.
571 : *
572 : * What we do here is re-acquire locks and redo parse analysis if necessary.
573 : * On return, the query_list is valid and we have sufficient locks to begin
574 : * planning.
575 : *
576 : * If any parse analysis activity is required, the caller's memory context is
577 : * used for that work.
578 : *
579 : * The result value is the transient analyzed-and-rewritten query tree if we
580 : * had to do re-analysis, and NIL otherwise. (This is returned just to save
581 : * a tree copying step in a subsequent BuildCachedPlan call.)
582 : */
583 : static List *
584 166696 : RevalidateCachedQuery(CachedPlanSource *plansource,
585 : QueryEnvironment *queryEnv)
586 : {
587 : bool snapshot_set;
588 : RawStmt *rawtree;
589 : List *tlist; /* transient query-tree list */
590 : List *qlist; /* permanent query-tree list */
591 : TupleDesc resultDesc;
592 : MemoryContext querytree_context;
593 : MemoryContext oldcxt;
594 :
595 : /*
596 : * For one-shot plans, we do not support revalidation checking; it's
597 : * assumed the query is parsed, planned, and executed in one transaction,
598 : * so that no lock re-acquisition is necessary. Also, if the statement
599 : * type can't require revalidation, we needn't do anything (and we mustn't
600 : * risk catalog accesses when handling, eg, transaction control commands).
601 : */
602 166696 : if (plansource->is_oneshot || !StmtPlanRequiresRevalidation(plansource))
603 : {
604 : Assert(plansource->is_valid);
605 24532 : return NIL;
606 : }
607 :
608 : /*
609 : * If the query is currently valid, we should have a saved search_path ---
610 : * check to see if that matches the current environment. If not, we want
611 : * to force replan.
612 : */
613 142164 : if (plansource->is_valid)
614 : {
615 : Assert(plansource->search_path != NULL);
616 137688 : if (!SearchPathMatchesCurrentEnvironment(plansource->search_path))
617 : {
618 : /* Invalidate the querytree and generic plan */
619 86 : plansource->is_valid = false;
620 86 : if (plansource->gplan)
621 74 : plansource->gplan->is_valid = false;
622 : }
623 : }
624 :
625 : /*
626 : * If the query rewrite phase had a possible RLS dependency, we must redo
627 : * it if either the role or the row_security setting has changed.
628 : */
629 142414 : if (plansource->is_valid && plansource->dependsOnRLS &&
630 250 : (plansource->rewriteRoleId != GetUserId() ||
631 174 : plansource->rewriteRowSecurity != row_security))
632 76 : plansource->is_valid = false;
633 :
634 : /*
635 : * If the query is currently valid, acquire locks on the referenced
636 : * objects; then check again. We need to do it this way to cover the race
637 : * condition that an invalidation message arrives before we get the locks.
638 : */
639 142164 : if (plansource->is_valid)
640 : {
641 137526 : AcquirePlannerLocks(plansource->query_list, true);
642 :
643 : /*
644 : * By now, if any invalidation has happened, the inval callback
645 : * functions will have marked the query invalid.
646 : */
647 137526 : if (plansource->is_valid)
648 : {
649 : /* Successfully revalidated and locked the query. */
650 137522 : return NIL;
651 : }
652 :
653 : /* Oops, the race case happened. Release useless locks. */
654 4 : AcquirePlannerLocks(plansource->query_list, false);
655 : }
656 :
657 : /*
658 : * Discard the no-longer-useful query tree. (Note: we don't want to do
659 : * this any earlier, else we'd not have been able to release locks
660 : * correctly in the race condition case.)
661 : */
662 4642 : plansource->is_valid = false;
663 4642 : plansource->query_list = NIL;
664 4642 : plansource->relationOids = NIL;
665 4642 : plansource->invalItems = NIL;
666 4642 : plansource->search_path = NULL;
667 :
668 : /*
669 : * Free the query_context. We don't really expect MemoryContextDelete to
670 : * fail, but just in case, make sure the CachedPlanSource is left in a
671 : * reasonably sane state. (The generic plan won't get unlinked yet, but
672 : * that's acceptable.)
673 : */
674 4642 : if (plansource->query_context)
675 : {
676 4618 : MemoryContext qcxt = plansource->query_context;
677 :
678 4618 : plansource->query_context = NULL;
679 4618 : MemoryContextDelete(qcxt);
680 : }
681 :
682 : /* Drop the generic plan reference if any */
683 4642 : ReleaseGenericPlan(plansource);
684 :
685 : /*
686 : * Now re-do parse analysis and rewrite. This not incidentally acquires
687 : * the locks we need to do planning safely.
688 : */
689 : Assert(plansource->is_complete);
690 :
691 : /*
692 : * If a snapshot is already set (the normal case), we can just use that
693 : * for parsing/planning. But if it isn't, install one. Note: no point in
694 : * checking whether parse analysis requires a snapshot; utility commands
695 : * don't have invalidatable plans, so we'd not get here for such a
696 : * command.
697 : */
698 4642 : snapshot_set = false;
699 4642 : if (!ActiveSnapshotSet())
700 : {
701 20 : PushActiveSnapshot(GetTransactionSnapshot());
702 20 : snapshot_set = true;
703 : }
704 :
705 : /*
706 : * Run parse analysis and rule rewriting. The parser tends to scribble on
707 : * its input, so we must copy the raw parse tree to prevent corruption of
708 : * the cache.
709 : */
710 4642 : rawtree = copyObject(plansource->raw_parse_tree);
711 4642 : if (rawtree == NULL)
712 0 : tlist = NIL;
713 4642 : else if (plansource->parserSetup != NULL)
714 4312 : tlist = pg_analyze_and_rewrite_withcb(rawtree,
715 : plansource->query_string,
716 : plansource->parserSetup,
717 : plansource->parserSetupArg,
718 : queryEnv);
719 : else
720 330 : tlist = pg_analyze_and_rewrite_fixedparams(rawtree,
721 : plansource->query_string,
722 330 : plansource->param_types,
723 : plansource->num_params,
724 : queryEnv);
725 :
726 : /* Release snapshot if we got one */
727 4616 : if (snapshot_set)
728 20 : PopActiveSnapshot();
729 :
730 : /*
731 : * Check or update the result tupdesc. XXX should we use a weaker
732 : * condition than equalTupleDescs() here?
733 : *
734 : * We assume the parameter types didn't change from the first time, so no
735 : * need to update that.
736 : */
737 4616 : resultDesc = PlanCacheComputeResultDesc(tlist);
738 4616 : if (resultDesc == NULL && plansource->resultDesc == NULL)
739 : {
740 : /* OK, doesn't return tuples */
741 : }
742 4472 : else if (resultDesc == NULL || plansource->resultDesc == NULL ||
743 4472 : !equalTupleDescs(resultDesc, plansource->resultDesc))
744 : {
745 : /* can we give a better error message? */
746 58 : if (plansource->fixed_result)
747 12 : ereport(ERROR,
748 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
749 : errmsg("cached plan must not change result type")));
750 46 : oldcxt = MemoryContextSwitchTo(plansource->context);
751 46 : if (resultDesc)
752 46 : resultDesc = CreateTupleDescCopy(resultDesc);
753 46 : if (plansource->resultDesc)
754 46 : FreeTupleDesc(plansource->resultDesc);
755 46 : plansource->resultDesc = resultDesc;
756 46 : MemoryContextSwitchTo(oldcxt);
757 : }
758 :
759 : /*
760 : * Allocate new query_context and copy the completed querytree into it.
761 : * It's transient until we complete the copying and dependency extraction.
762 : */
763 4604 : querytree_context = AllocSetContextCreate(CurrentMemoryContext,
764 : "CachedPlanQuery",
765 : ALLOCSET_START_SMALL_SIZES);
766 4604 : oldcxt = MemoryContextSwitchTo(querytree_context);
767 :
768 4604 : qlist = copyObject(tlist);
769 :
770 : /*
771 : * Use the planner machinery to extract dependencies. Data is saved in
772 : * query_context. (We assume that not a lot of extra cruft is created by
773 : * this call.)
774 : */
775 4604 : extract_query_dependencies((Node *) qlist,
776 : &plansource->relationOids,
777 : &plansource->invalItems,
778 : &plansource->dependsOnRLS);
779 :
780 : /* Update RLS info as well. */
781 4604 : plansource->rewriteRoleId = GetUserId();
782 4604 : plansource->rewriteRowSecurity = row_security;
783 :
784 : /*
785 : * Also save the current search_path in the query_context. (This should
786 : * not generate much extra cruft either, since almost certainly the path
787 : * is already valid.)
788 : */
789 4604 : plansource->search_path = GetSearchPathMatcher(querytree_context);
790 :
791 4604 : MemoryContextSwitchTo(oldcxt);
792 :
793 : /* Now reparent the finished query_context and save the links */
794 4604 : MemoryContextSetParent(querytree_context, plansource->context);
795 :
796 4604 : plansource->query_context = querytree_context;
797 4604 : plansource->query_list = qlist;
798 :
799 : /*
800 : * Note: we do not reset generic_cost or total_custom_cost, although we
801 : * could choose to do so. If the DDL or statistics change that prompted
802 : * the invalidation meant a significant change in the cost estimates, it
803 : * would be better to reset those variables and start fresh; but often it
804 : * doesn't, and we're better retaining our hard-won knowledge about the
805 : * relative costs.
806 : */
807 :
808 4604 : plansource->is_valid = true;
809 :
810 : /* Return transient copy of querytrees for possible use in planning */
811 4604 : return tlist;
812 : }
813 :
814 : /*
815 : * CheckCachedPlan: see if the CachedPlanSource's generic plan is valid.
816 : *
817 : * Caller must have already called RevalidateCachedQuery to verify that the
818 : * querytree is up to date.
819 : *
820 : * On a "true" return, we have acquired the locks needed to run the plan.
821 : * (We must do this for the "true" result to be race-condition-free.)
822 : */
823 : static bool
824 120688 : CheckCachedPlan(CachedPlanSource *plansource)
825 : {
826 120688 : CachedPlan *plan = plansource->gplan;
827 :
828 : /* Assert that caller checked the querytree */
829 : Assert(plansource->is_valid);
830 :
831 : /* If there's no generic plan, just say "false" */
832 120688 : if (!plan)
833 40914 : return false;
834 :
835 : Assert(plan->magic == CACHEDPLAN_MAGIC);
836 : /* Generic plans are never one-shot */
837 : Assert(!plan->is_oneshot);
838 :
839 : /*
840 : * If plan isn't valid for current role, we can't use it.
841 : */
842 79780 : if (plan->is_valid && plan->dependsOnRole &&
843 6 : plan->planRoleId != GetUserId())
844 6 : plan->is_valid = false;
845 :
846 : /*
847 : * If it appears valid, acquire locks and recheck; this is much the same
848 : * logic as in RevalidateCachedQuery, but for a plan.
849 : */
850 79774 : if (plan->is_valid)
851 : {
852 : /*
853 : * Plan must have positive refcount because it is referenced by
854 : * plansource; so no need to fear it disappears under us here.
855 : */
856 : Assert(plan->refcount > 0);
857 :
858 79750 : AcquireExecutorLocks(plan->stmt_list, true);
859 :
860 : /*
861 : * If plan was transient, check to see if TransactionXmin has
862 : * advanced, and if so invalidate it.
863 : */
864 79750 : if (plan->is_valid &&
865 79750 : TransactionIdIsValid(plan->saved_xmin) &&
866 0 : !TransactionIdEquals(plan->saved_xmin, TransactionXmin))
867 0 : plan->is_valid = false;
868 :
869 : /*
870 : * By now, if any invalidation has happened, the inval callback
871 : * functions will have marked the plan invalid.
872 : */
873 79750 : if (plan->is_valid)
874 : {
875 : /* Successfully revalidated and locked the query. */
876 79750 : return true;
877 : }
878 :
879 : /* Oops, the race case happened. Release useless locks. */
880 0 : AcquireExecutorLocks(plan->stmt_list, false);
881 : }
882 :
883 : /*
884 : * Plan has been invalidated, so unlink it from the parent and release it.
885 : */
886 24 : ReleaseGenericPlan(plansource);
887 :
888 24 : return false;
889 : }
890 :
891 : /*
892 : * BuildCachedPlan: construct a new CachedPlan from a CachedPlanSource.
893 : *
894 : * qlist should be the result value from a previous RevalidateCachedQuery,
895 : * or it can be set to NIL if we need to re-copy the plansource's query_list.
896 : *
897 : * To build a generic, parameter-value-independent plan, pass NULL for
898 : * boundParams. To build a custom plan, pass the actual parameter values via
899 : * boundParams. For best effect, the PARAM_FLAG_CONST flag should be set on
900 : * each parameter value; otherwise the planner will treat the value as a
901 : * hint rather than a hard constant.
902 : *
903 : * Planning work is done in the caller's memory context. The finished plan
904 : * is in a child memory context, which typically should get reparented
905 : * (unless this is a one-shot plan, in which case we don't copy the plan).
906 : */
907 : static CachedPlan *
908 75970 : BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
909 : ParamListInfo boundParams, QueryEnvironment *queryEnv)
910 : {
911 : CachedPlan *plan;
912 : List *plist;
913 : bool snapshot_set;
914 : bool is_transient;
915 : MemoryContext plan_context;
916 75970 : MemoryContext oldcxt = CurrentMemoryContext;
917 : ListCell *lc;
918 :
919 : /*
920 : * Normally the querytree should be valid already, but if it's not,
921 : * rebuild it.
922 : *
923 : * NOTE: GetCachedPlan should have called RevalidateCachedQuery first, so
924 : * we ought to be holding sufficient locks to prevent any invalidation.
925 : * However, if we're building a custom plan after having built and
926 : * rejected a generic plan, it's possible to reach here with is_valid
927 : * false due to an invalidation while making the generic plan. In theory
928 : * the invalidation must be a false positive, perhaps a consequence of an
929 : * sinval reset event or the debug_discard_caches code. But for safety,
930 : * let's treat it as real and redo the RevalidateCachedQuery call.
931 : */
932 75970 : if (!plansource->is_valid)
933 0 : qlist = RevalidateCachedQuery(plansource, queryEnv);
934 :
935 : /*
936 : * If we don't already have a copy of the querytree list that can be
937 : * scribbled on by the planner, make one. For a one-shot plan, we assume
938 : * it's okay to scribble on the original query_list.
939 : */
940 75970 : if (qlist == NIL)
941 : {
942 71368 : if (!plansource->is_oneshot)
943 59068 : qlist = copyObject(plansource->query_list);
944 : else
945 12300 : qlist = plansource->query_list;
946 : }
947 :
948 : /*
949 : * If a snapshot is already set (the normal case), we can just use that
950 : * for planning. But if it isn't, and we need one, install one.
951 : */
952 75970 : snapshot_set = false;
953 75970 : if (!ActiveSnapshotSet() &&
954 1628 : plansource->raw_parse_tree &&
955 814 : analyze_requires_snapshot(plansource->raw_parse_tree))
956 : {
957 274 : PushActiveSnapshot(GetTransactionSnapshot());
958 274 : snapshot_set = true;
959 : }
960 :
961 : /*
962 : * Generate the plan.
963 : */
964 75970 : plist = pg_plan_queries(qlist, plansource->query_string,
965 : plansource->cursor_options, boundParams);
966 :
967 : /* Release snapshot if we got one */
968 75802 : if (snapshot_set)
969 268 : PopActiveSnapshot();
970 :
971 : /*
972 : * Normally we make a dedicated memory context for the CachedPlan and its
973 : * subsidiary data. (It's probably not going to be large, but just in
974 : * case, allow it to grow large. It's transient for the moment.) But for
975 : * a one-shot plan, we just leave it in the caller's memory context.
976 : */
977 75802 : if (!plansource->is_oneshot)
978 : {
979 63578 : plan_context = AllocSetContextCreate(CurrentMemoryContext,
980 : "CachedPlan",
981 : ALLOCSET_START_SMALL_SIZES);
982 63578 : MemoryContextCopyAndSetIdentifier(plan_context, plansource->query_string);
983 :
984 : /*
985 : * Copy plan into the new context.
986 : */
987 63578 : MemoryContextSwitchTo(plan_context);
988 :
989 63578 : plist = copyObject(plist);
990 : }
991 : else
992 12224 : plan_context = CurrentMemoryContext;
993 :
994 : /*
995 : * Create and fill the CachedPlan struct within the new context.
996 : */
997 75802 : plan = (CachedPlan *) palloc(sizeof(CachedPlan));
998 75802 : plan->magic = CACHEDPLAN_MAGIC;
999 75802 : plan->stmt_list = plist;
1000 :
1001 : /*
1002 : * CachedPlan is dependent on role either if RLS affected the rewrite
1003 : * phase or if a role dependency was injected during planning. And it's
1004 : * transient if any plan is marked so.
1005 : */
1006 75802 : plan->planRoleId = GetUserId();
1007 75802 : plan->dependsOnRole = plansource->dependsOnRLS;
1008 75802 : is_transient = false;
1009 151604 : foreach(lc, plist)
1010 : {
1011 75802 : PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
1012 :
1013 75802 : if (plannedstmt->commandType == CMD_UTILITY)
1014 11308 : continue; /* Ignore utility statements */
1015 :
1016 64494 : if (plannedstmt->transientPlan)
1017 0 : is_transient = true;
1018 64494 : if (plannedstmt->dependsOnRole)
1019 12 : plan->dependsOnRole = true;
1020 : }
1021 75802 : if (is_transient)
1022 : {
1023 : Assert(TransactionIdIsNormal(TransactionXmin));
1024 0 : plan->saved_xmin = TransactionXmin;
1025 : }
1026 : else
1027 75802 : plan->saved_xmin = InvalidTransactionId;
1028 75802 : plan->refcount = 0;
1029 75802 : plan->context = plan_context;
1030 75802 : plan->is_oneshot = plansource->is_oneshot;
1031 75802 : plan->is_saved = false;
1032 75802 : plan->is_valid = true;
1033 :
1034 : /* assign generation number to new plan */
1035 75802 : plan->generation = ++(plansource->generation);
1036 :
1037 75802 : MemoryContextSwitchTo(oldcxt);
1038 :
1039 75802 : return plan;
1040 : }
1041 :
1042 : /*
1043 : * choose_custom_plan: choose whether to use custom or generic plan
1044 : *
1045 : * This defines the policy followed by GetCachedPlan.
1046 : */
1047 : static bool
1048 196560 : choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams)
1049 : {
1050 : double avg_custom_cost;
1051 :
1052 : /* One-shot plans will always be considered custom */
1053 196560 : if (plansource->is_oneshot)
1054 12300 : return true;
1055 :
1056 : /* Otherwise, never any point in a custom plan if there's no parameters */
1057 184260 : if (boundParams == NULL)
1058 117410 : return false;
1059 : /* ... nor when planning would be a no-op */
1060 66850 : if (!StmtPlanRequiresRevalidation(plansource))
1061 0 : return false;
1062 :
1063 : /* Let settings force the decision */
1064 66850 : if (plan_cache_mode == PLAN_CACHE_MODE_FORCE_GENERIC_PLAN)
1065 298 : return false;
1066 66552 : if (plan_cache_mode == PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN)
1067 6 : return true;
1068 :
1069 : /* See if caller wants to force the decision */
1070 66546 : if (plansource->cursor_options & CURSOR_OPT_GENERIC_PLAN)
1071 0 : return false;
1072 66546 : if (plansource->cursor_options & CURSOR_OPT_CUSTOM_PLAN)
1073 0 : return true;
1074 :
1075 : /* Generate custom plans until we have done at least 5 (arbitrary) */
1076 66546 : if (plansource->num_custom_plans < 5)
1077 21066 : return true;
1078 :
1079 45480 : avg_custom_cost = plansource->total_custom_cost / plansource->num_custom_plans;
1080 :
1081 : /*
1082 : * Prefer generic plan if it's less expensive than the average custom
1083 : * plan. (Because we include a charge for cost of planning in the
1084 : * custom-plan costs, this means the generic plan only has to be less
1085 : * expensive than the execution cost plus replan cost of the custom
1086 : * plans.)
1087 : *
1088 : * Note that if generic_cost is -1 (indicating we've not yet determined
1089 : * the generic plan cost), we'll always prefer generic at this point.
1090 : */
1091 45480 : if (plansource->generic_cost < avg_custom_cost)
1092 43820 : return false;
1093 :
1094 1660 : return true;
1095 : }
1096 :
1097 : /*
1098 : * cached_plan_cost: calculate estimated cost of a plan
1099 : *
1100 : * If include_planner is true, also include the estimated cost of constructing
1101 : * the plan. (We must factor that into the cost of using a custom plan, but
1102 : * we don't count it for a generic plan.)
1103 : */
1104 : static double
1105 75802 : cached_plan_cost(CachedPlan *plan, bool include_planner)
1106 : {
1107 75802 : double result = 0;
1108 : ListCell *lc;
1109 :
1110 151604 : foreach(lc, plan->stmt_list)
1111 : {
1112 75802 : PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
1113 :
1114 75802 : if (plannedstmt->commandType == CMD_UTILITY)
1115 11308 : continue; /* Ignore utility statements */
1116 :
1117 64494 : result += plannedstmt->planTree->total_cost;
1118 :
1119 64494 : if (include_planner)
1120 : {
1121 : /*
1122 : * Currently we use a very crude estimate of planning effort based
1123 : * on the number of relations in the finished plan's rangetable.
1124 : * Join planning effort actually scales much worse than linearly
1125 : * in the number of relations --- but only until the join collapse
1126 : * limits kick in. Also, while inheritance child relations surely
1127 : * add to planning effort, they don't make the join situation
1128 : * worse. So the actual shape of the planning cost curve versus
1129 : * number of relations isn't all that obvious. It will take
1130 : * considerable work to arrive at a less crude estimate, and for
1131 : * now it's not clear that's worth doing.
1132 : *
1133 : * The other big difficulty here is that we don't have any very
1134 : * good model of how planning cost compares to execution costs.
1135 : * The current multiplier of 1000 * cpu_operator_cost is probably
1136 : * on the low side, but we'll try this for awhile before making a
1137 : * more aggressive correction.
1138 : *
1139 : * If we ever do write a more complicated estimator, it should
1140 : * probably live in src/backend/optimizer/ not here.
1141 : */
1142 33140 : int nrelations = list_length(plannedstmt->rtable);
1143 :
1144 33140 : result += 1000.0 * cpu_operator_cost * (nrelations + 1);
1145 : }
1146 : }
1147 :
1148 75802 : return result;
1149 : }
1150 :
1151 : /*
1152 : * GetCachedPlan: get a cached plan from a CachedPlanSource.
1153 : *
1154 : * This function hides the logic that decides whether to use a generic
1155 : * plan or a custom plan for the given parameters: the caller does not know
1156 : * which it will get.
1157 : *
1158 : * On return, the plan is valid and we have sufficient locks to begin
1159 : * execution.
1160 : *
1161 : * On return, the refcount of the plan has been incremented; a later
1162 : * ReleaseCachedPlan() call is expected. If "owner" is not NULL then
1163 : * the refcount has been reported to that ResourceOwner (note that this
1164 : * is only supported for "saved" CachedPlanSources).
1165 : *
1166 : * Note: if any replanning activity is required, the caller's memory context
1167 : * is used for that work.
1168 : */
1169 : CachedPlan *
1170 155712 : GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams,
1171 : ResourceOwner owner, QueryEnvironment *queryEnv)
1172 : {
1173 155712 : CachedPlan *plan = NULL;
1174 : List *qlist;
1175 : bool customplan;
1176 :
1177 : /* Assert caller is doing things in a sane order */
1178 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1179 : Assert(plansource->is_complete);
1180 : /* This seems worth a real test, though */
1181 155712 : if (owner && !plansource->is_saved)
1182 0 : elog(ERROR, "cannot apply ResourceOwner to non-saved cached plan");
1183 :
1184 : /* Make sure the querytree list is valid and we have parse-time locks */
1185 155712 : qlist = RevalidateCachedQuery(plansource, queryEnv);
1186 :
1187 : /* Decide whether to use a custom plan */
1188 155674 : customplan = choose_custom_plan(plansource, boundParams);
1189 :
1190 155674 : if (!customplan)
1191 : {
1192 120688 : if (CheckCachedPlan(plansource))
1193 : {
1194 : /* We want a generic plan, and we already have a valid one */
1195 79750 : plan = plansource->gplan;
1196 : Assert(plan->magic == CACHEDPLAN_MAGIC);
1197 : }
1198 : else
1199 : {
1200 : /* Build a new generic plan */
1201 40938 : plan = BuildCachedPlan(plansource, qlist, NULL, queryEnv);
1202 : /* Just make real sure plansource->gplan is clear */
1203 40886 : ReleaseGenericPlan(plansource);
1204 : /* Link the new generic plan into the plansource */
1205 40886 : plansource->gplan = plan;
1206 40886 : plan->refcount++;
1207 : /* Immediately reparent into appropriate context */
1208 40886 : if (plansource->is_saved)
1209 : {
1210 : /* saved plans all live under CacheMemoryContext */
1211 30378 : MemoryContextSetParent(plan->context, CacheMemoryContext);
1212 30378 : plan->is_saved = true;
1213 : }
1214 : else
1215 : {
1216 : /* otherwise, it should be a sibling of the plansource */
1217 10508 : MemoryContextSetParent(plan->context,
1218 : MemoryContextGetParent(plansource->context));
1219 : }
1220 : /* Update generic_cost whenever we make a new generic plan */
1221 40886 : plansource->generic_cost = cached_plan_cost(plan, false);
1222 :
1223 : /*
1224 : * If, based on the now-known value of generic_cost, we'd not have
1225 : * chosen to use a generic plan, then forget it and make a custom
1226 : * plan. This is a bit of a wart but is necessary to avoid a
1227 : * glitch in behavior when the custom plans are consistently big
1228 : * winners; at some point we'll experiment with a generic plan and
1229 : * find it's a loser, but we don't want to actually execute that
1230 : * plan.
1231 : */
1232 40886 : customplan = choose_custom_plan(plansource, boundParams);
1233 :
1234 : /*
1235 : * If we choose to plan again, we need to re-copy the query_list,
1236 : * since the planner probably scribbled on it. We can force
1237 : * BuildCachedPlan to do that by passing NIL.
1238 : */
1239 40886 : qlist = NIL;
1240 : }
1241 : }
1242 :
1243 155622 : if (customplan)
1244 : {
1245 : /* Build a custom plan */
1246 35032 : plan = BuildCachedPlan(plansource, qlist, boundParams, queryEnv);
1247 : /* Accumulate total costs of custom plans */
1248 34916 : plansource->total_custom_cost += cached_plan_cost(plan, true);
1249 :
1250 34916 : plansource->num_custom_plans++;
1251 : }
1252 : else
1253 : {
1254 120590 : plansource->num_generic_plans++;
1255 : }
1256 :
1257 : Assert(plan != NULL);
1258 :
1259 : /* Flag the plan as in use by caller */
1260 155506 : if (owner)
1261 99204 : ResourceOwnerEnlarge(owner);
1262 155506 : plan->refcount++;
1263 155506 : if (owner)
1264 99204 : ResourceOwnerRememberPlanCacheRef(owner, plan);
1265 :
1266 : /*
1267 : * Saved plans should be under CacheMemoryContext so they will not go away
1268 : * until their reference count goes to zero. In the generic-plan cases we
1269 : * already took care of that, but for a custom plan, do it as soon as we
1270 : * have created a reference-counted link.
1271 : */
1272 155506 : if (customplan && plansource->is_saved)
1273 : {
1274 22680 : MemoryContextSetParent(plan->context, CacheMemoryContext);
1275 22680 : plan->is_saved = true;
1276 : }
1277 :
1278 155506 : return plan;
1279 : }
1280 :
1281 : /*
1282 : * ReleaseCachedPlan: release active use of a cached plan.
1283 : *
1284 : * This decrements the reference count, and frees the plan if the count
1285 : * has thereby gone to zero. If "owner" is not NULL, it is assumed that
1286 : * the reference count is managed by that ResourceOwner.
1287 : *
1288 : * Note: owner == NULL is used for releasing references that are in
1289 : * persistent data structures, such as the parent CachedPlanSource or a
1290 : * Portal. Transient references should be protected by a resource owner.
1291 : */
1292 : void
1293 239800 : ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
1294 : {
1295 : Assert(plan->magic == CACHEDPLAN_MAGIC);
1296 239800 : if (owner)
1297 : {
1298 : Assert(plan->is_saved);
1299 96134 : ResourceOwnerForgetPlanCacheRef(owner, plan);
1300 : }
1301 : Assert(plan->refcount > 0);
1302 239800 : plan->refcount--;
1303 239800 : if (plan->refcount == 0)
1304 : {
1305 : /* Mark it no longer valid */
1306 45330 : plan->magic = 0;
1307 :
1308 : /* One-shot plans do not own their context, so we can't free them */
1309 45330 : if (!plan->is_oneshot)
1310 33266 : MemoryContextDelete(plan->context);
1311 : }
1312 239800 : }
1313 :
1314 : /*
1315 : * CachedPlanAllowsSimpleValidityCheck: can we use CachedPlanIsSimplyValid?
1316 : *
1317 : * This function, together with CachedPlanIsSimplyValid, provides a fast path
1318 : * for revalidating "simple" generic plans. The core requirement to be simple
1319 : * is that the plan must not require taking any locks, which translates to
1320 : * not touching any tables; this happens to match up well with an important
1321 : * use-case in PL/pgSQL. This function tests whether that's true, along
1322 : * with checking some other corner cases that we'd rather not bother with
1323 : * handling in the fast path. (Note that it's still possible for such a plan
1324 : * to be invalidated, for example due to a change in a function that was
1325 : * inlined into the plan.)
1326 : *
1327 : * If the plan is simply valid, and "owner" is not NULL, record a refcount on
1328 : * the plan in that resowner before returning. It is caller's responsibility
1329 : * to be sure that a refcount is held on any plan that's being actively used.
1330 : *
1331 : * This must only be called on known-valid generic plans (eg, ones just
1332 : * returned by GetCachedPlan). If it returns true, the caller may re-use
1333 : * the cached plan as long as CachedPlanIsSimplyValid returns true; that
1334 : * check is much cheaper than the full revalidation done by GetCachedPlan.
1335 : * Nonetheless, no required checks are omitted.
1336 : */
1337 : bool
1338 24928 : CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource,
1339 : CachedPlan *plan, ResourceOwner owner)
1340 : {
1341 : ListCell *lc;
1342 :
1343 : /*
1344 : * Sanity-check that the caller gave us a validated generic plan. Notice
1345 : * that we *don't* assert plansource->is_valid as you might expect; that's
1346 : * because it's possible that that's already false when GetCachedPlan
1347 : * returns, e.g. because ResetPlanCache happened partway through. We
1348 : * should accept the plan as long as plan->is_valid is true, and expect to
1349 : * replan after the next CachedPlanIsSimplyValid call.
1350 : */
1351 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1352 : Assert(plan->magic == CACHEDPLAN_MAGIC);
1353 : Assert(plan->is_valid);
1354 : Assert(plan == plansource->gplan);
1355 : Assert(plansource->search_path != NULL);
1356 : Assert(SearchPathMatchesCurrentEnvironment(plansource->search_path));
1357 :
1358 : /* We don't support oneshot plans here. */
1359 24928 : if (plansource->is_oneshot)
1360 0 : return false;
1361 : Assert(!plan->is_oneshot);
1362 :
1363 : /*
1364 : * If the plan is dependent on RLS considerations, or it's transient,
1365 : * reject. These things probably can't ever happen for table-free
1366 : * queries, but for safety's sake let's check.
1367 : */
1368 24928 : if (plansource->dependsOnRLS)
1369 0 : return false;
1370 24928 : if (plan->dependsOnRole)
1371 0 : return false;
1372 24928 : if (TransactionIdIsValid(plan->saved_xmin))
1373 0 : return false;
1374 :
1375 : /*
1376 : * Reject if AcquirePlannerLocks would have anything to do. This is
1377 : * simplistic, but there's no need to inquire any more carefully; indeed,
1378 : * for current callers it shouldn't even be possible to hit any of these
1379 : * checks.
1380 : */
1381 49856 : foreach(lc, plansource->query_list)
1382 : {
1383 24928 : Query *query = lfirst_node(Query, lc);
1384 :
1385 24928 : if (query->commandType == CMD_UTILITY)
1386 0 : return false;
1387 24928 : if (query->rtable || query->cteList || query->hasSubLinks)
1388 0 : return false;
1389 : }
1390 :
1391 : /*
1392 : * Reject if AcquireExecutorLocks would have anything to do. This is
1393 : * probably unnecessary given the previous check, but let's be safe.
1394 : */
1395 49856 : foreach(lc, plan->stmt_list)
1396 : {
1397 24928 : PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
1398 : ListCell *lc2;
1399 :
1400 24928 : if (plannedstmt->commandType == CMD_UTILITY)
1401 0 : return false;
1402 :
1403 : /*
1404 : * We have to grovel through the rtable because it's likely to contain
1405 : * an RTE_RESULT relation, rather than being totally empty.
1406 : */
1407 49856 : foreach(lc2, plannedstmt->rtable)
1408 : {
1409 24928 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
1410 :
1411 24928 : if (rte->rtekind == RTE_RELATION)
1412 0 : return false;
1413 : }
1414 : }
1415 :
1416 : /*
1417 : * Okay, it's simple. Note that what we've primarily established here is
1418 : * that no locks need be taken before checking the plan's is_valid flag.
1419 : */
1420 :
1421 : /* Bump refcount if requested. */
1422 24928 : if (owner)
1423 : {
1424 24928 : ResourceOwnerEnlarge(owner);
1425 24928 : plan->refcount++;
1426 24928 : ResourceOwnerRememberPlanCacheRef(owner, plan);
1427 : }
1428 :
1429 24928 : return true;
1430 : }
1431 :
1432 : /*
1433 : * CachedPlanIsSimplyValid: quick check for plan still being valid
1434 : *
1435 : * This function must not be used unless CachedPlanAllowsSimpleValidityCheck
1436 : * previously said it was OK.
1437 : *
1438 : * If the plan is valid, and "owner" is not NULL, record a refcount on
1439 : * the plan in that resowner before returning. It is caller's responsibility
1440 : * to be sure that a refcount is held on any plan that's being actively used.
1441 : *
1442 : * The code here is unconditionally safe as long as the only use of this
1443 : * CachedPlanSource is in connection with the particular CachedPlan pointer
1444 : * that's passed in. If the plansource were being used for other purposes,
1445 : * it's possible that its generic plan could be invalidated and regenerated
1446 : * while the current caller wasn't looking, and then there could be a chance
1447 : * collision of address between this caller's now-stale plan pointer and the
1448 : * actual address of the new generic plan. For current uses, that scenario
1449 : * can't happen; but with a plansource shared across multiple uses, it'd be
1450 : * advisable to also save plan->generation and verify that that still matches.
1451 : */
1452 : bool
1453 260600 : CachedPlanIsSimplyValid(CachedPlanSource *plansource, CachedPlan *plan,
1454 : ResourceOwner owner)
1455 : {
1456 : /*
1457 : * Careful here: since the caller doesn't necessarily hold a refcount on
1458 : * the plan to start with, it's possible that "plan" is a dangling
1459 : * pointer. Don't dereference it until we've verified that it still
1460 : * matches the plansource's gplan (which is either valid or NULL).
1461 : */
1462 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1463 :
1464 : /*
1465 : * Has cache invalidation fired on this plan? We can check this right
1466 : * away since there are no locks that we'd need to acquire first. Note
1467 : * that here we *do* check plansource->is_valid, so as to force plan
1468 : * rebuild if that's become false.
1469 : */
1470 260600 : if (!plansource->is_valid ||
1471 256880 : plan == NULL || plan != plansource->gplan ||
1472 256880 : !plan->is_valid)
1473 3732 : return false;
1474 :
1475 : Assert(plan->magic == CACHEDPLAN_MAGIC);
1476 :
1477 : /* Is the search_path still the same as when we made it? */
1478 : Assert(plansource->search_path != NULL);
1479 256868 : if (!SearchPathMatchesCurrentEnvironment(plansource->search_path))
1480 56 : return false;
1481 :
1482 : /* It's still good. Bump refcount if requested. */
1483 256812 : if (owner)
1484 : {
1485 49100 : ResourceOwnerEnlarge(owner);
1486 49100 : plan->refcount++;
1487 49100 : ResourceOwnerRememberPlanCacheRef(owner, plan);
1488 : }
1489 :
1490 256812 : return true;
1491 : }
1492 :
1493 : /*
1494 : * CachedPlanSetParentContext: move a CachedPlanSource to a new memory context
1495 : *
1496 : * This can only be applied to unsaved plans; once saved, a plan always
1497 : * lives underneath CacheMemoryContext.
1498 : */
1499 : void
1500 28706 : CachedPlanSetParentContext(CachedPlanSource *plansource,
1501 : MemoryContext newcontext)
1502 : {
1503 : /* Assert caller is doing things in a sane order */
1504 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1505 : Assert(plansource->is_complete);
1506 :
1507 : /* These seem worth real tests, though */
1508 28706 : if (plansource->is_saved)
1509 0 : elog(ERROR, "cannot move a saved cached plan to another context");
1510 28706 : if (plansource->is_oneshot)
1511 0 : elog(ERROR, "cannot move a one-shot cached plan to another context");
1512 :
1513 : /* OK, let the caller keep the plan where he wishes */
1514 28706 : MemoryContextSetParent(plansource->context, newcontext);
1515 :
1516 : /*
1517 : * The query_context needs no special handling, since it's a child of
1518 : * plansource->context. But if there's a generic plan, it should be
1519 : * maintained as a sibling of plansource->context.
1520 : */
1521 28706 : if (plansource->gplan)
1522 : {
1523 : Assert(plansource->gplan->magic == CACHEDPLAN_MAGIC);
1524 0 : MemoryContextSetParent(plansource->gplan->context, newcontext);
1525 : }
1526 28706 : }
1527 :
1528 : /*
1529 : * CopyCachedPlan: make a copy of a CachedPlanSource
1530 : *
1531 : * This is a convenience routine that does the equivalent of
1532 : * CreateCachedPlan + CompleteCachedPlan, using the data stored in the
1533 : * input CachedPlanSource. The result is therefore "unsaved" (regardless
1534 : * of the state of the source), and we don't copy any generic plan either.
1535 : * The result will be currently valid, or not, the same as the source.
1536 : */
1537 : CachedPlanSource *
1538 0 : CopyCachedPlan(CachedPlanSource *plansource)
1539 : {
1540 : CachedPlanSource *newsource;
1541 : MemoryContext source_context;
1542 : MemoryContext querytree_context;
1543 : MemoryContext oldcxt;
1544 :
1545 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1546 : Assert(plansource->is_complete);
1547 :
1548 : /*
1549 : * One-shot plans can't be copied, because we haven't taken care that
1550 : * parsing/planning didn't scribble on the raw parse tree or querytrees.
1551 : */
1552 0 : if (plansource->is_oneshot)
1553 0 : elog(ERROR, "cannot copy a one-shot cached plan");
1554 :
1555 0 : source_context = AllocSetContextCreate(CurrentMemoryContext,
1556 : "CachedPlanSource",
1557 : ALLOCSET_START_SMALL_SIZES);
1558 :
1559 0 : oldcxt = MemoryContextSwitchTo(source_context);
1560 :
1561 0 : newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1562 0 : newsource->magic = CACHEDPLANSOURCE_MAGIC;
1563 0 : newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
1564 0 : newsource->query_string = pstrdup(plansource->query_string);
1565 0 : MemoryContextSetIdentifier(source_context, newsource->query_string);
1566 0 : newsource->commandTag = plansource->commandTag;
1567 0 : if (plansource->num_params > 0)
1568 : {
1569 0 : newsource->param_types = (Oid *)
1570 0 : palloc(plansource->num_params * sizeof(Oid));
1571 0 : memcpy(newsource->param_types, plansource->param_types,
1572 0 : plansource->num_params * sizeof(Oid));
1573 : }
1574 : else
1575 0 : newsource->param_types = NULL;
1576 0 : newsource->num_params = plansource->num_params;
1577 0 : newsource->parserSetup = plansource->parserSetup;
1578 0 : newsource->parserSetupArg = plansource->parserSetupArg;
1579 0 : newsource->cursor_options = plansource->cursor_options;
1580 0 : newsource->fixed_result = plansource->fixed_result;
1581 0 : if (plansource->resultDesc)
1582 0 : newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
1583 : else
1584 0 : newsource->resultDesc = NULL;
1585 0 : newsource->context = source_context;
1586 :
1587 0 : querytree_context = AllocSetContextCreate(source_context,
1588 : "CachedPlanQuery",
1589 : ALLOCSET_START_SMALL_SIZES);
1590 0 : MemoryContextSwitchTo(querytree_context);
1591 0 : newsource->query_list = copyObject(plansource->query_list);
1592 0 : newsource->relationOids = copyObject(plansource->relationOids);
1593 0 : newsource->invalItems = copyObject(plansource->invalItems);
1594 0 : if (plansource->search_path)
1595 0 : newsource->search_path = CopySearchPathMatcher(plansource->search_path);
1596 0 : newsource->query_context = querytree_context;
1597 0 : newsource->rewriteRoleId = plansource->rewriteRoleId;
1598 0 : newsource->rewriteRowSecurity = plansource->rewriteRowSecurity;
1599 0 : newsource->dependsOnRLS = plansource->dependsOnRLS;
1600 :
1601 0 : newsource->gplan = NULL;
1602 :
1603 0 : newsource->is_oneshot = false;
1604 0 : newsource->is_complete = true;
1605 0 : newsource->is_saved = false;
1606 0 : newsource->is_valid = plansource->is_valid;
1607 0 : newsource->generation = plansource->generation;
1608 :
1609 : /* We may as well copy any acquired cost knowledge */
1610 0 : newsource->generic_cost = plansource->generic_cost;
1611 0 : newsource->total_custom_cost = plansource->total_custom_cost;
1612 0 : newsource->num_generic_plans = plansource->num_generic_plans;
1613 0 : newsource->num_custom_plans = plansource->num_custom_plans;
1614 :
1615 0 : MemoryContextSwitchTo(oldcxt);
1616 :
1617 0 : return newsource;
1618 : }
1619 :
1620 : /*
1621 : * CachedPlanIsValid: test whether the rewritten querytree within a
1622 : * CachedPlanSource is currently valid (that is, not marked as being in need
1623 : * of revalidation).
1624 : *
1625 : * This result is only trustworthy (ie, free from race conditions) if
1626 : * the caller has acquired locks on all the relations used in the plan.
1627 : */
1628 : bool
1629 3056 : CachedPlanIsValid(CachedPlanSource *plansource)
1630 : {
1631 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1632 3056 : return plansource->is_valid;
1633 : }
1634 :
1635 : /*
1636 : * CachedPlanGetTargetList: return tlist, if any, describing plan's output
1637 : *
1638 : * The result is guaranteed up-to-date. However, it is local storage
1639 : * within the cached plan, and may disappear next time the plan is updated.
1640 : */
1641 : List *
1642 10984 : CachedPlanGetTargetList(CachedPlanSource *plansource,
1643 : QueryEnvironment *queryEnv)
1644 : {
1645 : Query *pstmt;
1646 :
1647 : /* Assert caller is doing things in a sane order */
1648 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1649 : Assert(plansource->is_complete);
1650 :
1651 : /*
1652 : * No work needed if statement doesn't return tuples (we assume this
1653 : * feature cannot be changed by an invalidation)
1654 : */
1655 10984 : if (plansource->resultDesc == NULL)
1656 0 : return NIL;
1657 :
1658 : /* Make sure the querytree list is valid and we have parse-time locks */
1659 10984 : RevalidateCachedQuery(plansource, queryEnv);
1660 :
1661 : /* Get the primary statement and find out what it returns */
1662 10984 : pstmt = QueryListGetPrimaryStmt(plansource->query_list);
1663 :
1664 10984 : return FetchStatementTargetList((Node *) pstmt);
1665 : }
1666 :
1667 : /*
1668 : * GetCachedExpression: construct a CachedExpression for an expression.
1669 : *
1670 : * This performs the same transformations on the expression as
1671 : * expression_planner(), ie, convert an expression as emitted by parse
1672 : * analysis to be ready to pass to the executor.
1673 : *
1674 : * The result is stashed in a private, long-lived memory context.
1675 : * (Note that this might leak a good deal of memory in the caller's
1676 : * context before that.) The passed-in expr tree is not modified.
1677 : */
1678 : CachedExpression *
1679 328 : GetCachedExpression(Node *expr)
1680 : {
1681 : CachedExpression *cexpr;
1682 : List *relationOids;
1683 : List *invalItems;
1684 : MemoryContext cexpr_context;
1685 : MemoryContext oldcxt;
1686 :
1687 : /*
1688 : * Pass the expression through the planner, and collect dependencies.
1689 : * Everything built here is leaked in the caller's context; that's
1690 : * intentional to minimize the size of the permanent data structure.
1691 : */
1692 328 : expr = (Node *) expression_planner_with_deps((Expr *) expr,
1693 : &relationOids,
1694 : &invalItems);
1695 :
1696 : /*
1697 : * Make a private memory context, and copy what we need into that. To
1698 : * avoid leaking a long-lived context if we fail while copying data, we
1699 : * initially make the context under the caller's context.
1700 : */
1701 328 : cexpr_context = AllocSetContextCreate(CurrentMemoryContext,
1702 : "CachedExpression",
1703 : ALLOCSET_SMALL_SIZES);
1704 :
1705 328 : oldcxt = MemoryContextSwitchTo(cexpr_context);
1706 :
1707 328 : cexpr = (CachedExpression *) palloc(sizeof(CachedExpression));
1708 328 : cexpr->magic = CACHEDEXPR_MAGIC;
1709 328 : cexpr->expr = copyObject(expr);
1710 328 : cexpr->is_valid = true;
1711 328 : cexpr->relationOids = copyObject(relationOids);
1712 328 : cexpr->invalItems = copyObject(invalItems);
1713 328 : cexpr->context = cexpr_context;
1714 :
1715 328 : MemoryContextSwitchTo(oldcxt);
1716 :
1717 : /*
1718 : * Reparent the expr's memory context under CacheMemoryContext so that it
1719 : * will live indefinitely.
1720 : */
1721 328 : MemoryContextSetParent(cexpr_context, CacheMemoryContext);
1722 :
1723 : /*
1724 : * Add the entry to the global list of cached expressions.
1725 : */
1726 328 : dlist_push_tail(&cached_expression_list, &cexpr->node);
1727 :
1728 328 : return cexpr;
1729 : }
1730 :
1731 : /*
1732 : * FreeCachedExpression
1733 : * Delete a CachedExpression.
1734 : */
1735 : void
1736 20 : FreeCachedExpression(CachedExpression *cexpr)
1737 : {
1738 : /* Sanity check */
1739 : Assert(cexpr->magic == CACHEDEXPR_MAGIC);
1740 : /* Unlink from global list */
1741 20 : dlist_delete(&cexpr->node);
1742 : /* Free all storage associated with CachedExpression */
1743 20 : MemoryContextDelete(cexpr->context);
1744 20 : }
1745 :
1746 : /*
1747 : * QueryListGetPrimaryStmt
1748 : * Get the "primary" stmt within a list, ie, the one marked canSetTag.
1749 : *
1750 : * Returns NULL if no such stmt. If multiple queries within the list are
1751 : * marked canSetTag, returns the first one. Neither of these cases should
1752 : * occur in present usages of this function.
1753 : */
1754 : static Query *
1755 11188 : QueryListGetPrimaryStmt(List *stmts)
1756 : {
1757 : ListCell *lc;
1758 :
1759 11188 : foreach(lc, stmts)
1760 : {
1761 11188 : Query *stmt = lfirst_node(Query, lc);
1762 :
1763 11188 : if (stmt->canSetTag)
1764 11188 : return stmt;
1765 : }
1766 0 : return NULL;
1767 : }
1768 :
1769 : /*
1770 : * AcquireExecutorLocks: acquire locks needed for execution of a cached plan;
1771 : * or release them if acquire is false.
1772 : */
1773 : static void
1774 79750 : AcquireExecutorLocks(List *stmt_list, bool acquire)
1775 : {
1776 : ListCell *lc1;
1777 :
1778 159500 : foreach(lc1, stmt_list)
1779 : {
1780 79750 : PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc1);
1781 : ListCell *lc2;
1782 :
1783 79750 : if (plannedstmt->commandType == CMD_UTILITY)
1784 : {
1785 : /*
1786 : * Ignore utility statements, except those (such as EXPLAIN) that
1787 : * contain a parsed-but-not-planned query. Note: it's okay to use
1788 : * ScanQueryForLocks, even though the query hasn't been through
1789 : * rule rewriting, because rewriting doesn't change the query
1790 : * representation.
1791 : */
1792 11440 : Query *query = UtilityContainsQuery(plannedstmt->utilityStmt);
1793 :
1794 11440 : if (query)
1795 6 : ScanQueryForLocks(query, acquire);
1796 11440 : continue;
1797 : }
1798 :
1799 178998 : foreach(lc2, plannedstmt->rtable)
1800 : {
1801 110688 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
1802 :
1803 110688 : if (!(rte->rtekind == RTE_RELATION ||
1804 63570 : (rte->rtekind == RTE_SUBQUERY && OidIsValid(rte->relid))))
1805 59800 : continue;
1806 :
1807 : /*
1808 : * Acquire the appropriate type of lock on each relation OID. Note
1809 : * that we don't actually try to open the rel, and hence will not
1810 : * fail if it's been dropped entirely --- we'll just transiently
1811 : * acquire a non-conflicting lock.
1812 : */
1813 50888 : if (acquire)
1814 50888 : LockRelationOid(rte->relid, rte->rellockmode);
1815 : else
1816 0 : UnlockRelationOid(rte->relid, rte->rellockmode);
1817 : }
1818 : }
1819 79750 : }
1820 :
1821 : /*
1822 : * AcquirePlannerLocks: acquire locks needed for planning of a querytree list;
1823 : * or release them if acquire is false.
1824 : *
1825 : * Note that we don't actually try to open the relations, and hence will not
1826 : * fail if one has been dropped entirely --- we'll just transiently acquire
1827 : * a non-conflicting lock.
1828 : */
1829 : static void
1830 137530 : AcquirePlannerLocks(List *stmt_list, bool acquire)
1831 : {
1832 : ListCell *lc;
1833 :
1834 275060 : foreach(lc, stmt_list)
1835 : {
1836 137530 : Query *query = lfirst_node(Query, lc);
1837 :
1838 137530 : if (query->commandType == CMD_UTILITY)
1839 : {
1840 : /* Ignore utility statements, unless they contain a Query */
1841 9570 : query = UtilityContainsQuery(query->utilityStmt);
1842 9570 : if (query)
1843 9442 : ScanQueryForLocks(query, acquire);
1844 9570 : continue;
1845 : }
1846 :
1847 127960 : ScanQueryForLocks(query, acquire);
1848 : }
1849 137530 : }
1850 :
1851 : /*
1852 : * ScanQueryForLocks: recursively scan one Query for AcquirePlannerLocks.
1853 : */
1854 : static void
1855 157672 : ScanQueryForLocks(Query *parsetree, bool acquire)
1856 : {
1857 : ListCell *lc;
1858 :
1859 : /* Shouldn't get called on utility commands */
1860 : Assert(parsetree->commandType != CMD_UTILITY);
1861 :
1862 : /*
1863 : * First, process RTEs of the current query level.
1864 : */
1865 301418 : foreach(lc, parsetree->rtable)
1866 : {
1867 143746 : RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
1868 :
1869 143746 : switch (rte->rtekind)
1870 : {
1871 100924 : case RTE_RELATION:
1872 : /* Acquire or release the appropriate type of lock */
1873 100924 : if (acquire)
1874 100920 : LockRelationOid(rte->relid, rte->rellockmode);
1875 : else
1876 4 : UnlockRelationOid(rte->relid, rte->rellockmode);
1877 100924 : break;
1878 :
1879 16918 : case RTE_SUBQUERY:
1880 : /* If this was a view, must lock/unlock the view */
1881 16918 : if (OidIsValid(rte->relid))
1882 : {
1883 3890 : if (acquire)
1884 3890 : LockRelationOid(rte->relid, rte->rellockmode);
1885 : else
1886 0 : UnlockRelationOid(rte->relid, rte->rellockmode);
1887 : }
1888 : /* Recurse into subquery-in-FROM */
1889 16918 : ScanQueryForLocks(rte->subquery, acquire);
1890 16918 : break;
1891 :
1892 25904 : default:
1893 : /* ignore other types of RTEs */
1894 25904 : break;
1895 : }
1896 : }
1897 :
1898 : /* Recurse into subquery-in-WITH */
1899 157726 : foreach(lc, parsetree->cteList)
1900 : {
1901 54 : CommonTableExpr *cte = lfirst_node(CommonTableExpr, lc);
1902 :
1903 54 : ScanQueryForLocks(castNode(Query, cte->ctequery), acquire);
1904 : }
1905 :
1906 : /*
1907 : * Recurse into sublink subqueries, too. But we already did the ones in
1908 : * the rtable and cteList.
1909 : */
1910 157672 : if (parsetree->hasSubLinks)
1911 : {
1912 3270 : query_tree_walker(parsetree, ScanQueryWalker,
1913 : (void *) &acquire,
1914 : QTW_IGNORE_RC_SUBQUERIES);
1915 : }
1916 157672 : }
1917 :
1918 : /*
1919 : * Walker to find sublink subqueries for ScanQueryForLocks
1920 : */
1921 : static bool
1922 80216 : ScanQueryWalker(Node *node, bool *acquire)
1923 : {
1924 80216 : if (node == NULL)
1925 36582 : return false;
1926 43634 : if (IsA(node, SubLink))
1927 : {
1928 3292 : SubLink *sub = (SubLink *) node;
1929 :
1930 : /* Do what we came for */
1931 3292 : ScanQueryForLocks(castNode(Query, sub->subselect), *acquire);
1932 : /* Fall through to process lefthand args of SubLink */
1933 : }
1934 :
1935 : /*
1936 : * Do NOT recurse into Query nodes, because ScanQueryForLocks already
1937 : * processed subselects of subselects for us.
1938 : */
1939 43634 : return expression_tree_walker(node, ScanQueryWalker,
1940 : (void *) acquire);
1941 : }
1942 :
1943 : /*
1944 : * PlanCacheComputeResultDesc: given a list of analyzed-and-rewritten Queries,
1945 : * determine the result tupledesc it will produce. Returns NULL if the
1946 : * execution will not return tuples.
1947 : *
1948 : * Note: the result is created or copied into current memory context.
1949 : */
1950 : static TupleDesc
1951 66402 : PlanCacheComputeResultDesc(List *stmt_list)
1952 : {
1953 : Query *query;
1954 :
1955 66402 : switch (ChoosePortalStrategy(stmt_list))
1956 : {
1957 47258 : case PORTAL_ONE_SELECT:
1958 : case PORTAL_ONE_MOD_WITH:
1959 47258 : query = linitial_node(Query, stmt_list);
1960 47258 : return ExecCleanTypeFromTL(query->targetList);
1961 :
1962 204 : case PORTAL_ONE_RETURNING:
1963 204 : query = QueryListGetPrimaryStmt(stmt_list);
1964 : Assert(query->returningList);
1965 204 : return ExecCleanTypeFromTL(query->returningList);
1966 :
1967 8040 : case PORTAL_UTIL_SELECT:
1968 8040 : query = linitial_node(Query, stmt_list);
1969 : Assert(query->utilityStmt);
1970 8040 : return UtilityTupleDescriptor(query->utilityStmt);
1971 :
1972 10900 : case PORTAL_MULTI_QUERY:
1973 : /* will not return tuples */
1974 10900 : break;
1975 : }
1976 10900 : return NULL;
1977 : }
1978 :
1979 : /*
1980 : * PlanCacheRelCallback
1981 : * Relcache inval callback function
1982 : *
1983 : * Invalidate all plans mentioning the given rel, or all plans mentioning
1984 : * any rel at all if relid == InvalidOid.
1985 : */
1986 : static void
1987 1857142 : PlanCacheRelCallback(Datum arg, Oid relid)
1988 : {
1989 : dlist_iter iter;
1990 :
1991 42640244 : dlist_foreach(iter, &saved_plan_list)
1992 : {
1993 40783102 : CachedPlanSource *plansource = dlist_container(CachedPlanSource,
1994 : node, iter.cur);
1995 :
1996 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1997 :
1998 : /* No work if it's already invalidated */
1999 40783102 : if (!plansource->is_valid)
2000 20109704 : continue;
2001 :
2002 : /* Never invalidate if parse/plan would be a no-op anyway */
2003 20673398 : if (!StmtPlanRequiresRevalidation(plansource))
2004 129338 : continue;
2005 :
2006 : /*
2007 : * Check the dependency list for the rewritten querytree.
2008 : */
2009 41088120 : if ((relid == InvalidOid) ? plansource->relationOids != NIL :
2010 20544060 : list_member_oid(plansource->relationOids, relid))
2011 : {
2012 : /* Invalidate the querytree and generic plan */
2013 3098 : plansource->is_valid = false;
2014 3098 : if (plansource->gplan)
2015 946 : plansource->gplan->is_valid = false;
2016 : }
2017 :
2018 : /*
2019 : * The generic plan, if any, could have more dependencies than the
2020 : * querytree does, so we have to check it too.
2021 : */
2022 20544060 : if (plansource->gplan && plansource->gplan->is_valid)
2023 : {
2024 : ListCell *lc;
2025 :
2026 39548740 : foreach(lc, plansource->gplan->stmt_list)
2027 : {
2028 19774396 : PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
2029 :
2030 19774396 : if (plannedstmt->commandType == CMD_UTILITY)
2031 2404 : continue; /* Ignore utility statements */
2032 39543984 : if ((relid == InvalidOid) ? plannedstmt->relationOids != NIL :
2033 19771992 : list_member_oid(plannedstmt->relationOids, relid))
2034 : {
2035 : /* Invalidate the generic plan only */
2036 52 : plansource->gplan->is_valid = false;
2037 52 : break; /* out of stmt_list scan */
2038 : }
2039 : }
2040 : }
2041 : }
2042 :
2043 : /* Likewise check cached expressions */
2044 2088132 : dlist_foreach(iter, &cached_expression_list)
2045 : {
2046 230990 : CachedExpression *cexpr = dlist_container(CachedExpression,
2047 : node, iter.cur);
2048 :
2049 : Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2050 :
2051 : /* No work if it's already invalidated */
2052 230990 : if (!cexpr->is_valid)
2053 22506 : continue;
2054 :
2055 416968 : if ((relid == InvalidOid) ? cexpr->relationOids != NIL :
2056 208484 : list_member_oid(cexpr->relationOids, relid))
2057 : {
2058 0 : cexpr->is_valid = false;
2059 : }
2060 : }
2061 1857142 : }
2062 :
2063 : /*
2064 : * PlanCacheObjectCallback
2065 : * Syscache inval callback function for PROCOID and TYPEOID caches
2066 : *
2067 : * Invalidate all plans mentioning the object with the specified hash value,
2068 : * or all plans mentioning any member of this cache if hashvalue == 0.
2069 : */
2070 : static void
2071 777816 : PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue)
2072 : {
2073 : dlist_iter iter;
2074 :
2075 17894880 : dlist_foreach(iter, &saved_plan_list)
2076 : {
2077 17117064 : CachedPlanSource *plansource = dlist_container(CachedPlanSource,
2078 : node, iter.cur);
2079 : ListCell *lc;
2080 :
2081 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
2082 :
2083 : /* No work if it's already invalidated */
2084 17117064 : if (!plansource->is_valid)
2085 7839866 : continue;
2086 :
2087 : /* Never invalidate if parse/plan would be a no-op anyway */
2088 9277198 : if (!StmtPlanRequiresRevalidation(plansource))
2089 63094 : continue;
2090 :
2091 : /*
2092 : * Check the dependency list for the rewritten querytree.
2093 : */
2094 9374746 : foreach(lc, plansource->invalItems)
2095 : {
2096 160754 : PlanInvalItem *item = (PlanInvalItem *) lfirst(lc);
2097 :
2098 160754 : if (item->cacheId != cacheid)
2099 100054 : continue;
2100 60700 : if (hashvalue == 0 ||
2101 60700 : item->hashValue == hashvalue)
2102 : {
2103 : /* Invalidate the querytree and generic plan */
2104 112 : plansource->is_valid = false;
2105 112 : if (plansource->gplan)
2106 100 : plansource->gplan->is_valid = false;
2107 112 : break;
2108 : }
2109 : }
2110 :
2111 : /*
2112 : * The generic plan, if any, could have more dependencies than the
2113 : * querytree does, so we have to check it too.
2114 : */
2115 9214104 : if (plansource->gplan && plansource->gplan->is_valid)
2116 : {
2117 17625916 : foreach(lc, plansource->gplan->stmt_list)
2118 : {
2119 8812970 : PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
2120 : ListCell *lc3;
2121 :
2122 8812970 : if (plannedstmt->commandType == CMD_UTILITY)
2123 1330 : continue; /* Ignore utility statements */
2124 8966120 : foreach(lc3, plannedstmt->invalItems)
2125 : {
2126 154504 : PlanInvalItem *item = (PlanInvalItem *) lfirst(lc3);
2127 :
2128 154504 : if (item->cacheId != cacheid)
2129 95668 : continue;
2130 58836 : if (hashvalue == 0 ||
2131 58836 : item->hashValue == hashvalue)
2132 : {
2133 : /* Invalidate the generic plan only */
2134 24 : plansource->gplan->is_valid = false;
2135 24 : break; /* out of invalItems scan */
2136 : }
2137 : }
2138 8811640 : if (!plansource->gplan->is_valid)
2139 24 : break; /* out of stmt_list scan */
2140 : }
2141 : }
2142 : }
2143 :
2144 : /* Likewise check cached expressions */
2145 896560 : dlist_foreach(iter, &cached_expression_list)
2146 : {
2147 118744 : CachedExpression *cexpr = dlist_container(CachedExpression,
2148 : node, iter.cur);
2149 : ListCell *lc;
2150 :
2151 : Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2152 :
2153 : /* No work if it's already invalidated */
2154 118744 : if (!cexpr->is_valid)
2155 10086 : continue;
2156 :
2157 108716 : foreach(lc, cexpr->invalItems)
2158 : {
2159 64 : PlanInvalItem *item = (PlanInvalItem *) lfirst(lc);
2160 :
2161 64 : if (item->cacheId != cacheid)
2162 44 : continue;
2163 20 : if (hashvalue == 0 ||
2164 20 : item->hashValue == hashvalue)
2165 : {
2166 6 : cexpr->is_valid = false;
2167 6 : break;
2168 : }
2169 : }
2170 : }
2171 777816 : }
2172 :
2173 : /*
2174 : * PlanCacheSysCallback
2175 : * Syscache inval callback function for other caches
2176 : *
2177 : * Just invalidate everything...
2178 : */
2179 : static void
2180 49824 : PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
2181 : {
2182 49824 : ResetPlanCache();
2183 49824 : }
2184 :
2185 : /*
2186 : * ResetPlanCache: invalidate all cached plans.
2187 : */
2188 : void
2189 50552 : ResetPlanCache(void)
2190 : {
2191 : dlist_iter iter;
2192 :
2193 251966 : dlist_foreach(iter, &saved_plan_list)
2194 : {
2195 201414 : CachedPlanSource *plansource = dlist_container(CachedPlanSource,
2196 : node, iter.cur);
2197 :
2198 : Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
2199 :
2200 : /* No work if it's already invalidated */
2201 201414 : if (!plansource->is_valid)
2202 186296 : continue;
2203 :
2204 : /*
2205 : * We *must not* mark transaction control statements as invalid,
2206 : * particularly not ROLLBACK, because they may need to be executed in
2207 : * aborted transactions when we can't revalidate them (cf bug #5269).
2208 : * In general there's no point in invalidating statements for which a
2209 : * new parse analysis/rewrite/plan cycle would certainly give the same
2210 : * results.
2211 : */
2212 15118 : if (!StmtPlanRequiresRevalidation(plansource))
2213 6004 : continue;
2214 :
2215 9114 : plansource->is_valid = false;
2216 9114 : if (plansource->gplan)
2217 8444 : plansource->gplan->is_valid = false;
2218 : }
2219 :
2220 : /* Likewise invalidate cached expressions */
2221 51528 : dlist_foreach(iter, &cached_expression_list)
2222 : {
2223 976 : CachedExpression *cexpr = dlist_container(CachedExpression,
2224 : node, iter.cur);
2225 :
2226 : Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2227 :
2228 976 : cexpr->is_valid = false;
2229 : }
2230 50552 : }
2231 :
2232 : /*
2233 : * Release all CachedPlans remembered by 'owner'
2234 : */
2235 : void
2236 15120 : ReleaseAllPlanCacheRefsInOwner(ResourceOwner owner)
2237 : {
2238 15120 : ResourceOwnerReleaseAllOfKind(owner, &planref_resowner_desc);
2239 15120 : }
2240 :
2241 : /* ResourceOwner callbacks */
2242 :
2243 : static void
2244 77098 : ResOwnerReleaseCachedPlan(Datum res)
2245 : {
2246 77098 : ReleaseCachedPlan((CachedPlan *) DatumGetPointer(res), NULL);
2247 77098 : }
|