Commit 7a50bb69 authored by Andres Freund's avatar Andres Freund

Add 'unit' parameter to ExplainProperty{Integer,Float}.

This allows to deduplicate some existing code, but mainly avoids some
duplication in upcoming commits.

In passing, fix variable names indicating wrong unit (seconds instead
of ms).

Author: Andres Freund
Discussion: https://postgr.es/m/20180314002740.cah3mdsonz5mxney@alap3.anarazel.de
parent f3e4b95e
...@@ -622,7 +622,7 @@ fileExplainForeignScan(ForeignScanState *node, ExplainState *es) ...@@ -622,7 +622,7 @@ fileExplainForeignScan(ForeignScanState *node, ExplainState *es)
if (!is_program && if (!is_program &&
stat(filename, &stat_buf) == 0) stat(filename, &stat_buf) == 0)
ExplainPropertyInteger("Foreign File Size", ExplainPropertyInteger("Foreign File Size", "b",
(int64) stat_buf.st_size, es); (int64) stat_buf.st_size, es);
} }
} }
......
...@@ -123,8 +123,8 @@ static void ExplainSubPlans(List *plans, List *ancestors, ...@@ -123,8 +123,8 @@ static void ExplainSubPlans(List *plans, List *ancestors,
const char *relationship, ExplainState *es); const char *relationship, ExplainState *es);
static void ExplainCustomChildren(CustomScanState *css, static void ExplainCustomChildren(CustomScanState *css,
List *ancestors, ExplainState *es); List *ancestors, ExplainState *es);
static void ExplainProperty(const char *qlabel, const char *value, static void ExplainProperty(const char *qlabel, const char *unit,
bool numeric, ExplainState *es); const char *value, bool numeric, ExplainState *es);
static void ExplainDummyGroup(const char *objtype, const char *labelname, static void ExplainDummyGroup(const char *objtype, const char *labelname,
ExplainState *es); ExplainState *es);
static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es); static void ExplainXMLTag(const char *tagname, int flags, ExplainState *es);
...@@ -549,11 +549,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, ...@@ -549,11 +549,7 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
{ {
double plantime = INSTR_TIME_GET_DOUBLE(*planduration); double plantime = INSTR_TIME_GET_DOUBLE(*planduration);
if (es->format == EXPLAIN_FORMAT_TEXT) ExplainPropertyFloat("Planning Time", "ms", 1000.0 * plantime, 3, es);
appendStringInfo(es->str, "Planning time: %.3f ms\n",
1000.0 * plantime);
else
ExplainPropertyFloat("Planning Time", 1000.0 * plantime, 3, es);
} }
/* Print info about runtime of triggers */ /* Print info about runtime of triggers */
...@@ -585,14 +581,8 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es, ...@@ -585,14 +581,8 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
* the output). By default, ANALYZE sets SUMMARY to true. * the output). By default, ANALYZE sets SUMMARY to true.
*/ */
if (es->summary && es->analyze) if (es->summary && es->analyze)
{ ExplainPropertyFloat("Execution Time", "ms", 1000.0 * totaltime, 3,
if (es->format == EXPLAIN_FORMAT_TEXT) es);
appendStringInfo(es->str, "Execution time: %.3f ms\n",
1000.0 * totaltime);
else
ExplainPropertyFloat("Execution Time", 1000.0 * totaltime,
3, es);
}
ExplainCloseGroup("Query", NULL, true, es); ExplainCloseGroup("Query", NULL, true, es);
} }
...@@ -764,8 +754,9 @@ report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es) ...@@ -764,8 +754,9 @@ report_triggers(ResultRelInfo *rInfo, bool show_relname, ExplainState *es)
ExplainPropertyText("Constraint Name", conname, es); ExplainPropertyText("Constraint Name", conname, es);
ExplainPropertyText("Relation", relname, es); ExplainPropertyText("Relation", relname, es);
if (es->timing) if (es->timing)
ExplainPropertyFloat("Time", 1000.0 * instr->total, 3, es); ExplainPropertyFloat("Time", "ms", 1000.0 * instr->total, 3,
ExplainPropertyFloat("Calls", instr->ntuples, 0, es); es);
ExplainPropertyFloat("Calls", NULL, instr->ntuples, 0, es);
} }
if (conname) if (conname)
...@@ -1280,10 +1271,14 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1280,10 +1271,14 @@ ExplainNode(PlanState *planstate, List *ancestors,
} }
else else
{ {
ExplainPropertyFloat("Startup Cost", plan->startup_cost, 2, es); ExplainPropertyFloat("Startup Cost", NULL, plan->startup_cost,
ExplainPropertyFloat("Total Cost", plan->total_cost, 2, es); 2, es);
ExplainPropertyFloat("Plan Rows", plan->plan_rows, 0, es); ExplainPropertyFloat("Total Cost", NULL, plan->total_cost,
ExplainPropertyInteger("Plan Width", plan->plan_width, es); 2, es);
ExplainPropertyFloat("Plan Rows", NULL, plan->plan_rows,
0, es);
ExplainPropertyInteger("Plan Width", NULL, plan->plan_width,
es);
} }
} }
...@@ -1304,8 +1299,8 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1304,8 +1299,8 @@ ExplainNode(PlanState *planstate, List *ancestors,
planstate->instrument && planstate->instrument->nloops > 0) planstate->instrument && planstate->instrument->nloops > 0)
{ {
double nloops = planstate->instrument->nloops; double nloops = planstate->instrument->nloops;
double startup_sec = 1000.0 * planstate->instrument->startup / nloops; double startup_ms = 1000.0 * planstate->instrument->startup / nloops;
double total_sec = 1000.0 * planstate->instrument->total / nloops; double total_ms = 1000.0 * planstate->instrument->total / nloops;
double rows = planstate->instrument->ntuples / nloops; double rows = planstate->instrument->ntuples / nloops;
if (es->format == EXPLAIN_FORMAT_TEXT) if (es->format == EXPLAIN_FORMAT_TEXT)
...@@ -1313,7 +1308,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1313,7 +1308,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
if (es->timing) if (es->timing)
appendStringInfo(es->str, appendStringInfo(es->str,
" (actual time=%.3f..%.3f rows=%.0f loops=%.0f)", " (actual time=%.3f..%.3f rows=%.0f loops=%.0f)",
startup_sec, total_sec, rows, nloops); startup_ms, total_ms, rows, nloops);
else else
appendStringInfo(es->str, appendStringInfo(es->str,
" (actual rows=%.0f loops=%.0f)", " (actual rows=%.0f loops=%.0f)",
...@@ -1323,11 +1318,13 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1323,11 +1318,13 @@ ExplainNode(PlanState *planstate, List *ancestors,
{ {
if (es->timing) if (es->timing)
{ {
ExplainPropertyFloat("Actual Startup Time", startup_sec, 3, es); ExplainPropertyFloat("Actual Startup Time", "s", startup_ms,
ExplainPropertyFloat("Actual Total Time", total_sec, 3, es); 3, es);
ExplainPropertyFloat("Actual Total Time", "s", total_ms,
3, es);
} }
ExplainPropertyFloat("Actual Rows", rows, 0, es); ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
ExplainPropertyFloat("Actual Loops", nloops, 0, es); ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
} }
} }
else if (es->analyze) else if (es->analyze)
...@@ -1338,11 +1335,11 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1338,11 +1335,11 @@ ExplainNode(PlanState *planstate, List *ancestors,
{ {
if (es->timing) if (es->timing)
{ {
ExplainPropertyFloat("Actual Startup Time", 0.0, 3, es); ExplainPropertyFloat("Actual Startup Time", "ms", 0.0, 3, es);
ExplainPropertyFloat("Actual Total Time", 0.0, 3, es); ExplainPropertyFloat("Actual Total Time", "ms", 0.0, 3, es);
} }
ExplainPropertyFloat("Actual Rows", 0.0, 0, es); ExplainPropertyFloat("Actual Rows", NULL, 0.0, 0, es);
ExplainPropertyFloat("Actual Loops", 0.0, 0, es); ExplainPropertyFloat("Actual Loops", NULL, 0.0, 0, es);
} }
} }
...@@ -1400,9 +1397,12 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1400,9 +1397,12 @@ ExplainNode(PlanState *planstate, List *ancestors,
show_instrumentation_count("Rows Removed by Filter", 1, show_instrumentation_count("Rows Removed by Filter", 1,
planstate, es); planstate, es);
if (es->analyze) if (es->analyze)
ExplainPropertyInteger("Heap Fetches", {
((IndexOnlyScanState *) planstate)->ioss_HeapFetches, long heapFetches =
es); ((IndexOnlyScanState *) planstate)->ioss_HeapFetches;
ExplainPropertyInteger("Heap Fetches", NULL, heapFetches, es);
}
break; break;
case T_BitmapIndexScan: case T_BitmapIndexScan:
show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig, show_scan_qual(((BitmapIndexScan *) plan)->indexqualorig,
...@@ -1444,7 +1444,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1444,7 +1444,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
if (plan->qual) if (plan->qual)
show_instrumentation_count("Rows Removed by Filter", 1, show_instrumentation_count("Rows Removed by Filter", 1,
planstate, es); planstate, es);
ExplainPropertyInteger("Workers Planned", ExplainPropertyInteger("Workers Planned", NULL,
gather->num_workers, es); gather->num_workers, es);
/* Show params evaluated at gather node */ /* Show params evaluated at gather node */
...@@ -1456,7 +1456,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1456,7 +1456,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
int nworkers; int nworkers;
nworkers = ((GatherState *) planstate)->nworkers_launched; nworkers = ((GatherState *) planstate)->nworkers_launched;
ExplainPropertyInteger("Workers Launched", ExplainPropertyInteger("Workers Launched", NULL,
nworkers, es); nworkers, es);
} }
if (gather->single_copy || es->format != EXPLAIN_FORMAT_TEXT) if (gather->single_copy || es->format != EXPLAIN_FORMAT_TEXT)
...@@ -1471,7 +1471,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1471,7 +1471,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
if (plan->qual) if (plan->qual)
show_instrumentation_count("Rows Removed by Filter", 1, show_instrumentation_count("Rows Removed by Filter", 1,
planstate, es); planstate, es);
ExplainPropertyInteger("Workers Planned", ExplainPropertyInteger("Workers Planned", NULL,
gm->num_workers, es); gm->num_workers, es);
/* Show params evaluated at gather-merge node */ /* Show params evaluated at gather-merge node */
...@@ -1483,7 +1483,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1483,7 +1483,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
int nworkers; int nworkers;
nworkers = ((GatherMergeState *) planstate)->nworkers_launched; nworkers = ((GatherMergeState *) planstate)->nworkers_launched;
ExplainPropertyInteger("Workers Launched", ExplainPropertyInteger("Workers Launched", NULL,
nworkers, es); nworkers, es);
} }
} }
...@@ -1653,14 +1653,14 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1653,14 +1653,14 @@ ExplainNode(PlanState *planstate, List *ancestors,
{ {
Instrumentation *instrument = &w->instrument[n]; Instrumentation *instrument = &w->instrument[n];
double nloops = instrument->nloops; double nloops = instrument->nloops;
double startup_sec; double startup_ms;
double total_sec; double total_ms;
double rows; double rows;
if (nloops <= 0) if (nloops <= 0)
continue; continue;
startup_sec = 1000.0 * instrument->startup / nloops; startup_ms = 1000.0 * instrument->startup / nloops;
total_sec = 1000.0 * instrument->total / nloops; total_ms = 1000.0 * instrument->total / nloops;
rows = instrument->ntuples / nloops; rows = instrument->ntuples / nloops;
if (es->format == EXPLAIN_FORMAT_TEXT) if (es->format == EXPLAIN_FORMAT_TEXT)
...@@ -1670,7 +1670,7 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1670,7 +1670,7 @@ ExplainNode(PlanState *planstate, List *ancestors,
if (es->timing) if (es->timing)
appendStringInfo(es->str, appendStringInfo(es->str,
"actual time=%.3f..%.3f rows=%.0f loops=%.0f\n", "actual time=%.3f..%.3f rows=%.0f loops=%.0f\n",
startup_sec, total_sec, rows, nloops); startup_ms, total_ms, rows, nloops);
else else
appendStringInfo(es->str, appendStringInfo(es->str,
"actual rows=%.0f loops=%.0f\n", "actual rows=%.0f loops=%.0f\n",
...@@ -1688,15 +1688,17 @@ ExplainNode(PlanState *planstate, List *ancestors, ...@@ -1688,15 +1688,17 @@ ExplainNode(PlanState *planstate, List *ancestors,
opened_group = true; opened_group = true;
} }
ExplainOpenGroup("Worker", NULL, true, es); ExplainOpenGroup("Worker", NULL, true, es);
ExplainPropertyInteger("Worker Number", n, es); ExplainPropertyInteger("Worker Number", NULL, n, es);
if (es->timing) if (es->timing)
{ {
ExplainPropertyFloat("Actual Startup Time", startup_sec, 3, es); ExplainPropertyFloat("Actual Startup Time", "ms",
ExplainPropertyFloat("Actual Total Time", total_sec, 3, es); startup_ms, 3, es);
ExplainPropertyFloat("Actual Total Time", "ms",
total_ms, 3, es);
} }
ExplainPropertyFloat("Actual Rows", rows, 0, es); ExplainPropertyFloat("Actual Rows", NULL, rows, 0, es);
ExplainPropertyFloat("Actual Loops", nloops, 0, es); ExplainPropertyFloat("Actual Loops", NULL, nloops, 0, es);
if (es->buffers) if (es->buffers)
show_buffer_usage(es, &instrument->bufusage); show_buffer_usage(es, &instrument->bufusage);
...@@ -2326,7 +2328,7 @@ show_sort_info(SortState *sortstate, ExplainState *es) ...@@ -2326,7 +2328,7 @@ show_sort_info(SortState *sortstate, ExplainState *es)
else else
{ {
ExplainPropertyText("Sort Method", sortMethod, es); ExplainPropertyText("Sort Method", sortMethod, es);
ExplainPropertyInteger("Sort Space Used", spaceUsed, es); ExplainPropertyInteger("Sort Space Used", "kB", spaceUsed, es);
ExplainPropertyText("Sort Space Type", spaceType, es); ExplainPropertyText("Sort Space Type", spaceType, es);
} }
} }
...@@ -2365,9 +2367,9 @@ show_sort_info(SortState *sortstate, ExplainState *es) ...@@ -2365,9 +2367,9 @@ show_sort_info(SortState *sortstate, ExplainState *es)
opened_group = true; opened_group = true;
} }
ExplainOpenGroup("Worker", NULL, true, es); ExplainOpenGroup("Worker", NULL, true, es);
ExplainPropertyInteger("Worker Number", n, es); ExplainPropertyInteger("Worker Number", NULL, n, es);
ExplainPropertyText("Sort Method", sortMethod, es); ExplainPropertyText("Sort Method", sortMethod, es);
ExplainPropertyInteger("Sort Space Used", spaceUsed, es); ExplainPropertyInteger("Sort Space Used", "kB", spaceUsed, es);
ExplainPropertyText("Sort Space Type", spaceType, es); ExplainPropertyText("Sort Space Type", spaceType, es);
ExplainCloseGroup("Worker", NULL, true, es); ExplainCloseGroup("Worker", NULL, true, es);
} }
...@@ -2446,13 +2448,16 @@ show_hash_info(HashState *hashstate, ExplainState *es) ...@@ -2446,13 +2448,16 @@ show_hash_info(HashState *hashstate, ExplainState *es)
if (es->format != EXPLAIN_FORMAT_TEXT) if (es->format != EXPLAIN_FORMAT_TEXT)
{ {
ExplainPropertyInteger("Hash Buckets", hinstrument.nbuckets, es); ExplainPropertyInteger("Hash Buckets", NULL,
ExplainPropertyInteger("Original Hash Buckets", hinstrument.nbuckets, es);
hinstrument.nbuckets_original, es); ExplainPropertyInteger("Original Hash Buckets", NULL,
ExplainPropertyInteger("Hash Batches", hinstrument.nbatch, es); hinstrument.nbuckets_original, es);
ExplainPropertyInteger("Original Hash Batches", ExplainPropertyInteger("Hash Batches", NULL,
hinstrument.nbatch_original, es); hinstrument.nbatch, es);
ExplainPropertyInteger("Peak Memory Usage", spacePeakKb, es); ExplainPropertyInteger("Original Hash Batches", NULL,
hinstrument.nbatch_original, es);
ExplainPropertyInteger("Peak Memory Usage", "kB",
spacePeakKb, es);
} }
else if (hinstrument.nbatch_original != hinstrument.nbatch || else if (hinstrument.nbatch_original != hinstrument.nbatch ||
hinstrument.nbuckets_original != hinstrument.nbuckets) hinstrument.nbuckets_original != hinstrument.nbuckets)
...@@ -2485,9 +2490,9 @@ show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es) ...@@ -2485,9 +2490,9 @@ show_tidbitmap_info(BitmapHeapScanState *planstate, ExplainState *es)
{ {
if (es->format != EXPLAIN_FORMAT_TEXT) if (es->format != EXPLAIN_FORMAT_TEXT)
{ {
ExplainPropertyInteger("Exact Heap Blocks", ExplainPropertyInteger("Exact Heap Blocks", NULL,
planstate->exact_pages, es); planstate->exact_pages, es);
ExplainPropertyInteger("Lossy Heap Blocks", ExplainPropertyInteger("Lossy Heap Blocks", NULL,
planstate->lossy_pages, es); planstate->lossy_pages, es);
} }
else else
...@@ -2530,9 +2535,9 @@ show_instrumentation_count(const char *qlabel, int which, ...@@ -2530,9 +2535,9 @@ show_instrumentation_count(const char *qlabel, int which,
if (nfiltered > 0 || es->format != EXPLAIN_FORMAT_TEXT) if (nfiltered > 0 || es->format != EXPLAIN_FORMAT_TEXT)
{ {
if (nloops > 0) if (nloops > 0)
ExplainPropertyFloat(qlabel, nfiltered / nloops, 0, es); ExplainPropertyFloat(qlabel, NULL, nfiltered / nloops, 0, es);
else else
ExplainPropertyFloat(qlabel, 0.0, 0, es); ExplainPropertyFloat(qlabel, NULL, 0.0, 0, es);
} }
} }
...@@ -2698,30 +2703,34 @@ show_buffer_usage(ExplainState *es, const BufferUsage *usage) ...@@ -2698,30 +2703,34 @@ show_buffer_usage(ExplainState *es, const BufferUsage *usage)
} }
else else
{ {
ExplainPropertyInteger("Shared Hit Blocks", ExplainPropertyInteger("Shared Hit Blocks", NULL,
usage->shared_blks_hit, es); usage->shared_blks_hit, es);
ExplainPropertyInteger("Shared Read Blocks", ExplainPropertyInteger("Shared Read Blocks", NULL,
usage->shared_blks_read, es); usage->shared_blks_read, es);
ExplainPropertyInteger("Shared Dirtied Blocks", ExplainPropertyInteger("Shared Dirtied Blocks", NULL,
usage->shared_blks_dirtied, es); usage->shared_blks_dirtied, es);
ExplainPropertyInteger("Shared Written Blocks", ExplainPropertyInteger("Shared Written Blocks", NULL,
usage->shared_blks_written, es); usage->shared_blks_written, es);
ExplainPropertyInteger("Local Hit Blocks", ExplainPropertyInteger("Local Hit Blocks", NULL,
usage->local_blks_hit, es); usage->local_blks_hit, es);
ExplainPropertyInteger("Local Read Blocks", ExplainPropertyInteger("Local Read Blocks", NULL,
usage->local_blks_read, es); usage->local_blks_read, es);
ExplainPropertyInteger("Local Dirtied Blocks", ExplainPropertyInteger("Local Dirtied Blocks", NULL,
usage->local_blks_dirtied, es); usage->local_blks_dirtied, es);
ExplainPropertyInteger("Local Written Blocks", ExplainPropertyInteger("Local Written Blocks", NULL,
usage->local_blks_written, es); usage->local_blks_written, es);
ExplainPropertyInteger("Temp Read Blocks", ExplainPropertyInteger("Temp Read Blocks", NULL,
usage->temp_blks_read, es); usage->temp_blks_read, es);
ExplainPropertyInteger("Temp Written Blocks", ExplainPropertyInteger("Temp Written Blocks", NULL,
usage->temp_blks_written, es); usage->temp_blks_written, es);
if (track_io_timing) if (track_io_timing)
{ {
ExplainPropertyFloat("I/O Read Time", INSTR_TIME_GET_MILLISEC(usage->blk_read_time), 3, es); ExplainPropertyFloat("I/O Read Time", "ms",
ExplainPropertyFloat("I/O Write Time", INSTR_TIME_GET_MILLISEC(usage->blk_write_time), 3, es); INSTR_TIME_GET_MILLISEC(usage->blk_read_time),
3, es);
ExplainPropertyFloat("I/O Write Time", "ms",
INSTR_TIME_GET_MILLISEC(usage->blk_write_time),
3, es);
} }
} }
} }
...@@ -3021,10 +3030,10 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors, ...@@ -3021,10 +3030,10 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
if (node->onConflictAction != ONCONFLICT_NONE) if (node->onConflictAction != ONCONFLICT_NONE)
{ {
ExplainProperty("Conflict Resolution", ExplainPropertyText("Conflict Resolution",
node->onConflictAction == ONCONFLICT_NOTHING ? node->onConflictAction == ONCONFLICT_NOTHING ?
"NOTHING" : "UPDATE", "NOTHING" : "UPDATE",
false, es); es);
/* /*
* Don't display arbiter indexes at all when DO NOTHING variant * Don't display arbiter indexes at all when DO NOTHING variant
...@@ -3055,8 +3064,10 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors, ...@@ -3055,8 +3064,10 @@ show_modifytable_info(ModifyTableState *mtstate, List *ancestors,
other_path = mtstate->ps.instrument->nfiltered2; other_path = mtstate->ps.instrument->nfiltered2;
insert_path = total - other_path; insert_path = total - other_path;
ExplainPropertyFloat("Tuples Inserted", insert_path, 0, es); ExplainPropertyFloat("Tuples Inserted", NULL,
ExplainPropertyFloat("Conflicting Tuples", other_path, 0, es); insert_path, 0, es);
ExplainPropertyFloat("Conflicting Tuples", NULL,
other_path, 0, es);
} }
} }
...@@ -3259,18 +3270,23 @@ ExplainPropertyListNested(const char *qlabel, List *data, ExplainState *es) ...@@ -3259,18 +3270,23 @@ ExplainPropertyListNested(const char *qlabel, List *data, ExplainState *es)
* If "numeric" is true, the value is a number (or other value that * If "numeric" is true, the value is a number (or other value that
* doesn't need quoting in JSON). * doesn't need quoting in JSON).
* *
* If unit is is non-NULL the text format will display it after the value.
*
* This usually should not be invoked directly, but via one of the datatype * This usually should not be invoked directly, but via one of the datatype
* specific routines ExplainPropertyText, ExplainPropertyInteger, etc. * specific routines ExplainPropertyText, ExplainPropertyInteger, etc.
*/ */
static void static void
ExplainProperty(const char *qlabel, const char *value, bool numeric, ExplainProperty(const char *qlabel, const char *unit, const char *value,
ExplainState *es) bool numeric, ExplainState *es)
{ {
switch (es->format) switch (es->format)
{ {
case EXPLAIN_FORMAT_TEXT: case EXPLAIN_FORMAT_TEXT:
appendStringInfoSpaces(es->str, es->indent * 2); appendStringInfoSpaces(es->str, es->indent * 2);
appendStringInfo(es->str, "%s: %s\n", qlabel, value); if (unit)
appendStringInfo(es->str, "%s: %s %s\n", qlabel, value, unit);
else
appendStringInfo(es->str, "%s: %s\n", qlabel, value);
break; break;
case EXPLAIN_FORMAT_XML: case EXPLAIN_FORMAT_XML:
...@@ -3315,19 +3331,20 @@ ExplainProperty(const char *qlabel, const char *value, bool numeric, ...@@ -3315,19 +3331,20 @@ ExplainProperty(const char *qlabel, const char *value, bool numeric,
void void
ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es) ExplainPropertyText(const char *qlabel, const char *value, ExplainState *es)
{ {
ExplainProperty(qlabel, value, false, es); ExplainProperty(qlabel, NULL, value, false, es);
} }
/* /*
* Explain an integer-valued property. * Explain an integer-valued property.
*/ */
void void
ExplainPropertyInteger(const char *qlabel, int64 value, ExplainState *es) ExplainPropertyInteger(const char *qlabel, const char *unit, int64 value,
ExplainState *es)
{ {
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), INT64_FORMAT, value); snprintf(buf, sizeof(buf), INT64_FORMAT, value);
ExplainProperty(qlabel, buf, true, es); ExplainProperty(qlabel, unit, buf, true, es);
} }
/* /*
...@@ -3335,13 +3352,13 @@ ExplainPropertyInteger(const char *qlabel, int64 value, ExplainState *es) ...@@ -3335,13 +3352,13 @@ ExplainPropertyInteger(const char *qlabel, int64 value, ExplainState *es)
* fractional digits. * fractional digits.
*/ */
void void
ExplainPropertyFloat(const char *qlabel, double value, int ndigits, ExplainPropertyFloat(const char *qlabel, const char *unit, double value,
ExplainState *es) int ndigits, ExplainState *es)
{ {
char *buf; char *buf;
buf = psprintf("%.*f", ndigits, value); buf = psprintf("%.*f", ndigits, value);
ExplainProperty(qlabel, buf, true, es); ExplainProperty(qlabel, unit, buf, true, es);
pfree(buf); pfree(buf);
} }
...@@ -3351,7 +3368,7 @@ ExplainPropertyFloat(const char *qlabel, double value, int ndigits, ...@@ -3351,7 +3368,7 @@ ExplainPropertyFloat(const char *qlabel, double value, int ndigits,
void void
ExplainPropertyBool(const char *qlabel, bool value, ExplainState *es) ExplainPropertyBool(const char *qlabel, bool value, ExplainState *es)
{ {
ExplainProperty(qlabel, value ? "true" : "false", true, es); ExplainProperty(qlabel, NULL, value ? "true" : "false", true, es);
} }
/* /*
......
...@@ -93,10 +93,10 @@ extern void ExplainPropertyListNested(const char *qlabel, List *data, ...@@ -93,10 +93,10 @@ extern void ExplainPropertyListNested(const char *qlabel, List *data,
ExplainState *es); ExplainState *es);
extern void ExplainPropertyText(const char *qlabel, const char *value, extern void ExplainPropertyText(const char *qlabel, const char *value,
ExplainState *es); ExplainState *es);
extern void ExplainPropertyInteger(const char *qlabel, int64 value, extern void ExplainPropertyInteger(const char *qlabel, const char *unit,
ExplainState *es); int64 value, ExplainState *es);
extern void ExplainPropertyFloat(const char *qlabel, double value, int ndigits, extern void ExplainPropertyFloat(const char *qlabel, const char *unit,
ExplainState *es); double value, int ndigits, ExplainState *es);
extern void ExplainPropertyBool(const char *qlabel, bool value, extern void ExplainPropertyBool(const char *qlabel, bool value,
ExplainState *es); ExplainState *es);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment