PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 and
31  * user-defined functions. On relcache invalidation events or pg_proc
32  * syscache invalidation events, we invalidate just those plans that depend
33  * on the particular object being modified. (Note: this scheme assumes
34  * that any table modification that requires replanning will generate a
35  * relcache inval event.) We also watch for inval events on certain other
36  * system catalogs, such as pg_namespace; but for them, our response is
37  * just to invalidate all plans. We expect updates on those catalogs to
38  * be infrequent enough that more-detailed tracking is not worth the effort.
39  *
40  *
41  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
42  * Portions Copyright (c) 1994, Regents of the University of California
43  *
44  * IDENTIFICATION
45  * src/backend/utils/cache/plancache.c
46  *
47  *-------------------------------------------------------------------------
48  */
49 #include "postgres.h"
50 
51 #include <limits.h>
52 
53 #include "access/transam.h"
54 #include "catalog/namespace.h"
55 #include "executor/executor.h"
56 #include "miscadmin.h"
57 #include "nodes/nodeFuncs.h"
58 #include "optimizer/cost.h"
59 #include "optimizer/planmain.h"
60 #include "optimizer/prep.h"
61 #include "parser/analyze.h"
62 #include "parser/parsetree.h"
63 #include "storage/lmgr.h"
64 #include "tcop/pquery.h"
65 #include "tcop/utility.h"
66 #include "utils/inval.h"
67 #include "utils/memutils.h"
68 #include "utils/resowner_private.h"
69 #include "utils/rls.h"
70 #include "utils/snapmgr.h"
71 #include "utils/syscache.h"
72 
73 
74 /*
75  * We must skip "overhead" operations that involve database access when the
76  * cached plan's subject statement is a transaction control command.
77  */
78 #define IsTransactionStmtPlan(plansource) \
79  ((plansource)->raw_parse_tree && \
80  IsA((plansource)->raw_parse_tree->stmt, TransactionStmt))
81 
82 /*
83  * This is the head of the backend's list of "saved" CachedPlanSources (i.e.,
84  * those that are in long-lived storage and are examined for sinval events).
85  * We thread the structs manually instead of using List cells so that we can
86  * guarantee to save a CachedPlanSource without error.
87  */
89 
90 static void ReleaseGenericPlan(CachedPlanSource *plansource);
91 static List *RevalidateCachedQuery(CachedPlanSource *plansource);
92 static bool CheckCachedPlan(CachedPlanSource *plansource);
93 static CachedPlan *BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
94  ParamListInfo boundParams);
95 static bool choose_custom_plan(CachedPlanSource *plansource,
96  ParamListInfo boundParams);
97 static double cached_plan_cost(CachedPlan *plan, bool include_planner);
98 static Query *QueryListGetPrimaryStmt(List *stmts);
99 static void AcquireExecutorLocks(List *stmt_list, bool acquire);
100 static void AcquirePlannerLocks(List *stmt_list, bool acquire);
101 static void ScanQueryForLocks(Query *parsetree, bool acquire);
102 static bool ScanQueryWalker(Node *node, bool *acquire);
103 static TupleDesc PlanCacheComputeResultDesc(List *stmt_list);
104 static void PlanCacheRelCallback(Datum arg, Oid relid);
105 static void PlanCacheFuncCallback(Datum arg, int cacheid, uint32 hashvalue);
106 static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue);
107 
108 
109 /*
110  * InitPlanCache: initialize module during InitPostgres.
111  *
112  * All we need to do is hook into inval.c's callback lists.
113  */
114 void
116 {
124 }
125 
126 /*
127  * CreateCachedPlan: initially create a plan cache entry.
128  *
129  * Creation of a cached plan is divided into two steps, CreateCachedPlan and
130  * CompleteCachedPlan. CreateCachedPlan should be called after running the
131  * query through raw_parser, but before doing parse analysis and rewrite;
132  * CompleteCachedPlan is called after that. The reason for this arrangement
133  * is that it can save one round of copying of the raw parse tree, since
134  * the parser will normally scribble on the raw parse tree. Callers would
135  * otherwise need to make an extra copy of the parse tree to ensure they
136  * still had a clean copy to present at plan cache creation time.
137  *
138  * All arguments presented to CreateCachedPlan are copied into a memory
139  * context created as a child of the call-time CurrentMemoryContext, which
140  * should be a reasonably short-lived working context that will go away in
141  * event of an error. This ensures that the cached plan data structure will
142  * likewise disappear if an error occurs before we have fully constructed it.
143  * Once constructed, the cached plan can be made longer-lived, if needed,
144  * by calling SaveCachedPlan.
145  *
146  * raw_parse_tree: output of raw_parser(), or NULL if empty query
147  * query_string: original query text
148  * commandTag: compile-time-constant tag for query, or NULL if empty query
149  */
151 CreateCachedPlan(RawStmt *raw_parse_tree,
152  const char *query_string,
153  const char *commandTag)
154 {
155  CachedPlanSource *plansource;
156  MemoryContext source_context;
157  MemoryContext oldcxt;
158 
159  Assert(query_string != NULL); /* required as of 8.4 */
160 
161  /*
162  * Make a dedicated memory context for the CachedPlanSource and its
163  * permanent subsidiary data. It's probably not going to be large, but
164  * just in case, allow it to grow large. Initially it's a child of the
165  * caller's context (which we assume to be transient), so that it will be
166  * cleaned up on error.
167  */
169  "CachedPlanSource",
171 
172  /*
173  * Create and fill the CachedPlanSource struct within the new context.
174  * Most fields are just left empty for the moment.
175  */
176  oldcxt = MemoryContextSwitchTo(source_context);
177 
178  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
179  plansource->magic = CACHEDPLANSOURCE_MAGIC;
180  plansource->raw_parse_tree = copyObject(raw_parse_tree);
181  plansource->query_string = pstrdup(query_string);
182  plansource->commandTag = commandTag;
183  plansource->param_types = NULL;
184  plansource->num_params = 0;
185  plansource->parserSetup = NULL;
186  plansource->parserSetupArg = NULL;
187  plansource->cursor_options = 0;
188  plansource->fixed_result = false;
189  plansource->resultDesc = NULL;
190  plansource->context = source_context;
191  plansource->query_list = NIL;
192  plansource->relationOids = NIL;
193  plansource->invalItems = NIL;
194  plansource->search_path = NULL;
195  plansource->query_context = NULL;
196  plansource->rewriteRoleId = InvalidOid;
197  plansource->rewriteRowSecurity = false;
198  plansource->dependsOnRLS = false;
199  plansource->gplan = NULL;
200  plansource->is_oneshot = false;
201  plansource->is_complete = false;
202  plansource->is_saved = false;
203  plansource->is_valid = false;
204  plansource->generation = 0;
205  plansource->next_saved = NULL;
206  plansource->generic_cost = -1;
207  plansource->total_custom_cost = 0;
208  plansource->num_custom_plans = 0;
209 
210  MemoryContextSwitchTo(oldcxt);
211 
212  return plansource;
213 }
214 
215 /*
216  * CreateOneShotCachedPlan: initially create a one-shot plan cache entry.
217  *
218  * This variant of CreateCachedPlan creates a plan cache entry that is meant
219  * to be used only once. No data copying occurs: all data structures remain
220  * in the caller's memory context (which typically should get cleared after
221  * completing execution). The CachedPlanSource struct itself is also created
222  * in that context.
223  *
224  * A one-shot plan cannot be saved or copied, since we make no effort to
225  * preserve the raw parse tree unmodified. There is also no support for
226  * invalidation, so plan use must be completed in the current transaction,
227  * and DDL that might invalidate the querytree_list must be avoided as well.
228  *
229  * raw_parse_tree: output of raw_parser(), or NULL if empty query
230  * query_string: original query text
231  * commandTag: compile-time-constant tag for query, or NULL if empty query
232  */
235  const char *query_string,
236  const char *commandTag)
237 {
238  CachedPlanSource *plansource;
239 
240  Assert(query_string != NULL); /* required as of 8.4 */
241 
242  /*
243  * Create and fill the CachedPlanSource struct within the caller's memory
244  * context. Most fields are just left empty for the moment.
245  */
246  plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
247  plansource->magic = CACHEDPLANSOURCE_MAGIC;
248  plansource->raw_parse_tree = raw_parse_tree;
249  plansource->query_string = query_string;
250  plansource->commandTag = commandTag;
251  plansource->param_types = NULL;
252  plansource->num_params = 0;
253  plansource->parserSetup = NULL;
254  plansource->parserSetupArg = NULL;
255  plansource->cursor_options = 0;
256  plansource->fixed_result = false;
257  plansource->resultDesc = NULL;
258  plansource->context = CurrentMemoryContext;
259  plansource->query_list = NIL;
260  plansource->relationOids = NIL;
261  plansource->invalItems = NIL;
262  plansource->search_path = NULL;
263  plansource->query_context = NULL;
264  plansource->rewriteRoleId = InvalidOid;
265  plansource->rewriteRowSecurity = false;
266  plansource->dependsOnRLS = false;
267  plansource->gplan = NULL;
268  plansource->is_oneshot = true;
269  plansource->is_complete = false;
270  plansource->is_saved = false;
271  plansource->is_valid = false;
272  plansource->generation = 0;
273  plansource->next_saved = NULL;
274  plansource->generic_cost = -1;
275  plansource->total_custom_cost = 0;
276  plansource->num_custom_plans = 0;
277 
278  return plansource;
279 }
280 
281 /*
282  * CompleteCachedPlan: second step of creating a plan cache entry.
283  *
284  * Pass in the analyzed-and-rewritten form of the query, as well as the
285  * required subsidiary data about parameters and such. All passed values will
286  * be copied into the CachedPlanSource's memory, except as specified below.
287  * After this is called, GetCachedPlan can be called to obtain a plan, and
288  * optionally the CachedPlanSource can be saved using SaveCachedPlan.
289  *
290  * If querytree_context is not NULL, the querytree_list must be stored in that
291  * context (but the other parameters need not be). The querytree_list is not
292  * copied, rather the given context is kept as the initial query_context of
293  * the CachedPlanSource. (It should have been created as a child of the
294  * caller's working memory context, but it will now be reparented to belong
295  * to the CachedPlanSource.) The querytree_context is normally the context in
296  * which the caller did raw parsing and parse analysis. This approach saves
297  * one tree copying step compared to passing NULL, but leaves lots of extra
298  * cruft in the query_context, namely whatever extraneous stuff parse analysis
299  * created, as well as whatever went unused from the raw parse tree. Using
300  * this option is a space-for-time tradeoff that is appropriate if the
301  * CachedPlanSource is not expected to survive long.
302  *
303  * plancache.c cannot know how to copy the data referenced by parserSetupArg,
304  * and it would often be inappropriate to do so anyway. When using that
305  * option, it is caller's responsibility that the referenced data remains
306  * valid for as long as the CachedPlanSource exists.
307  *
308  * If the CachedPlanSource is a "oneshot" plan, then no querytree copying
309  * occurs at all, and querytree_context is ignored; it is caller's
310  * responsibility that the passed querytree_list is sufficiently long-lived.
311  *
312  * plansource: structure returned by CreateCachedPlan
313  * querytree_list: analyzed-and-rewritten form of query (list of Query nodes)
314  * querytree_context: memory context containing querytree_list,
315  * or NULL to copy querytree_list into a fresh context
316  * param_types: array of fixed parameter type OIDs, or NULL if none
317  * num_params: number of fixed parameters
318  * parserSetup: alternate method for handling query parameters
319  * parserSetupArg: data to pass to parserSetup
320  * cursor_options: options bitmask to pass to planner
321  * fixed_result: TRUE to disallow future changes in query's result tupdesc
322  */
323 void
325  List *querytree_list,
326  MemoryContext querytree_context,
327  Oid *param_types,
328  int num_params,
329  ParserSetupHook parserSetup,
330  void *parserSetupArg,
331  int cursor_options,
332  bool fixed_result)
333 {
334  MemoryContext source_context = plansource->context;
336 
337  /* Assert caller is doing things in a sane order */
338  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
339  Assert(!plansource->is_complete);
340 
341  /*
342  * If caller supplied a querytree_context, reparent it underneath the
343  * CachedPlanSource's context; otherwise, create a suitable context and
344  * copy the querytree_list into it. But no data copying should be done
345  * for one-shot plans; for those, assume the passed querytree_list is
346  * sufficiently long-lived.
347  */
348  if (plansource->is_oneshot)
349  {
350  querytree_context = CurrentMemoryContext;
351  }
352  else if (querytree_context != NULL)
353  {
354  MemoryContextSetParent(querytree_context, source_context);
355  MemoryContextSwitchTo(querytree_context);
356  }
357  else
358  {
359  /* Again, it's a good bet the querytree_context can be small */
360  querytree_context = AllocSetContextCreate(source_context,
361  "CachedPlanQuery",
363  MemoryContextSwitchTo(querytree_context);
364  querytree_list = copyObject(querytree_list);
365  }
366 
367  plansource->query_context = querytree_context;
368  plansource->query_list = querytree_list;
369 
370  if (!plansource->is_oneshot && !IsTransactionStmtPlan(plansource))
371  {
372  /*
373  * Use the planner machinery to extract dependencies. Data is saved
374  * in query_context. (We assume that not a lot of extra cruft is
375  * created by this call.) We can skip this for one-shot plans, and
376  * transaction control commands have no such dependencies anyway.
377  */
378  extract_query_dependencies((Node *) querytree_list,
379  &plansource->relationOids,
380  &plansource->invalItems,
381  &plansource->dependsOnRLS);
382 
383  /* Update RLS info as well. */
384  plansource->rewriteRoleId = GetUserId();
385  plansource->rewriteRowSecurity = row_security;
386 
387  /*
388  * Also save the current search_path in the query_context. (This
389  * should not generate much extra cruft either, since almost certainly
390  * the path is already valid.) Again, we don't really need this for
391  * one-shot plans; and we *must* skip this for transaction control
392  * commands, because this could result in catalog accesses.
393  */
394  plansource->search_path = GetOverrideSearchPath(querytree_context);
395  }
396 
397  /*
398  * Save the final parameter types (or other parameter specification data)
399  * into the source_context, as well as our other parameters. Also save
400  * the result tuple descriptor.
401  */
402  MemoryContextSwitchTo(source_context);
403 
404  if (num_params > 0)
405  {
406  plansource->param_types = (Oid *) palloc(num_params * sizeof(Oid));
407  memcpy(plansource->param_types, param_types, num_params * sizeof(Oid));
408  }
409  else
410  plansource->param_types = NULL;
411  plansource->num_params = num_params;
412  plansource->parserSetup = parserSetup;
413  plansource->parserSetupArg = parserSetupArg;
414  plansource->cursor_options = cursor_options;
415  plansource->fixed_result = fixed_result;
416  plansource->resultDesc = PlanCacheComputeResultDesc(querytree_list);
417 
418  MemoryContextSwitchTo(oldcxt);
419 
420  plansource->is_complete = true;
421  plansource->is_valid = true;
422 }
423 
424 /*
425  * SaveCachedPlan: save a cached plan permanently
426  *
427  * This function moves the cached plan underneath CacheMemoryContext (making
428  * it live for the life of the backend, unless explicitly dropped), and adds
429  * it to the list of cached plans that are checked for invalidation when an
430  * sinval event occurs.
431  *
432  * This is guaranteed not to throw error, except for the caller-error case
433  * of trying to save a one-shot plan. Callers typically depend on that
434  * since this is called just before or just after adding a pointer to the
435  * CachedPlanSource to some permanent data structure of their own. Up until
436  * this is done, a CachedPlanSource is just transient data that will go away
437  * automatically on transaction abort.
438  */
439 void
441 {
442  /* Assert caller is doing things in a sane order */
443  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
444  Assert(plansource->is_complete);
445  Assert(!plansource->is_saved);
446 
447  /* This seems worth a real test, though */
448  if (plansource->is_oneshot)
449  elog(ERROR, "cannot save one-shot cached plan");
450 
451  /*
452  * In typical use, this function would be called before generating any
453  * plans from the CachedPlanSource. If there is a generic plan, moving it
454  * into CacheMemoryContext would be pretty risky since it's unclear
455  * whether the caller has taken suitable care with making references
456  * long-lived. Best thing to do seems to be to discard the plan.
457  */
458  ReleaseGenericPlan(plansource);
459 
460  /*
461  * Reparent the source memory context under CacheMemoryContext so that it
462  * will live indefinitely. The query_context follows along since it's
463  * already a child of the other one.
464  */
466 
467  /*
468  * Add the entry to the global list of cached plans.
469  */
470  plansource->next_saved = first_saved_plan;
471  first_saved_plan = plansource;
472 
473  plansource->is_saved = true;
474 }
475 
476 /*
477  * DropCachedPlan: destroy a cached plan.
478  *
479  * Actually this only destroys the CachedPlanSource: any referenced CachedPlan
480  * is released, but not destroyed until its refcount goes to zero. That
481  * handles the situation where DropCachedPlan is called while the plan is
482  * still in use.
483  */
484 void
486 {
487  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
488 
489  /* If it's been saved, remove it from the list */
490  if (plansource->is_saved)
491  {
492  if (first_saved_plan == plansource)
493  first_saved_plan = plansource->next_saved;
494  else
495  {
496  CachedPlanSource *psrc;
497 
498  for (psrc = first_saved_plan; psrc; psrc = psrc->next_saved)
499  {
500  if (psrc->next_saved == plansource)
501  {
502  psrc->next_saved = plansource->next_saved;
503  break;
504  }
505  }
506  }
507  plansource->is_saved = false;
508  }
509 
510  /* Decrement generic CachePlan's refcount and drop if no longer needed */
511  ReleaseGenericPlan(plansource);
512 
513  /* Mark it no longer valid */
514  plansource->magic = 0;
515 
516  /*
517  * Remove the CachedPlanSource and all subsidiary data (including the
518  * query_context if any). But if it's a one-shot we can't free anything.
519  */
520  if (!plansource->is_oneshot)
521  MemoryContextDelete(plansource->context);
522 }
523 
524 /*
525  * ReleaseGenericPlan: release a CachedPlanSource's generic plan, if any.
526  */
527 static void
529 {
530  /* Be paranoid about the possibility that ReleaseCachedPlan fails */
531  if (plansource->gplan)
532  {
533  CachedPlan *plan = plansource->gplan;
534 
535  Assert(plan->magic == CACHEDPLAN_MAGIC);
536  plansource->gplan = NULL;
537  ReleaseCachedPlan(plan, false);
538  }
539 }
540 
541 /*
542  * RevalidateCachedQuery: ensure validity of analyzed-and-rewritten query tree.
543  *
544  * What we do here is re-acquire locks and redo parse analysis if necessary.
545  * On return, the query_list is valid and we have sufficient locks to begin
546  * planning.
547  *
548  * If any parse analysis activity is required, the caller's memory context is
549  * used for that work.
550  *
551  * The result value is the transient analyzed-and-rewritten query tree if we
552  * had to do re-analysis, and NIL otherwise. (This is returned just to save
553  * a tree copying step in a subsequent BuildCachedPlan call.)
554  */
555 static List *
557 {
558  bool snapshot_set;
559  RawStmt *rawtree;
560  List *tlist; /* transient query-tree list */
561  List *qlist; /* permanent query-tree list */
562  TupleDesc resultDesc;
563  MemoryContext querytree_context;
564  MemoryContext oldcxt;
565 
566  /*
567  * For one-shot plans, we do not support revalidation checking; it's
568  * assumed the query is parsed, planned, and executed in one transaction,
569  * so that no lock re-acquisition is necessary. Also, there is never any
570  * need to revalidate plans for transaction control commands (and we
571  * mustn't risk any catalog accesses when handling those).
572  */
573  if (plansource->is_oneshot || IsTransactionStmtPlan(plansource))
574  {
575  Assert(plansource->is_valid);
576  return NIL;
577  }
578 
579  /*
580  * If the query is currently valid, we should have a saved search_path ---
581  * check to see if that matches the current environment. If not, we want
582  * to force replan.
583  */
584  if (plansource->is_valid)
585  {
586  Assert(plansource->search_path != NULL);
588  {
589  /* Invalidate the querytree and generic plan */
590  plansource->is_valid = false;
591  if (plansource->gplan)
592  plansource->gplan->is_valid = false;
593  }
594  }
595 
596  /*
597  * If the query rewrite phase had a possible RLS dependency, we must redo
598  * it if either the role or the row_security setting has changed.
599  */
600  if (plansource->is_valid && plansource->dependsOnRLS &&
601  (plansource->rewriteRoleId != GetUserId() ||
602  plansource->rewriteRowSecurity != row_security))
603  plansource->is_valid = false;
604 
605  /*
606  * If the query is currently valid, acquire locks on the referenced
607  * objects; then check again. We need to do it this way to cover the race
608  * condition that an invalidation message arrives before we get the locks.
609  */
610  if (plansource->is_valid)
611  {
612  AcquirePlannerLocks(plansource->query_list, true);
613 
614  /*
615  * By now, if any invalidation has happened, the inval callback
616  * functions will have marked the query invalid.
617  */
618  if (plansource->is_valid)
619  {
620  /* Successfully revalidated and locked the query. */
621  return NIL;
622  }
623 
624  /* Oops, the race case happened. Release useless locks. */
625  AcquirePlannerLocks(plansource->query_list, false);
626  }
627 
628  /*
629  * Discard the no-longer-useful query tree. (Note: we don't want to do
630  * this any earlier, else we'd not have been able to release locks
631  * correctly in the race condition case.)
632  */
633  plansource->is_valid = false;
634  plansource->query_list = NIL;
635  plansource->relationOids = NIL;
636  plansource->invalItems = NIL;
637  plansource->search_path = NULL;
638 
639  /*
640  * Free the query_context. We don't really expect MemoryContextDelete to
641  * fail, but just in case, make sure the CachedPlanSource is left in a
642  * reasonably sane state. (The generic plan won't get unlinked yet, but
643  * that's acceptable.)
644  */
645  if (plansource->query_context)
646  {
647  MemoryContext qcxt = plansource->query_context;
648 
649  plansource->query_context = NULL;
650  MemoryContextDelete(qcxt);
651  }
652 
653  /* Drop the generic plan reference if any */
654  ReleaseGenericPlan(plansource);
655 
656  /*
657  * Now re-do parse analysis and rewrite. This not incidentally acquires
658  * the locks we need to do planning safely.
659  */
660  Assert(plansource->is_complete);
661 
662  /*
663  * If a snapshot is already set (the normal case), we can just use that
664  * for parsing/planning. But if it isn't, install one. Note: no point in
665  * checking whether parse analysis requires a snapshot; utility commands
666  * don't have invalidatable plans, so we'd not get here for such a
667  * command.
668  */
669  snapshot_set = false;
670  if (!ActiveSnapshotSet())
671  {
673  snapshot_set = true;
674  }
675 
676  /*
677  * Run parse analysis and rule rewriting. The parser tends to scribble on
678  * its input, so we must copy the raw parse tree to prevent corruption of
679  * the cache.
680  */
681  rawtree = copyObject(plansource->raw_parse_tree);
682  if (rawtree == NULL)
683  tlist = NIL;
684  else if (plansource->parserSetup != NULL)
685  tlist = pg_analyze_and_rewrite_params(rawtree,
686  plansource->query_string,
687  plansource->parserSetup,
688  plansource->parserSetupArg);
689  else
690  tlist = pg_analyze_and_rewrite(rawtree,
691  plansource->query_string,
692  plansource->param_types,
693  plansource->num_params);
694 
695  /* Release snapshot if we got one */
696  if (snapshot_set)
698 
699  /*
700  * Check or update the result tupdesc. XXX should we use a weaker
701  * condition than equalTupleDescs() here?
702  *
703  * We assume the parameter types didn't change from the first time, so no
704  * need to update that.
705  */
706  resultDesc = PlanCacheComputeResultDesc(tlist);
707  if (resultDesc == NULL && plansource->resultDesc == NULL)
708  {
709  /* OK, doesn't return tuples */
710  }
711  else if (resultDesc == NULL || plansource->resultDesc == NULL ||
712  !equalTupleDescs(resultDesc, plansource->resultDesc))
713  {
714  /* can we give a better error message? */
715  if (plansource->fixed_result)
716  ereport(ERROR,
717  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
718  errmsg("cached plan must not change result type")));
719  oldcxt = MemoryContextSwitchTo(plansource->context);
720  if (resultDesc)
721  resultDesc = CreateTupleDescCopy(resultDesc);
722  if (plansource->resultDesc)
723  FreeTupleDesc(plansource->resultDesc);
724  plansource->resultDesc = resultDesc;
725  MemoryContextSwitchTo(oldcxt);
726  }
727 
728  /*
729  * Allocate new query_context and copy the completed querytree into it.
730  * It's transient until we complete the copying and dependency extraction.
731  */
732  querytree_context = AllocSetContextCreate(CurrentMemoryContext,
733  "CachedPlanQuery",
735  oldcxt = MemoryContextSwitchTo(querytree_context);
736 
737  qlist = copyObject(tlist);
738 
739  /*
740  * Use the planner machinery to extract dependencies. Data is saved in
741  * query_context. (We assume that not a lot of extra cruft is created by
742  * this call.)
743  */
745  &plansource->relationOids,
746  &plansource->invalItems,
747  &plansource->dependsOnRLS);
748 
749  /* Update RLS info as well. */
750  plansource->rewriteRoleId = GetUserId();
751  plansource->rewriteRowSecurity = row_security;
752 
753  /*
754  * Also save the current search_path in the query_context. (This should
755  * not generate much extra cruft either, since almost certainly the path
756  * is already valid.)
757  */
758  plansource->search_path = GetOverrideSearchPath(querytree_context);
759 
760  MemoryContextSwitchTo(oldcxt);
761 
762  /* Now reparent the finished query_context and save the links */
763  MemoryContextSetParent(querytree_context, plansource->context);
764 
765  plansource->query_context = querytree_context;
766  plansource->query_list = qlist;
767 
768  /*
769  * Note: we do not reset generic_cost or total_custom_cost, although we
770  * could choose to do so. If the DDL or statistics change that prompted
771  * the invalidation meant a significant change in the cost estimates, it
772  * would be better to reset those variables and start fresh; but often it
773  * doesn't, and we're better retaining our hard-won knowledge about the
774  * relative costs.
775  */
776 
777  plansource->is_valid = true;
778 
779  /* Return transient copy of querytrees for possible use in planning */
780  return tlist;
781 }
782 
783 /*
784  * CheckCachedPlan: see if the CachedPlanSource's generic plan is valid.
785  *
786  * Caller must have already called RevalidateCachedQuery to verify that the
787  * querytree is up to date.
788  *
789  * On a "true" return, we have acquired the locks needed to run the plan.
790  * (We must do this for the "true" result to be race-condition-free.)
791  */
792 static bool
794 {
795  CachedPlan *plan = plansource->gplan;
796 
797  /* Assert that caller checked the querytree */
798  Assert(plansource->is_valid);
799 
800  /* If there's no generic plan, just say "false" */
801  if (!plan)
802  return false;
803 
804  Assert(plan->magic == CACHEDPLAN_MAGIC);
805  /* Generic plans are never one-shot */
806  Assert(!plan->is_oneshot);
807 
808  /*
809  * If plan isn't valid for current role, we can't use it.
810  */
811  if (plan->is_valid && plan->dependsOnRole &&
812  plan->planRoleId != GetUserId())
813  plan->is_valid = false;
814 
815  /*
816  * If it appears valid, acquire locks and recheck; this is much the same
817  * logic as in RevalidateCachedQuery, but for a plan.
818  */
819  if (plan->is_valid)
820  {
821  /*
822  * Plan must have positive refcount because it is referenced by
823  * plansource; so no need to fear it disappears under us here.
824  */
825  Assert(plan->refcount > 0);
826 
827  AcquireExecutorLocks(plan->stmt_list, true);
828 
829  /*
830  * If plan was transient, check to see if TransactionXmin has
831  * advanced, and if so invalidate it.
832  */
833  if (plan->is_valid &&
836  plan->is_valid = false;
837 
838  /*
839  * By now, if any invalidation has happened, the inval callback
840  * functions will have marked the plan invalid.
841  */
842  if (plan->is_valid)
843  {
844  /* Successfully revalidated and locked the query. */
845  return true;
846  }
847 
848  /* Oops, the race case happened. Release useless locks. */
849  AcquireExecutorLocks(plan->stmt_list, false);
850  }
851 
852  /*
853  * Plan has been invalidated, so unlink it from the parent and release it.
854  */
855  ReleaseGenericPlan(plansource);
856 
857  return false;
858 }
859 
860 /*
861  * BuildCachedPlan: construct a new CachedPlan from a CachedPlanSource.
862  *
863  * qlist should be the result value from a previous RevalidateCachedQuery,
864  * or it can be set to NIL if we need to re-copy the plansource's query_list.
865  *
866  * To build a generic, parameter-value-independent plan, pass NULL for
867  * boundParams. To build a custom plan, pass the actual parameter values via
868  * boundParams. For best effect, the PARAM_FLAG_CONST flag should be set on
869  * each parameter value; otherwise the planner will treat the value as a
870  * hint rather than a hard constant.
871  *
872  * Planning work is done in the caller's memory context. The finished plan
873  * is in a child memory context, which typically should get reparented
874  * (unless this is a one-shot plan, in which case we don't copy the plan).
875  */
876 static CachedPlan *
878  ParamListInfo boundParams)
879 {
880  CachedPlan *plan;
881  List *plist;
882  bool snapshot_set;
883  bool is_transient;
884  MemoryContext plan_context;
886  ListCell *lc;
887 
888  /*
889  * Normally the querytree should be valid already, but if it's not,
890  * rebuild it.
891  *
892  * NOTE: GetCachedPlan should have called RevalidateCachedQuery first, so
893  * we ought to be holding sufficient locks to prevent any invalidation.
894  * However, if we're building a custom plan after having built and
895  * rejected a generic plan, it's possible to reach here with is_valid
896  * false due to an invalidation while making the generic plan. In theory
897  * the invalidation must be a false positive, perhaps a consequence of an
898  * sinval reset event or the CLOBBER_CACHE_ALWAYS debug code. But for
899  * safety, let's treat it as real and redo the RevalidateCachedQuery call.
900  */
901  if (!plansource->is_valid)
902  qlist = RevalidateCachedQuery(plansource);
903 
904  /*
905  * If we don't already have a copy of the querytree list that can be
906  * scribbled on by the planner, make one. For a one-shot plan, we assume
907  * it's okay to scribble on the original query_list.
908  */
909  if (qlist == NIL)
910  {
911  if (!plansource->is_oneshot)
912  qlist = copyObject(plansource->query_list);
913  else
914  qlist = plansource->query_list;
915  }
916 
917  /*
918  * If a snapshot is already set (the normal case), we can just use that
919  * for planning. But if it isn't, and we need one, install one.
920  */
921  snapshot_set = false;
922  if (!ActiveSnapshotSet() &&
923  plansource->raw_parse_tree &&
925  {
927  snapshot_set = true;
928  }
929 
930  /*
931  * Generate the plan.
932  */
933  plist = pg_plan_queries(qlist, plansource->cursor_options, boundParams);
934 
935  /* Release snapshot if we got one */
936  if (snapshot_set)
938 
939  /*
940  * Normally we make a dedicated memory context for the CachedPlan and its
941  * subsidiary data. (It's probably not going to be large, but just in
942  * case, allow it to grow large. It's transient for the moment.) But for
943  * a one-shot plan, we just leave it in the caller's memory context.
944  */
945  if (!plansource->is_oneshot)
946  {
948  "CachedPlan",
950 
951  /*
952  * Copy plan into the new context.
953  */
954  MemoryContextSwitchTo(plan_context);
955 
956  plist = copyObject(plist);
957  }
958  else
959  plan_context = CurrentMemoryContext;
960 
961  /*
962  * Create and fill the CachedPlan struct within the new context.
963  */
964  plan = (CachedPlan *) palloc(sizeof(CachedPlan));
965  plan->magic = CACHEDPLAN_MAGIC;
966  plan->stmt_list = plist;
967 
968  /*
969  * CachedPlan is dependent on role either if RLS affected the rewrite
970  * phase or if a role dependency was injected during planning. And it's
971  * transient if any plan is marked so.
972  */
973  plan->planRoleId = GetUserId();
974  plan->dependsOnRole = plansource->dependsOnRLS;
975  is_transient = false;
976  foreach(lc, plist)
977  {
978  PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc));
979 
980  if (plannedstmt->commandType == CMD_UTILITY)
981  continue; /* Ignore utility statements */
982 
983  if (plannedstmt->transientPlan)
984  is_transient = true;
985  if (plannedstmt->dependsOnRole)
986  plan->dependsOnRole = true;
987  }
988  if (is_transient)
989  {
991  plan->saved_xmin = TransactionXmin;
992  }
993  else
995  plan->refcount = 0;
996  plan->context = plan_context;
997  plan->is_oneshot = plansource->is_oneshot;
998  plan->is_saved = false;
999  plan->is_valid = true;
1000 
1001  /* assign generation number to new plan */
1002  plan->generation = ++(plansource->generation);
1003 
1004  MemoryContextSwitchTo(oldcxt);
1005 
1006  return plan;
1007 }
1008 
1009 /*
1010  * choose_custom_plan: choose whether to use custom or generic plan
1011  *
1012  * This defines the policy followed by GetCachedPlan.
1013  */
1014 static bool
1016 {
1017  double avg_custom_cost;
1018 
1019  /* One-shot plans will always be considered custom */
1020  if (plansource->is_oneshot)
1021  return true;
1022 
1023  /* Otherwise, never any point in a custom plan if there's no parameters */
1024  if (boundParams == NULL)
1025  return false;
1026  /* ... nor for transaction control statements */
1027  if (IsTransactionStmtPlan(plansource))
1028  return false;
1029 
1030  /* See if caller wants to force the decision */
1031  if (plansource->cursor_options & CURSOR_OPT_GENERIC_PLAN)
1032  return false;
1033  if (plansource->cursor_options & CURSOR_OPT_CUSTOM_PLAN)
1034  return true;
1035 
1036  /* Generate custom plans until we have done at least 5 (arbitrary) */
1037  if (plansource->num_custom_plans < 5)
1038  return true;
1039 
1040  avg_custom_cost = plansource->total_custom_cost / plansource->num_custom_plans;
1041 
1042  /*
1043  * Prefer generic plan if it's less expensive than the average custom
1044  * plan. (Because we include a charge for cost of planning in the
1045  * custom-plan costs, this means the generic plan only has to be less
1046  * expensive than the execution cost plus replan cost of the custom
1047  * plans.)
1048  *
1049  * Note that if generic_cost is -1 (indicating we've not yet determined
1050  * the generic plan cost), we'll always prefer generic at this point.
1051  */
1052  if (plansource->generic_cost < avg_custom_cost)
1053  return false;
1054 
1055  return true;
1056 }
1057 
1058 /*
1059  * cached_plan_cost: calculate estimated cost of a plan
1060  *
1061  * If include_planner is true, also include the estimated cost of constructing
1062  * the plan. (We must factor that into the cost of using a custom plan, but
1063  * we don't count it for a generic plan.)
1064  */
1065 static double
1066 cached_plan_cost(CachedPlan *plan, bool include_planner)
1067 {
1068  double result = 0;
1069  ListCell *lc;
1070 
1071  foreach(lc, plan->stmt_list)
1072  {
1073  PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc));
1074 
1075  if (plannedstmt->commandType == CMD_UTILITY)
1076  continue; /* Ignore utility statements */
1077 
1078  result += plannedstmt->planTree->total_cost;
1079 
1080  if (include_planner)
1081  {
1082  /*
1083  * Currently we use a very crude estimate of planning effort based
1084  * on the number of relations in the finished plan's rangetable.
1085  * Join planning effort actually scales much worse than linearly
1086  * in the number of relations --- but only until the join collapse
1087  * limits kick in. Also, while inheritance child relations surely
1088  * add to planning effort, they don't make the join situation
1089  * worse. So the actual shape of the planning cost curve versus
1090  * number of relations isn't all that obvious. It will take
1091  * considerable work to arrive at a less crude estimate, and for
1092  * now it's not clear that's worth doing.
1093  *
1094  * The other big difficulty here is that we don't have any very
1095  * good model of how planning cost compares to execution costs.
1096  * The current multiplier of 1000 * cpu_operator_cost is probably
1097  * on the low side, but we'll try this for awhile before making a
1098  * more aggressive correction.
1099  *
1100  * If we ever do write a more complicated estimator, it should
1101  * probably live in src/backend/optimizer/ not here.
1102  */
1103  int nrelations = list_length(plannedstmt->rtable);
1104 
1105  result += 1000.0 * cpu_operator_cost * (nrelations + 1);
1106  }
1107  }
1108 
1109  return result;
1110 }
1111 
1112 /*
1113  * GetCachedPlan: get a cached plan from a CachedPlanSource.
1114  *
1115  * This function hides the logic that decides whether to use a generic
1116  * plan or a custom plan for the given parameters: the caller does not know
1117  * which it will get.
1118  *
1119  * On return, the plan is valid and we have sufficient locks to begin
1120  * execution.
1121  *
1122  * On return, the refcount of the plan has been incremented; a later
1123  * ReleaseCachedPlan() call is expected. The refcount has been reported
1124  * to the CurrentResourceOwner if useResOwner is true (note that that must
1125  * only be true if it's a "saved" CachedPlanSource).
1126  *
1127  * Note: if any replanning activity is required, the caller's memory context
1128  * is used for that work.
1129  */
1130 CachedPlan *
1132  bool useResOwner)
1133 {
1134  CachedPlan *plan = NULL;
1135  List *qlist;
1136  bool customplan;
1137 
1138  /* Assert caller is doing things in a sane order */
1139  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1140  Assert(plansource->is_complete);
1141  /* This seems worth a real test, though */
1142  if (useResOwner && !plansource->is_saved)
1143  elog(ERROR, "cannot apply ResourceOwner to non-saved cached plan");
1144 
1145  /* Make sure the querytree list is valid and we have parse-time locks */
1146  qlist = RevalidateCachedQuery(plansource);
1147 
1148  /* Decide whether to use a custom plan */
1149  customplan = choose_custom_plan(plansource, boundParams);
1150 
1151  if (!customplan)
1152  {
1153  if (CheckCachedPlan(plansource))
1154  {
1155  /* We want a generic plan, and we already have a valid one */
1156  plan = plansource->gplan;
1157  Assert(plan->magic == CACHEDPLAN_MAGIC);
1158  }
1159  else
1160  {
1161  /* Build a new generic plan */
1162  plan = BuildCachedPlan(plansource, qlist, NULL);
1163  /* Just make real sure plansource->gplan is clear */
1164  ReleaseGenericPlan(plansource);
1165  /* Link the new generic plan into the plansource */
1166  plansource->gplan = plan;
1167  plan->refcount++;
1168  /* Immediately reparent into appropriate context */
1169  if (plansource->is_saved)
1170  {
1171  /* saved plans all live under CacheMemoryContext */
1173  plan->is_saved = true;
1174  }
1175  else
1176  {
1177  /* otherwise, it should be a sibling of the plansource */
1179  MemoryContextGetParent(plansource->context));
1180  }
1181  /* Update generic_cost whenever we make a new generic plan */
1182  plansource->generic_cost = cached_plan_cost(plan, false);
1183 
1184  /*
1185  * If, based on the now-known value of generic_cost, we'd not have
1186  * chosen to use a generic plan, then forget it and make a custom
1187  * plan. This is a bit of a wart but is necessary to avoid a
1188  * glitch in behavior when the custom plans are consistently big
1189  * winners; at some point we'll experiment with a generic plan and
1190  * find it's a loser, but we don't want to actually execute that
1191  * plan.
1192  */
1193  customplan = choose_custom_plan(plansource, boundParams);
1194 
1195  /*
1196  * If we choose to plan again, we need to re-copy the query_list,
1197  * since the planner probably scribbled on it. We can force
1198  * BuildCachedPlan to do that by passing NIL.
1199  */
1200  qlist = NIL;
1201  }
1202  }
1203 
1204  if (customplan)
1205  {
1206  /* Build a custom plan */
1207  plan = BuildCachedPlan(plansource, qlist, boundParams);
1208  /* Accumulate total costs of custom plans, but 'ware overflow */
1209  if (plansource->num_custom_plans < INT_MAX)
1210  {
1211  plansource->total_custom_cost += cached_plan_cost(plan, true);
1212  plansource->num_custom_plans++;
1213  }
1214  }
1215 
1216  Assert(plan != NULL);
1217 
1218  /* Flag the plan as in use by caller */
1219  if (useResOwner)
1221  plan->refcount++;
1222  if (useResOwner)
1224 
1225  /*
1226  * Saved plans should be under CacheMemoryContext so they will not go away
1227  * until their reference count goes to zero. In the generic-plan cases we
1228  * already took care of that, but for a custom plan, do it as soon as we
1229  * have created a reference-counted link.
1230  */
1231  if (customplan && plansource->is_saved)
1232  {
1234  plan->is_saved = true;
1235  }
1236 
1237  return plan;
1238 }
1239 
1240 /*
1241  * ReleaseCachedPlan: release active use of a cached plan.
1242  *
1243  * This decrements the reference count, and frees the plan if the count
1244  * has thereby gone to zero. If useResOwner is true, it is assumed that
1245  * the reference count is managed by the CurrentResourceOwner.
1246  *
1247  * Note: useResOwner = false is used for releasing references that are in
1248  * persistent data structures, such as the parent CachedPlanSource or a
1249  * Portal. Transient references should be protected by a resource owner.
1250  */
1251 void
1252 ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
1253 {
1254  Assert(plan->magic == CACHEDPLAN_MAGIC);
1255  if (useResOwner)
1256  {
1257  Assert(plan->is_saved);
1259  }
1260  Assert(plan->refcount > 0);
1261  plan->refcount--;
1262  if (plan->refcount == 0)
1263  {
1264  /* Mark it no longer valid */
1265  plan->magic = 0;
1266 
1267  /* One-shot plans do not own their context, so we can't free them */
1268  if (!plan->is_oneshot)
1270  }
1271 }
1272 
1273 /*
1274  * CachedPlanSetParentContext: move a CachedPlanSource to a new memory context
1275  *
1276  * This can only be applied to unsaved plans; once saved, a plan always
1277  * lives underneath CacheMemoryContext.
1278  */
1279 void
1281  MemoryContext newcontext)
1282 {
1283  /* Assert caller is doing things in a sane order */
1284  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1285  Assert(plansource->is_complete);
1286 
1287  /* These seem worth real tests, though */
1288  if (plansource->is_saved)
1289  elog(ERROR, "cannot move a saved cached plan to another context");
1290  if (plansource->is_oneshot)
1291  elog(ERROR, "cannot move a one-shot cached plan to another context");
1292 
1293  /* OK, let the caller keep the plan where he wishes */
1294  MemoryContextSetParent(plansource->context, newcontext);
1295 
1296  /*
1297  * The query_context needs no special handling, since it's a child of
1298  * plansource->context. But if there's a generic plan, it should be
1299  * maintained as a sibling of plansource->context.
1300  */
1301  if (plansource->gplan)
1302  {
1303  Assert(plansource->gplan->magic == CACHEDPLAN_MAGIC);
1304  MemoryContextSetParent(plansource->gplan->context, newcontext);
1305  }
1306 }
1307 
1308 /*
1309  * CopyCachedPlan: make a copy of a CachedPlanSource
1310  *
1311  * This is a convenience routine that does the equivalent of
1312  * CreateCachedPlan + CompleteCachedPlan, using the data stored in the
1313  * input CachedPlanSource. The result is therefore "unsaved" (regardless
1314  * of the state of the source), and we don't copy any generic plan either.
1315  * The result will be currently valid, or not, the same as the source.
1316  */
1319 {
1320  CachedPlanSource *newsource;
1321  MemoryContext source_context;
1322  MemoryContext querytree_context;
1323  MemoryContext oldcxt;
1324 
1325  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1326  Assert(plansource->is_complete);
1327 
1328  /*
1329  * One-shot plans can't be copied, because we haven't taken care that
1330  * parsing/planning didn't scribble on the raw parse tree or querytrees.
1331  */
1332  if (plansource->is_oneshot)
1333  elog(ERROR, "cannot copy a one-shot cached plan");
1334 
1336  "CachedPlanSource",
1338 
1339  oldcxt = MemoryContextSwitchTo(source_context);
1340 
1341  newsource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource));
1342  newsource->magic = CACHEDPLANSOURCE_MAGIC;
1343  newsource->raw_parse_tree = copyObject(plansource->raw_parse_tree);
1344  newsource->query_string = pstrdup(plansource->query_string);
1345  newsource->commandTag = plansource->commandTag;
1346  if (plansource->num_params > 0)
1347  {
1348  newsource->param_types = (Oid *)
1349  palloc(plansource->num_params * sizeof(Oid));
1350  memcpy(newsource->param_types, plansource->param_types,
1351  plansource->num_params * sizeof(Oid));
1352  }
1353  else
1354  newsource->param_types = NULL;
1355  newsource->num_params = plansource->num_params;
1356  newsource->parserSetup = plansource->parserSetup;
1357  newsource->parserSetupArg = plansource->parserSetupArg;
1358  newsource->cursor_options = plansource->cursor_options;
1359  newsource->fixed_result = plansource->fixed_result;
1360  if (plansource->resultDesc)
1361  newsource->resultDesc = CreateTupleDescCopy(plansource->resultDesc);
1362  else
1363  newsource->resultDesc = NULL;
1364  newsource->context = source_context;
1365 
1366  querytree_context = AllocSetContextCreate(source_context,
1367  "CachedPlanQuery",
1369  MemoryContextSwitchTo(querytree_context);
1370  newsource->query_list = copyObject(plansource->query_list);
1371  newsource->relationOids = copyObject(plansource->relationOids);
1372  newsource->invalItems = copyObject(plansource->invalItems);
1373  if (plansource->search_path)
1374  newsource->search_path = CopyOverrideSearchPath(plansource->search_path);
1375  newsource->query_context = querytree_context;
1376  newsource->rewriteRoleId = plansource->rewriteRoleId;
1377  newsource->rewriteRowSecurity = plansource->rewriteRowSecurity;
1378  newsource->dependsOnRLS = plansource->dependsOnRLS;
1379 
1380  newsource->gplan = NULL;
1381 
1382  newsource->is_oneshot = false;
1383  newsource->is_complete = true;
1384  newsource->is_saved = false;
1385  newsource->is_valid = plansource->is_valid;
1386  newsource->generation = plansource->generation;
1387  newsource->next_saved = NULL;
1388 
1389  /* We may as well copy any acquired cost knowledge */
1390  newsource->generic_cost = plansource->generic_cost;
1391  newsource->total_custom_cost = plansource->total_custom_cost;
1392  newsource->num_custom_plans = plansource->num_custom_plans;
1393 
1394  MemoryContextSwitchTo(oldcxt);
1395 
1396  return newsource;
1397 }
1398 
1399 /*
1400  * CachedPlanIsValid: test whether the rewritten querytree within a
1401  * CachedPlanSource is currently valid (that is, not marked as being in need
1402  * of revalidation).
1403  *
1404  * This result is only trustworthy (ie, free from race conditions) if
1405  * the caller has acquired locks on all the relations used in the plan.
1406  */
1407 bool
1409 {
1410  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1411  return plansource->is_valid;
1412 }
1413 
1414 /*
1415  * CachedPlanGetTargetList: return tlist, if any, describing plan's output
1416  *
1417  * The result is guaranteed up-to-date. However, it is local storage
1418  * within the cached plan, and may disappear next time the plan is updated.
1419  */
1420 List *
1422 {
1423  Query *pstmt;
1424 
1425  /* Assert caller is doing things in a sane order */
1426  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1427  Assert(plansource->is_complete);
1428 
1429  /*
1430  * No work needed if statement doesn't return tuples (we assume this
1431  * feature cannot be changed by an invalidation)
1432  */
1433  if (plansource->resultDesc == NULL)
1434  return NIL;
1435 
1436  /* Make sure the querytree list is valid and we have parse-time locks */
1437  RevalidateCachedQuery(plansource);
1438 
1439  /* Get the primary statement and find out what it returns */
1440  pstmt = QueryListGetPrimaryStmt(plansource->query_list);
1441 
1442  return FetchStatementTargetList((Node *) pstmt);
1443 }
1444 
1445 /*
1446  * QueryListGetPrimaryStmt
1447  * Get the "primary" stmt within a list, ie, the one marked canSetTag.
1448  *
1449  * Returns NULL if no such stmt. If multiple queries within the list are
1450  * marked canSetTag, returns the first one. Neither of these cases should
1451  * occur in present usages of this function.
1452  */
1453 static Query *
1455 {
1456  ListCell *lc;
1457 
1458  foreach(lc, stmts)
1459  {
1460  Query *stmt = castNode(Query, lfirst(lc));
1461 
1462  if (stmt->canSetTag)
1463  return stmt;
1464  }
1465  return NULL;
1466 }
1467 
1468 /*
1469  * AcquireExecutorLocks: acquire locks needed for execution of a cached plan;
1470  * or release them if acquire is false.
1471  */
1472 static void
1473 AcquireExecutorLocks(List *stmt_list, bool acquire)
1474 {
1475  ListCell *lc1;
1476 
1477  foreach(lc1, stmt_list)
1478  {
1479  PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc1));
1480  int rt_index;
1481  ListCell *lc2;
1482 
1483  if (plannedstmt->commandType == CMD_UTILITY)
1484  {
1485  /*
1486  * Ignore utility statements, except those (such as EXPLAIN) that
1487  * contain a parsed-but-not-planned query. Note: it's okay to use
1488  * ScanQueryForLocks, even though the query hasn't been through
1489  * rule rewriting, because rewriting doesn't change the query
1490  * representation.
1491  */
1492  Query *query = UtilityContainsQuery(plannedstmt->utilityStmt);
1493 
1494  if (query)
1495  ScanQueryForLocks(query, acquire);
1496  continue;
1497  }
1498 
1499  rt_index = 0;
1500  foreach(lc2, plannedstmt->rtable)
1501  {
1502  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc2);
1503  LOCKMODE lockmode;
1504  PlanRowMark *rc;
1505 
1506  rt_index++;
1507 
1508  if (rte->rtekind != RTE_RELATION)
1509  continue;
1510 
1511  /*
1512  * Acquire the appropriate type of lock on each relation OID. Note
1513  * that we don't actually try to open the rel, and hence will not
1514  * fail if it's been dropped entirely --- we'll just transiently
1515  * acquire a non-conflicting lock.
1516  */
1517  if (list_member_int(plannedstmt->resultRelations, rt_index) ||
1518  list_member_int(plannedstmt->nonleafResultRelations, rt_index))
1519  lockmode = RowExclusiveLock;
1520  else if ((rc = get_plan_rowmark(plannedstmt->rowMarks, rt_index)) != NULL &&
1522  lockmode = RowShareLock;
1523  else
1524  lockmode = AccessShareLock;
1525 
1526  if (acquire)
1527  LockRelationOid(rte->relid, lockmode);
1528  else
1529  UnlockRelationOid(rte->relid, lockmode);
1530  }
1531  }
1532 }
1533 
1534 /*
1535  * AcquirePlannerLocks: acquire locks needed for planning of a querytree list;
1536  * or release them if acquire is false.
1537  *
1538  * Note that we don't actually try to open the relations, and hence will not
1539  * fail if one has been dropped entirely --- we'll just transiently acquire
1540  * a non-conflicting lock.
1541  */
1542 static void
1543 AcquirePlannerLocks(List *stmt_list, bool acquire)
1544 {
1545  ListCell *lc;
1546 
1547  foreach(lc, stmt_list)
1548  {
1549  Query *query = castNode(Query, lfirst(lc));
1550 
1551  if (query->commandType == CMD_UTILITY)
1552  {
1553  /* Ignore utility statements, unless they contain a Query */
1554  query = UtilityContainsQuery(query->utilityStmt);
1555  if (query)
1556  ScanQueryForLocks(query, acquire);
1557  continue;
1558  }
1559 
1560  ScanQueryForLocks(query, acquire);
1561  }
1562 }
1563 
1564 /*
1565  * ScanQueryForLocks: recursively scan one Query for AcquirePlannerLocks.
1566  */
1567 static void
1568 ScanQueryForLocks(Query *parsetree, bool acquire)
1569 {
1570  ListCell *lc;
1571  int rt_index;
1572 
1573  /* Shouldn't get called on utility commands */
1574  Assert(parsetree->commandType != CMD_UTILITY);
1575 
1576  /*
1577  * First, process RTEs of the current query level.
1578  */
1579  rt_index = 0;
1580  foreach(lc, parsetree->rtable)
1581  {
1582  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
1583  LOCKMODE lockmode;
1584 
1585  rt_index++;
1586  switch (rte->rtekind)
1587  {
1588  case RTE_RELATION:
1589  /* Acquire or release the appropriate type of lock */
1590  if (rt_index == parsetree->resultRelation)
1591  lockmode = RowExclusiveLock;
1592  else if (get_parse_rowmark(parsetree, rt_index) != NULL)
1593  lockmode = RowShareLock;
1594  else
1595  lockmode = AccessShareLock;
1596  if (acquire)
1597  LockRelationOid(rte->relid, lockmode);
1598  else
1599  UnlockRelationOid(rte->relid, lockmode);
1600  break;
1601 
1602  case RTE_SUBQUERY:
1603  /* Recurse into subquery-in-FROM */
1604  ScanQueryForLocks(rte->subquery, acquire);
1605  break;
1606 
1607  default:
1608  /* ignore other types of RTEs */
1609  break;
1610  }
1611  }
1612 
1613  /* Recurse into subquery-in-WITH */
1614  foreach(lc, parsetree->cteList)
1615  {
1617 
1618  ScanQueryForLocks(castNode(Query, cte->ctequery), acquire);
1619  }
1620 
1621  /*
1622  * Recurse into sublink subqueries, too. But we already did the ones in
1623  * the rtable and cteList.
1624  */
1625  if (parsetree->hasSubLinks)
1626  {
1628  (void *) &acquire,
1630  }
1631 }
1632 
1633 /*
1634  * Walker to find sublink subqueries for ScanQueryForLocks
1635  */
1636 static bool
1637 ScanQueryWalker(Node *node, bool *acquire)
1638 {
1639  if (node == NULL)
1640  return false;
1641  if (IsA(node, SubLink))
1642  {
1643  SubLink *sub = (SubLink *) node;
1644 
1645  /* Do what we came for */
1646  ScanQueryForLocks(castNode(Query, sub->subselect), *acquire);
1647  /* Fall through to process lefthand args of SubLink */
1648  }
1649 
1650  /*
1651  * Do NOT recurse into Query nodes, because ScanQueryForLocks already
1652  * processed subselects of subselects for us.
1653  */
1655  (void *) acquire);
1656 }
1657 
1658 /*
1659  * PlanCacheComputeResultDesc: given a list of analyzed-and-rewritten Queries,
1660  * determine the result tupledesc it will produce. Returns NULL if the
1661  * execution will not return tuples.
1662  *
1663  * Note: the result is created or copied into current memory context.
1664  */
1665 static TupleDesc
1667 {
1668  Query *query;
1669 
1670  switch (ChoosePortalStrategy(stmt_list))
1671  {
1672  case PORTAL_ONE_SELECT:
1673  case PORTAL_ONE_MOD_WITH:
1674  query = castNode(Query, linitial(stmt_list));
1675  return ExecCleanTypeFromTL(query->targetList, false);
1676 
1677  case PORTAL_ONE_RETURNING:
1678  query = QueryListGetPrimaryStmt(stmt_list);
1679  Assert(query->returningList);
1680  return ExecCleanTypeFromTL(query->returningList, false);
1681 
1682  case PORTAL_UTIL_SELECT:
1683  query = castNode(Query, linitial(stmt_list));
1684  Assert(query->utilityStmt);
1685  return UtilityTupleDescriptor(query->utilityStmt);
1686 
1687  case PORTAL_MULTI_QUERY:
1688  /* will not return tuples */
1689  break;
1690  }
1691  return NULL;
1692 }
1693 
1694 /*
1695  * PlanCacheRelCallback
1696  * Relcache inval callback function
1697  *
1698  * Invalidate all plans mentioning the given rel, or all plans mentioning
1699  * any rel at all if relid == InvalidOid.
1700  */
1701 static void
1703 {
1704  CachedPlanSource *plansource;
1705 
1706  for (plansource = first_saved_plan; plansource; plansource = plansource->next_saved)
1707  {
1708  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1709 
1710  /* No work if it's already invalidated */
1711  if (!plansource->is_valid)
1712  continue;
1713 
1714  /* Never invalidate transaction control commands */
1715  if (IsTransactionStmtPlan(plansource))
1716  continue;
1717 
1718  /*
1719  * Check the dependency list for the rewritten querytree.
1720  */
1721  if ((relid == InvalidOid) ? plansource->relationOids != NIL :
1722  list_member_oid(plansource->relationOids, relid))
1723  {
1724  /* Invalidate the querytree and generic plan */
1725  plansource->is_valid = false;
1726  if (plansource->gplan)
1727  plansource->gplan->is_valid = false;
1728  }
1729 
1730  /*
1731  * The generic plan, if any, could have more dependencies than the
1732  * querytree does, so we have to check it too.
1733  */
1734  if (plansource->gplan && plansource->gplan->is_valid)
1735  {
1736  ListCell *lc;
1737 
1738  foreach(lc, plansource->gplan->stmt_list)
1739  {
1740  PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc));
1741 
1742  if (plannedstmt->commandType == CMD_UTILITY)
1743  continue; /* Ignore utility statements */
1744  if ((relid == InvalidOid) ? plannedstmt->relationOids != NIL :
1745  list_member_oid(plannedstmt->relationOids, relid))
1746  {
1747  /* Invalidate the generic plan only */
1748  plansource->gplan->is_valid = false;
1749  break; /* out of stmt_list scan */
1750  }
1751  }
1752  }
1753  }
1754 }
1755 
1756 /*
1757  * PlanCacheFuncCallback
1758  * Syscache inval callback function for PROCOID cache
1759  *
1760  * Invalidate all plans mentioning the object with the specified hash value,
1761  * or all plans mentioning any member of this cache if hashvalue == 0.
1762  *
1763  * Note that the coding would support use for multiple caches, but right
1764  * now only user-defined functions are tracked this way.
1765  */
1766 static void
1767 PlanCacheFuncCallback(Datum arg, int cacheid, uint32 hashvalue)
1768 {
1769  CachedPlanSource *plansource;
1770 
1771  for (plansource = first_saved_plan; plansource; plansource = plansource->next_saved)
1772  {
1773  ListCell *lc;
1774 
1775  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1776 
1777  /* No work if it's already invalidated */
1778  if (!plansource->is_valid)
1779  continue;
1780 
1781  /* Never invalidate transaction control commands */
1782  if (IsTransactionStmtPlan(plansource))
1783  continue;
1784 
1785  /*
1786  * Check the dependency list for the rewritten querytree.
1787  */
1788  foreach(lc, plansource->invalItems)
1789  {
1790  PlanInvalItem *item = (PlanInvalItem *) lfirst(lc);
1791 
1792  if (item->cacheId != cacheid)
1793  continue;
1794  if (hashvalue == 0 ||
1795  item->hashValue == hashvalue)
1796  {
1797  /* Invalidate the querytree and generic plan */
1798  plansource->is_valid = false;
1799  if (plansource->gplan)
1800  plansource->gplan->is_valid = false;
1801  break;
1802  }
1803  }
1804 
1805  /*
1806  * The generic plan, if any, could have more dependencies than the
1807  * querytree does, so we have to check it too.
1808  */
1809  if (plansource->gplan && plansource->gplan->is_valid)
1810  {
1811  foreach(lc, plansource->gplan->stmt_list)
1812  {
1813  PlannedStmt *plannedstmt = castNode(PlannedStmt, lfirst(lc));
1814  ListCell *lc3;
1815 
1816  if (plannedstmt->commandType == CMD_UTILITY)
1817  continue; /* Ignore utility statements */
1818  foreach(lc3, plannedstmt->invalItems)
1819  {
1820  PlanInvalItem *item = (PlanInvalItem *) lfirst(lc3);
1821 
1822  if (item->cacheId != cacheid)
1823  continue;
1824  if (hashvalue == 0 ||
1825  item->hashValue == hashvalue)
1826  {
1827  /* Invalidate the generic plan only */
1828  plansource->gplan->is_valid = false;
1829  break; /* out of invalItems scan */
1830  }
1831  }
1832  if (!plansource->gplan->is_valid)
1833  break; /* out of stmt_list scan */
1834  }
1835  }
1836  }
1837 }
1838 
1839 /*
1840  * PlanCacheSysCallback
1841  * Syscache inval callback function for other caches
1842  *
1843  * Just invalidate everything...
1844  */
1845 static void
1846 PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
1847 {
1848  ResetPlanCache();
1849 }
1850 
1851 /*
1852  * ResetPlanCache: invalidate all cached plans.
1853  */
1854 void
1856 {
1857  CachedPlanSource *plansource;
1858 
1859  for (plansource = first_saved_plan; plansource; plansource = plansource->next_saved)
1860  {
1861  ListCell *lc;
1862 
1863  Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC);
1864 
1865  /* No work if it's already invalidated */
1866  if (!plansource->is_valid)
1867  continue;
1868 
1869  /*
1870  * We *must not* mark transaction control statements as invalid,
1871  * particularly not ROLLBACK, because they may need to be executed in
1872  * aborted transactions when we can't revalidate them (cf bug #5269).
1873  */
1874  if (IsTransactionStmtPlan(plansource))
1875  continue;
1876 
1877  /*
1878  * In general there is no point in invalidating utility statements
1879  * since they have no plans anyway. So invalidate it only if it
1880  * contains at least one non-utility statement, or contains a utility
1881  * statement that contains a pre-analyzed query (which could have
1882  * dependencies.)
1883  */
1884  foreach(lc, plansource->query_list)
1885  {
1886  Query *query = castNode(Query, lfirst(lc));
1887 
1888  if (query->commandType != CMD_UTILITY ||
1890  {
1891  /* non-utility statement, so invalidate */
1892  plansource->is_valid = false;
1893  if (plansource->gplan)
1894  plansource->gplan->is_valid = false;
1895  /* no need to look further */
1896  break;
1897  }
1898  }
1899  }
1900 }
Oid planRoleId
Definition: plancache.h:136
#define CACHEDPLAN_MAGIC
Definition: plancache.h:25
bool dependsOnRole
Definition: plannodes.h:57
MemoryContext context
Definition: plancache.h:92
#define NIL
Definition: pg_list.h:69
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2257
bool rewriteRowSecurity
Definition: plancache.h:101
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
#define IsA(nodeptr, _type_)
Definition: nodes.h:557
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
RowMarkType markType
Definition: plannodes.h:981
bool analyze_requires_snapshot(RawStmt *parseTree)
Definition: analyze.c:345
static void AcquireExecutorLocks(List *stmt_list, bool acquire)
Definition: plancache.c:1473
bool is_valid
Definition: plancache.h:135
RowMarkClause * get_parse_rowmark(Query *qry, Index rtindex)
static void ReleaseGenericPlan(CachedPlanSource *plansource)
Definition: plancache.c:528
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
MemoryContext MemoryContextGetParent(MemoryContext context)
Definition: mcxt.c:403
CachedPlanSource * CreateOneShotCachedPlan(RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
Definition: plancache.c:234
int LOCKMODE
Definition: lockdefs.h:26
List * nonleafResultRelations
Definition: plannodes.h:69
Oid GetUserId(void)
Definition: miscinit.c:283
void UnlockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:182
#define castNode(_type_, nodeptr)
Definition: nodes.h:575
const char * commandTag
Definition: plancache.h:84
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
static void ScanQueryForLocks(Query *parsetree, bool acquire)
Definition: plancache.c:1568
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
List * relationOids
Definition: plannodes.h:77
char * pstrdup(const char *in)
Definition: mcxt.c:1077
int resultRelation
Definition: parsenodes.h:113
int refcount
Definition: plancache.h:141
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define AccessShareLock
Definition: lockdefs.h:36
Definition: nodes.h:506
int errcode(int sqlerrcode)
Definition: elog.c:575
void ResourceOwnerRememberPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1064
bool dependsOnRole
Definition: plancache.h:137
void ResourceOwnerEnlargePlanCacheRefs(ResourceOwner owner)
Definition: resowner.c:1053
return result
Definition: formatting.c:1618
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
MemoryContext context
Definition: plancache.h:142
unsigned int Oid
Definition: postgres_ext.h:31
Node * utilityStmt
Definition: parsenodes.h:111
bool transientPlan
Definition: plannodes.h:55
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
static void PlanCacheFuncCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:1767
double total_custom_cost
Definition: plancache.h:115
#define RowMarkRequiresRowShareLock(marktype)
Definition: plannodes.h:934
struct CachedPlan * gplan
Definition: plancache.h:104
struct Plan * planTree
Definition: plannodes.h:61
List * invalItems
Definition: plannodes.h:79
List * targetList
Definition: parsenodes.h:131
TransactionId TransactionXmin
Definition: snapmgr.c:164
TupleDesc resultDesc
Definition: plancache.h:91
#define QTW_IGNORE_RC_SUBQUERIES
Definition: nodeFuncs.h:22
void CacheRegisterRelcacheCallback(RelcacheCallbackFunction func, Datum arg)
Definition: inval.c:1405
void ResourceOwnerForgetPlanCacheRef(ResourceOwner owner, CachedPlan *plan)
Definition: resowner.c:1073
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:1844
List * pg_analyze_and_rewrite(RawStmt *parsetree, const char *query_string, Oid *paramTypes, int numParams)
Definition: postgres.c:644
struct CachedPlanSource * next_saved
Definition: plancache.h:112
#define CURSOR_OPT_CUSTOM_PLAN
Definition: parsenodes.h:2578
#define linitial(l)
Definition: pg_list.h:110
List * rtable
Definition: parsenodes.h:128
#define ERROR
Definition: elog.h:43
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner)
Definition: plancache.c:1131
List * FetchStatementTargetList(Node *stmt)
Definition: pquery.c:357
static void PlanCacheRelCallback(Datum arg, Oid relid)
Definition: plancache.c:1702
static Query * QueryListGetPrimaryStmt(List *stmts)
Definition: plancache.c:1454
CachedPlanSource * CopyCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:1318
OverrideSearchPath * CopyOverrideSearchPath(OverrideSearchPath *path)
Definition: namespace.c:3207
List * invalItems
Definition: plancache.h:96
OverrideSearchPath * GetOverrideSearchPath(MemoryContext context)
Definition: namespace.c:3171
bool list_member_int(const List *list, int datum)
Definition: list.c:485
void ResetPlanCache(void)
Definition: plancache.c:1855
Oid * param_types
Definition: plancache.h:85
static CachedPlanSource * first_saved_plan
Definition: plancache.c:88
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
List * relationOids
Definition: plancache.h:95
#define RowExclusiveLock
Definition: lockdefs.h:38
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
Definition: plancache.c:151
Node * utilityStmt
Definition: plannodes.h:83
void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
Definition: plancache.c:1252
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:268
void * parserSetupArg
Definition: plancache.h:88
static bool ScanQueryWalker(Node *node, bool *acquire)
Definition: plancache.c:1637
void(* ParserSetupHook)(struct ParseState *pstate, void *arg)
Definition: params.h:66
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:846
double cpu_operator_cost
Definition: costsize.c:108
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
List * returningList
Definition: parsenodes.h:135
void CachedPlanSetParentContext(CachedPlanSource *plansource, MemoryContext newcontext)
Definition: plancache.c:1280
ParserSetupHook parserSetup
Definition: plancache.h:87
#define ereport(elevel, rest)
Definition: elog.h:122
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg)
Definition: postgres.c:679
#define RowShareLock
Definition: lockdefs.h:37
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
void CacheRegisterSyscacheCallback(int cacheid, SyscacheCallbackFunction func, Datum arg)
Definition: inval.c:1381
void * palloc0(Size size)
Definition: mcxt.c:878
bool is_saved
Definition: plancache.h:134
uintptr_t Datum
Definition: postgres.h:372
CmdType commandType
Definition: plannodes.h:45
List * rowMarks
Definition: plannodes.h:75
uint32 hashValue
Definition: plannodes.h:1002
#define InvalidOid
Definition: postgres_ext.h:36
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:440
CmdType commandType
Definition: parsenodes.h:103
bool OverrideSearchPathMatchesCurrent(OverrideSearchPath *path)
Definition: namespace.c:3223
bool list_member_oid(const List *list, Oid datum)
Definition: list.c:505
#define NULL
Definition: c.h:229
bool row_security
Definition: guc.c:449
double generic_cost
Definition: plancache.h:114
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
void extract_query_dependencies(Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
Definition: setrefs.c:2511
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:324
bool canSetTag
Definition: parsenodes.h:109
const char * query_string
Definition: plancache.h:83
int generation
Definition: plancache.h:140
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1855
static int list_length(const List *l)
Definition: pg_list.h:89
List * CachedPlanGetTargetList(CachedPlanSource *plansource)
Definition: plancache.c:1421
List * rtable
Definition: plannodes.h:63
struct RawStmt * raw_parse_tree
Definition: plancache.h:82
static void PlanCacheSysCallback(Datum arg, int cacheid, uint32 hashvalue)
Definition: plancache.c:1846
void InitPlanCache(void)
Definition: plancache.c:115
PortalStrategy ChoosePortalStrategy(List *stmts)
Definition: pquery.c:218
static bool CheckCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:793
bool is_oneshot
Definition: plancache.h:133
void FreeTupleDesc(TupleDesc tupdesc)
Definition: tupdesc.c:266
RTEKind rtekind
Definition: parsenodes.h:916
static CachedPlan * BuildCachedPlan(CachedPlanSource *plansource, List *qlist, ParamListInfo boundParams)
Definition: plancache.c:877
List * cteList
Definition: parsenodes.h:126
Query * subquery
Definition: parsenodes.h:934
void * palloc(Size size)
Definition: mcxt.c:849
#define CURSOR_OPT_GENERIC_PLAN
Definition: parsenodes.h:2577
int errmsg(const char *fmt,...)
Definition: elog.c:797
bool hasSubLinks
Definition: parsenodes.h:119
static void AcquirePlannerLocks(List *stmt_list, bool acquire)
Definition: plancache.c:1543
List * resultRelations
Definition: plannodes.h:66
MemoryContext query_context
Definition: plancache.h:99
PlanRowMark * get_plan_rowmark(List *rowmarks, Index rtindex)
Definition: preptlist.c:401
Cost total_cost
Definition: plannodes.h:115
bool equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
Definition: tupdesc.c:352
void * arg
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:485
bool CachedPlanIsValid(CachedPlanSource *plansource)
Definition: plancache.c:1408
TupleDesc ExecCleanTypeFromTL(List *targetList, bool hasoid)
Definition: execTuples.c:900
#define ALLOCSET_START_SMALL_SIZES
Definition: memutils.h:182
List * query_list
Definition: plancache.h:94
List * stmt_list
Definition: plancache.h:132
#define elog
Definition: elog.h:219
#define IsTransactionStmtPlan(plansource)
Definition: plancache.c:78
#define CACHEDPLANSOURCE_MAGIC
Definition: plancache.h:24
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static List * RevalidateCachedQuery(CachedPlanSource *plansource)
Definition: plancache.c:556
#define copyObject(obj)
Definition: nodes.h:618
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:105
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
TransactionId saved_xmin
Definition: plancache.h:138
Definition: pg_list.h:45
TupleDesc UtilityTupleDescriptor(Node *parsetree)
Definition: utility.c:1753
List * pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams)
Definition: postgres.c:842
static bool choose_custom_plan(CachedPlanSource *plansource, ParamListInfo boundParams)
Definition: plancache.c:1015
static TupleDesc PlanCacheComputeResultDesc(List *stmt_list)
Definition: plancache.c:1666
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
struct OverrideSearchPath * search_path
Definition: plancache.h:97
static double cached_plan_cost(CachedPlan *plan, bool include_planner)
Definition: plancache.c:1066