psql omits row count under "\x auto"

Started by Noah Mischover 13 years ago6 messages
#1Noah Misch
noah@leadboat.com

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

#2Robert Haas
robertmhaas@gmail.com
In reply to: Noah Misch (#1)
Re: psql omits row count under "\x auto"

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

#3Noah Misch
noah@leadboat.com
In reply to: Robert Haas (#2)
Re: psql omits row count under "\x auto"

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.

#4Peter Eisentraut
peter_e@gmx.net
In reply to: Noah Misch (#1)
Re: psql omits row count under "\x auto"

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.

#5Noah Misch
noah@leadboat.com
In reply to: Peter Eisentraut (#4)
1 attachment(s)
Re: psql omits row count under "\x auto"

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;
  
#6Robert Haas
robertmhaas@gmail.com
In reply to: Noah Misch (#5)
Re: psql omits row count under "\x auto"

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