Commit 9b7a84f2 authored by Robert Haas's avatar Robert Haas

Tweak psql to print row counts when \x auto chooses non-expanded output.

Noah Misch
parent f2f9439f
...@@ -2407,12 +2407,12 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet) ...@@ -2407,12 +2407,12 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
else if (strcmp(param, "footer") == 0) else if (strcmp(param, "footer") == 0)
{ {
if (value) if (value)
popt->default_footer = ParseVariableBool(value); popt->topt.default_footer = ParseVariableBool(value);
else else
popt->default_footer = !popt->default_footer; popt->topt.default_footer = !popt->topt.default_footer;
if (!quiet) if (!quiet)
{ {
if (popt->default_footer) if (popt->topt.default_footer)
puts(_("Default footer is on.")); puts(_("Default footer is on."));
else else
puts(_("Default footer is off.")); puts(_("Default footer is off."));
......
...@@ -1130,6 +1130,7 @@ describeOneTableDetails(const char *schemaname, ...@@ -1130,6 +1130,7 @@ describeOneTableDetails(const char *schemaname,
retval = false; retval = false;
myopt.default_footer = false;
/* This output looks confusing in expanded mode. */ /* This output looks confusing in expanded mode. */
myopt.expanded = false; myopt.expanded = false;
...@@ -2363,6 +2364,8 @@ describeRoles(const char *pattern, bool verbose) ...@@ -2363,6 +2364,8 @@ describeRoles(const char *pattern, bool verbose)
const char align = 'l'; const char align = 'l';
char **attr; char **attr;
myopt.default_footer = false;
initPQExpBuffer(&buf); initPQExpBuffer(&buf);
if (pset.sversion >= 80100) if (pset.sversion >= 80100)
...@@ -3362,7 +3365,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname) ...@@ -3362,7 +3365,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
sprintf(title, _("Text search parser \"%s\""), prsname); sprintf(title, _("Text search parser \"%s\""), prsname);
myopt.title = title; myopt.title = title;
myopt.footers = NULL; myopt.footers = NULL;
myopt.default_footer = false; myopt.topt.default_footer = false;
myopt.translate_header = true; myopt.translate_header = true;
myopt.translate_columns = translate_columns; myopt.translate_columns = translate_columns;
...@@ -3393,7 +3396,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname) ...@@ -3393,7 +3396,7 @@ describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
sprintf(title, _("Token types for parser \"%s\""), prsname); sprintf(title, _("Token types for parser \"%s\""), prsname);
myopt.title = title; myopt.title = title;
myopt.footers = NULL; myopt.footers = NULL;
myopt.default_footer = true; myopt.topt.default_footer = true;
myopt.translate_header = true; myopt.translate_header = true;
myopt.translate_columns = NULL; myopt.translate_columns = NULL;
...@@ -3725,7 +3728,7 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname, ...@@ -3725,7 +3728,7 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
myopt.nullPrint = NULL; myopt.nullPrint = NULL;
myopt.title = title.data; myopt.title = title.data;
myopt.footers = NULL; myopt.footers = NULL;
myopt.default_footer = false; myopt.topt.default_footer = false;
myopt.translate_header = true; myopt.translate_header = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile); printQuery(res, &myopt, pset.queryFout, pset.logfile);
......
...@@ -44,6 +44,9 @@ static char *decimal_point; ...@@ -44,6 +44,9 @@ static char *decimal_point;
static char *grouping; static char *grouping;
static char *thousands_sep; static char *thousands_sep;
static char default_footer[100];
static printTableFooter default_footer_cell = { default_footer, NULL };
/* Line style control structures */ /* Line style control structures */
const printTextFormat pg_asciiformat = const printTextFormat pg_asciiformat =
{ {
...@@ -278,6 +281,34 @@ print_separator(struct separator sep, FILE *fout) ...@@ -278,6 +281,34 @@ print_separator(struct separator sep, FILE *fout)
} }
/*
* Return the list of explicitly-requested footers or, when applicable, the
* default "(xx rows)" footer. Always omit the default footer when given
* non-default footers, "\pset footer off", or a specific instruction to that
* effect from a calling backslash command. Vertical formats number each row,
* making the default footer redundant; they do not call this function.
*
* The return value may point to static storage; do not keep it across calls.
*/
static printTableFooter *
footers_with_default(const printTableContent *cont)
{
if (cont->footers == NULL && cont->opt->default_footer)
{
unsigned long total_records;
total_records = cont->opt->prior_records + cont->nrows;
snprintf(default_footer, sizeof(default_footer),
ngettext("(%lu row)", "(%lu rows)", total_records),
total_records);
return &default_footer_cell;
}
else
return cont->footers;
}
/*************************/ /*************************/
/* Unaligned text */ /* Unaligned text */
/*************************/ /*************************/
...@@ -340,11 +371,13 @@ print_unaligned_text(const printTableContent *cont, FILE *fout) ...@@ -340,11 +371,13 @@ print_unaligned_text(const printTableContent *cont, FILE *fout)
/* print footers */ /* print footers */
if (cont->opt->stop_table) if (cont->opt->stop_table)
{ {
if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed) printTableFooter *footers = footers_with_default(cont);
if (!opt_tuples_only && footers != NULL && !cancel_pressed)
{ {
printTableFooter *f; printTableFooter *f;
for (f = cont->footers; f; f = f->next) for (f = footers; f; f = f->next)
{ {
if (need_recordsep) if (need_recordsep)
{ {
...@@ -1034,16 +1067,18 @@ print_aligned_text(const printTableContent *cont, FILE *fout) ...@@ -1034,16 +1067,18 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
if (cont->opt->stop_table) if (cont->opt->stop_table)
{ {
printTableFooter *footers = footers_with_default(cont);
if (opt_border == 2 && !cancel_pressed) if (opt_border == 2 && !cancel_pressed)
_print_horizontal_line(col_count, width_wrap, opt_border, _print_horizontal_line(col_count, width_wrap, opt_border,
PRINT_RULE_BOTTOM, format, fout); PRINT_RULE_BOTTOM, format, fout);
/* print footers */ /* print footers */
if (cont->footers && !opt_tuples_only && !cancel_pressed) if (footers && !opt_tuples_only && !cancel_pressed)
{ {
printTableFooter *f; printTableFooter *f;
for (f = cont->footers; f; f = f->next) for (f = footers; f; f = f->next)
fprintf(fout, "%s\n", f->data); fprintf(fout, "%s\n", f->data);
} }
...@@ -1447,15 +1482,17 @@ print_html_text(const printTableContent *cont, FILE *fout) ...@@ -1447,15 +1482,17 @@ print_html_text(const printTableContent *cont, FILE *fout)
if (cont->opt->stop_table) if (cont->opt->stop_table)
{ {
printTableFooter *footers = footers_with_default(cont);
fputs("</table>\n", fout); fputs("</table>\n", fout);
/* print footers */ /* print footers */
if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed) if (!opt_tuples_only && footers != NULL && !cancel_pressed)
{ {
printTableFooter *f; printTableFooter *f;
fputs("<p>", fout); fputs("<p>", fout);
for (f = cont->footers; f; f = f->next) for (f = footers; f; f = f->next)
{ {
html_escaped_print(f->data, fout); html_escaped_print(f->data, fout);
fputs("<br />\n", fout); fputs("<br />\n", fout);
...@@ -1668,17 +1705,19 @@ print_latex_text(const printTableContent *cont, FILE *fout) ...@@ -1668,17 +1705,19 @@ print_latex_text(const printTableContent *cont, FILE *fout)
if (cont->opt->stop_table) if (cont->opt->stop_table)
{ {
printTableFooter *footers = footers_with_default(cont);
if (opt_border == 2) if (opt_border == 2)
fputs("\\hline\n", fout); fputs("\\hline\n", fout);
fputs("\\end{tabular}\n\n\\noindent ", fout); fputs("\\end{tabular}\n\n\\noindent ", fout);
/* print footers */ /* print footers */
if (cont->footers && !opt_tuples_only && !cancel_pressed) if (footers && !opt_tuples_only && !cancel_pressed)
{ {
printTableFooter *f; printTableFooter *f;
for (f = cont->footers; f; f = f->next) for (f = footers; f; f = f->next)
{ {
latex_escaped_print(f->data, fout); latex_escaped_print(f->data, fout);
fputs(" \\\\\n", fout); fputs(" \\\\\n", fout);
...@@ -1871,14 +1910,16 @@ print_troff_ms_text(const printTableContent *cont, FILE *fout) ...@@ -1871,14 +1910,16 @@ print_troff_ms_text(const printTableContent *cont, FILE *fout)
if (cont->opt->stop_table) if (cont->opt->stop_table)
{ {
printTableFooter *footers = footers_with_default(cont);
fputs(".TE\n.DS L\n", fout); fputs(".TE\n.DS L\n", fout);
/* print footers */ /* print footers */
if (cont->footers && !opt_tuples_only && !cancel_pressed) if (footers && !opt_tuples_only && !cancel_pressed)
{ {
printTableFooter *f; printTableFooter *f;
for (f = cont->footers; f; f = f->next) for (f = footers; f; f = f->next)
{ {
troff_ms_escaped_print(f->data, fout); troff_ms_escaped_print(f->data, fout);
fputc('\n', fout); fputc('\n', fout);
...@@ -2481,18 +2522,6 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f ...@@ -2481,18 +2522,6 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
for (footer = opt->footers; *footer; footer++) for (footer = opt->footers; *footer; footer++)
printTableAddFooter(&cont, *footer); printTableAddFooter(&cont, *footer);
} }
else if (!opt->topt.expanded && opt->default_footer)
{
unsigned long total_records;
char default_footer[100];
total_records = opt->topt.prior_records + cont.nrows;
snprintf(default_footer, sizeof(default_footer),
ngettext("(%lu row)", "(%lu rows)", total_records),
total_records);
printTableAddFooter(&cont, default_footer);
}
printTable(&cont, fout, flog); printTable(&cont, fout, flog);
printTableCleanup(&cont); printTableCleanup(&cont);
......
...@@ -85,6 +85,7 @@ typedef struct printTableOpt ...@@ -85,6 +85,7 @@ typedef struct printTableOpt
bool tuples_only; /* don't output headers, row counts, etc. */ bool tuples_only; /* don't output headers, row counts, etc. */
bool start_table; /* print start decoration, eg <table> */ bool start_table; /* print start decoration, eg <table> */
bool stop_table; /* print stop decoration, eg </table> */ bool stop_table; /* print stop decoration, eg </table> */
bool default_footer; /* allow "(xx rows)" default footer */
unsigned long prior_records; /* start offset for record counters */ unsigned long prior_records; /* start offset for record counters */
const printTextFormat *line_style; /* line style (NULL for default) */ const printTextFormat *line_style; /* line style (NULL for default) */
struct separator fieldSep; /* field separator for unaligned text mode */ struct separator fieldSep; /* field separator for unaligned text mode */
...@@ -141,7 +142,6 @@ typedef struct printQueryOpt ...@@ -141,7 +142,6 @@ typedef struct printQueryOpt
bool quote; /* quote all values as much as possible */ bool quote; /* quote all values as much as possible */
char *title; /* override title */ char *title; /* override title */
char **footers; /* override footer (default is "(xx rows)") */ char **footers; /* override footer (default is "(xx rows)") */
bool default_footer; /* print default footer if footers==NULL */
bool translate_header; /* do gettext on column headers */ bool translate_header; /* do gettext on column headers */
const bool *translate_columns; /* translate_columns[i-1] => do const bool *translate_columns; /* translate_columns[i-1] => do
* gettext on col i */ * gettext on col i */
......
...@@ -129,7 +129,7 @@ main(int argc, char *argv[]) ...@@ -129,7 +129,7 @@ main(int argc, char *argv[])
pset.popt.topt.pager = 1; pset.popt.topt.pager = 1;
pset.popt.topt.start_table = true; pset.popt.topt.start_table = true;
pset.popt.topt.stop_table = true; pset.popt.topt.stop_table = true;
pset.popt.default_footer = true; pset.popt.topt.default_footer = true;
/* We must get COLUMNS here before readline() sets it */ /* We must get COLUMNS here before readline() sets it */
pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0; pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
......
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