Coverage Report

Created: 2026-10-16 06:48

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