PostgreSQL源码学习调度器#14

database

本节介绍PortalRun函数。

PortalRun函数

//src/include/tcop/pquery.h

extern bool PortalRun(Portal portal, long count, bool isTopLevel,

bool run_once, DestReceiver *dest, DestReceiver *altdest,

char *completionTag);

//src/backend/tcop/pquery.c

AssertArg(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

回到顶部