diff options
Diffstat (limited to 'src/backend/tcop')
-rw-r--r-- | src/backend/tcop/fastpath.c | 7 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 56 | ||||
-rw-r--r-- | src/backend/tcop/pquery.c | 84 |
3 files changed, 68 insertions, 79 deletions
diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c index 80cf04680a9..90848112580 100644 --- a/src/backend/tcop/fastpath.c +++ b/src/backend/tcop/fastpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.99 2008/03/26 18:48:59 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/fastpath.c,v 1.100 2008/05/12 20:02:01 alvherre Exp $ * * NOTES * This cruft is the server side of PQfn. @@ -309,7 +309,7 @@ HandleFunctionRequest(StringInfo msgBuf) * Now that we know we are in a valid transaction, set snapshot in case * needed by function itself or one of the datatype I/O routines. */ - ActiveSnapshot = CopySnapshot(GetTransactionSnapshot()); + PushActiveSnapshot(GetTransactionSnapshot()); /* * Begin parsing the buffer contents. @@ -396,6 +396,9 @@ HandleFunctionRequest(StringInfo msgBuf) SendFunctionResult(retval, fcinfo.isnull, fip->rettype, rformat); + /* We no longer need the snapshot */ + PopActiveSnapshot(); + /* * Emit duration logging if appropriate. */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index d9599851c59..d212eb9449e 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.551 2008/05/12 00:00:50 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.552 2008/05/12 20:02:01 alvherre Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -732,49 +732,37 @@ List * pg_plan_queries(List *querytrees, int cursorOptions, ParamListInfo boundParams, bool needSnapshot) { - List * volatile stmt_list = NIL; - Snapshot saveActiveSnapshot = ActiveSnapshot; + List *stmt_list = NIL; + ListCell *query_list; + bool snapshot_set = false; - /* PG_TRY to ensure previous ActiveSnapshot is restored on error */ - PG_TRY(); + foreach(query_list, querytrees) { - Snapshot mySnapshot = NULL; - ListCell *query_list; + Query *query = (Query *) lfirst(query_list); + Node *stmt; - foreach(query_list, querytrees) + if (query->commandType == CMD_UTILITY) { - Query *query = (Query *) lfirst(query_list); - Node *stmt; - - if (query->commandType == CMD_UTILITY) - { - /* Utility commands have no plans. */ - stmt = query->utilityStmt; - } - else + /* Utility commands have no plans. */ + stmt = query->utilityStmt; + } + else + { + if (needSnapshot && !snapshot_set) { - if (needSnapshot && mySnapshot == NULL) - { - mySnapshot = CopySnapshot(GetTransactionSnapshot()); - ActiveSnapshot = mySnapshot; - } - stmt = (Node *) pg_plan_query(query, cursorOptions, - boundParams); + PushActiveSnapshot(GetTransactionSnapshot()); + snapshot_set = true; } - stmt_list = lappend(stmt_list, stmt); + stmt = (Node *) pg_plan_query(query, cursorOptions, + boundParams); } - if (mySnapshot) - FreeSnapshot(mySnapshot); + stmt_list = lappend(stmt_list, stmt); } - PG_CATCH(); - { - ActiveSnapshot = saveActiveSnapshot; - PG_RE_THROW(); - } - PG_END_TRY(); - ActiveSnapshot = saveActiveSnapshot; + + if (snapshot_set) + PopActiveSnapshot(); return stmt_list; } 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; |