* ExplainNode - * Appends a description of a plan tree to es->str * * planstate points to the executor state node for the current plan node. * We need to work from a PlanState node, not just a Plan node, in order to * get at the instrumentation data (if any) as well as the list of subplans. * * ancestors is a list of parent Plan and SubPlan nodes, most-closely-nested * first. These are
| 1536 | * function signature from upstream.) |
| 1537 | */ |
| 1538 | static void |
| 1539 | ExplainNode(PlanState *planstate, List *ancestors, |
| 1540 | const char *relationship, const char *plan_name, |
| 1541 | ExplainState *es) |
| 1542 | { |
| 1543 | Plan *plan = planstate->plan; |
| 1544 | PlanState *parentplanstate; |
| 1545 | ExecSlice *save_currentSlice = es->currentSlice; /* save */ |
| 1546 | const char *pname; /* node type name for text output */ |
| 1547 | const char *sname; /* node type name for non-text output */ |
| 1548 | const char *strategy = NULL; |
| 1549 | const char *partialmode = NULL; |
| 1550 | const char *operation = NULL; |
| 1551 | const char *custom_name = NULL; |
| 1552 | ExplainWorkersState *save_workers_state = es->workers_state; |
| 1553 | int save_indent = es->indent; |
| 1554 | bool haschildren; |
| 1555 | bool skip_outer=false; |
| 1556 | char *skip_outer_msg = NULL; |
| 1557 | int motion_recv; |
| 1558 | int motion_snd; |
| 1559 | ExecSlice *parentSlice = NULL; |
| 1560 | |
| 1561 | /* Remember who called us. */ |
| 1562 | parentplanstate = es->parentPlanState; |
| 1563 | es->parentPlanState = planstate; |
| 1564 | |
| 1565 | /* |
| 1566 | * If this is a Motion node, we're descending into a new slice. |
| 1567 | */ |
| 1568 | if (IsA(plan, Motion)) |
| 1569 | { |
| 1570 | Motion *pMotion = (Motion *) plan; |
| 1571 | SliceTable *sliceTable = planstate->state->es_sliceTable; |
| 1572 | |
| 1573 | if (sliceTable) |
| 1574 | { |
| 1575 | es->currentSlice = &sliceTable->slices[pMotion->motionID]; |
| 1576 | parentSlice = es->currentSlice->parentIndex == -1 ? NULL : |
| 1577 | &sliceTable->slices[es->currentSlice->parentIndex]; |
| 1578 | } |
| 1579 | } |
| 1580 | |
| 1581 | /* |
| 1582 | * Prepare per-worker output buffers, if needed. We'll append the data in |
| 1583 | * these to the main output string further down. |
| 1584 | */ |
| 1585 | if (planstate->worker_instrument && es->analyze && !es->hide_workers) |
| 1586 | es->workers_state = ExplainCreateWorkersState(planstate->worker_instrument->num_workers); |
| 1587 | else |
| 1588 | es->workers_state = NULL; |
| 1589 | |
| 1590 | /* Identify plan node type, and print generic details */ |
| 1591 | switch (nodeTag(plan)) |
| 1592 | { |
| 1593 | case T_Result: |
| 1594 | pname = sname = "Result"; |
| 1595 | break; |
no test coverage detected