PostgreSQL源码学习调度器#14
本节介绍PortalRun函数。
PortalRun函数
//src/include/tcop/pquery.hextern bool PortalRun(Portal portal, long count, bool isTopLevel,
bool run_once, DestReceiver *dest, DestReceiver *altdest,
char *completionTag);
//src/backend/tcop/pquery.cAssertArg(PortalIsValid(portal));
/* 动态追踪的探针 */
TRACE_POSTGRESQL_QUERY_EXECUTE_START();
/* 初始化completionTag */
if (completionTag)
completionTag[0] = "";
/* 需要记录且portal策略不是multi_query时,在这里重置portal计时。
* PORTAL_MULTI_QUERY 会为每个query分别计时(上节有讲) */
if (log_executor_stats && portal->strategy != PORTAL_MULTI_QUERY)
{
elog(DEBUG3, "PortalRun");
ResetUsage();
}
/* 检查portal是否被错误使用,并标记portal为active状态 */
MarkPortalActive(portal);
/* 设置run_once标志 */
Assert(!portal->run_once || run_once);
portal->run_once = run_once;
/* 设置全局portal上下文指针 */
saveTopTransactionResourceOwner = TopTransactionResourceOwner;
saveTopTransactionContext = TopTransactionContext;
saveActivePortal = ActivePortal;
saveResourceOwner = CurrentResourceOwner;
savePortalContext = PortalContext;
saveMemoryContext = CurrentMemoryContext;
PG_TRY();
{
ActivePortal = portal;
if (portal->resowner)
CurrentResourceOwner = portal->resowner;
PortalContext = portal->portalContext;
/* 切换到portal的内存上下文 */
MemoryContextSwitchTo(PortalContext);
switch (portal->strategy)
{
case PORTAL_ONE_SELECT:
case PORTAL_ONE_RETURNING:
case PORTAL_ONE_MOD_WITH:
case PORTAL_UTIL_SELECT:
/* 将结果存储在portal的tuplestore中 */
if (portal->strategy != PORTAL_ONE_SELECT && !portal->holdStore)
FillPortalStore(portal, isTopLevel);
/* 获取所需的结果 */
nprocessed = PortalRunSelect(portal, true, count, dest);
/* 处理completionTag */
if (completionTag && portal->commandTag)
{
if (strcmp(portal->commandTag, "SELECT") == 0)
snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
"SELECT " UINT64_FORMAT, nprocessed);
else
strcpy(completionTag, portal->commandTag);
}
/* 标记portal为no active状态 */
portal->status = PORTAL_READY;
/* 当且仅当atEnd为true时表示处理完成了 */
result = portal->atEnd;
break;
/* 需要有多个query分开处理 */
case PORTAL_MULTI_QUERY:
PortalRunMulti(portal, isTopLevel, false,
dest, altdest, completionTag);
/* 防止portal的命令被重新执行 */
MarkPortalDone(portal);
/* 这里总是true */
result = true;
break;
default:
elog(ERROR, "unrecognized portal strategy: %d",
(int) portal->strategy);
result = false; /* keep compiler quiet */
break;
}
}
PG_CATCH();
{
/* 出现未捕获的异常,标记portal为failed */
MarkPortalFailed(portal);
/* 恢复全局变量并传递错误 */
if (saveMemoryContext == saveTopTransactionContext)
MemoryContextSwitchTo(TopTransactionContext);
else
MemoryContextSwitchTo(saveMemoryContext);
ActivePortal = saveActivePortal;
if (saveResourceOwner == saveTopTransactionResourceOwner)
CurrentResourceOwner = TopTransactionResourceOwner;
else
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
PG_RE_THROW();
}
PG_END_TRY();
/* 恢复全局变量 */
if (saveMemoryContext == saveTopTransactionContext)
MemoryContextSwitchTo(TopTransactionContext);
else
MemoryContextSwitchTo(saveMemoryContext);
ActivePortal = saveActivePortal;
if (saveResourceOwner == saveTopTransactionResourceOwner)
CurrentResourceOwner = TopTransactionResourceOwner;
else
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
/* 需要记录且portal策略不是multi_query时,在这里输出portal计时 */
if (log_executor_stats && portal->strategy != PORTAL_MULTI_QUERY)
ShowUsage("EXECUTOR STATISTICS");
/* 动态追踪的探针 */
TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();
return result;
以上是 PostgreSQL源码学习调度器#14 的全部内容, 来源链接: utcz.com/z/534180.html