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