openGauss源码解析(149)

openGauss源码解析:执行器解析(43)

3. VecLimit算子

VecLimit算子用于处理Limit子句,对应的代码源文件是“veclimit.cpp”。VecLimit算子对应的主要数据结构是VecLimitState,VecLimitState继承于LimitState。具体定义代码如下:

struct VecLimitState : public LimitState {

VectorBatch* subBatch;

};

VecLimit算子的相关函数包括ExecInitVecLimit(初始化节点)、ExecVecLimit(执行节点)、ExecReScanVecLimit(重置节点)、ExecEndVecLimit(退出节点)。

ExecInitVecLimit函数用于初始化VecLimit算子,将VecLimit计划节点转换为VecLimit执行节点。主要执行流程如下。

(1) 创建VecLimit执行节点,创建表达式上下文,分别初始化limitOffset(调用“ExecInitExpr((Expr)node->limitOffset, (PlanState)limit_state))” 函数和limitCount(调用“ExecInitExpr((Expr)node->limitCount, (PlanState)limit_state)”函数)表达式。
(2) 调用“ExecInitResultTupleSlot(estate, &limit_state->ps) ”函数进行初始化元组。
(3) 调用“ExecInitNode(outer_plan, estate, eflags) ”函数进行初始化外部计划。最后置空投影结构。

ExecVecLimit函数是VecLimit算子的主体函数。函数中通过switch来处理VecLimit算子中存在的多种状态,node->Istate存在的状态有LIMIT_INITIAL、LIMIT_RESCAN、LIMIT_EMPTY、LIMIT_INWINDOW、LIMIT_SUBPLANEOF、LIMIT_WINDOWEND、LIMIT_WINDOWSTART。其中LIMIT_INITIAL表示处理Limit算子初始化,LIMIT_RESCAN表示重新执行子节点计划,LIMIT_EMPTY表示Limit算子是空集,LIMIT_INWINDOW表示处理窗口函数(在窗口函数内前向和后向移动),LIMIT_SUBPLANEOF表示处理子节点计划(移动到子节点计划尾部),LIMIT_WINDOWEND表示在窗口结尾部分结束,LIMIT_WINDOWSTART表示在窗口开始部分结束。

ExecEndVecLimit函数用于在执行VecLimit算子结束时释放相关资源,通过依次调用“ExecFreeExprContext(&node->ps)”函数和“ExecEndNode(outerPlanState(node))”函数释放表达式上下文和节点相关信息。

ExecReScanVecLimit函数用于重新执行扫描计划。在参数发生改变时,通过调用“recompute_limits(node)”函数完成执行节点的重新扫描和VecLimit状态机的重置。在chgParam为空时,还需要调用VecExecReScan函数重新扫描计划节点。

4. VecGroup算子

VecGroup算子用于处理SQL语句中的“GROUP BY”子句,对满足条件的元组做分组处理。

VecGroup算子对应的代码源文件是“vecgroup.cpp”。VecGroup算子对应的主要数据结构是VecGroupState,继承于GroupState。相关代码如下:

struct VecGroupState : public GroupState {

void** container;

void* cap;

uint16 idx;

int cellSize;

bool keySimple;

FmgrInfo* buildFunc;

FmgrInfo* buildScanFunc;

VectorBatch* scanBatch;

VarBuf* currentBuf;

VarBuf* bckBuf;

vecqual_func jitted_vecqual;

};

VecGroup算子的相应函数有:ExecInitVecGroup(初始化节点)、ExecVecGroup(执行节点)、ExecEndVecGroup(退出节点)、ExecReScanVecGroup(重置节点)。

ExecInitVecGroup函数用于初始化VecGroup算子,主要执行流程如下。

(1) 创建并初始化VecGroupState执行节点,并为节点创建表达式上下文。
(2) 调用“ExecInitResultTupleSlot(estate,&grp_state->ss.ps);”函数分配存储投影结果的slot。
(3) 调用投影表达式初始化函数ExecInitVecExpr依次对plan.targetlist和plan.qual进行初始化。
(4) 调用ExecInitNode函数初始化子节点。
(5) 调用ExecAssignResultTypeFromTL函数初始化结果扫描描述符和调用ExecAssignVectorForExprEval函数创建投影结构。

ExecVecGroup函数是VecGroup算子的主体函数。主要执行流程如下。

(1) 获取下层元组中符合having子句条件的第1个元组。
(2) 依次获取组内的所有元组,直到获取到分组属性不同的元组,此时表示当前分组获取结束;如果获取到空元组,则表示完成分组操作,设置grp_done字段为true并结束执行。
(3) 扫描下一个符合having条件的元组,将缓存的元组作为分组的开始,并返回新元组。
(4) 重复(2)、(3)直到结束。

ExecEndVecGroup函数用于清理VecGroup算子执行过程中使用的资源。主要执行流程是:首先调用ExecFreeExprContext函数清理表达式上下文,最后调用“ExecEndNode(outerPlanState(node))”函数清理子计划节点。

ExecReScanVecGroup函数用于重新执行扫描计划,通过调用VecExecReScan函数实现重新扫描。

posted @ 2024-04-30 11:04  openGauss-bot  阅读(6)  评论(0编辑  收藏  举报