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