* SaveCachedPlan: save a cached plan permanently * * This function moves the cached plan underneath CacheMemoryContext (making * it live for the life of the backend, unless explicitly dropped), and adds * it to the list of cached plans that are checked for invalidation when an * sinval event occurs. * * This is guaranteed not to throw error, except for the caller-error case * of trying to
| 459 | * automatically on transaction abort. |
| 460 | */ |
| 461 | void |
| 462 | SaveCachedPlan(CachedPlanSource *plansource) |
| 463 | { |
| 464 | /* Assert caller is doing things in a sane order */ |
| 465 | Assert(plansource->magic == CACHEDPLANSOURCE_MAGIC); |
| 466 | Assert(plansource->is_complete); |
| 467 | Assert(!plansource->is_saved); |
| 468 | |
| 469 | /* This seems worth a real test, though */ |
| 470 | if (plansource->is_oneshot) |
| 471 | elog(ERROR, "cannot save one-shot cached plan"); |
| 472 | |
| 473 | /* |
| 474 | * In typical use, this function would be called before generating any |
| 475 | * plans from the CachedPlanSource. If there is a generic plan, moving it |
| 476 | * into CacheMemoryContext would be pretty risky since it's unclear |
| 477 | * whether the caller has taken suitable care with making references |
| 478 | * long-lived. Best thing to do seems to be to discard the plan. |
| 479 | */ |
| 480 | ReleaseGenericPlan(plansource); |
| 481 | |
| 482 | /* |
| 483 | * Reparent the source memory context under CacheMemoryContext so that it |
| 484 | * will live indefinitely. The query_context follows along since it's |
| 485 | * already a child of the other one. |
| 486 | */ |
| 487 | MemoryContextSetParent(plansource->context, CacheMemoryContext); |
| 488 | |
| 489 | /* |
| 490 | * Add the entry to the global list of cached plans. |
| 491 | */ |
| 492 | dlist_push_tail(&saved_plan_list, &plansource->node); |
| 493 | |
| 494 | plansource->is_saved = true; |
| 495 | } |
| 496 | |
| 497 | /* |
| 498 | * DropCachedPlan: destroy a cached plan. |
no test coverage detected