diff options
Diffstat (limited to 'src/backend/tcop/pquery.c')
-rw-r--r-- | src/backend/tcop/pquery.c | 84 |
1 files changed, 41 insertions, 43 deletions
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index cf5f2784142..a4afab04025 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.122 2008/03/26 18:48:59 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.123 2008/05/12 20:02:02 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -70,8 +70,9 @@ CreateQueryDesc(PlannedStmt *plannedstmt, qd->operation = plannedstmt->commandType; /* operation */ qd->plannedstmt = plannedstmt; /* plan */ qd->utilitystmt = plannedstmt->utilityStmt; /* in case DECLARE CURSOR */ - qd->snapshot = snapshot; /* snapshot */ - qd->crosscheck_snapshot = crosscheck_snapshot; /* RI check snapshot */ + qd->snapshot = RegisterSnapshot(snapshot); /* snapshot */ + /* RI check snapshot */ + qd->crosscheck_snapshot = RegisterSnapshot(crosscheck_snapshot); qd->dest = dest; /* output dest */ qd->params = params; /* parameter values passed into query */ qd->doInstrument = doInstrument; /* instrumentation wanted? */ @@ -98,7 +99,7 @@ CreateUtilityQueryDesc(Node *utilitystmt, qd->operation = CMD_UTILITY; /* operation */ qd->plannedstmt = NULL; qd->utilitystmt = utilitystmt; /* utility command */ - qd->snapshot = snapshot; /* snapshot */ + qd->snapshot = RegisterSnapshot(snapshot); /* snapshot */ qd->crosscheck_snapshot = InvalidSnapshot; /* RI check snapshot */ qd->dest = dest; /* output dest */ qd->params = params; /* parameter values passed into query */ @@ -120,6 +121,11 @@ FreeQueryDesc(QueryDesc *qdesc) { /* Can't be a live query */ Assert(qdesc->estate == NULL); + + /* forget our snapshots */ + UnregisterSnapshot(qdesc->snapshot); + UnregisterSnapshot(qdesc->crosscheck_snapshot); + /* Only the QueryDesc itself need be freed */ pfree(qdesc); } @@ -152,16 +158,15 @@ ProcessQuery(PlannedStmt *plan, elog(DEBUG3, "ProcessQuery"); /* - * Must always set snapshot for plannable queries. Note we assume that - * caller will take care of restoring ActiveSnapshot on exit/error. + * Must always set a snapshot for plannable queries. */ - ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); + PushActiveSnapshot(GetTransactionSnapshot()); /* * Create the QueryDesc object */ queryDesc = CreateQueryDesc(plan, - ActiveSnapshot, InvalidSnapshot, + GetActiveSnapshot(), InvalidSnapshot, dest, params, false); /* @@ -216,15 +221,14 @@ ProcessQuery(PlannedStmt *plan, /* Now take care of any queued AFTER triggers */ AfterTriggerEndQuery(queryDesc->estate); + PopActiveSnapshot(); + /* * Now, we close down all the scans and free allocated resources. */ ExecutorEnd(queryDesc); FreeQueryDesc(queryDesc); - - FreeSnapshot(ActiveSnapshot); - ActiveSnapshot = NULL; } /* @@ -446,7 +450,6 @@ void PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot) { Portal saveActivePortal; - Snapshot saveActiveSnapshot; ResourceOwner saveResourceOwner; MemoryContext savePortalContext; MemoryContext oldContext; @@ -460,13 +463,11 @@ PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot) * Set up global portal context pointers. */ saveActivePortal = ActivePortal; - saveActiveSnapshot = ActiveSnapshot; saveResourceOwner = CurrentResourceOwner; savePortalContext = PortalContext; PG_TRY(); { ActivePortal = portal; - ActiveSnapshot = NULL; /* will be set later */ CurrentResourceOwner = portal->resowner; PortalContext = PortalGetHeapMemory(portal); @@ -487,21 +488,18 @@ PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot) { case PORTAL_ONE_SELECT: - /* - * Must set snapshot before starting executor. Be sure to - * copy it into the portal's context. - */ + /* Must set snapshot before starting executor. */ if (snapshot) - ActiveSnapshot = CopySnapshot(snapshot); + PushActiveSnapshot(snapshot); else - ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); + PushActiveSnapshot(GetTransactionSnapshot()); /* * Create QueryDesc in portal's context; for the moment, set * the destination to DestNone. */ queryDesc = CreateQueryDesc((PlannedStmt *) linitial(portal->stmts), - ActiveSnapshot, + GetActiveSnapshot(), InvalidSnapshot, None_Receiver, params, @@ -545,6 +543,8 @@ PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot) portal->atEnd = false; /* allow fetches */ portal->portalPos = 0; portal->posOverflow = false; + + PopActiveSnapshot(); break; case PORTAL_ONE_RETURNING: @@ -608,7 +608,6 @@ PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot) /* Restore global vars and propagate error */ ActivePortal = saveActivePortal; - ActiveSnapshot = saveActiveSnapshot; CurrentResourceOwner = saveResourceOwner; PortalContext = savePortalContext; @@ -619,7 +618,6 @@ PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot) MemoryContextSwitchTo(oldContext); ActivePortal = saveActivePortal; - ActiveSnapshot = saveActiveSnapshot; CurrentResourceOwner = saveResourceOwner; PortalContext = savePortalContext; @@ -707,7 +705,6 @@ PortalRun(Portal portal, long count, bool isTopLevel, ResourceOwner saveTopTransactionResourceOwner; MemoryContext saveTopTransactionContext; Portal saveActivePortal; - Snapshot saveActiveSnapshot; ResourceOwner saveResourceOwner; MemoryContext savePortalContext; MemoryContext saveMemoryContext; @@ -751,14 +748,12 @@ PortalRun(Portal portal, long count, bool isTopLevel, saveTopTransactionResourceOwner = TopTransactionResourceOwner; saveTopTransactionContext = TopTransactionContext; saveActivePortal = ActivePortal; - saveActiveSnapshot = ActiveSnapshot; saveResourceOwner = CurrentResourceOwner; savePortalContext = PortalContext; saveMemoryContext = CurrentMemoryContext; PG_TRY(); { ActivePortal = portal; - ActiveSnapshot = NULL; /* will be set later */ CurrentResourceOwner = portal->resowner; PortalContext = PortalGetHeapMemory(portal); @@ -839,7 +834,6 @@ PortalRun(Portal portal, long count, bool isTopLevel, else MemoryContextSwitchTo(saveMemoryContext); ActivePortal = saveActivePortal; - ActiveSnapshot = saveActiveSnapshot; if (saveResourceOwner == saveTopTransactionResourceOwner) CurrentResourceOwner = TopTransactionResourceOwner; else @@ -855,7 +849,6 @@ PortalRun(Portal portal, long count, bool isTopLevel, else MemoryContextSwitchTo(saveMemoryContext); ActivePortal = saveActivePortal; - ActiveSnapshot = saveActiveSnapshot; if (saveResourceOwner == saveTopTransactionResourceOwner) CurrentResourceOwner = TopTransactionResourceOwner; else @@ -940,9 +933,10 @@ PortalRunSelect(Portal portal, nprocessed = RunFromStore(portal, direction, count, dest); else { - ActiveSnapshot = queryDesc->snapshot; + PushActiveSnapshot(queryDesc->snapshot); ExecutorRun(queryDesc, direction, count); nprocessed = queryDesc->estate->es_processed; + PopActiveSnapshot(); } if (!ScanDirectionIsNoMovement(direction)) @@ -982,9 +976,10 @@ PortalRunSelect(Portal portal, nprocessed = RunFromStore(portal, direction, count, dest); else { - ActiveSnapshot = queryDesc->snapshot; + PushActiveSnapshot(queryDesc->snapshot); ExecutorRun(queryDesc, direction, count); nprocessed = queryDesc->estate->es_processed; + PopActiveSnapshot(); } if (!ScanDirectionIsNoMovement(direction)) @@ -1140,6 +1135,8 @@ static void PortalRunUtility(Portal portal, Node *utilityStmt, bool isTopLevel, DestReceiver *dest, char *completionTag) { + bool active_snapshot_set; + elog(DEBUG3, "ProcessUtility"); /* @@ -1152,9 +1149,6 @@ PortalRunUtility(Portal portal, Node *utilityStmt, bool isTopLevel, * hacks. Beware of listing anything that can modify the database --- if, * say, it has to update an index with expressions that invoke * user-defined functions, then it had better have a snapshot. - * - * Note we assume that caller will take care of restoring ActiveSnapshot - * on exit/error. */ if (!(IsA(utilityStmt, TransactionStmt) || IsA(utilityStmt, LockStmt) || @@ -1167,9 +1161,12 @@ PortalRunUtility(Portal portal, Node *utilityStmt, bool isTopLevel, IsA(utilityStmt, NotifyStmt) || IsA(utilityStmt, UnlistenStmt) || IsA(utilityStmt, CheckPointStmt))) - ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); + { + PushActiveSnapshot(GetTransactionSnapshot()); + active_snapshot_set = true; + } else - ActiveSnapshot = NULL; + active_snapshot_set = false; ProcessUtility(utilityStmt, portal->sourceText, @@ -1181,9 +1178,15 @@ PortalRunUtility(Portal portal, Node *utilityStmt, bool isTopLevel, /* Some utility statements may change context on us */ MemoryContextSwitchTo(PortalGetHeapMemory(portal)); - if (ActiveSnapshot) - FreeSnapshot(ActiveSnapshot); - ActiveSnapshot = NULL; + /* + * Some utility commands may pop the ActiveSnapshot stack from under us, + * so we only pop the stack if we actually see a snapshot set. Note that + * the set of utility commands that do this must be the same set + * disallowed to run inside a transaction; otherwise, we could be popping + * a snapshot that belongs to some other operation. + */ + if (active_snapshot_set && ActiveSnapshotSet()) + PopActiveSnapshot(); } /* @@ -1321,7 +1324,6 @@ PortalRunFetch(Portal portal, { long result; Portal saveActivePortal; - Snapshot saveActiveSnapshot; ResourceOwner saveResourceOwner; MemoryContext savePortalContext; MemoryContext oldContext; @@ -1341,13 +1343,11 @@ PortalRunFetch(Portal portal, * Set up global portal context pointers. */ saveActivePortal = ActivePortal; - saveActiveSnapshot = ActiveSnapshot; saveResourceOwner = CurrentResourceOwner; savePortalContext = PortalContext; PG_TRY(); { ActivePortal = portal; - ActiveSnapshot = NULL; /* will be set later */ CurrentResourceOwner = portal->resowner; PortalContext = PortalGetHeapMemory(portal); @@ -1388,7 +1388,6 @@ PortalRunFetch(Portal portal, /* Restore global vars and propagate error */ ActivePortal = saveActivePortal; - ActiveSnapshot = saveActiveSnapshot; CurrentResourceOwner = saveResourceOwner; PortalContext = savePortalContext; @@ -1402,7 +1401,6 @@ PortalRunFetch(Portal portal, portal->status = PORTAL_READY; ActivePortal = saveActivePortal; - ActiveSnapshot = saveActiveSnapshot; CurrentResourceOwner = saveResourceOwner; PortalContext = savePortalContext; |