久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

PostgreSQL中ExecProcNode和ExecProcNodeFirst函數(shù)的實現(xiàn)邏輯是什么

155次閱讀
沒有評論

共計 6882 個字符,預計需要花費 18 分鐘才能閱讀完成。

行業(yè)資訊    
數(shù)據(jù)庫    
關系型數(shù)據(jù)庫    
PostgreSQL 中 ExecProcNode 和 ExecProcNodeFirst 函數(shù)的實現(xiàn)邏輯是什么

這篇文章主要講解了“PostgreSQL 中 ExecProcNode 和 ExecProcNodeFirst 函數(shù)的實現(xiàn)邏輯是什么”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著丸趣 TV 小編的思路慢慢深入,一起來研究和學習“PostgreSQL 中 ExecProcNode 和 ExecProcNodeFirst 函數(shù)的實現(xiàn)邏輯是什么”吧!

一、基礎信息

ExecProcNode/ExecProcNodeFirst 函數(shù)使用的數(shù)據(jù)結(jié)構(gòu)、宏定義以及依賴的函數(shù)等。
數(shù)據(jù)結(jié)構(gòu) / 宏定義
1、ExecProcNodeMtd
ExecProcNodeMtd 是一個函數(shù)指針類型,指向的函數(shù)輸入?yún)?shù)是 PlanState 結(jié)構(gòu)體指針,輸出參數(shù)是 TupleTableSlot 結(jié)構(gòu)體指針

 /* ----------------
 * 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);

依賴的函數(shù)
1、check_stack_depth

// 檢查 stack 的深度,如超出系統(tǒng)限制,則主動報錯
 /*
 * 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

// 外部調(diào)用者可通過改變 node 實現(xiàn)遍歷
 /* ----------------------------------------------------------------
 * 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);
 }
 #endif

2、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;
 // 執(zhí)行該 Node 的處理過程
 return node- ExecProcNode(node);
}

三、跟蹤分析

插入測試數(shù)據(jù):

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();
#查看輸入?yún)?shù)
(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  實際對應的函數(shù)是 ExecProcNodeFirst
#ExecProcNodeReal  實際對應的函數(shù)是 ExecModifyTable(上一章節(jié)已粗略解析)(gdb) next
440 if (node- instrument)
(gdb) 
#實際調(diào)用 ExecModifyTable 函數(shù)(這個函數(shù)由更高層的調(diào)用函數(shù)植入)443 node- ExecProcNode = node- ExecProcNodeReal;
(gdb) 
445 return node- ExecProcNode(node);
(gdb) next
#第二次調(diào)用(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 }
#第二次調(diào)用的參數(shù)
(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 對應的實際函數(shù)是 ExecResult
(gdb)

感謝各位的閱讀,以上就是“PostgreSQL 中 ExecProcNode 和 ExecProcNodeFirst 函數(shù)的實現(xiàn)邏輯是什么”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對 PostgreSQL 中 ExecProcNode 和 ExecProcNodeFirst 函數(shù)的實現(xiàn)邏輯是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是丸趣 TV,丸趣 TV 小編將為大家推送更多相關知識點的文章,歡迎關注!

正文完
 
丸趣
版權聲明:本站原創(chuàng)文章,由 丸趣 2023-07-20發(fā)表,共計6882字。
轉(zhuǎn)載說明:除特殊說明外本站除技術相關以外文章皆由網(wǎng)絡搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 金坛市| 祥云县| 庆元县| 凉山| 弋阳县| 新晃| 鄂托克前旗| 健康| 肇源县| 东乡| 曲阜市| 靖江市| 庆城县| 昆山市| 利津县| 米泉市| 宜丰县| 自治县| 呼和浩特市| 隆回县| 南投县| 光山县| 施秉县| 芷江| 洛隆县| 乌什县| 延寿县| 宝应县| 新乐市| 广宗县| 鄱阳县| 巴林左旗| 项城市| 军事| 安岳县| 贵溪市| 秦安县| 奉节县| 亳州市| 陆丰市| 唐山市|