PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章主要讲解了"PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,
千家信息网最后更新 2026年11月01日PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么
这篇文章主要讲解了"PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"PostgreSQL中ExecProcNode和ExecProcNodeFirst函数的实现逻辑是什么"吧!
一、基础信息
ExecProcNode/ExecProcNodeFirst函数使用的数据结构、宏定义以及依赖的函数等。
数据结构/宏定义
1、ExecProcNodeMtd
ExecProcNodeMtd是一个函数指针类型,指向的函数输入参数是PlanState结构体指针,输出参数是TupleTableSlot 结构体指针
/* ---------------- * ExecProcNodeMtd * * This is the method called by ExecProcNode to return the next tuple * from an executor node. It returns NULL, or an empty TupleTableSlot, * if no more tuples are available. * ---------------- */ typedef TupleTableSlot *(*ExecProcNodeMtd) (struct PlanState *pstate);
依赖的函数
1、check_stack_depth
//检查stack的深度,如超出系统限制,则主动报错 /* * check_stack_depth/stack_is_too_deep: check for excessively deep recursion * * This should be called someplace in any recursive routine that might possibly * recurse deep enough to overflow the stack. Most Unixen treat stack * overflow as an unrecoverable SIGSEGV, so we want to error out ourselves * before hitting the hardware limit. * * check_stack_depth() just throws an error summarily. stack_is_too_deep() * can be used by code that wants to handle the error condition itself. */ 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; /* * Compute distance from reference point to my local variables */ stack_depth = (long) (stack_base_ptr - &stack_top_loc); /* * Take abs value, since stacks grow up on some machines, down on others */ if (stack_depth < 0) stack_depth = -stack_depth; /* * Trouble? * * The test on stack_base_ptr prevents us from erroring out if called * during process setup or in a non-backend process. Logically it should * be done first, but putting it here avoids wasting cycles during normal * cases. */ if (stack_depth > max_stack_depth_bytes && stack_base_ptr != NULL) return true; /* * On IA64 there is a separate "register" stack that requires its own * independent check. For this, we have to measure the change in the * "BSP" pointer from PostgresMain to here. Logic is just as above, * except that we know IA64's register stack grows up. * * Note we assume that the same max_stack_depth applies to both stacks. */ #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 /* IA64 */ return false; }2、ExecProcNodeInstr
/* * ExecProcNode wrapper that performs instrumentation calls. By keeping * this a separate function, we avoid overhead in the normal case where * no instrumentation is wanted. */ 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实现遍历 /* ---------------------------------------------------------------- * ExecProcNode * * Execute the given node to return a(nother) tuple. * ---------------------------------------------------------------- */ #ifndef FRONTEND static inline TupleTableSlot * ExecProcNode(PlanState *node) { if (node->chgParam != NULL) /* something changed? */ ExecReScan(node); /* let ReScan handle this */ return node->ExecProcNode(node); } #endif2、ExecProcNodeFirst
/* * ExecProcNode wrapper that performs some one-time checks, before calling * the relevant node method (possibly via an instrumentation wrapper). *//*输入: node-PlanState指针输出: 存储Tuple的Slot*/static TupleTableSlot *ExecProcNodeFirst(PlanState *node){ /* * Perform stack depth check during the first execution of the node. We * only do so the first time round because it turns out to not be cheap on * some common architectures (eg. x86). This relies on the assumption * that ExecProcNode calls for a given plan node will always be made at * roughly the same stack depth. */ //检查Stack是否超深 check_stack_depth(); /* * If instrumentation is required, change the wrapper to one that just * does instrumentation. Otherwise we can dispense with all wrappers and * have ExecProcNode() directly call the relevant function from now on. */ //如果instrument(TODO) if (node->instrument) node->ExecProcNode = ExecProcNodeInstr; else node->ExecProcNode = node->ExecProcNodeReal; //执行该Node的处理过程 return node->ExecProcNode(node);}三、跟踪分析
插入测试数据:
testdb=# -- 获取pidtestdb=# 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 2835GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7Copyright (C) 2013 Free Software Foundation, Inc....(gdb) b ExecProcNodeFirstBreakpoint 1 at 0x69a797: file execProcnode.c, line 433.(gdb) cContinuing.Breakpoint 1, ExecProcNodeFirst (node=0x2cca790) at execProcnode.c:433433 check_stack_depth();#查看输入参数(gdb) p *node$1 = {type = T_ModifyTableState, plan = 0x2c1d028, state = 0x2cca440, ExecProcNode = 0x69a78b , ExecProcNodeReal = 0x6c2485 , 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) next440 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:433433 check_stack_depth();(gdb) next440 if (node->instrument)(gdb) next443 node->ExecProcNode = node->ExecProcNodeReal;(gdb) next445 return node->ExecProcNode(node);(gdb) next446 }(gdb) nextExecProcNode (node=0x2ccac80) at ../../../src/include/executor/executor.h:238238 }#第二次调用的参数(gdb) p *node$2 = {type = T_ResultState, plan = 0x2cd0488, state = 0x2cca440, ExecProcNode = 0x6c5094 , ExecProcNodeReal = 0x6c5094 , 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函数的实现逻辑是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
函数
逻辑
参数
实际
指针
结构
数据
学习
输入
内容
数据结构
分析
检查
输出
粗略
主动
信息
基础
就是
思路
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网络科技
中智农互联网科技
西安纸贵互联网科技有限公司
湖南永感互联网科技有限公司
国智互联网科技
互联网科技财经
金融科技与互联网金融
互联网的科技创新
互联网科技小额贷款
互联网科技公司有哪些
华脉科技工业互联网产品
深圳前海聚择互联网科技有限公司
互联网大会黑科技排名
语蝶互联网科技有限公司
中国航天科技大学国际工业互联网
新兴科技互联网创新大赛颁奖典礼
开一家科技互联网公司需要多少钱
互联网时代的科技公司
互联网科技数字货币
科技互联网公司两年变化
互联网科技公司
湖南永感互联网科技有限公司
重生之互联网科技帝国
嘟嘟瓜互联网科技
互联网科技美容
无锡溥仪互联网科技有限公司
卫星互联网科技股票
中国科技创新与世界互联网大会
畅思互联网科技
互联网科技创新方面的资料