Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the implementation logic of ExecProcNode and ExecProcNodeFirst functions in PostgreSQL?

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly explains "what is the implementation logic of ExecProcNode and ExecProcNodeFirst functions in PostgreSQL". The content of the explanation is simple and clear, and it is easy to learn and understand. Please follow Xiaobian's train of thought to study and learn "what is the implementation logic of ExecProcNode and ExecProcNodeFirst functions in PostgreSQL".

I. basic information

The data structures, macro definitions, and dependent functions used by the ExecProcNode/ExecProcNodeFirst function.

Data structure / Macro definition

1 、 ExecProcNodeMtd

ExecProcNodeMtd is a function pointer type. The input parameter to the function is the PlanState structure pointer, and the output parameter is the TupleTableSlot structure pointer.

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

Dependent function

1 、 check_stack_depth

/ / check the depth of stack. If the system limit is exceeded, an active error will be reported / * * 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;} II. Source code interpretation

1 、 ExecProcNode

/ / external callers can traverse / *-* ExecProcNode * * Execute the given node to return a (nother) tuple by changing node. *-* / # 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). * / / * input: node-PlanState pointer output: Slot*/static TupleTableSlot * ExecProcNodeFirst (PlanState * node) {/ * * Perform stack depth check during the first execution of the node for storing Tuple. 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. * / / check whether Stack is ultra-deep 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. * / / if instrument (TODO) if (node- > instrument) node- > ExecProcNode = ExecProcNodeInstr; else node- > ExecProcNode = node- > ExecProcNodeReal; / / execute the Node process return node- > ExecProcNode (node)

Insert test data:

Testdb=#-- get pidtestdb=# select pg_backend_pid (); pg_backend_pid-2835 (1 row) testdb=#-insert 1 line of testdb=# insert into t_insert values (14) (14) ExecProcNodeFirstEntitureExecProcNodeFirstMagnology ExecProcNodeFirst`); (hangs)

Start the gdb analysis:

[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 () # check the input parameters (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 actual corresponding function is ExecProcNodeFirst#ExecProcNodeReal actual corresponding function is ExecModifyTable (roughly explained in the previous chapter) (gdb) next440 if (node- > instrument) (gdb) # actual call ExecModifyTable function (this function is implanted by higher-level calling functions) 443 node- > ExecProcNode = node- > ExecProcNodeReal (gdb) 445 return node- > ExecProcNode (node); (gdb) next# second call (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} # parameters for the second call (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 = ps_ResultTupleSlot, 0x2ccad90 = 0x2ccad90, 0x2ccad90 = 0x2ccad90 The actual function corresponding to scandesc = 0x0} # ExecProcNode is ExecResult (gdb). Thank you for reading. The above is the content of "what is the implementation logic of ExecProcNode and ExecProcNodeFirst functions in PostgreSQL". After the study of this article, I believe you have a deeper understanding of what the implementation logic of ExecProcNode and ExecProcNodeFirst functions in PostgreSQL is, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Database

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report