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