PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
plancache.c
Go to the documentation of this file.
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 */
96
97/*
98 * This is the head of the backend's list of CachedExpressions.
99 */
101
102static void ReleaseGenericPlan(CachedPlanSource *plansource);
104 QueryEnvironment *queryEnv);
105static bool CheckCachedPlan(CachedPlanSource *plansource);
106static CachedPlan *BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
107 ParamListInfo boundParams, QueryEnvironment *queryEnv);
108static bool choose_custom_plan(CachedPlanSource *plansource,
109 ParamListInfo boundParams);
110static double cached_plan_cost(CachedPlan *plan, bool include_planner);
111static Query *QueryListGetPrimaryStmt(List *stmts);
112static void AcquireExecutorLocks(List *stmt_list, bool acquire);
113static void AcquirePlannerLocks(List *stmt_list, bool acquire);
114static void ScanQueryForLocks(Query *parsetree, bool acquire);
115static bool ScanQueryWalker(Node *node, bool *acquire);
116static TupleDesc PlanCacheComputeResultDesc(List *stmt_list);
117static void PlanCacheRelCallback(Datum arg, Oid relid);
118static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue);
119static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue);
120
121/* ResourceOwner callbacks to track plancache references */
123
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 */
134static inline void
136{
138}
139static inline void
141{
143}
144
145
146/* GUC parameter */
148
149/*
150 * InitPlanCache: initialize module during InitPostgres.
151 *
152 * All we need to do is hook into inval.c's callback lists.
153 */
154void
156{
164 CacheRegisterSyscacheCallback(FOREIGNDATAWRAPPEROID, PlanCacheSysCallback, (Datum) 0);
165}
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 */
192CreateCachedPlan(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 */
210 "CachedPlanSource",
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 oldcxt = MemoryContextSwitchTo(source_context);
218
219 plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
220 plansource->magic = CACHEDPLANSOURCE_MAGIC;
221 plansource->raw_parse_tree = copyObject(raw_parse_tree);
222 plansource->query_string = pstrdup(query_string);
223 MemoryContextSetIdentifier(source_context, plansource->query_string);
224 plansource->commandTag = commandTag;
225 plansource->param_types = NULL;
226 plansource->num_params = 0;
227 plansource->parserSetup = NULL;
228 plansource->parserSetupArg = NULL;
229 plansource->cursor_options = 0;
230 plansource->fixed_result = false;
231 plansource->resultDesc = NULL;
232 plansource->context = source_context;
233 plansource->query_list = NIL;
234 plansource->relationOids = NIL;
235 plansource->invalItems = NIL;
236 plansource->search_path = NULL;
237 plansource->query_context = NULL;
238 plansource->rewriteRoleId = InvalidOid;
239 plansource->rewriteRowSecurity = false;
240 plansource->dependsOnRLS = false;
241 plansource->gplan = NULL;
242 plansource->is_oneshot = false;
243 plansource->is_complete = false;
244 plansource->is_saved = false;
245 plansource->is_valid = false;
246 plansource->generation = 0;
247 plansource->generic_cost = -1;
248 plansource->total_custom_cost = 0;
249 plansource->num_generic_plans = 0;
250 plansource->num_custom_plans = 0;
251
252 MemoryContextSwitchTo(oldcxt);
253
254 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 */
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 plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
289 plansource->magic = CACHEDPLANSOURCE_MAGIC;
290 plansource->raw_parse_tree = raw_parse_tree;
291 plansource->query_string = query_string;
292 plansource->commandTag = commandTag;
293 plansource->param_types = NULL;
294 plansource->num_params = 0;
295 plansource->parserSetup = NULL;
296 plansource->parserSetupArg = NULL;
297 plansource->cursor_options = 0;
298 plansource->fixed_result = false;
299 plansource->resultDesc = NULL;
300 plansource->context = CurrentMemoryContext;
301 plansource->query_list = NIL;
302 plansource->relationOids = NIL;
303 plansource->invalItems = NIL;
304 plansource->search_path = NULL;
305 plansource->query_context = NULL;
306 plansource->rewriteRoleId = InvalidOid;
307 plansource->rewriteRowSecurity = false;
308 plansource->dependsOnRLS = false;
309 plansource->gplan = NULL;
310 plansource->is_oneshot = true;
311 plansource->is_complete = false;
312 plansource->is_saved = false;
313 plansource->is_valid = false;
314 plansource->generation = 0;
315 plansource->generic_cost = -1;
316 plansource->total_custom_cost = 0;
317 plansource->num_generic_plans = 0;
318 plansource->num_custom_plans = 0;
319
320 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 */
365void
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 MemoryContext source_context = plansource->context;
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 if (plansource->is_oneshot)
391 {
392 querytree_context = CurrentMemoryContext;
393 }
394 else if (querytree_context != NULL)
395 {
396 MemoryContextSetParent(querytree_context, source_context);
397 MemoryContextSwitchTo(querytree_context);
398 }
399 else
400 {
401 /* Again, it's a good bet the querytree_context can be small */
402 querytree_context = AllocSetContextCreate(source_context,
403 "CachedPlanQuery",
405 MemoryContextSwitchTo(querytree_context);
406 querytree_list = copyObject(querytree_list);
407 }
408
409 plansource->query_context = querytree_context;
410 plansource->query_list = querytree_list;
411
412 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 extract_query_dependencies((Node *) querytree_list,
421 &plansource->relationOids,
422 &plansource->invalItems,
423 &plansource->dependsOnRLS);
424
425 /* Update RLS info as well. */
426 plansource->rewriteRoleId = GetUserId();
427 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 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 MemoryContextSwitchTo(source_context);
445
446 if (num_params > 0)
447 {
448 plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
449 memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
450 }
451 else
452 plansource->param_types = NULL;
453 plansource->num_params = num_params;
454 plansource->parserSetup = parserSetup;
455 plansource->parserSetupArg = parserSetupArg;
456 plansource->cursor_options = cursor_options;
457 plansource->fixed_result = fixed_result;
458 plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
459
460 MemoryContextSwitchTo(oldcxt);
461
462 plansource->is_complete = true;
463 plansource->is_valid = true;
464}
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 */
481void
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 if (plansource->is_oneshot)
491 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 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 */
508
509 /*
510 * Add the entry to the global list of cached plans.
511 */
512 dlist_push_tail(&saved_plan_list, &plansource->node);
513
514 plansource->is_saved = true;
515}
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 */
525void
527{
528 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
529
530 /* If it's been saved, remove it from the list */
531 if (plansource->is_saved)
532 {
533 dlist_delete(&plansource->node);
534 plansource->is_saved = false;
535 }
536
537 /* Decrement generic CachedPlan's refcount and drop if no longer needed */
538 ReleaseGenericPlan(plansource);
539
540 /* Mark it no longer valid */
541 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 if (!plansource->is_oneshot)
548 MemoryContextDelete(plansource->context);
549}
550
551/*
552 * ReleaseGenericPlan: release a CachedPlanSource's generic plan, if any.
553 */
554static void
556{
557 /* Be paranoid about the possibility that ReleaseCachedPlan fails */
558 if (plansource->gplan)
559 {
560 CachedPlan *plan = plansource->gplan;
561
562 Assert(plan->magic == CACHEDPLAN_MAGIC);
563 plansource->gplan = NULL;
564 ReleaseCachedPlan(plan, NULL);
565 }
566}
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 */
582static List *
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 if (plansource->is_oneshot || !StmtPlanRequiresRevalidation(plansource))
602 {
603 Assert(plansource->is_valid);
604 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 if (plansource->is_valid)
613 {
614 Assert(plansource->search_path != NULL);
616 {
617 /* Invalidate the querytree and generic plan */
618 plansource->is_valid = false;
619 if (plansource->gplan)
620 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 if (plansource->is_valid && plansource->dependsOnRLS &&
629 (plansource->rewriteRoleId != GetUserId() ||
630 plansource->rewriteRowSecurity != row_security))
631 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 if (plansource->is_valid)
639 {
640 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 if (plansource->is_valid)
647 {
648 /* Successfully revalidated and locked the query. */
649 return NIL;
650 }
651
652 /* Oops, the race case happened. Release useless locks. */
653 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 plansource->is_valid = false;
662 plansource->query_list = NIL;
663 plansource->relationOids = NIL;
664 plansource->invalItems = NIL;
665 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 if (plansource->query_context)
674 {
675 MemoryContext qcxt = plansource->query_context;
676
677 plansource->query_context = NULL;
679 }
680
681 /* Drop the generic plan reference if any */
682 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 snapshot_set = false;
698 if (!ActiveSnapshotSet())
699 {
701 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 rawtree = copyObject(plansource->raw_parse_tree);
710 if (rawtree == NULL)
711 tlist = NIL;
712 else if (plansource->parserSetup != NULL)
713 tlist = pg_analyze_and_rewrite_withcb(rawtree,
714 plansource->query_string,
715 plansource->parserSetup,
716 plansource->parserSetupArg,
717 queryEnv);
718 else
720 plansource->query_string,
721 plansource->param_types,
722 plansource->num_params,
723 queryEnv);
724
725 /* Release snapshot if we got one */
726 if (snapshot_set)
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 resultDesc = PlanCacheComputeResultDesc(tlist);
736 if (resultDesc == NULL && plansource->resultDesc == NULL)
737 {
738 /* OK, doesn't return tuples */
739 }
740 else if (resultDesc == NULL || plansource->resultDesc == NULL ||
741 !equalRowTypes(resultDesc, plansource->resultDesc))
742 {
743 /* can we give a better error message? */
744 if (plansource->fixed_result)
746 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
747 errmsg("cached plan must not change result type")));
748 oldcxt = MemoryContextSwitchTo(plansource->context);
749 if (resultDesc)
750 resultDesc = CreateTupleDescCopy(resultDesc);
751 if (plansource->resultDesc)
752 FreeTupleDesc(plansource->resultDesc);
753 plansource->resultDesc = resultDesc;
754 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 */
762 "CachedPlanQuery",
764 oldcxt = MemoryContextSwitchTo(querytree_context);
765
766 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 */
774 &plansource->relationOids,
775 &plansource->invalItems,
776 &plansource->dependsOnRLS);
777
778 /* Update RLS info as well. */
779 plansource->rewriteRoleId = GetUserId();
780 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 plansource->search_path = GetSearchPathMatcher(querytree_context);
788
789 MemoryContextSwitchTo(oldcxt);
790
791 /* Now reparent the finished query_context and save the links */
792 MemoryContextSetParent(querytree_context, plansource->context);
793
794 plansource->query_context = querytree_context;
795 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 plansource->is_valid = true;
807
808 /* Return transient copy of querytrees for possible use in planning */
809 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 */
821static bool
823{
824 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 if (!plan)
831 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 if (plan->is_valid && plan->dependsOnRole &&
841 plan->planRoleId != GetUserId())
842 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 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 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 if (plan->is_valid &&
863 TransactionIdIsValid(plan->saved_xmin) &&
865 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 if (plan->is_valid)
872 {
873 /* Successfully revalidated and locked the query. */
874 return true;
875 }
876
877 /* Oops, the race case happened. Release useless locks. */
878 AcquireExecutorLocks(plan->stmt_list, false);
879 }
880
881 /*
882 * Plan has been invalidated, so unlink it from the parent and release it.
883 */
884 ReleaseGenericPlan(plansource);
885
886 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 */
905static CachedPlan *
907 ParamListInfo boundParams, QueryEnvironment *queryEnv)
908{
910 List *plist;
911 bool snapshot_set;
912 bool is_transient;
913 MemoryContext plan_context;
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 if (!plansource->is_valid)
931 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 if (qlist == NIL)
939 {
940 if (!plansource->is_oneshot)
941 qlist = copyObject(plansource->query_list);
942 else
943 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 snapshot_set = false;
951 if (!ActiveSnapshotSet() &&
952 plansource->raw_parse_tree &&
954 {
956 snapshot_set = true;
957 }
958
959 /*
960 * Generate the plan.
961 */
962 plist = pg_plan_queries(qlist, plansource->query_string,
963 plansource->cursor_options, boundParams);
964
965 /* Release snapshot if we got one */
966 if (snapshot_set)
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 if (!plansource->is_oneshot)
976 {
978 "CachedPlan",
980 MemoryContextCopyAndSetIdentifier(plan_context, plansource->query_string);
981
982 /*
983 * Copy plan into the new context.
984 */
985 MemoryContextSwitchTo(plan_context);
986
987 plist = copyObject(plist);
988 }
989 else
990 plan_context = CurrentMemoryContext;
991
992 /*
993 * Create and fill the CachedPlan struct within the new context.
994 */
995 plan = (CachedPlan *) palloc(sizeof(CachedPlan));
996 plan->magic = CACHEDPLAN_MAGIC;
997 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 plan->planRoleId = GetUserId();
1005 plan->dependsOnRole = plansource->dependsOnRLS;
1006 is_transient = false;
1007 foreach(lc, plist)
1008 {
1009 PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
1010
1011 if (plannedstmt->commandType == CMD_UTILITY)
1012 continue; /* Ignore utility statements */
1013
1014 if (plannedstmt->transientPlan)
1015 is_transient = true;
1016 if (plannedstmt->dependsOnRole)
1017 plan->dependsOnRole = true;
1018 }
1019 if (is_transient)
1020 {
1022 plan->saved_xmin = TransactionXmin;
1023 }
1024 else
1025 plan->saved_xmin = InvalidTransactionId;
1026 plan->refcount = 0;
1027 plan->context = plan_context;
1028 plan->is_oneshot = plansource->is_oneshot;
1029 plan->is_saved = false;
1030 plan->is_valid = true;
1031
1032 /* assign generation number to new plan */
1033 plan->generation = ++(plansource->generation);
1034
1035 MemoryContextSwitchTo(oldcxt);
1036
1037 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 */
1045static bool
1047{
1048 double avg_custom_cost;
1049
1050 /* One-shot plans will always be considered custom */
1051 if (plansource->is_oneshot)
1052 return true;
1053
1054 /* Otherwise, never any point in a custom plan if there's no parameters */
1055 if (boundParams == NULL)
1056 return false;
1057 /* ... nor when planning would be a no-op */
1058 if (!StmtPlanRequiresRevalidation(plansource))
1059 return false;
1060
1061 /* Let settings force the decision */
1063 return false;
1065 return true;
1066
1067 /* See if caller wants to force the decision */
1068 if (plansource->cursor_options & CURSOR_OPT_GENERIC_PLAN)
1069 return false;
1070 if (plansource->cursor_options & CURSOR_OPT_CUSTOM_PLAN)
1071 return true;
1072
1073 /* Generate custom plans until we have done at least 5 (arbitrary) */
1074 if (plansource->num_custom_plans < 5)
1075 return true;
1076
1077 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 if (plansource->generic_cost < avg_custom_cost)
1090 return false;
1091
1092 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 */
1102static double
1103cached_plan_cost(CachedPlan *plan, bool include_planner)
1104{
1105 double result = 0;
1106 ListCell *lc;
1107
1108 foreach(lc, plan->stmt_list)
1109 {
1110 PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
1111
1112 if (plannedstmt->commandType == CMD_UTILITY)
1113 continue; /* Ignore utility statements */
1114
1115 result += plannedstmt->planTree->total_cost;
1116
1117 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 int nrelations = list_length(plannedstmt->rtable);
1141
1142 result += 1000.0 * cpu_operator_cost * (nrelations + 1);
1143 }
1144 }
1145
1146 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 */
1167CachedPlan *
1169 ResourceOwner owner, QueryEnvironment *queryEnv)
1170{
1171 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 if (owner && !plansource->is_saved)
1180 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 qlist = RevalidateCachedQuery(plansource, queryEnv);
1184
1185 /* Decide whether to use a custom plan */
1186 customplan = choose_custom_plan(plansource, boundParams);
1187
1188 if (!customplan)
1189 {
1190 if (CheckCachedPlan(plansource))
1191 {
1192 /* We want a generic plan, and we already have a valid one */
1193 plan = plansource->gplan;
1194 Assert(plan->magic == CACHEDPLAN_MAGIC);
1195 }
1196 else
1197 {
1198 /* Build a new generic plan */
1199 plan = BuildCachedPlan(plansource, qlist, NULL, queryEnv);
1200 /* Just make real sure plansource->gplan is clear */
1201 ReleaseGenericPlan(plansource);
1202 /* Link the new generic plan into the plansource */
1203 plansource->gplan = plan;
1204 plan->refcount++;
1205 /* Immediately reparent into appropriate context */
1206 if (plansource->is_saved)
1207 {
1208 /* saved plans all live under CacheMemoryContext */
1210 plan->is_saved = true;
1211 }
1212 else
1213 {
1214 /* otherwise, it should be a sibling of the plansource */
1216 MemoryContextGetParent(plansource->context));
1217 }
1218 /* Update generic_cost whenever we make a new generic plan */
1219 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 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 qlist = NIL;
1238 }
1239 }
1240
1241 if (customplan)
1242 {
1243 /* Build a custom plan */
1244 plan = BuildCachedPlan(plansource, qlist, boundParams, queryEnv);
1245 /* Accumulate total costs of custom plans */
1246 plansource->total_custom_cost += cached_plan_cost(plan, true);
1247
1248 plansource->num_custom_plans++;
1249 }
1250 else
1251 {
1252 plansource->num_generic_plans++;
1253 }
1254
1255 Assert(plan != NULL);
1256
1257 /* Flag the plan as in use by caller */
1258 if (owner)
1259 ResourceOwnerEnlarge(owner);
1260 plan->refcount++;
1261 if (owner)
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 if (customplan && plansource->is_saved)
1271 {
1273 plan->is_saved = true;
1274 }
1275
1276 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 */
1290void
1292{
1293 Assert(plan->magic == CACHEDPLAN_MAGIC);
1294 if (owner)
1295 {
1296 Assert(plan->is_saved);
1298 }
1299 Assert(plan->refcount > 0);
1300 plan->refcount--;
1301 if (plan->refcount == 0)
1302 {
1303 /* Mark it no longer valid */
1304 plan->magic = 0;
1305
1306 /* One-shot plans do not own their context, so we can't free them */
1307 if (!plan->is_oneshot)
1308 MemoryContextDelete(plan->context);
1309 }
1310}
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 */
1335bool
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);
1355
1356 /* We don't support oneshot plans here. */
1357 if (plansource->is_oneshot)
1358 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 if (plansource->dependsOnRLS)
1367 return false;
1368 if (plan->dependsOnRole)
1369 return false;
1370 if (TransactionIdIsValid(plan->saved_xmin))
1371 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 foreach(lc, plansource->query_list)
1380 {
1381 Query *query = lfirst_node(Query, lc);
1382
1383 if (query->commandType == CMD_UTILITY)
1384 return false;
1385 if (query->rtable || query->cteList || query->hasSubLinks)
1386 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 foreach(lc, plan->stmt_list)
1394 {
1395 PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
1396 ListCell *lc2;
1397
1398 if (plannedstmt->commandType == CMD_UTILITY)
1399 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 foreach(lc2, plannedstmt->rtable)
1406 {
1407 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
1408
1409 if (rte->rtekind == RTE_RELATION)
1410 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 if (owner)
1421 {
1422 ResourceOwnerEnlarge(owner);
1423 plan->refcount++;
1425 }
1426
1427 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 */
1450bool
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 if (!plansource->is_valid ||
1469 plan == NULL || plan != plansource->gplan ||
1470 !plan->is_valid)
1471 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);
1478 return false;
1479
1480 /* It's still good. Bump refcount if requested. */
1481 if (owner)
1482 {
1483 ResourceOwnerEnlarge(owner);
1484 plan->refcount++;
1486 }
1487
1488 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 */
1497void
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 if (plansource->is_saved)
1507 elog(ERROR, "cannot move a saved cached plan to another context");
1508 if (plansource->is_oneshot)
1509 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 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 if (plansource->gplan)
1520 {
1521 Assert(plansource->gplan->magic == CACHEDPLAN_MAGIC);
1522 MemoryContextSetParent(plansource->gplan->context, newcontext);
1523 }
1524}
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 */
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 if (plansource->is_oneshot)
1551 elog(ERROR, "cannot copy a one-shot cached plan");
1552
1554 "CachedPlanSource",
1556
1557 oldcxt = MemoryContextSwitchTo(source_context);
1558
1559 newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1560 newsource->magic = CACHEDPLANSOURCE_MAGIC;
1561 newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
1562 newsource->query_string = pstrdup(plansource->query_string);
1563 MemoryContextSetIdentifier(source_context, newsource->query_string);
1564 newsource->commandTag = plansource->commandTag;
1565 if (plansource->num_params > 0)
1566 {
1567 newsource->param_types = (Oid *)
1568 palloc(plansource->num_params * sizeof(Oid));
1569 memcpy(newsource->param_types, plansource->param_types,
1570 plansource->num_params * sizeof(Oid));
1571 }
1572 else
1573 newsource->param_types = NULL;
1574 newsource->num_params = plansource->num_params;
1575 newsource->parserSetup = plansource->parserSetup;
1576 newsource->parserSetupArg = plansource->parserSetupArg;
1577 newsource->cursor_options = plansource->cursor_options;
1578 newsource->fixed_result = plansource->fixed_result;
1579 if (plansource->resultDesc)
1580 newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
1581 else
1582 newsource->resultDesc = NULL;
1583 newsource->context = source_context;
1584
1585 querytree_context = AllocSetContextCreate(source_context,
1586 "CachedPlanQuery",
1588 MemoryContextSwitchTo(querytree_context);
1589 newsource->query_list = copyObject(plansource->query_list);
1590 newsource->relationOids = copyObject(plansource->relationOids);
1591 newsource->invalItems = copyObject(plansource->invalItems);
1592 if (plansource->search_path)
1593 newsource->search_path = CopySearchPathMatcher(plansource->search_path);
1594 newsource->query_context = querytree_context;
1595 newsource->rewriteRoleId = plansource->rewriteRoleId;
1596 newsource->rewriteRowSecurity = plansource->rewriteRowSecurity;
1597 newsource->dependsOnRLS = plansource->dependsOnRLS;
1598
1599 newsource->gplan = NULL;
1600
1601 newsource->is_oneshot = false;
1602 newsource->is_complete = true;
1603 newsource->is_saved = false;
1604 newsource->is_valid = plansource->is_valid;
1605 newsource->generation = plansource->generation;
1606
1607 /* We may as well copy any acquired cost knowledge */
1608 newsource->generic_cost = plansource->generic_cost;
1609 newsource->total_custom_cost = plansource->total_custom_cost;
1610 newsource->num_generic_plans = plansource->num_generic_plans;
1611 newsource->num_custom_plans = plansource->num_custom_plans;
1612
1613 MemoryContextSwitchTo(oldcxt);
1614
1615 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 */
1626bool
1628{
1629 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1630 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 */
1639List *
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 if (plansource->resultDesc == NULL)
1654 return NIL;
1655
1656 /* Make sure the querytree list is valid and we have parse-time locks */
1657 RevalidateCachedQuery(plansource, queryEnv);
1658
1659 /* Get the primary statement and find out what it returns */
1660 pstmt = QueryListGetPrimaryStmt(plansource->query_list);
1661
1662 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 */
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 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 */
1700 "CachedExpression",
1702
1703 oldcxt = MemoryContextSwitchTo(cexpr_context);
1704
1705 cexpr = (CachedExpression *) palloc(sizeof(CachedExpression));
1706 cexpr->magic = CACHEDEXPR_MAGIC;
1707 cexpr->expr = copyObject(expr);
1708 cexpr->is_valid = true;
1709 cexpr->relationOids = copyObject(relationOids);
1710 cexpr->invalItems = copyObject(invalItems);
1711 cexpr->context = cexpr_context;
1712
1713 MemoryContextSwitchTo(oldcxt);
1714
1715 /*
1716 * Reparent the expr's memory context under CacheMemoryContext so that it
1717 * will live indefinitely.
1718 */
1720
1721 /*
1722 * Add the entry to the global list of cached expressions.
1723 */
1725
1726 return cexpr;
1727}
1728
1729/*
1730 * FreeCachedExpression
1731 * Delete a CachedExpression.
1732 */
1733void
1735{
1736 /* Sanity check */
1737 Assert(cexpr->magic == CACHEDEXPR_MAGIC);
1738 /* Unlink from global list */
1739 dlist_delete(&cexpr->node);
1740 /* Free all storage associated with CachedExpression */
1742}
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 */
1752static Query *
1754{
1755 ListCell *lc;
1756
1757 foreach(lc, stmts)
1758 {
1759 Query *stmt = lfirst_node(Query, lc);
1760
1761 if (stmt->canSetTag)
1762 return stmt;
1763 }
1764 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 */
1771static void
1772AcquireExecutorLocks(List *stmt_list, bool acquire)
1773{
1774 ListCell *lc1;
1775
1776 foreach(lc1, stmt_list)
1777 {
1778 PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc1);
1779 ListCell *lc2;
1780
1781 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 Query *query = UtilityContainsQuery(plannedstmt->utilityStmt);
1791
1792 if (query)
1793 ScanQueryForLocks(query, acquire);
1794 continue;
1795 }
1796
1797 foreach(lc2, plannedstmt->rtable)
1798 {
1799 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
1800
1801 if (!(rte->rtekind == RTE_RELATION ||
1802 (rte->rtekind == RTE_SUBQUERY && OidIsValid(rte->relid))))
1803 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 if (acquire)
1812 LockRelationOid(rte->relid, rte->rellockmode);
1813 else
1814 UnlockRelationOid(rte->relid, rte->rellockmode);
1815 }
1816 }
1817}
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 */
1827static void
1828AcquirePlannerLocks(List *stmt_list, bool acquire)
1829{
1830 ListCell *lc;
1831
1832 foreach(lc, stmt_list)
1833 {
1834 Query *query = lfirst_node(Query, lc);
1835
1836 if (query->commandType == CMD_UTILITY)
1837 {
1838 /* Ignore utility statements, unless they contain a Query */
1839 query = UtilityContainsQuery(query->utilityStmt);
1840 if (query)
1841 ScanQueryForLocks(query, acquire);
1842 continue;
1843 }
1844
1845 ScanQueryForLocks(query, acquire);
1846 }
1847}
1848
1849/*
1850 * ScanQueryForLocks: recursively scan one Query for AcquirePlannerLocks.
1851 */
1852static void
1853ScanQueryForLocks(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 foreach(lc, parsetree->rtable)
1864 {
1865 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
1866
1867 switch (rte->rtekind)
1868 {
1869 case RTE_RELATION:
1870 /* Acquire or release the appropriate type of lock */
1871 if (acquire)
1872 LockRelationOid(rte->relid, rte->rellockmode);
1873 else
1874 UnlockRelationOid(rte->relid, rte->rellockmode);
1875 break;
1876
1877 case RTE_SUBQUERY:
1878 /* If this was a view, must lock/unlock the view */
1879 if (OidIsValid(rte->relid))
1880 {
1881 if (acquire)
1882 LockRelationOid(rte->relid, rte->rellockmode);
1883 else
1884 UnlockRelationOid(rte->relid, rte->rellockmode);
1885 }
1886 /* Recurse into subquery-in-FROM */
1887 ScanQueryForLocks(rte->subquery, acquire);
1888 break;
1889
1890 default:
1891 /* ignore other types of RTEs */
1892 break;
1893 }
1894 }
1895
1896 /* Recurse into subquery-in-WITH */
1897 foreach(lc, parsetree->cteList)
1898 {
1900
1901 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 if (parsetree->hasSubLinks)
1909 {
1910 query_tree_walker(parsetree, ScanQueryWalker, &acquire,
1912 }
1913}
1914
1915/*
1916 * Walker to find sublink subqueries for ScanQueryForLocks
1917 */
1918static bool
1919ScanQueryWalker(Node *node, bool *acquire)
1920{
1921 if (node == NULL)
1922 return false;
1923 if (IsA(node, SubLink))
1924 {
1925 SubLink *sub = (SubLink *) node;
1926
1927 /* Do what we came for */
1928 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 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 */
1946static TupleDesc
1948{
1949 Query *query;
1950
1951 switch (ChoosePortalStrategy(stmt_list))
1952 {
1953 case PORTAL_ONE_SELECT:
1955 query = linitial_node(Query, stmt_list);
1956 return ExecCleanTypeFromTL(query->targetList);
1957
1959 query = QueryListGetPrimaryStmt(stmt_list);
1960 Assert(query->returningList);
1961 return ExecCleanTypeFromTL(query->returningList);
1962
1963 case PORTAL_UTIL_SELECT:
1964 query = linitial_node(Query, stmt_list);
1965 Assert(query->utilityStmt);
1966 return UtilityTupleDescriptor(query->utilityStmt);
1967
1968 case PORTAL_MULTI_QUERY:
1969 /* will not return tuples */
1970 break;
1971 }
1972 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 */
1982static void
1984{
1985 dlist_iter iter;
1986
1988 {
1990 node, iter.cur);
1991
1992 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1993
1994 /* No work if it's already invalidated */
1995 if (!plansource->is_valid)
1996 continue;
1997
1998 /* Never invalidate if parse/plan would be a no-op anyway */
1999 if (!StmtPlanRequiresRevalidation(plansource))
2000 continue;
2001
2002 /*
2003 * Check the dependency list for the rewritten querytree.
2004 */
2005 if ((relid == InvalidOid) ? plansource->relationOids != NIL :
2006 list_member_oid(plansource->relationOids, relid))
2007 {
2008 /* Invalidate the querytree and generic plan */
2009 plansource->is_valid = false;
2010 if (plansource->gplan)
2011 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 if (plansource->gplan && plansource->gplan->is_valid)
2019 {
2020 ListCell *lc;
2021
2022 foreach(lc, plansource->gplan->stmt_list)
2023 {
2024 PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
2025
2026 if (plannedstmt->commandType == CMD_UTILITY)
2027 continue; /* Ignore utility statements */
2028 if ((relid == InvalidOid) ? plannedstmt->relationOids != NIL :
2029 list_member_oid(plannedstmt->relationOids, relid))
2030 {
2031 /* Invalidate the generic plan only */
2032 plansource->gplan->is_valid = false;
2033 break; /* out of stmt_list scan */
2034 }
2035 }
2036 }
2037 }
2038
2039 /* Likewise check cached expressions */
2041 {
2043 node, iter.cur);
2044
2045 Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2046
2047 /* No work if it's already invalidated */
2048 if (!cexpr->is_valid)
2049 continue;
2050
2051 if ((relid == InvalidOid) ? cexpr->relationOids != NIL :
2052 list_member_oid(cexpr->relationOids, relid))
2053 {
2054 cexpr->is_valid = false;
2055 }
2056 }
2057}
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 */
2066static void
2067PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue)
2068{
2069 dlist_iter iter;
2070
2072 {
2074 node, iter.cur);
2075 ListCell *lc;
2076
2077 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
2078
2079 /* No work if it's already invalidated */
2080 if (!plansource->is_valid)
2081 continue;
2082
2083 /* Never invalidate if parse/plan would be a no-op anyway */
2084 if (!StmtPlanRequiresRevalidation(plansource))
2085 continue;
2086
2087 /*
2088 * Check the dependency list for the rewritten querytree.
2089 */
2090 foreach(lc, plansource->invalItems)
2091 {
2092 PlanInvalItem *item = (PlanInvalItem *) lfirst(lc);
2093
2094 if (item->cacheId != cacheid)
2095 continue;
2096 if (hashvalue == 0 ||
2097 item->hashValue == hashvalue)
2098 {
2099 /* Invalidate the querytree and generic plan */
2100 plansource->is_valid = false;
2101 if (plansource->gplan)
2102 plansource->gplan->is_valid = false;
2103 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 if (plansource->gplan && plansource->gplan->is_valid)
2112 {
2113 foreach(lc, plansource->gplan->stmt_list)
2114 {
2115 PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
2116 ListCell *lc3;
2117
2118 if (plannedstmt->commandType == CMD_UTILITY)
2119 continue; /* Ignore utility statements */
2120 foreach(lc3, plannedstmt->invalItems)
2121 {
2122 PlanInvalItem *item = (PlanInvalItem *) lfirst(lc3);
2123
2124 if (item->cacheId != cacheid)
2125 continue;
2126 if (hashvalue == 0 ||
2127 item->hashValue == hashvalue)
2128 {
2129 /* Invalidate the generic plan only */
2130 plansource->gplan->is_valid = false;
2131 break; /* out of invalItems scan */
2132 }
2133 }
2134 if (!plansource->gplan->is_valid)
2135 break; /* out of stmt_list scan */
2136 }
2137 }
2138 }
2139
2140 /* Likewise check cached expressions */
2142 {
2144 node, iter.cur);
2145 ListCell *lc;
2146
2147 Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2148
2149 /* No work if it's already invalidated */
2150 if (!cexpr->is_valid)
2151 continue;
2152
2153 foreach(lc, cexpr->invalItems)
2154 {
2155 PlanInvalItem *item = (PlanInvalItem *) lfirst(lc);
2156
2157 if (item->cacheId != cacheid)
2158 continue;
2159 if (hashvalue == 0 ||
2160 item->hashValue == hashvalue)
2161 {
2162 cexpr->is_valid = false;
2163 break;
2164 }
2165 }
2166 }
2167}
2168
2169/*
2170 * PlanCacheSysCallback
2171 * Syscache inval callback function for other caches
2172 *
2173 * Just invalidate everything...
2174 */
2175static void
2176PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
2177{
2179}
2180
2181/*
2182 * ResetPlanCache: invalidate all cached plans.
2183 */
2184void
2186{
2187 dlist_iter iter;
2188
2190 {
2192 node, iter.cur);
2193
2194 Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
2195
2196 /* No work if it's already invalidated */
2197 if (!plansource->is_valid)
2198 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 if (!StmtPlanRequiresRevalidation(plansource))
2209 continue;
2210
2211 plansource->is_valid = false;
2212 if (plansource->gplan)
2213 plansource->gplan->is_valid = false;
2214 }
2215
2216 /* Likewise invalidate cached expressions */
2218 {
2220 node, iter.cur);
2221
2222 Assert(cexpr->magic == CACHEDEXPR_MAGIC);
2223
2224 cexpr->is_valid = false;
2225 }
2226}
2227
2228/*
2229 * Release all CachedPlans remembered by 'owner'
2230 */
2231void
2233{
2235}
2236
2237/* ResourceOwner callbacks */
2238
2239static void
2241{
2243}
#define Assert(condition)
Definition: c.h:812
uint32_t uint32
Definition: c.h:485
#define OidIsValid(objectId)
Definition: c.h:729
CommandTag
Definition: cmdtag.h:23
double cpu_operator_cost
Definition: costsize.c:134
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
TupleDesc ExecCleanTypeFromTL(List *targetList)
Definition: execTuples.c:2137
bool row_security
Definition: guc_tables.c:510
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364
#define DLIST_STATIC_INIT(name)
Definition: ilist.h:281
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
#define stmt
Definition: indent_codes.h:59
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1746
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1704
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:722
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:226
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:637
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:731
MemoryContext CacheMemoryContext
Definition: mcxt.c:152
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
Definition: mcxt.c:612
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:177
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:170
#define MemoryContextCopyAndSetIdentifier(cxt, id)
Definition: memutils.h:101
Oid GetUserId(void)
Definition: miscinit.c:517
SearchPathMatcher * GetSearchPathMatcher(MemoryContext context)
Definition: namespace.c:3852
bool SearchPathMatchesCurrentEnvironment(SearchPathMatcher *path)
Definition: namespace.c:3911
SearchPathMatcher * CopySearchPathMatcher(SearchPathMatcher *path)
Definition: namespace.c:3889
#define query_tree_walker(q, w, c, f)
Definition: nodeFuncs.h:158
#define expression_tree_walker(n, w, c)
Definition: nodeFuncs.h:153
#define QTW_IGNORE_RC_SUBQUERIES
Definition: nodeFuncs.h:24
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define copyObject(obj)
Definition: nodes.h:224
@ CMD_UTILITY
Definition: nodes.h:270
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
Definition: params.h:108
@ RTE_SUBQUERY
Definition: parsenodes.h:1018
@ RTE_RELATION
Definition: parsenodes.h:1017
#define CURSOR_OPT_GENERIC_PLAN
Definition: parsenodes.h:3315
#define CURSOR_OPT_CUSTOM_PLAN
Definition: parsenodes.h:3316
bool analyze_requires_snapshot(RawStmt *parseTree)
Definition: analyze.c:576
void * arg
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial_node(type, l)
Definition: pg_list.h:181
#define NIL
Definition: pg_list.h:68
#define plan(x)
Definition: pg_regress.c:161
void CachedPlanSetParentContext(CachedPlanSource *plansource, MemoryContext newcontext)
Definition: plancache.c:1498
bool CachedPlanIsValid(CachedPlanSource *plansource)
Definition: plancache.c:1627
static dlist_head cached_expression_list
Definition: plancache.c:100
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:526
static bool choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams)
Definition: plancache.c:1046
bool CachedPlanAllowsSimpleValidityCheck(CachedPlanSource *plansource, CachedPlan *plan, ResourceOwner owner)
Definition: plancache.c:1336
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:555
static CachedPlan * BuildCachedPlan(CachedPlanSource *plansource, List *qlist, ParamListInfo boundParams, QueryEnvironment *queryEnv)
Definition: plancache.c:906
static bool CheckCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:822
int plan_cache_mode
Definition: plancache.c:147
void FreeCachedExpression(CachedExpression *cexpr)
Definition: plancache.c:1734
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:482
void CompleteCachedPlan(CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, Oid *param_types, int num_params, ParserSetupHook parserSetup, void *parserSetupArg, int cursor_options, bool fixed_result)
Definition: plancache.c:366
static void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: plancache.c:135
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition: plancache.c:1168
CachedExpression * GetCachedExpression(Node *expr)
Definition: plancache.c:1677
bool CachedPlanIsSimplyValid(CachedPlanSource *plansource, CachedPlan *plan, ResourceOwner owner)
Definition: plancache.c:1451
CachedPlanSource * CreateOneShotCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
Definition: plancache.c:276
static bool ScanQueryWalker(Node *node, bool *acquire)
Definition: plancache.c:1919
static const ResourceOwnerDesc planref_resowner_desc
Definition: plancache.c:124
static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:2176
static List * RevalidateCachedQuery(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:583
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
Definition: plancache.c:192
static void PlanCacheObjectCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:2067
List * CachedPlanGetTargetList(CachedPlanSource *plansource, QueryEnvironment *queryEnv)
Definition: plancache.c:1640
CachedPlanSource * CopyCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:1536
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
Definition: plancache.c:1291
static TupleDesc PlanCacheComputeResultDesc(List *stmt_list)
Definition: plancache.c:1947
static dlist_head saved_plan_list
Definition: plancache.c:95
void InitPlanCache(void)
Definition: plancache.c:155
static void AcquirePlannerLocks(List *stmt_list, bool acquire)
Definition: plancache.c:1828
static void ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: plancache.c:140
static double cached_plan_cost(CachedPlan *plan, bool include_planner)
Definition: plancache.c:1103
static void ResOwnerReleaseCachedPlan(Datum res)
Definition: plancache.c:2240
static void ScanQueryForLocks(Query *parsetree, bool acquire)
Definition: plancache.c:1853
void ReleaseAllPlanCacheRefsInOwner(ResourceOwner owner)
Definition: plancache.c:2232
void ResetPlanCache(void)
Definition: plancache.c:2185
static void PlanCacheRelCallback(Datum arg, Oid relid)
Definition: plancache.c:1983
static Query * QueryListGetPrimaryStmt(List *stmts)
Definition: plancache.c:1753
#define StmtPlanRequiresRevalidation(plansource)
Definition: plancache.c:85
static void AcquireExecutorLocks(List *stmt_list, bool acquire)
Definition: plancache.c:1772
#define CACHEDPLAN_MAGIC
Definition: plancache.h:41
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:40
#define CACHEDEXPR_MAGIC
Definition: plancache.h:42
@ PLAN_CACHE_MODE_FORCE_CUSTOM_PLAN
Definition: plancache.h:34
@ PLAN_CACHE_MODE_FORCE_GENERIC_PLAN
Definition: plancache.h:33
@ PLAN_CACHE_MODE_AUTO
Definition: plancache.h:32
Expr * expression_planner_with_deps(Expr *expr, List **relationOids, List **invalItems)
Definition: planner.c:6597
@ PORTAL_ONE_RETURNING
Definition: portal.h:92
@ PORTAL_MULTI_QUERY
Definition: portal.h:95
@ PORTAL_ONE_SELECT
Definition: portal.h:91
@ PORTAL_ONE_MOD_WITH
Definition: portal.h:93
@ PORTAL_UTIL_SELECT
Definition: portal.h:94
List * pg_analyze_and_rewrite_withcb(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:757
List * pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:969
List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:664
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
PortalStrategy ChoosePortalStrategy(List *stmts)
Definition: pquery.c:209
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:348
MemoryContextSwitchTo(old_ctx)
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:554
void ResourceOwnerReleaseAllOfKind(ResourceOwner owner, const ResourceOwnerDesc *kind)
Definition: resowner.c:801
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:514
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442
#define RELEASE_PRIO_PLANCACHE_REFS
Definition: resowner.h:73
@ RESOURCE_RELEASE_AFTER_LOCKS
Definition: resowner.h:56
void extract_query_dependencies(Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
Definition: setrefs.c:3557
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:212
void PushActiveSnapshot(Snapshot snapshot)
Definition: snapmgr.c:610
TransactionId TransactionXmin
Definition: snapmgr.c:99
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:740
void PopActiveSnapshot(void)
Definition: snapmgr.c:703
List * relationOids
Definition: plancache.h:181
MemoryContext context
Definition: plancache.h:183
dlist_node node
Definition: plancache.h:184
List * invalItems
Definition: plancache.h:182
dlist_node node
Definition: plancache.h:129
struct CachedPlan * gplan
Definition: plancache.h:121
struct SearchPathMatcher * search_path
Definition: plancache.h:114
MemoryContext query_context
Definition: plancache.h:116
CommandTag commandTag
Definition: plancache.h:101
double total_custom_cost
Definition: plancache.h:132
MemoryContext context
Definition: plancache.h:109
List * invalItems
Definition: plancache.h:113
const char * query_string
Definition: plancache.h:100
ParserSetupHook parserSetup
Definition: plancache.h:104
struct RawStmt * raw_parse_tree
Definition: plancache.h:99
TupleDesc resultDesc
Definition: plancache.h:108
int64 num_custom_plans
Definition: plancache.h:133
int64 num_generic_plans
Definition: plancache.h:134
bool rewriteRowSecurity
Definition: plancache.h:118
List * query_list
Definition: plancache.h:111
List * relationOids
Definition: plancache.h:112
double generic_cost
Definition: plancache.h:131
void * parserSetupArg
Definition: plancache.h:105
bool is_valid
Definition: plancache.h:153
MemoryContext context
Definition: plancache.h:160
List * stmt_list
Definition: plancache.h:150
Definition: pg_list.h:54
Definition: nodes.h:129
uint32 hashValue
Definition: plannodes.h:1571
Cost total_cost
Definition: plannodes.h:130
struct Plan * planTree
Definition: plannodes.h:70
List * invalItems
Definition: plannodes.h:91
bool transientPlan
Definition: plannodes.h:62
List * relationOids
Definition: plannodes.h:89
bool dependsOnRole
Definition: plannodes.h:64
CmdType commandType
Definition: plannodes.h:52
Node * utilityStmt
Definition: plannodes.h:95
List * rtable
Definition: plannodes.h:72
List * returningList
Definition: parsenodes.h:200
List * cteList
Definition: parsenodes.h:168
List * rtable
Definition: parsenodes.h:170
CmdType commandType
Definition: parsenodes.h:121
Node * utilityStmt
Definition: parsenodes.h:136
List * targetList
Definition: parsenodes.h:193
Query * subquery
Definition: parsenodes.h:1104
RTEKind rtekind
Definition: parsenodes.h:1047
const char * name
Definition: resowner.h:93
dlist_node * cur
Definition: ilist.h:179
#define InvalidTransactionId
Definition: transam.h:31
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:478
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:235
bool equalRowTypes(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:732
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:2179
TupleDesc UtilityTupleDescriptor(Node *parsetree)
Definition: utility.c:2084