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