aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/pquery.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/tcop/pquery.c')
-rw-r--r--src/backend/tcop/pquery.c93
1 files changed, 72 insertions, 21 deletions
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index fca98fc0fa5..5a1c8b4867b 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.86 2004/09/10 18:40:00 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.87 2004/09/13 20:07:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -32,6 +32,11 @@
Portal ActivePortal = NULL;
+static void ProcessQuery(Query *parsetree,
+ Plan *plan,
+ ParamListInfo params,
+ DestReceiver *dest,
+ char *completionTag);
static uint32 RunFromStore(Portal portal, ScanDirection direction, long count,
DestReceiver *dest);
static long PortalRunSelect(Portal portal, bool forward, long count,
@@ -54,6 +59,8 @@ static void DoPortalRewind(Portal portal);
QueryDesc *
CreateQueryDesc(Query *parsetree,
Plan *plantree,
+ Snapshot snapshot,
+ Snapshot crosscheck_snapshot,
DestReceiver *dest,
ParamListInfo params,
bool doInstrument)
@@ -63,6 +70,8 @@ CreateQueryDesc(Query *parsetree,
qd->operation = parsetree->commandType; /* operation */
qd->parsetree = parsetree; /* parse tree */
qd->plantree = plantree; /* plan */
+ qd->snapshot = snapshot; /* snapshot */
+ qd->crosscheck_snapshot = crosscheck_snapshot; /* RI check snapshot */
qd->dest = dest; /* output dest */
qd->params = params; /* parameter values passed into query */
qd->doInstrument = doInstrument; /* instrumentation wanted? */
@@ -90,7 +99,7 @@ FreeQueryDesc(QueryDesc *qdesc)
/*
* ProcessQuery
- * Execute a single query
+ * Execute a single plannable query within a PORTAL_MULTI_QUERY portal
*
* parsetree: the query tree
* plan: the plan tree for the query
@@ -104,7 +113,7 @@ FreeQueryDesc(QueryDesc *qdesc)
* Must be called in a memory context that will be reset or deleted on
* error; otherwise the executor's memory usage will be leaked.
*/
-void
+static void
ProcessQuery(Query *parsetree,
Plan *plan,
ParamListInfo params,
@@ -114,6 +123,9 @@ ProcessQuery(Query *parsetree,
int operation = parsetree->commandType;
QueryDesc *queryDesc;
+ ereport(DEBUG3,
+ (errmsg_internal("ProcessQuery")));
+
/*
* Check for special-case destinations
*/
@@ -133,9 +145,17 @@ ProcessQuery(Query *parsetree,
}
/*
+ * Must always set snapshot for plannable queries. Note we assume
+ * that caller will take care of restoring ActiveSnapshot on exit/error.
+ */
+ ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
+
+ /*
* Create the QueryDesc object
*/
- queryDesc = CreateQueryDesc(parsetree, plan, dest, params, false);
+ queryDesc = CreateQueryDesc(parsetree, plan,
+ ActiveSnapshot, InvalidSnapshot,
+ dest, params, false);
/*
* Set up to collect AFTER triggers
@@ -145,7 +165,7 @@ ProcessQuery(Query *parsetree,
/*
* Call ExecStart to prepare the plan for execution
*/
- ExecutorStart(queryDesc, false, false);
+ ExecutorStart(queryDesc, false);
/*
* Run the plan to completion.
@@ -195,6 +215,9 @@ ProcessQuery(Query *parsetree,
AfterTriggerEndQuery();
FreeQueryDesc(queryDesc);
+
+ FreeSnapshot(ActiveSnapshot);
+ ActiveSnapshot = NULL;
}
/*
@@ -238,13 +261,19 @@ ChoosePortalStrategy(List *parseTrees)
* the query, they must be passed in here (caller is responsible for
* giving them appropriate lifetime).
*
+ * The caller can optionally pass a snapshot to be used; pass InvalidSnapshot
+ * for the normal behavior of setting a new snapshot. This parameter is
+ * presently ignored for non-PORTAL_ONE_SELECT portals (it's only intended
+ * to be used for cursors).
+ *
* On return, portal is ready to accept PortalRun() calls, and the result
* tupdesc (if any) is known.
*/
void
-PortalStart(Portal portal, ParamListInfo params)
+PortalStart(Portal portal, ParamListInfo params, Snapshot snapshot)
{
Portal saveActivePortal;
+ Snapshot saveActiveSnapshot;
ResourceOwner saveResourceOwner;
MemoryContext savePortalContext;
MemoryContext oldContext;
@@ -259,11 +288,13 @@ PortalStart(Portal portal, ParamListInfo params)
* QueryContext?)
*/
saveActivePortal = ActivePortal;
+ saveActiveSnapshot = ActiveSnapshot;
saveResourceOwner = CurrentResourceOwner;
savePortalContext = PortalContext;
PG_TRY();
{
ActivePortal = portal;
+ ActiveSnapshot = NULL; /* will be set later */
CurrentResourceOwner = portal->resowner;
PortalContext = PortalGetHeapMemory(portal);
@@ -285,9 +316,13 @@ PortalStart(Portal portal, ParamListInfo params)
case PORTAL_ONE_SELECT:
/*
- * Must set query snapshot before starting executor.
+ * Must set snapshot before starting executor. Be sure to
+ * copy it into the portal's context.
*/
- SetQuerySnapshot();
+ if (snapshot)
+ ActiveSnapshot = CopySnapshot(snapshot);
+ else
+ ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
/*
* Create QueryDesc in portal's context; for the moment,
@@ -295,6 +330,8 @@ PortalStart(Portal portal, ParamListInfo params)
*/
queryDesc = CreateQueryDesc((Query *) linitial(portal->parseTrees),
(Plan *) linitial(portal->planTrees),
+ ActiveSnapshot,
+ InvalidSnapshot,
None_Receiver,
params,
false);
@@ -309,7 +346,7 @@ PortalStart(Portal portal, ParamListInfo params)
/*
* Call ExecStart to prepare the plan for execution
*/
- ExecutorStart(queryDesc, false, false);
+ ExecutorStart(queryDesc, false);
/*
* This tells PortalCleanup to shut down the executor
@@ -333,8 +370,8 @@ PortalStart(Portal portal, ParamListInfo params)
case PORTAL_UTIL_SELECT:
/*
- * We don't set query snapshot here, because
- * PortalRunUtility will take care of it.
+ * We don't set snapshot here, because
+ * PortalRunUtility will take care of it if needed.
*/
portal->tupDesc =
UtilityTupleDescriptor(((Query *) linitial(portal->parseTrees))->utilityStmt);
@@ -361,6 +398,7 @@ PortalStart(Portal portal, ParamListInfo params)
/* Restore global vars and propagate error */
ActivePortal = saveActivePortal;
+ ActiveSnapshot = saveActiveSnapshot;
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
@@ -371,6 +409,7 @@ PortalStart(Portal portal, ParamListInfo params)
MemoryContextSwitchTo(oldContext);
ActivePortal = saveActivePortal;
+ ActiveSnapshot = saveActiveSnapshot;
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
@@ -453,6 +492,7 @@ PortalRun(Portal portal, long count,
{
bool result;
Portal saveActivePortal;
+ Snapshot saveActiveSnapshot;
ResourceOwner saveResourceOwner;
MemoryContext savePortalContext;
MemoryContext saveQueryContext;
@@ -485,12 +525,14 @@ PortalRun(Portal portal, long count,
* Set up global portal context pointers.
*/
saveActivePortal = ActivePortal;
+ saveActiveSnapshot = ActiveSnapshot;
saveResourceOwner = CurrentResourceOwner;
savePortalContext = PortalContext;
saveQueryContext = QueryContext;
PG_TRY();
{
ActivePortal = portal;
+ ActiveSnapshot = NULL; /* will be set later */
CurrentResourceOwner = portal->resowner;
PortalContext = PortalGetHeapMemory(portal);
QueryContext = portal->queryContext;
@@ -579,6 +621,7 @@ PortalRun(Portal portal, long count,
/* Restore global vars and propagate error */
ActivePortal = saveActivePortal;
+ ActiveSnapshot = saveActiveSnapshot;
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
QueryContext = saveQueryContext;
@@ -590,6 +633,7 @@ PortalRun(Portal portal, long count,
MemoryContextSwitchTo(oldContext);
ActivePortal = saveActivePortal;
+ ActiveSnapshot = saveActiveSnapshot;
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
QueryContext = saveQueryContext;
@@ -670,6 +714,7 @@ PortalRunSelect(Portal portal,
nprocessed = RunFromStore(portal, direction, count, dest);
else
{
+ ActiveSnapshot = queryDesc->snapshot;
ExecutorRun(queryDesc, direction, count);
nprocessed = queryDesc->estate->es_processed;
}
@@ -711,6 +756,7 @@ PortalRunSelect(Portal portal,
nprocessed = RunFromStore(portal, direction, count, dest);
else
{
+ ActiveSnapshot = queryDesc->snapshot;
ExecutorRun(queryDesc, direction, count);
nprocessed = queryDesc->estate->es_processed;
}
@@ -834,6 +880,9 @@ PortalRunUtility(Portal portal, Query *query,
* 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) ||
@@ -847,7 +896,9 @@ PortalRunUtility(Portal portal, Query *query,
IsA(utilityStmt, NotifyStmt) ||
IsA(utilityStmt, UnlistenStmt) ||
IsA(utilityStmt, CheckPointStmt)))
- SetQuerySnapshot();
+ ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
+ else
+ ActiveSnapshot = NULL;
if (query->canSetTag)
{
@@ -864,6 +915,10 @@ PortalRunUtility(Portal portal, Query *query,
/* Some utility statements may change context on us */
MemoryContextSwitchTo(PortalGetHeapMemory(portal));
+
+ if (ActiveSnapshot)
+ FreeSnapshot(ActiveSnapshot);
+ ActiveSnapshot = NULL;
}
/*
@@ -924,15 +979,6 @@ PortalRunMulti(Portal portal,
/*
* process a plannable query.
*/
- ereport(DEBUG3,
- (errmsg_internal("ProcessQuery")));
-
- /* Must always set snapshot for plannable queries */
- SetQuerySnapshot();
-
- /*
- * execute the plan
- */
if (log_executor_stats)
ResetUsage();
@@ -1005,6 +1051,7 @@ PortalRunFetch(Portal portal,
{
long result;
Portal saveActivePortal;
+ Snapshot saveActiveSnapshot;
ResourceOwner saveResourceOwner;
MemoryContext savePortalContext;
MemoryContext saveQueryContext;
@@ -1025,12 +1072,14 @@ PortalRunFetch(Portal portal,
* Set up global portal context pointers.
*/
saveActivePortal = ActivePortal;
+ saveActiveSnapshot = ActiveSnapshot;
saveResourceOwner = CurrentResourceOwner;
savePortalContext = PortalContext;
saveQueryContext = QueryContext;
PG_TRY();
{
ActivePortal = portal;
+ ActiveSnapshot = NULL; /* will be set later */
CurrentResourceOwner = portal->resowner;
PortalContext = PortalGetHeapMemory(portal);
QueryContext = portal->queryContext;
@@ -1056,6 +1105,7 @@ PortalRunFetch(Portal portal,
/* Restore global vars and propagate error */
ActivePortal = saveActivePortal;
+ ActiveSnapshot = saveActiveSnapshot;
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
QueryContext = saveQueryContext;
@@ -1070,6 +1120,7 @@ PortalRunFetch(Portal portal,
portal->status = PORTAL_READY;
ActivePortal = saveActivePortal;
+ ActiveSnapshot = saveActiveSnapshot;
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
QueryContext = saveQueryContext;