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