1
1
diff --git a/contrib/Makefile b/contrib/Makefile
2
- index bbf220407b..8c3dc186ef 100644
2
+ index bbf220407b0..8c3dc186efa 100644
3
3
--- a/contrib/Makefile
4
4
+++ b/contrib/Makefile
5
5
@@ -7,6 +7,7 @@ include $(top_builddir)/src/Makefile.global
@@ -11,7 +11,7 @@ index bbf220407b..8c3dc186ef 100644
11
11
auto_explain \
12
12
basic_archive \
13
13
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
14
- index 060c6186dd..742a0a3e84 100644
14
+ index 060c6186ddd..6e69b70aab4 100644
15
15
--- a/src/backend/commands/explain.c
16
16
+++ b/src/backend/commands/explain.c
17
17
@@ -24,6 +24,7 @@
@@ -46,7 +46,52 @@ index 060c6186dd..742a0a3e84 100644
46
46
ExplainCloseGroup("Query", NULL, true, es);
47
47
}
48
48
49
- @@ -1661,6 +1672,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
49
+ @@ -1621,6 +1632,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
50
+ double total_ms = 1000.0 * planstate->instrument->total / nloops;
51
+ double rows = planstate->instrument->ntuples / nloops;
52
+
53
+ + Assert(planstate->instrument->finished >= TS_NOT_APPLICABLE &&
54
+ + planstate->instrument->finished <= TS_LOOP_FINISHED);
55
+ +
56
+ if (es->format == EXPLAIN_FORMAT_TEXT)
57
+ {
58
+ if (es->timing)
59
+ @@ -1631,6 +1645,16 @@ ExplainNode(PlanState *planstate, List *ancestors,
60
+ appendStringInfo(es->str,
61
+ " (actual rows=%.0f loops=%.0f)",
62
+ rows, nloops);
63
+ +
64
+ + if (es->verbose)
65
+ + {
66
+ + if (planstate->instrument->finished == TS_IN_ACTION)
67
+ + appendStringInfoString(es->str, " (early terminated)");
68
+ + else
69
+ + {
70
+ + /* Don't make a noise in a common case */
71
+ + }
72
+ + }
73
+ }
74
+ else
75
+ {
76
+ @@ -1643,6 +1667,17 @@ ExplainNode(PlanState *planstate, List *ancestors,
77
+ }
78
+ ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
79
+ ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
80
+ +
81
+ + if (es->verbose)
82
+ + {
83
+ + if (planstate->instrument->finished == TS_IN_ACTION)
84
+ + ExplainPropertyText("Termination Status",
85
+ + "early terminated", es);
86
+ + else
87
+ + {
88
+ + /* Don't make a noise in a common case */
89
+ + }
90
+ + }
91
+ }
92
+ }
93
+ else if (es->analyze)
94
+ @@ -1661,6 +1696,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
50
95
}
51
96
}
52
97
@@ -56,8 +101,48 @@ index 060c6186dd..742a0a3e84 100644
56
101
/* in text format, first line ends here */
57
102
if (es->format == EXPLAIN_FORMAT_TEXT)
58
103
appendStringInfoChar(es->str, '\n');
104
+ diff --git a/src/backend/executor/execAsync.c b/src/backend/executor/execAsync.c
105
+ index d8d79e972ee..06f36ece184 100644
106
+ --- a/src/backend/executor/execAsync.c
107
+ +++ b/src/backend/executor/execAsync.c
108
+ @@ -89,7 +89,7 @@ ExecAsyncNotify(AsyncRequest *areq)
109
+ {
110
+ /* must provide our own instrumentation support */
111
+ if (areq->requestee->instrument)
112
+ - InstrStartNode(areq->requestee->instrument);
113
+ + InstrStartNodeExecution(areq->requestee->instrument);
114
+
115
+ switch (nodeTag(areq->requestee))
116
+ {
117
+ @@ -106,7 +106,7 @@ ExecAsyncNotify(AsyncRequest *areq)
118
+
119
+ /* must provide our own instrumentation support */
120
+ if (areq->requestee->instrument)
121
+ - InstrStopNode(areq->requestee->instrument,
122
+ + InstrStopNodeExecution(areq->requestee->instrument,
123
+ TupIsNull(areq->result) ? 0.0 : 1.0);
124
+ }
125
+
126
+ diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
127
+ index 41cdf0515bf..47b016c2c94 100644
128
+ --- a/src/backend/executor/execProcnode.c
129
+ +++ b/src/backend/executor/execProcnode.c
130
+ @@ -475,11 +475,11 @@ ExecProcNodeInstr(PlanState *node)
131
+ {
132
+ TupleTableSlot *result;
133
+
134
+ - InstrStartNode(node->instrument);
135
+ + InstrStartNodeExecution(node->instrument);
136
+
137
+ result = node->ExecProcNodeReal(node);
138
+
139
+ - InstrStopNode(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
140
+ + InstrStopNodeExecution(node->instrument, TupIsNull(result) ? 0.0 : 1.0);
141
+
142
+ return result;
143
+ }
59
144
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
60
- index b39b77050e..f6262419e9 100644
145
+ index b39b77050e0..f6262419e92 100644
61
146
--- a/src/backend/nodes/copyfuncs.c
62
147
+++ b/src/backend/nodes/copyfuncs.c
63
148
@@ -136,6 +136,7 @@ CopyPlanFields(const Plan *from, Plan *newnode)
@@ -69,7 +154,7 @@ index b39b77050e..f6262419e9 100644
69
154
70
155
/*
71
156
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
72
- index 3f8e58626c..256c76acf2 100644
157
+ index 3f8e58626cc..256c76acf29 100644
73
158
--- a/src/backend/nodes/outfuncs.c
74
159
+++ b/src/backend/nodes/outfuncs.c
75
160
@@ -356,6 +356,7 @@ _outPlanInfo(StringInfo str, const Plan *node)
@@ -81,7 +166,7 @@ index 3f8e58626c..256c76acf2 100644
81
166
82
167
/*
83
168
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
84
- index c84e5af3a2..ae0e78b142 100644
169
+ index c84e5af3a26..ae0e78b1424 100644
85
170
--- a/src/backend/nodes/readfuncs.c
86
171
+++ b/src/backend/nodes/readfuncs.c
87
172
@@ -1666,6 +1666,11 @@ ReadCommonPlan(Plan *local_node)
@@ -97,7 +182,7 @@ index c84e5af3a2..ae0e78b142 100644
97
182
98
183
/*
99
184
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
100
- index 0ba26b207b..7baf41539e 100644
185
+ index 0ba26b207b0..7baf41539e1 100644
101
186
--- a/src/backend/optimizer/path/costsize.c
102
187
+++ b/src/backend/optimizer/path/costsize.c
103
188
@@ -99,6 +99,11 @@
@@ -362,7 +447,7 @@ index 0ba26b207b..7baf41539e 100644
362
447
{
363
448
double parallel_divisor = path->parallel_workers;
364
449
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
365
- index 1bc59c9457..81cf03514d 100644
450
+ index 1bc59c94578..81cf03514d3 100644
366
451
--- a/src/backend/optimizer/plan/createplan.c
367
452
+++ b/src/backend/optimizer/plan/createplan.c
368
453
@@ -70,6 +70,7 @@
@@ -393,7 +478,7 @@ index 1bc59c9457..81cf03514d 100644
393
478
394
479
/*
395
480
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
396
- index 468105d91e..63822050ff 100644
481
+ index c588693dc43..1ad88d77ce5 100644
397
482
--- a/src/backend/optimizer/plan/planner.c
398
483
+++ b/src/backend/optimizer/plan/planner.c
399
484
@@ -143,7 +143,8 @@ static List *extract_rollup_sets(List *groupingSets);
@@ -406,7 +491,7 @@ index 468105d91e..63822050ff 100644
406
491
grouping_sets_data *gd,
407
492
List *target_list);
408
493
static RelOptInfo *create_grouping_paths(PlannerInfo *root,
409
- @@ -3220 ,7 +3221 ,8 @@ standard_qp_callback(PlannerInfo *root, void *extra)
494
+ @@ -3221 ,7 +3222 ,8 @@ standard_qp_callback(PlannerInfo *root, void *extra)
410
495
*/
411
496
static double
412
497
get_number_of_groups(PlannerInfo *root,
@@ -416,7 +501,7 @@ index 468105d91e..63822050ff 100644
416
501
grouping_sets_data *gd,
417
502
List *target_list)
418
503
{
419
- @@ -3257 ,7 +3259 ,7 @@ get_number_of_groups(PlannerInfo *root,
504
+ @@ -3258 ,7 +3260 ,7 @@ get_number_of_groups(PlannerInfo *root,
420
505
GroupingSetData *gs = lfirst_node(GroupingSetData, lc2);
421
506
double numGroups = estimate_num_groups(root,
422
507
groupExprs,
@@ -425,7 +510,7 @@ index 468105d91e..63822050ff 100644
425
510
&gset,
426
511
NULL);
427
512
428
- @@ -3283 ,7 +3285 ,7 @@ get_number_of_groups(PlannerInfo *root,
513
+ @@ -3284 ,7 +3286 ,7 @@ get_number_of_groups(PlannerInfo *root,
429
514
GroupingSetData *gs = lfirst_node(GroupingSetData, lc2);
430
515
double numGroups = estimate_num_groups(root,
431
516
groupExprs,
@@ -434,7 +519,7 @@ index 468105d91e..63822050ff 100644
434
519
&gset,
435
520
NULL);
436
521
437
- @@ -3300 ,8 +3302 ,8 @@ get_number_of_groups(PlannerInfo *root,
522
+ @@ -3301 ,8 +3303 ,8 @@ get_number_of_groups(PlannerInfo *root,
438
523
groupExprs = get_sortgrouplist_exprs(parse->groupClause,
439
524
target_list);
440
525
@@ -445,7 +530,7 @@ index 468105d91e..63822050ff 100644
445
530
}
446
531
}
447
532
else if (parse->groupingSets)
448
- @@ -3688 ,7 +3690 ,8 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
533
+ @@ -3689 ,7 +3691 ,8 @@ create_ordinary_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel,
449
534
* Estimate number of groups.
450
535
*/
451
536
dNumGroups = get_number_of_groups(root,
@@ -455,7 +540,7 @@ index 468105d91e..63822050ff 100644
455
540
gd,
456
541
extra->targetList);
457
542
458
- @@ -6653 ,13 +6656 ,15 @@ create_partial_grouping_paths(PlannerInfo *root,
543
+ @@ -6654 ,13 +6657 ,15 @@ create_partial_grouping_paths(PlannerInfo *root,
459
544
if (cheapest_total_path != NULL)
460
545
dNumPartialGroups =
461
546
get_number_of_groups(root,
@@ -474,7 +559,7 @@ index 468105d91e..63822050ff 100644
474
559
extra->targetList);
475
560
476
561
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
477
- index 520409f4ba..fd0524d72b 100644
562
+ index 3c75fd56f22..f15d22c41be 100644
478
563
--- a/src/backend/optimizer/util/relnode.c
479
564
+++ b/src/backend/optimizer/util/relnode.c
480
565
@@ -259,6 +259,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
@@ -540,7 +625,7 @@ index 520409f4ba..fd0524d72b 100644
540
625
541
626
return ppi;
542
627
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
543
- index 8d1b374bdf..ac4ea7b6e4 100644
628
+ index 2dd399d5e37..53178369c70 100644
544
629
--- a/src/backend/utils/adt/selfuncs.c
545
630
+++ b/src/backend/utils/adt/selfuncs.c
546
631
@@ -143,6 +143,7 @@
@@ -573,7 +658,7 @@ index 8d1b374bdf..ac4ea7b6e4 100644
573
658
* estimate_num_groups - Estimate number of groups in a grouped query
574
659
*
575
660
diff --git a/src/include/commands/explain.h b/src/include/commands/explain.h
576
- index 666977fb1f..33b109afbb 100644
661
+ index 666977fb1f8..33b109afbbd 100644
577
662
--- a/src/include/commands/explain.h
578
663
+++ b/src/include/commands/explain.h
579
664
@@ -75,6 +75,18 @@ extern PGDLLIMPORT ExplainOneQuery_hook_type ExplainOneQuery_hook;
@@ -595,8 +680,57 @@ index 666977fb1f..33b109afbb 100644
595
680
596
681
extern void ExplainQuery(ParseState *pstate, ExplainStmt *stmt,
597
682
ParamListInfo params, DestReceiver *dest);
683
+ diff --git a/src/include/executor/instrument.h b/src/include/executor/instrument.h
684
+ index 2945cce3a97..1f6b3451d58 100644
685
+ --- a/src/include/executor/instrument.h
686
+ +++ b/src/include/executor/instrument.h
687
+ @@ -63,6 +63,13 @@ typedef enum InstrumentOption
688
+ INSTRUMENT_ALL = PG_INT32_MAX
689
+ } InstrumentOption;
690
+
691
+ + typedef enum TermStatus
692
+ + {
693
+ + TS_NOT_APPLICABLE = 0, /* Can be used by some analyzing tools, to skip such a node */
694
+ + TS_IN_ACTION,
695
+ + TS_LOOP_FINISHED
696
+ + } TermStatus;
697
+ +
698
+ typedef struct Instrumentation
699
+ {
700
+ /* Parameters set at node creation: */
701
+ @@ -72,6 +79,7 @@ typedef struct Instrumentation
702
+ bool async_mode; /* true if node is in async mode */
703
+ /* Info about current plan cycle: */
704
+ bool running; /* true if we've completed first tuple */
705
+ + TermStatus finished; /* true, if we have finished loop of the node scanning */
706
+ instr_time starttime; /* start time of current iteration of node */
707
+ instr_time counter; /* accumulated runtime for this node */
708
+ double firsttuple; /* time for first tuple of this cycle */
709
+ @@ -99,6 +107,22 @@ typedef struct WorkerInstrumentation
710
+ extern PGDLLIMPORT BufferUsage pgBufferUsage;
711
+ extern PGDLLIMPORT WalUsage pgWalUsage;
712
+
713
+ + /*
714
+ + * Just to reduce invasiveness of solution.
715
+ + */
716
+ + #define InstrStartNodeExecution(instr) \
717
+ + { \
718
+ + InstrStartNode(instr); \
719
+ + instr->finished = TS_IN_ACTION; \
720
+ + }
721
+ +
722
+ + #define InstrStopNodeExecution(instr, ntuples) \
723
+ + { \
724
+ + InstrStopNode(instr, ntuples); \
725
+ + if (!instr->async_mode && (ntuples) < 1.0) \
726
+ + instr->finished = TS_LOOP_FINISHED; \
727
+ + }
728
+ +
729
+ extern Instrumentation *InstrAlloc(int n, int instrument_options,
730
+ bool async_mode);
731
+ extern void InstrInit(Instrumentation *instr, int instrument_options);
598
732
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
599
- index 8556b2ffe7..48b191e426 100644
733
+ index cbaefd9f043..06d8bac7d16 100644
600
734
--- a/src/include/nodes/pathnodes.h
601
735
+++ b/src/include/nodes/pathnodes.h
602
736
@@ -757,6 +757,10 @@ typedef struct RelOptInfo
@@ -637,7 +771,7 @@ index 8556b2ffe7..48b191e426 100644
637
771
638
772
639
773
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
640
- index 0ea9a22dfb..d084e4f8a0 100644
774
+ index 493a2a9e4a5..adb7f4134c4 100644
641
775
--- a/src/include/nodes/plannodes.h
642
776
+++ b/src/include/nodes/plannodes.h
643
777
@@ -159,6 +159,9 @@ typedef struct Plan
@@ -651,7 +785,7 @@ index 0ea9a22dfb..d084e4f8a0 100644
651
785
652
786
/* ----------------
653
787
diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h
654
- index bc12071af6..13fa62652f 100644
788
+ index bc12071af6e..13fa62652fa 100644
655
789
--- a/src/include/optimizer/cost.h
656
790
+++ b/src/include/optimizer/cost.h
657
791
@@ -41,6 +41,37 @@ typedef enum
@@ -735,7 +869,7 @@ index bc12071af6..13fa62652f 100644
735
869
736
870
#endif /* COST_H */
737
871
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
738
- index d2d46b15df..88608af01d 100644
872
+ index d2d46b15df5..88608af01d7 100644
739
873
--- a/src/include/optimizer/pathnode.h
740
874
+++ b/src/include/optimizer/pathnode.h
741
875
@@ -18,6 +18,10 @@
@@ -750,7 +884,7 @@ index d2d46b15df..88608af01d 100644
750
884
* prototypes for pathnode.c
751
885
*/
752
886
diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h
753
- index c4f61c1a09..ade32a6f44 100644
887
+ index c4f61c1a09c..ade32a6f444 100644
754
888
--- a/src/include/optimizer/planmain.h
755
889
+++ b/src/include/optimizer/planmain.h
756
890
@@ -24,6 +24,12 @@ extern PGDLLIMPORT double cursor_tuple_fraction;
@@ -767,7 +901,7 @@ index c4f61c1a09..ade32a6f44 100644
767
901
* prototypes for plan/planmain.c
768
902
*/
769
903
diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h
770
- index 8f3d73edfb..91537e2325 100644
904
+ index 8f3d73edfb2..91537e23252 100644
771
905
--- a/src/include/utils/selfuncs.h
772
906
+++ b/src/include/utils/selfuncs.h
773
907
@@ -144,6 +144,13 @@ typedef bool (*get_index_stats_hook_type) (PlannerInfo *root,
0 commit comments