PortalRunUtility函数执行utility语句,如果是TransactionStmt、LockStmt、VariableSetStmt、VariableShowStmt、ConstraintsSetStmt、FetchStmt、ListenStmt、NotifyStmt、UnlistenStmt、CheckPointStmt则不需要快照。

static void PortalRunUtility(Portal portal, PlannedStmt *pstmt, bool isTopLevel, bool setHoldSnapshot, DestReceiver *dest, char *completionTag) {
Node *utilityStmt = pstmt->utilityStmt;
Snapshot snapshot;

/*
* Set snapshot if utility stmt needs one. Most reliable way to do this
* seems to be to enumerate those that do not need one; this is a short
* list. Transaction control, LOCK, and SET must *not* set a snapshot
* since they need to be executable at the start of a transaction-snapshot
* mode transaction without freezing a snapshot. By extension we allow
* SHOW not to set a snapshot. The other stmts listed are just efficiency
* 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.
*/
if (!(IsA(utilityStmt, TransactionStmt) ||
IsA(utilityStmt, LockStmt) ||
IsA(utilityStmt, VariableSetStmt) ||
IsA(utilityStmt, VariableShowStmt) ||
IsA(utilityStmt, ConstraintsSetStmt) ||
/* efficiency hacks from here down */
IsA(utilityStmt, FetchStmt) ||
IsA(utilityStmt, ListenStmt) ||
IsA(utilityStmt, NotifyStmt) ||
IsA(utilityStmt, UnlistenStmt) ||
IsA(utilityStmt, CheckPointStmt))) {
snapshot = GetTransactionSnapshot();
/* If told to, register the snapshot we're using and save in portal */
if (setHoldSnapshot) { // 注册快照,并将快照放到portal中
snapshot = RegisterSnapshot(snapshot);
portal->holdSnapshot = snapshot;
}
PushActiveSnapshot(snapshot);
/* PushActiveSnapshot might have copied the snapshot */
snapshot = GetActiveSnapshot();
} else
snapshot = NULL;

ProcessUtility(pstmt, portal->sourceText, isTopLevel ? PROCESS_UTILITY_TOPLEVEL : PROCESS_UTILITY_QUERY,portal->portalParams, portal->queryEnv, dest, completionTag);

/* Some utility statements may change context on us */ // 切换到portal的内存上下文
MemoryContextSwitchTo(portal->portalContext);

/* Some utility commands may pop the ActiveSnapshot stack from under us, so be careful to only pop the stack if our snapshot is still at the top. */
if (snapshot != NULL && ActiveSnapshotSet() && snapshot == GetActiveSnapshot())
PopActiveSnapshot(); // 如果有快照就需要Pop快照
}

PostgreSQL数据库查询执行——PortalRunUtility_数据库