Skip to content

Commit 8dd401a

Browse files
committed
Add new function planstate_tree_walker.
ExplainPreScanNode knows how to iterate over a generic tree of plan states; factor that logic out into a separate walker function so that other code, such as upcoming patches for parallel query, can also use it. Patch by me, reviewed by Tom Lane.
1 parent 293fd7c commit 8dd401a

File tree

3 files changed

+132
-90
lines changed

3 files changed

+132
-90
lines changed

src/backend/commands/explain.c

Lines changed: 3 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,7 @@ static void ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
5555
static void report_triggers(ResultRelInfo *rInfo, bool show_relname,
5656
ExplainState *es);
5757
static double elapsed_time(instr_time *starttime);
58-
static void ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used);
59-
static void ExplainPreScanMemberNodes(List *plans, PlanState **planstates,
60-
Bitmapset **rels_used);
61-
static void ExplainPreScanSubPlans(List *plans, Bitmapset **rels_used);
58+
static bool ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used);
6259
static void ExplainNode(PlanState *planstate, List *ancestors,
6360
const char *relationship, const char *plan_name,
6461
ExplainState *es);
@@ -724,7 +721,7 @@ elapsed_time(instr_time *starttime)
724721
* This ensures that we don't confusingly assign un-suffixed aliases to RTEs
725722
* that never appear in the EXPLAIN output (such as inheritance parents).
726723
*/
727-
static void
724+
static bool
728725
ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
729726
{
730727
Plan *plan = planstate->plan;
@@ -764,91 +761,7 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used)
764761
break;
765762
}
766763

767-
/* initPlan-s */
768-
if (planstate->initPlan)
769-
ExplainPreScanSubPlans(planstate->initPlan, rels_used);
770-
771-
/* lefttree */
772-
if (outerPlanState(planstate))
773-
ExplainPreScanNode(outerPlanState(planstate), rels_used);
774-
775-
/* righttree */
776-
if (innerPlanState(planstate))
777-
ExplainPreScanNode(innerPlanState(planstate), rels_used);
778-
779-
/* special child plans */
780-
switch (nodeTag(plan))
781-
{
782-
case T_ModifyTable:
783-
ExplainPreScanMemberNodes(((ModifyTable *) plan)->plans,
784-
((ModifyTableState *) planstate)->mt_plans,
785-
rels_used);
786-
break;
787-
case T_Append:
788-
ExplainPreScanMemberNodes(((Append *) plan)->appendplans,
789-
((AppendState *) planstate)->appendplans,
790-
rels_used);
791-
break;
792-
case T_MergeAppend:
793-
ExplainPreScanMemberNodes(((MergeAppend *) plan)->mergeplans,
794-
((MergeAppendState *) planstate)->mergeplans,
795-
rels_used);
796-
break;
797-
case T_BitmapAnd:
798-
ExplainPreScanMemberNodes(((BitmapAnd *) plan)->bitmapplans,
799-
((BitmapAndState *) planstate)->bitmapplans,
800-
rels_used);
801-
break;
802-
case T_BitmapOr:
803-
ExplainPreScanMemberNodes(((BitmapOr *) plan)->bitmapplans,
804-
((BitmapOrState *) planstate)->bitmapplans,
805-
rels_used);
806-
break;
807-
case T_SubqueryScan:
808-
ExplainPreScanNode(((SubqueryScanState *) planstate)->subplan,
809-
rels_used);
810-
break;
811-
default:
812-
break;
813-
}
814-
815-
/* subPlan-s */
816-
if (planstate->subPlan)
817-
ExplainPreScanSubPlans(planstate->subPlan, rels_used);
818-
}
819-
820-
/*
821-
* Prescan the constituent plans of a ModifyTable, Append, MergeAppend,
822-
* BitmapAnd, or BitmapOr node.
823-
*
824-
* Note: we don't actually need to examine the Plan list members, but
825-
* we need the list in order to determine the length of the PlanState array.
826-
*/
827-
static void
828-
ExplainPreScanMemberNodes(List *plans, PlanState **planstates,
829-
Bitmapset **rels_used)
830-
{
831-
int nplans = list_length(plans);
832-
int j;
833-
834-
for (j = 0; j < nplans; j++)
835-
ExplainPreScanNode(planstates[j], rels_used);
836-
}
837-
838-
/*
839-
* Prescan a list of SubPlans (or initPlans, which also use SubPlan nodes).
840-
*/
841-
static void
842-
ExplainPreScanSubPlans(List *plans, Bitmapset **rels_used)
843-
{
844-
ListCell *lst;
845-
846-
foreach(lst, plans)
847-
{
848-
SubPlanState *sps = (SubPlanState *) lfirst(lst);
849-
850-
ExplainPreScanNode(sps->planstate, rels_used);
851-
}
764+
return planstate_tree_walker(planstate, ExplainPreScanNode, rels_used);
852765
}
853766

