|
33 | 33 | * Portions Copyright (c) 1994, Regents of the University of California
|
34 | 34 | *
|
35 | 35 | * IDENTIFICATION
|
36 |
| - * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.8 2007/04/16 18:21:07 tgl Exp $ |
| 36 | + * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.9 2007/05/14 18:13:21 tgl Exp $ |
37 | 37 | *
|
38 | 38 | *-------------------------------------------------------------------------
|
39 | 39 | */
|
@@ -69,6 +69,7 @@ static List *cached_plans_list = NIL;
|
69 | 69 |
|
70 | 70 | static void StoreCachedPlan(CachedPlanSource *plansource, List *stmt_list,
|
71 | 71 | MemoryContext plan_context);
|
| 72 | +static List *do_planning(List *querytrees, int cursorOptions); |
72 | 73 | static void AcquireExecutorLocks(List *stmt_list, bool acquire);
|
73 | 74 | static void AcquirePlannerLocks(List *stmt_list, bool acquire);
|
74 | 75 | static void LockRelid(Oid relid, LOCKMODE lockmode, void *arg);
|
@@ -462,12 +463,8 @@ RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner)
|
462 | 463 |
|
463 | 464 | if (plansource->fully_planned)
|
464 | 465 | {
|
465 |
| - /* |
466 |
| - * Generate plans for queries. Assume snapshot is not set yet |
467 |
| - * (XXX this may be wasteful, won't all callers have done that?) |
468 |
| - */ |
469 |
| - slist = pg_plan_queries(slist, plansource->cursor_options, NULL, |
470 |
| - true); |
| 466 | + /* Generate plans for queries */ |
| 467 | + slist = do_planning(slist, plansource->cursor_options); |
471 | 468 | }
|
472 | 469 |
|
473 | 470 | /*
|
@@ -522,6 +519,49 @@ RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner)
|
522 | 519 | return plan;
|
523 | 520 | }
|
524 | 521 |
|
| 522 | +/* |
| 523 | + * Invoke the planner on some rewritten queries. This is broken out of |
| 524 | + * RevalidateCachedPlan just to avoid plastering "volatile" all over that |
| 525 | + * function's variables. |
| 526 | + */ |
| 527 | +static List * |
| 528 | +do_planning(List *querytrees, int cursorOptions) |
| 529 | +{ |
| 530 | + List *stmt_list; |
| 531 | + |
| 532 | + /* |
| 533 | + * If a snapshot is already set (the normal case), we can just use that |
| 534 | + * for planning. But if it isn't, we have to tell pg_plan_queries to make |
| 535 | + * a snap if it needs one. In that case we should arrange to reset |
| 536 | + * ActiveSnapshot afterward, to ensure that RevalidateCachedPlan has no |
| 537 | + * caller-visible effects on the snapshot. Having to replan is an unusual |
| 538 | + * case, and it seems a really bad idea for RevalidateCachedPlan to affect |
| 539 | + * the snapshot only in unusual cases. (Besides, the snap might have |
| 540 | + * been created in a short-lived context.) |
| 541 | + */ |
| 542 | + if (ActiveSnapshot != NULL) |
| 543 | + stmt_list = pg_plan_queries(querytrees, cursorOptions, NULL, false); |
| 544 | + else |
| 545 | + { |
| 546 | + PG_TRY(); |
| 547 | + { |
| 548 | + stmt_list = pg_plan_queries(querytrees, cursorOptions, NULL, true); |
| 549 | + } |
| 550 | + PG_CATCH(); |
| 551 | + { |
| 552 | + /* Restore global vars and propagate error */ |
| 553 | + ActiveSnapshot = NULL; |
| 554 | + PG_RE_THROW(); |
| 555 | + } |
| 556 | + PG_END_TRY(); |
| 557 | + |
| 558 | + ActiveSnapshot = NULL; |
| 559 | + } |
| 560 | + |
| 561 | + return stmt_list; |
| 562 | +} |
| 563 | + |
| 564 | + |
525 | 565 | /*
|
526 | 566 | * ReleaseCachedPlan: release active use of a cached plan.
|
527 | 567 | *
|
|
0 commit comments