PostgreSQL源码学习执行器#9

database

本节介绍ExecutePlan函数

相关数据结构

typedef enum ScanDirection

{

BackwardScanDirection = -1,

NoMovementScanDirection = 0,

ForwardScanDirection = 1

} ScanDirection;

ExecutePlan函数

static void

ExecutePlan(EState *estate,

PlanState *planstate,

bool use_parallel_mode,

CmdType operation,

bool sendTuples,

uint64 numberTuples,

ScanDirection direction,

DestReceiver *dest,

bool execute_once);

执行查询计划,直到获取到numberTuples个元组,并且处理时朝direction方向移动。

//src/backend/executor/execMain.c

/* 初始化本地变量 */

current_tuple_count = 0;

/* 设置扫描移动方向 */

estate->es_direction = direction;

/* 如果计划可能被多次执行,那么它不可以并行执行,因为处理可能提前退出 */

if (!execute_once)

use_parallel_mode = false;

estate->es_use_parallel_mode = use_parallel_mode;

if (use_parallel_mode)

EnterParallelMode();

/* 循环,直到我们从计划中处理了适当数量的元组。*/

for (;;)

{

/* 重置每个输出元组的expr上下文 */

ResetPerTupleExprContext(estate);

/* 执行计划并获取一个元组 */

slot = ExecProcNode(planstate);

/* 如果没有元组了,那么假定就是执行完成了,所以跳出循环 */

if (TupIsNull(slot))

{

/* 如果不需要倒退那直接在这里释放资源就行 */

if (!(estate->es_top_eflags & EXEC_FLAG_BACKWARD))

(void) ExecShutdownNode(planstate);

break;

}

/* 有需要的话,对元组进行“垃圾属性”过滤“ */

if (estate->es_junkFilter != NULL)

slot = ExecFilterJunk(estate->es_junkFilter, slot);

/* 有需要的话,发送元组到某处 */

if (sendTuples)

{

/* 若发送失败,那么假定是目标被关闭了,所以结束循环 */

if (!dest->receiveSlot(slot, dest))

break;

}

/* 如果是SELECT操作,统计处理的元组数量 */

if (operation == CMD_SELECT)

(estate->es_processed)++;

/* 检查处理的元组数量,如果已经够了,那么退出。

* 如果numberTuples是0的话,表示没有限制 */

current_tuple_count++;

if (numberTuples && numberTuples == current_tuple_count)

{

/* 如果不需要倒退那直接在这里释放资源就行 */

if (!(estate->es_top_eflags & EXEC_FLAG_BACKWARD))

(void) ExecShutdownNode(planstate);

break;

}

}

if (use_parallel_mode)

ExitParallelMode();

以上是 PostgreSQL源码学习执行器#9 的全部内容, 来源链接: utcz.com/z/534159.html

回到顶部