854767
/*

src/backend/nodes/nodeFuncs.c

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "catalog/pg_type.h"
1919
#include "miscadmin.h"
2020
#include "nodes/makefuncs.h"
21+
#include "nodes/execnodes.h"
2122
#include "nodes/nodeFuncs.h"
2223
#include "nodes/relation.h"
2324
#include "utils/builtins.h"
@@ -26,6 +27,10 @@
2627

2728
static bool expression_returns_set_walker(Node *node, void *context);
2829
static int leftmostLoc(int loc1, int loc2);
30+
static bool planstate_walk_subplans(List *plans, bool (*walker) (),
31+
void *context);
32+
static bool planstate_walk_members(List *plans, PlanState **planstates,
33+
bool (*walker) (), void *context);
2934

3035

3136
/*
@@ -3412,3 +3417,123 @@ raw_expression_tree_walker(Node *node,
34123417
}
34133418
return false;
34143419
}
3420+
3421+
/*
3422+
* planstate_tree_walker --- walk plan state trees
3423+
*
3424+
* The walker has already visited the current node, and so we need only
3425+
* recurse into any sub-nodes it has.
3426+
*/
3427+
bool
3428+
planstate_tree_walker(PlanState *planstate, bool (*walker) (), void *context)
3429+
{
3430+
Plan *plan = planstate->plan;
3431+
3432+
/* initPlan-s */
3433+
if (planstate_walk_subplans(planstate->initPlan, walker, context))
3434+
return true;
3435+
3436+
/* lefttree */
3437+
if (outerPlanState(planstate))
3438+
{
3439+
if (walker(outerPlanState(planstate), context))
3440+
return true;
3441+
}
3442+
3443+
/* righttree */
3444+
if (innerPlanState(planstate))
3445+
{
3446+
if (walker(innerPlanState(planstate), context))
3447+
return true;
3448+
}
3449+
3450+
/* special child plans */
3451+
switch (nodeTag(plan))
3452+
{
3453+
case T_ModifyTable:
3454+
if (planstate_walk_members(((ModifyTable *) plan)->plans,
3455+
((ModifyTableState *) planstate)->mt_plans,
3456+
walker, context))
3457+
return true;
3458+
break;
3459+
case T_Append:
3460+
if (planstate_walk_members(((Append *) plan)->appendplans,
3461+
((AppendState *) planstate)->appendplans,
3462+
walker, context))
3463+
return true;
3464+
break;
3465+
case T_MergeAppend:
3466+
if (planstate_walk_members(((MergeAppend *) plan)->mergeplans,
3467+
((MergeAppendState *) planstate)->mergeplans,
3468+
walker, context))
3469+
return true;
3470+
break;
3471+
case T_BitmapAnd:
3472+
if (planstate_walk_members(((BitmapAnd *) plan)->bitmapplans,
3473+
((BitmapAndState *) planstate)->bitmapplans,
3474+
walker, context))
3475+
return true;
3476+
break;
3477+
case T_BitmapOr:
3478+
if (planstate_walk_members(((BitmapOr *) plan)->bitmapplans,
3479+
((BitmapOrState *) planstate)->bitmapplans,
3480+
walker, context))
3481+
return true;
3482+
break;
3483+
case T_SubqueryScan:
3484+
if (walker(((SubqueryScanState *) planstate)->subplan, context))
3485+
return true;
3486+
break;
3487+
default:
3488+
break;
3489+
}
3490+
3491+
/* subPlan-s */
3492+
if (planstate_walk_subplans(planstate->subPlan, walker, context))
3493+
return true;
3494+
3495+
return false;
3496+
}
3497+
3498+
/*
3499+
* Walk a list of SubPlans (or initPlans, which also use SubPlan nodes).
3500+
*/
3501+
static bool
3502+
planstate_walk_subplans(List *plans, bool (*walker) (), void *context)
3503+
{
3504+
ListCell *lc;
3505+
3506+
foreach(lc, plans)
3507+
{
3508+
SubPlanState *sps = (SubPlanState *) lfirst(lc);
3509+
3510+
Assert(IsA(sps, SubPlanState));
3511+
if (walker(sps->planstate, context))
3512+
return true;
3513+
}
3514+
3515+
return false;
3516+
}
3517+
3518+
/*
3519+
* Walk the constituent plans of a ModifyTable, Append, MergeAppend,
3520+
* BitmapAnd, or BitmapOr node.
3521+
*
3522+
* Note: we don't actually need to examine the Plan list members, but
3523+
* we need the list in order to determine the length of the PlanState array.
3524+
*/
3525+
static bool
3526+
planstate_walk_members(List *plans, PlanState **planstates,
3527+
bool (*walker) (), void *context)
3528+
{
3529+
int nplans = list_length(plans);
3530+
int j;
3531+
3532+
for (j = 0; j < nplans; j++)
3533+
{
3534+
if (walker(planstates[j], context))
3535+
return true;
3536+
}
3537+
3538+
return false;
3539+
}

src/include/nodes/nodeFuncs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,8 @@ extern Node *query_or_expression_tree_mutator(Node *node, Node *(*mutator) (),
6363
extern bool raw_expression_tree_walker(Node *node, bool (*walker) (),
6464
void *context);
6565

66+
struct PlanState;
67+
extern bool planstate_tree_walker(struct PlanState *planstate, bool (*walker) (),
68+
void *context);
69+
6670
#endif /* NODEFUNCS_H */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy