psql omits row count under "\x auto"
I've been enjoying "\x auto" in .psqlrc, but I noticed the row count footer
missing when it chooses ordinary output:
[local] test=# \x off
Expanded display is off.
[local] test=# select 1;
?column?
----------
1
(1 row)
[local] test=# \x auto
Expanded display is used automatically.
[local] test=# select 1;
?column?
----------
1
[local] test=#
Looks like the logic in printQuery() needs further treatment.
Thanks,
nm
On Mon, Apr 23, 2012 at 12:30 PM, Noah Misch <noah@leadboat.com> wrote:
Looks like the logic in printQuery() needs further treatment.
Do you want to propose a patch, or are you hoping someone else is
going to address this?
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
On Wed, Apr 25, 2012 at 04:57:36PM -0400, Robert Haas wrote:
On Mon, Apr 23, 2012 at 12:30 PM, Noah Misch <noah@leadboat.com> wrote:
Looks like the logic in printQuery() needs further treatment.
Do you want to propose a patch, or are you hoping someone else is
going to address this?
I figured Peter might have a preference for how to fix it. If not, I can put
something together.
On mån, 2012-04-23 at 12:30 -0400, Noah Misch wrote:
I've been enjoying "\x auto" in .psqlrc, but I noticed the row count footer
missing when it chooses ordinary output:
Looks like the logic in printQuery() needs further treatment.
Hmm, this looks a bit tricky, because at the time we add the footer we
don't yet know which output format will be used. I don't have a good
idea how to fix that at the moment.
On Thu, Apr 26, 2012 at 09:25:25PM +0300, Peter Eisentraut wrote:
On m??n, 2012-04-23 at 12:30 -0400, Noah Misch wrote:
I've been enjoying "\x auto" in .psqlrc, but I noticed the row count footer
missing when it chooses ordinary output:Looks like the logic in printQuery() needs further treatment.
Hmm, this looks a bit tricky, because at the time we add the footer we
don't yet know which output format will be used. I don't have a good
idea how to fix that at the moment.
I fiddled with this and settled on moving the default_footer boolean setting
and the interpretation thereof down from the printQuery() level to the
printTable() level. That permits delaying the decision until we determine
whether the final output format is indeed vertical.
Attachments:
expanded-auto-rowcount-v1.patchtext/plain; charset=us-asciiDownload
*** a/src/bin/psql/command.c
--- b/src/bin/psql/command.c
***************
*** 2407,2418 **** do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
else if (strcmp(param, "footer") == 0)
{
if (value)
! popt->default_footer = ParseVariableBool(value);
else
! popt->default_footer = !popt->default_footer;
if (!quiet)
{
! if (popt->default_footer)
puts(_("Default footer is on."));
else
puts(_("Default footer is off."));
--- 2407,2418 ----
else if (strcmp(param, "footer") == 0)
{
if (value)
! popt->topt.default_footer = ParseVariableBool(value);
else
! popt->topt.default_footer = !popt->topt.default_footer;
if (!quiet)
{
! if (popt->topt.default_footer)
puts(_("Default footer is on."));
else
puts(_("Default footer is off."));
*** a/src/bin/psql/describe.c
--- b/src/bin/psql/describe.c
***************
*** 1130,1135 **** describeOneTableDetails(const char *schemaname,
--- 1130,1136 ----
retval = false;
+ myopt.default_footer = false;
/* This output looks confusing in expanded mode. */
myopt.expanded = false;
***************
*** 2363,2368 **** describeRoles(const char *pattern, bool verbose)
--- 2364,2371 ----
const char align = 'l';
char **attr;
+ myopt.default_footer = false;
+
initPQExpBuffer(&buf);
if (pset.sversion >= 80100)
***************
*** 3362,3368 **** describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
sprintf(title, _("Text search parser \"%s\""), prsname);
myopt.title = title;
myopt.footers = NULL;
! myopt.default_footer = false;
myopt.translate_header = true;
myopt.translate_columns = translate_columns;
--- 3365,3371 ----
sprintf(title, _("Text search parser \"%s\""), prsname);
myopt.title = title;
myopt.footers = NULL;
! myopt.topt.default_footer = false;
myopt.translate_header = true;
myopt.translate_columns = translate_columns;
***************
*** 3393,3399 **** describeOneTSParser(const char *oid, const char *nspname, const char *prsname)
sprintf(title, _("Token types for parser \"%s\""), prsname);
myopt.title = title;
myopt.footers = NULL;
! myopt.default_footer = true;
myopt.translate_header = true;
myopt.translate_columns = NULL;
--- 3396,3402 ----
sprintf(title, _("Token types for parser \"%s\""), prsname);
myopt.title = title;
myopt.footers = NULL;
! myopt.topt.default_footer = true;
myopt.translate_header = true;
myopt.translate_columns = NULL;
***************
*** 3725,3731 **** describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
myopt.nullPrint = NULL;
myopt.title = title.data;
myopt.footers = NULL;
! myopt.default_footer = false;
myopt.translate_header = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile);
--- 3728,3734 ----
myopt.nullPrint = NULL;
myopt.title = title.data;
myopt.footers = NULL;
! myopt.topt.default_footer = false;
myopt.translate_header = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile);
*** a/src/bin/psql/print.c
--- b/src/bin/psql/print.c
***************
*** 44,49 **** static char *decimal_point;
--- 44,52 ----
static char *grouping;
static char *thousands_sep;
+ static char default_footer[100];
+ static printTableFooter default_footer_cell = { default_footer, NULL };
+
/* Line style control structures */
const printTextFormat pg_asciiformat =
{
***************
*** 278,283 **** print_separator(struct separator sep, FILE *fout)
--- 281,314 ----
}
+ /*
+ * 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 */
/*************************/
***************
*** 340,350 **** print_unaligned_text(const printTableContent *cont, FILE *fout)
/* print footers */
if (cont->opt->stop_table)
{
! if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
{
printTableFooter *f;
! for (f = cont->footers; f; f = f->next)
{
if (need_recordsep)
{
--- 371,383 ----
/* print footers */
if (cont->opt->stop_table)
{
! printTableFooter *footers = footers_with_default(cont);
!
! if (!opt_tuples_only && footers != NULL && !cancel_pressed)
{
printTableFooter *f;
! for (f = footers; f; f = f->next)
{
if (need_recordsep)
{
***************
*** 1034,1049 **** print_aligned_text(const printTableContent *cont, FILE *fout)
if (cont->opt->stop_table)
{
if (opt_border == 2 && !cancel_pressed)
_print_horizontal_line(col_count, width_wrap, opt_border,
PRINT_RULE_BOTTOM, format, fout);
/* print footers */
! if (cont->footers && !opt_tuples_only && !cancel_pressed)
{
printTableFooter *f;
! for (f = cont->footers; f; f = f->next)
fprintf(fout, "%s\n", f->data);
}
--- 1067,1084 ----
if (cont->opt->stop_table)
{
+ printTableFooter *footers = footers_with_default(cont);
+
if (opt_border == 2 && !cancel_pressed)
_print_horizontal_line(col_count, width_wrap, opt_border,
PRINT_RULE_BOTTOM, format, fout);
/* print footers */
! if (footers && !opt_tuples_only && !cancel_pressed)
{
printTableFooter *f;
! for (f = footers; f; f = f->next)
fprintf(fout, "%s\n", f->data);
}
***************
*** 1447,1461 **** print_html_text(const printTableContent *cont, FILE *fout)
if (cont->opt->stop_table)
{
fputs("</table>\n", fout);
/* print footers */
! if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed)
{
printTableFooter *f;
fputs("<p>", fout);
! for (f = cont->footers; f; f = f->next)
{
html_escaped_print(f->data, fout);
fputs("<br />\n", fout);
--- 1482,1498 ----
if (cont->opt->stop_table)
{
+ printTableFooter *footers = footers_with_default(cont);
+
fputs("</table>\n", fout);
/* print footers */
! if (!opt_tuples_only && footers != NULL && !cancel_pressed)
{
printTableFooter *f;
fputs("<p>", fout);
! for (f = footers; f; f = f->next)
{
html_escaped_print(f->data, fout);
fputs("<br />\n", fout);
***************
*** 1668,1684 **** print_latex_text(const printTableContent *cont, FILE *fout)
if (cont->opt->stop_table)
{
if (opt_border == 2)
fputs("\\hline\n", fout);
fputs("\\end{tabular}\n\n\\noindent ", fout);
/* print footers */
! if (cont->footers && !opt_tuples_only && !cancel_pressed)
{
printTableFooter *f;
! for (f = cont->footers; f; f = f->next)
{
latex_escaped_print(f->data, fout);
fputs(" \\\\\n", fout);
--- 1705,1723 ----
if (cont->opt->stop_table)
{
+ printTableFooter *footers = footers_with_default(cont);
+
if (opt_border == 2)
fputs("\\hline\n", fout);
fputs("\\end{tabular}\n\n\\noindent ", fout);
/* print footers */
! if (footers && !opt_tuples_only && !cancel_pressed)
{
printTableFooter *f;
! for (f = footers; f; f = f->next)
{
latex_escaped_print(f->data, fout);
fputs(" \\\\\n", fout);
***************
*** 1871,1884 **** print_troff_ms_text(const printTableContent *cont, FILE *fout)
if (cont->opt->stop_table)
{
fputs(".TE\n.DS L\n", fout);
/* print footers */
! if (cont->footers && !opt_tuples_only && !cancel_pressed)
{
printTableFooter *f;
! for (f = cont->footers; f; f = f->next)
{
troff_ms_escaped_print(f->data, fout);
fputc('\n', fout);
--- 1910,1925 ----
if (cont->opt->stop_table)
{
+ printTableFooter *footers = footers_with_default(cont);
+
fputs(".TE\n.DS L\n", fout);
/* print footers */
! if (footers && !opt_tuples_only && !cancel_pressed)
{
printTableFooter *f;
! for (f = footers; f; f = f->next)
{
troff_ms_escaped_print(f->data, fout);
fputc('\n', fout);
***************
*** 2481,2498 **** printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
for (footer = opt->footers; *footer; 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);
printTableCleanup(&cont);
--- 2522,2527 ----
*** a/src/bin/psql/print.h
--- b/src/bin/psql/print.h
***************
*** 85,90 **** typedef struct printTableOpt
--- 85,91 ----
bool tuples_only; /* don't output headers, row counts, etc. */
bool start_table; /* print start 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 */
const printTextFormat *line_style; /* line style (NULL for default) */
struct separator fieldSep; /* field separator for unaligned text mode */
***************
*** 141,147 **** typedef struct printQueryOpt
bool quote; /* quote all values as much as possible */
char *title; /* override title */
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 */
const bool *translate_columns; /* translate_columns[i-1] => do
* gettext on col i */
--- 142,147 ----
*** a/src/bin/psql/startup.c
--- b/src/bin/psql/startup.c
***************
*** 129,135 **** main(int argc, char *argv[])
pset.popt.topt.pager = 1;
pset.popt.topt.start_table = true;
pset.popt.topt.stop_table = true;
! pset.popt.default_footer = true;
/* We must get COLUMNS here before readline() sets it */
pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
--- 129,135 ----
pset.popt.topt.pager = 1;
pset.popt.topt.start_table = true;
pset.popt.topt.stop_table = true;
! pset.popt.topt.default_footer = true;
/* We must get COLUMNS here before readline() sets it */
pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
On Fri, Apr 27, 2012 at 3:05 PM, Noah Misch <noah@leadboat.com> wrote:
On Thu, Apr 26, 2012 at 09:25:25PM +0300, Peter Eisentraut wrote:
On m??n, 2012-04-23 at 12:30 -0400, Noah Misch wrote:
I've been enjoying "\x auto" in .psqlrc, but I noticed the row count footer
missing when it chooses ordinary output:Looks like the logic in printQuery() needs further treatment.
Hmm, this looks a bit tricky, because at the time we add the footer we
don't yet know which output format will be used. I don't have a good
idea how to fix that at the moment.I fiddled with this and settled on moving the default_footer boolean setting
and the interpretation thereof down from the printQuery() level to the
printTable() level. That permits delaying the decision until we determine
whether the final output format is indeed vertical.
Committed.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company