文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么

2024-04-02 19:55

关注

这篇文章主要讲解了“PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么”吧!

一、基础信息

ExecProcNode/ExecProcNodeFirst函数使用的数据结构、宏定义以及依赖的函数等。
数据结构/宏定义
1、ExecProcNodeMtd
ExecProcNodeMtd是一个函数指针类型,指向的函数输入参数是PlanState结构体指针,输出参数是TupleTableSlot 结构体指针

 
 typedef TupleTableSlot *(*ExecProcNodeMtd) (struct PlanState *pstate);

依赖的函数
1、check_stack_depth

//检查stack的深度,如超出系统限制,则主动报错
 
 void
 check_stack_depth(void)
 {
     if (stack_is_too_deep())
     {
         ereport(ERROR,
                 (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
                  errmsg("stack depth limit exceeded"),
                  errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
                          "after ensuring the platform's stack depth limit is adequate.",
                          max_stack_depth)));
     }
 }
 
 bool
 stack_is_too_deep(void)
 {
     char        stack_top_loc;
     long        stack_depth;
 
     
     stack_depth = (long) (stack_base_ptr - &stack_top_loc);
 
     
     if (stack_depth < 0)
         stack_depth = -stack_depth;
 
     
     if (stack_depth > max_stack_depth_bytes &&
         stack_base_ptr != NULL)
         return true;
 
     
 #if defined(__ia64__) || defined(__ia64)
     stack_depth = (long) (ia64_get_bsp() - register_stack_base_ptr);
 
     if (stack_depth > max_stack_depth_bytes &&
         register_stack_base_ptr != NULL)
         return true;
 #endif                          
 
     return false;
 }

2、ExecProcNodeInstr

 
 static TupleTableSlot *
 ExecProcNodeInstr(PlanState *node)
 {
     TupleTableSlot *result;
 
     InstrStartNode(node->instrument);
 
     result = node->ExecProcNodeReal(node);
 
     InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
 
     return result;
 }

二、源码解读

1、ExecProcNode

//外部调用者可通过改变node实现遍历
 
 #ifndef FRONTEND
 static inline TupleTableSlot *
 ExecProcNode(PlanState *node)
 {
     if (node->chgParam != NULL) 
         ExecReScan(node);       
 
     return node->ExecProcNode(node);
 }
 #endif

2、ExecProcNodeFirst



static TupleTableSlot *
ExecProcNodeFirst(PlanState *node)
{
    
    //检查Stack是否超深
    check_stack_depth();

    
    //如果instrument(TODO)
    if (node->instrument)
        node->ExecProcNode = ExecProcNodeInstr;
    else
        node->ExecProcNode = node->ExecProcNodeReal;
    //执行该Node的处理过程
    return node->ExecProcNode(node);
}

三、跟踪分析

插入测试数据:

testdb=# -- 获取pid
testdb=# select pg_backend_pid();
 pg_backend_pid 
----------------
           2835
(1 row)
testdb=# -- 插入1行
testdb=# insert into t_insert values(14,'ExecProcNodeFirst','ExecProcNodeFirst','ExecProcNodeFirst');
(挂起)

启动gdb分析:

[root@localhost ~]# gdb -p 2835
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
Copyright (C) 2013 Free Software Foundation, Inc.
...
(gdb) b ExecProcNodeFirst
Breakpoint 1 at 0x69a797: file execProcnode.c, line 433.
(gdb) c
Continuing.

Breakpoint 1, ExecProcNodeFirst (node=0x2cca790) at execProcnode.c:433
433     check_stack_depth();
#查看输入参数
(gdb) p *node
$1 = {type = T_ModifyTableState, plan = 0x2c1d028, state = 0x2cca440, ExecProcNode = 0x69a78b <ExecProcNodeFirst>, ExecProcNodeReal = 0x6c2485 <ExecModifyTable>, instrument = 0x0, 
  worker_instrument = 0x0, qual = 0x0, lefttree = 0x0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2ccb6a0, ps_ExprContext = 0x0, ps_ProjInfo = 0x0, 
  scandesc = 0x0}
#ExecProcNode 实际对应的函数是ExecProcNodeFirst
#ExecProcNodeReal 实际对应的函数是ExecModifyTable(上一章节已粗略解析)
(gdb) next
440     if (node->instrument)
(gdb) 
#实际调用ExecModifyTable函数(这个函数由更高层的调用函数植入)
443         node->ExecProcNode = node->ExecProcNodeReal;
(gdb) 
445     return node->ExecProcNode(node);
(gdb) next
#第二次调用(TODO)
Breakpoint 1, ExecProcNodeFirst (node=0x2ccac80) at execProcnode.c:433
433     check_stack_depth();
(gdb) next
440     if (node->instrument)
(gdb) next
443         node->ExecProcNode = node->ExecProcNodeReal;
(gdb) next
445     return node->ExecProcNode(node);
(gdb) next
446 }
(gdb) next
ExecProcNode (node=0x2ccac80) at ../../../src/include/executor/executor.h:238
238 }
#第二次调用的参数
(gdb) p *node
$2 = {type = T_ResultState, plan = 0x2cd0488, state = 0x2cca440, ExecProcNode = 0x6c5094 <ExecResult>, ExecProcNodeReal = 0x6c5094 <ExecResult>, instrument = 0x0, worker_instrument = 0x0, qual = 0x0, 
  lefttree = 0x0, righttree = 0x0, initPlan = 0x0, subPlan = 0x0, chgParam = 0x0, ps_ResultTupleSlot = 0x2ccad90, ps_ExprContext = 0x2ccab30, ps_ProjInfo = 0x2ccabc0, scandesc = 0x0}
#ExecProcNode对应的实际函数是ExecResult
(gdb)

感谢各位的阅读,以上就是“PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么”的内容了,经过本文的学习后,相信大家对PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