@@ -11,7 +11,7 @@ index 92184ed487..ac8abbfd03 100644
1111 auto_explain\
1212 bloom\
1313diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
14- index a40bc14ec5..28ec281a70 100644
14+ index a40bc14ec5..d157c3043e 100644
1515--- a/src/backend/commands/explain.c
1616+++ b/src/backend/commands/explain.c
1717@@ -24,6 +24,7 @@
@@ -22,17 +22,20 @@ index a40bc14ec5..28ec281a70 100644
2222 #include "parser/parsetree.h"
2323 #include "rewrite/rewriteHandler.h"
2424 #include "storage/bufmgr.h"
25- @@ -46,6 +47,9 @@ ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL;
25+ @@ -46,6 +47,12 @@ ExplainOneQuery_hook_type ExplainOneQuery_hook = NULL;
2626 /* Hook for plugins to get control in explain_get_index_name() */
2727 explain_get_index_name_hook_type explain_get_index_name_hook = NULL;
2828
2929+ /* Hook for plugins to get control in ExplainOnePlan() */
3030+ ExplainOnePlan_hook_type ExplainOnePlan_hook = NULL;
31+ +
32+ + /* Hook for plugins to get control in ExplainOnePlan() */
33+ + ExplainOneNode_hook_type ExplainOneNode_hook = NULL;
3134+
3235
3336 /* OR-able flags for ExplainXMLTag() */
3437 #define X_OPENING 0
35- @@ -597,6 +601 ,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
38+ @@ -597,6 +604 ,10 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
3639 ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
3740 es);
3841
@@ -43,42 +46,13 @@ index a40bc14ec5..28ec281a70 100644
4346 ExplainCloseGroup("Query", NULL, true, es);
4447 }
4548
46- @@ -1521,6 +1529,38 @@ ExplainNode(PlanState *planstate, List *ancestors,
49+ @@ -1521,6 +1532,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
4750 appendStringInfo(es->str,
4851 " (actual rows=%.0f loops=%.0f)",
4952 rows, nloops);
5053+
51- + #ifdef AQO_EXPLAIN
52- + if (es->verbose && plan && planstate->instrument)
53- + {
54- + int wrkrs = 1;
55- + double error = -1.;
56- +
57- + if (planstate->worker_instrument && IsParallelTuplesProcessing(plan))
58- + {
59- + int i;
60- + for (i = 0; i < planstate->worker_instrument->num_workers; i++)
61- + {
62- + Instrumentation *instrument = &planstate->worker_instrument->instrument[i];
63- + if (instrument->nloops <= 0)
64- + continue;
65- + wrkrs++;
66- + }
67- + }
68- +
69- + if (plan->predicted_cardinality > 0.)
70- + {
71- + error = 100. * (plan->predicted_cardinality - (rows*wrkrs))
72- + / plan->predicted_cardinality;
73- + appendStringInfo(es->str,
74- + " (AQO: cardinality=%.0lf, error=%.0lf%%, fsspace_hash=%d)",
75- + plan->predicted_cardinality, error, plan->fss_hash);
76- + }
77- + else
78- + appendStringInfo(es->str, " (AQO not used, fsspace_hash=%d)",
79- + plan->fss_hash);
80- + }
81- + #endif
54+ + if (ExplainOneNode_hook)
55+ + ExplainOneNode_hook(es, planstate, plan, rows);
8256 }
8357 else
8458 {
@@ -909,10 +883,10 @@ index 7758a49fa4..4f221a000b 100644
909883
910884 return ppi;
911885diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
912- index f8b79ec120..b5eda01907 100644
886+ index f8b79ec120..f970971a4a 100644
913887--- a/src/include/commands/explain.h
914888+++ b/src/include/commands/explain.h
915- @@ -62,6 +62,12 @@ extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook;
889+ @@ -62,6 +62,19 @@ extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook;
916890 typedef const char *(*explain_get_index_name_hook_type) (Oid indexId);
917891 extern PGDLLIMPORT explain_get_index_name_hook_type explain_get_index_name_hook;
918892
@@ -922,6 +896,13 @@ index f8b79ec120..b5eda01907 100644
922896+ ParamListInfo params, const instr_time *planduration,
923897+ QueryEnvironment *queryEnv);
924898+ extern PGDLLIMPORT ExplainOnePlan_hook_type ExplainOnePlan_hook;
899+ +
900+ + /* Explain a plan node info */
901+ + typedef void (*ExplainOneNode_hook_type) (ExplainState *es,
902+ + PlanState *ps,
903+ + Plan *plan,
904+ + double rows);
905+ + extern PGDLLIMPORT ExplainOneNode_hook_type ExplainOneNode_hook;
925906
926907 extern void ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
927908 ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest);