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.
*** 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;
  
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to