LCOV - code coverage report
Current view: top level - src/backend/utils/cache - plancache.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 582 679 85.7 %
Date: 2025-02-22 07:14:56 Functions: 35 37 94.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14