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