openGauss数据库源码解析 | 执行器解析解析(14)

3. Limit算子

Limit算子节点主要用来处理LIMIT/OFFSET子句,用于限制子查询语句处理元组的数量,对应的代码源文件是“nodeLimit.cpp”。算子对应的主要函数如表7-26所示。

表7-26  Limit算子主要函数

主要函数

说明

ExecInitLimit

初始化Limit状态节点

ExecLimit

迭代获取元组

ExecEndLimit

清理Limit状态节点

recompute_limits

初始化limit/offset表达式

Limit算子对应的关键结构体是LimitState,相关代码如下:

typedef struct LimitState {

    PlanState ps;            /* 计划状态节点*/

    ExprState* limitOffset;  /* 偏移位置*/

    ExprState* limitCount;   /* 总数 */

    int64 offset;            /* 当前偏移位置 */

    int64 count;             /* 当前总数 */

    bool noCount;            /* 忽略总数标识 */

    LimitStateCond lstate;   /* 状态机当前状态 */

    int64 position;          /* 上一个元组的位置 */

    TupleTableSlot* subSlot; /* 上一个元组 */

} LimitState;

ExecInitLimit函数用于把Limit计划节点转成Limit执行节点。主要执行流程如下。

(1) 初始化Limit状态节点(LimitState)并做子表达式处理,分别初始化limitOffset(调用“ExecInitExpr((Expr*)node->limitOffset, (PlanState*)limit_state)”函数)和limitCount(调用“ExecInitExpr((Expr*)node->limitCount, (PlanState*)limit_state);”函数)表达式。
(2) 调用“ExecInitResultTupleSlot(estate, &limit_state->ps)”函数做元组初始化。
(3) 外部计划初始化(调用“outer_plan = outerPlan(node); outerPlanState(limit_state) = ExecInitNode(outer_plan, estate, eflags);”函数)。
(4) 对投影信息置空(由于Limit无投影)。

ExecLimit是执行Limit算子的入口,每次返回一个元组。在函数体内部通过“switch (node->lstate) ”函数来处理Limit算子的各种Limit状态,如果Limit对应的状态不是叶子节点则调用ExecProcNode做递归处理。“node->lstate”对应的状态有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用于在窗口开始处结束。

recompute_limits函数用于在初始化时处理limit/offset表达式。主要执行流程如下。

(1) 处理计划节点中的limitOffset,如果非空则对limitOffset对应的表达式做求值处理,判断limitOffset是否满足约束条件,如果不满足则做报错处理。
(2) 处理计划节点中的limitCount,如果非空则对limitCount对应的表达式做求值处理,判断limitCount是否满足约束条件,如果不满足则做报错处理。
(3) 调用pass_down_bound递归处理子节点。
4. Group算子

Group算子用于处理GROUP BY子句(节点),对满足条件的元组做分组处理,对应的代码源文件是“nodeGroup.cpp”。Group算子对应的子节点返回的元组是按照分组属性排列的结果。算子对应的主要函数如表7-27所示。

表7-27  Group算子主要函数

主要函数

说明

ExecInitGroup

初始化Group状态节点

ExecGroup

迭代获取元组

ExecEndGroup

清理Group状态节点

ExecResScanGroup

重置Group状态节点

ExecInitGroup函数初始Group状态节点。主要执行流程如下。

(1) 构造Group状态节点。
(2) 初始化目标表达式和过滤表达式。
(3) 初始化唯一子节点(用于输出元组)。
(4) 获取唯一值过滤函数。

ExecGroup函数输出分组后的元组。Group子节点输出的元组已按照分组属性排序,在迭代输出时只要发现同上一个元组属性不匹配,则生成新的元组(新分组)输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值