summaryrefslogtreecommitdiff
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.c132
1 files changed, 50 insertions, 82 deletions
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 3b5da73051d..704be399cf7 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -43,7 +43,7 @@ static uint64 RunFromStore(Portal portal, ScanDirection direction, uint64 count,
DestReceiver *dest);
static uint64 PortalRunSelect(Portal portal, bool forward, long count,
DestReceiver *dest);
-static void PortalRunUtility(Portal portal, Node *utilityStmt,
+static void PortalRunUtility(Portal portal, PlannedStmt *pstmt,
bool isTopLevel, bool setHoldSnapshot,
DestReceiver *dest, char *completionTag);
static void PortalRunMulti(Portal portal,
@@ -73,7 +73,6 @@ CreateQueryDesc(PlannedStmt *plannedstmt,
qd->operation = plannedstmt->commandType; /* operation */
qd->plannedstmt = plannedstmt; /* plan */
- qd->utilitystmt = plannedstmt->utilityStmt; /* in case DECLARE CURSOR */
qd->sourceText = sourceText; /* query text */
qd->snapshot = RegisterSnapshot(snapshot); /* snapshot */
/* RI check snapshot */
@@ -93,37 +92,6 @@ CreateQueryDesc(PlannedStmt *plannedstmt,
}
/*
- * CreateUtilityQueryDesc
- */
-QueryDesc *
-CreateUtilityQueryDesc(Node *utilitystmt,
- const char *sourceText,
- Snapshot snapshot,
- DestReceiver *dest,
- ParamListInfo params)
-{
- QueryDesc *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
-
- qd->operation = CMD_UTILITY; /* operation */
- qd->plannedstmt = NULL;
- qd->utilitystmt = utilitystmt; /* utility command */
- qd->sourceText = sourceText; /* query text */
- 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 */
- qd->instrument_options = false; /* uninteresting for utilities */
-
- /* null these fields until set by ExecutorStart */
- qd->tupDesc = NULL;
- qd->estate = NULL;
- qd->planstate = NULL;
- qd->totaltime = NULL;
-
- return qd;
-}
-
-/*
* FreeQueryDesc
*/
void
@@ -236,7 +204,7 @@ ProcessQuery(PlannedStmt *plan,
* ChoosePortalStrategy
* Select portal execution strategy given the intended statement list.
*
- * The list elements can be Querys, PlannedStmts, or utility statements.
+ * The list elements can be Querys or PlannedStmts.
* That's more general than portals need, but plancache.c uses this too.
*
* See the comments in portal.h.
@@ -263,16 +231,14 @@ ChoosePortalStrategy(List *stmts)
if (query->canSetTag)
{
- if (query->commandType == CMD_SELECT &&
- query->utilityStmt == NULL)
+ if (query->commandType == CMD_SELECT)
{
if (query->hasModifyingCTE)
return PORTAL_ONE_MOD_WITH;
else
return PORTAL_ONE_SELECT;
}
- if (query->commandType == CMD_UTILITY &&
- query->utilityStmt != NULL)
+ if (query->commandType == CMD_UTILITY)
{
if (UtilityReturnsTuples(query->utilityStmt))
return PORTAL_UTIL_SELECT;
@@ -287,24 +253,24 @@ ChoosePortalStrategy(List *stmts)
if (pstmt->canSetTag)
{
- if (pstmt->commandType == CMD_SELECT &&
- pstmt->utilityStmt == NULL)
+ if (pstmt->commandType == CMD_SELECT)
{
if (pstmt->hasModifyingCTE)
return PORTAL_ONE_MOD_WITH;
else
return PORTAL_ONE_SELECT;
}
+ if (pstmt->commandType == CMD_UTILITY)
+ {
+ if (UtilityReturnsTuples(pstmt->utilityStmt))
+ return PORTAL_UTIL_SELECT;
+ /* it can't be ONE_RETURNING, so give up */
+ return PORTAL_MULTI_QUERY;
+ }
}
}
else
- {
- /* must be a utility command; assume it's canSetTag */
- if (UtilityReturnsTuples(stmt))
- return PORTAL_UTIL_SELECT;
- /* it can't be ONE_RETURNING, so give up */
- return PORTAL_MULTI_QUERY;
- }
+ elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
}
/*
@@ -325,7 +291,8 @@ ChoosePortalStrategy(List *stmts)
{
if (++nSetTag > 1)
return PORTAL_MULTI_QUERY; /* no need to look further */
- if (query->returningList == NIL)
+ if (query->commandType == CMD_UTILITY ||
+ query->returningList == NIL)
return PORTAL_MULTI_QUERY; /* no need to look further */
}
}
@@ -337,11 +304,13 @@ ChoosePortalStrategy(List *stmts)
{
if (++nSetTag > 1)
return PORTAL_MULTI_QUERY; /* no need to look further */
- if (!pstmt->hasReturning)
+ if (pstmt->commandType == CMD_UTILITY ||
+ !pstmt->hasReturning)
return PORTAL_MULTI_QUERY; /* no need to look further */
}
}
- /* otherwise, utility command, assumed not canSetTag */
+ else
+ elog(ERROR, "unrecognized node type: %d", (int) nodeTag(stmt));
}
if (nSetTag == 1)
return PORTAL_ONE_RETURNING;
@@ -364,7 +333,7 @@ FetchPortalTargetList(Portal portal)
if (portal->strategy == PORTAL_MULTI_QUERY)
return NIL;
/* get the primary statement and find out what it returns */
- return FetchStatementTargetList(PortalGetPrimaryStmt(portal));
+ return FetchStatementTargetList((Node *) PortalGetPrimaryStmt(portal));
}
/*
@@ -372,7 +341,7 @@ FetchPortalTargetList(Portal portal)
* Given a statement that returns tuples, extract the query targetlist.
* Returns NIL if the statement doesn't have a determinable targetlist.
*
- * This can be applied to a Query, a PlannedStmt, or a utility statement.
+ * This can be applied to a Query or a PlannedStmt.
* That's more general than portals need, but plancache.c uses this too.
*
* Note: do not modify the result.
@@ -388,16 +357,14 @@ FetchStatementTargetList(Node *stmt)
{
Query *query = (Query *) stmt;
- if (query->commandType == CMD_UTILITY &&
- query->utilityStmt != NULL)
+ if (query->commandType == CMD_UTILITY)
{
/* transfer attention to utility statement */
stmt = query->utilityStmt;
}
else
{
- if (query->commandType == CMD_SELECT &&
- query->utilityStmt == NULL)
+ if (query->commandType == CMD_SELECT)
return query->targetList;
if (query->returningList)
return query->returningList;
@@ -408,12 +375,19 @@ FetchStatementTargetList(Node *stmt)
{
PlannedStmt *pstmt = (PlannedStmt *) stmt;
- if (pstmt->commandType == CMD_SELECT &&
- pstmt->utilityStmt == NULL)
- return pstmt->planTree->targetlist;
- if (pstmt->hasReturning)
- return pstmt->planTree->targetlist;
- return NIL;
+ if (pstmt->commandType == CMD_UTILITY)
+ {
+ /* transfer attention to utility statement */
+ stmt = pstmt->utilityStmt;
+ }
+ else
+ {
+ if (pstmt->commandType == CMD_SELECT)
+ return pstmt->planTree->targetlist;
+ if (pstmt->hasReturning)
+ return pstmt->planTree->targetlist;
+ return NIL;
+ }
}
if (IsA(stmt, FetchStmt))
{
@@ -566,8 +540,7 @@ PortalStart(Portal portal, ParamListInfo params,
{
PlannedStmt *pstmt;
- pstmt = (PlannedStmt *) PortalGetPrimaryStmt(portal);
- Assert(IsA(pstmt, PlannedStmt));
+ pstmt = PortalGetPrimaryStmt(portal);
portal->tupDesc =
ExecCleanTypeFromTL(pstmt->planTree->targetlist,
false);
@@ -588,10 +561,10 @@ PortalStart(Portal portal, ParamListInfo params,
* take care of it if needed.
*/
{
- Node *ustmt = PortalGetPrimaryStmt(portal);
+ PlannedStmt *pstmt = PortalGetPrimaryStmt(portal);
- Assert(!IsA(ustmt, PlannedStmt));
- portal->tupDesc = UtilityTupleDescriptor(ustmt);
+ Assert(pstmt->commandType == CMD_UTILITY);
+ portal->tupDesc = UtilityTupleDescriptor(pstmt->utilityStmt);
}
/*
@@ -1047,7 +1020,7 @@ FillPortalStore(Portal portal, bool isTopLevel)
break;
case PORTAL_UTIL_SELECT:
- PortalRunUtility(portal, (Node *) linitial(portal->stmts),
+ PortalRunUtility(portal, (PlannedStmt *) linitial(portal->stmts),
isTopLevel, true, treceiver, completionTag);
break;
@@ -1143,10 +1116,11 @@ RunFromStore(Portal portal, ScanDirection direction, uint64 count,
* Execute a utility statement inside a portal.
*/
static void
-PortalRunUtility(Portal portal, Node *utilityStmt,
+PortalRunUtility(Portal portal, PlannedStmt *pstmt,
bool isTopLevel, bool setHoldSnapshot,
DestReceiver *dest, char *completionTag)
{
+ Node *utilityStmt = pstmt->utilityStmt;
Snapshot snapshot;
/*
@@ -1186,7 +1160,7 @@ PortalRunUtility(Portal portal, Node *utilityStmt,
else
snapshot = NULL;
- ProcessUtility(utilityStmt,
+ ProcessUtility(pstmt,
portal->sourceText,
isTopLevel ? PROCESS_UTILITY_TOPLEVEL : PROCESS_UTILITY_QUERY,
portal->portalParams,
@@ -1241,21 +1215,18 @@ PortalRunMulti(Portal portal,
*/
foreach(stmtlist_item, portal->stmts)
{
- Node *stmt = (Node *) lfirst(stmtlist_item);
+ PlannedStmt *pstmt = (PlannedStmt *) lfirst(stmtlist_item);
/*
* If we got a cancel signal in prior command, quit
*/
CHECK_FOR_INTERRUPTS();
- if (IsA(stmt, PlannedStmt) &&
- ((PlannedStmt *) stmt)->utilityStmt == NULL)
+ if (pstmt->utilityStmt == NULL)
{
/*
* process a plannable query.
*/
- PlannedStmt *pstmt = (PlannedStmt *) stmt;
-
TRACE_POSTGRESQL_QUERY_EXECUTE_START();
if (log_executor_stats)
@@ -1320,9 +1291,6 @@ PortalRunMulti(Portal portal,
/*
* process utility functions (create, destroy, etc..)
*
- * These are assumed canSetTag if they're the only stmt in the
- * portal.
- *
* We must not set a snapshot here for utility commands (if one is
* needed, PortalRunUtility will do it). If a utility command is
* alone in a portal then everything's fine. The only case where
@@ -1331,18 +1299,18 @@ PortalRunMulti(Portal portal,
* whether it has a snapshot or not, so we just leave the current
* snapshot alone if we have one.
*/
- if (list_length(portal->stmts) == 1)
+ if (pstmt->canSetTag)
{
Assert(!active_snapshot_set);
/* statement can set tag string */
- PortalRunUtility(portal, stmt, isTopLevel, false,
+ PortalRunUtility(portal, pstmt, isTopLevel, false,
dest, completionTag);
}
else
{
- Assert(IsA(stmt, NotifyStmt));
+ Assert(IsA(pstmt->utilityStmt, NotifyStmt));
/* stmt added by rewrite cannot set tag */
- PortalRunUtility(portal, stmt, isTopLevel, false,
+ PortalRunUtility(portal, pstmt, isTopLevel, false,
altdest, NULL);
}
}