Bruce Momjian wrote: > The attached patch causes psql to use the pager if newlines or > 'format=wrapped' has caused a single row to span more than one line and > the output is then too long for the screen. It also uses the pager if > psql thinks the data will wrap off the edge of the screen. > > The display width as defined by \pset columns, $COLUMNS, or the ioctl > (as previously discussed) We don't have similar settings for the number > of display rows. I assume that is OK. > > I believe this makes the pager more reliable, and in fact I have removed > the psql manual mention that pager computations are somewhat imperfect.
Update patch applied. -- Bruce Momjian <[EMAIL PROTECTED]> http://momjian.us EnterpriseDB http://enterprisedb.com + If your life is a hard drive, Christ can be your backup. +
Index: doc/src/sgml/ref/psql-ref.sgml =================================================================== RCS file: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v retrieving revision 1.204 diff -c -c -r1.204 psql-ref.sgml *** doc/src/sgml/ref/psql-ref.sgml 14 May 2008 04:07:01 -0000 1.204 --- doc/src/sgml/ref/psql-ref.sgml 16 May 2008 16:49:19 -0000 *************** *** 1555,1561 **** <term><literal>columns</literal></term> <listitem> <para> ! Controls the target width for the <literal>wrapped</> format. Zero (the default) causes the <literal>wrapped</> format to affect only screen output. </para> --- 1555,1562 ---- <term><literal>columns</literal></term> <listitem> <para> ! Controls the target width for the <literal>wrapped</> format, ! and width for determining if wide output requires the pager. Zero (the default) causes the <literal>wrapped</> format to affect only screen output. </para> *************** *** 1717,1726 **** When the pager is <literal>off</>, the pager is not used. When the pager is <literal>on</>, the pager is used only when appropriate, i.e. the output is to a terminal and will not fit on the screen. ! (<application>psql</> does not do a perfect job of estimating ! when to use the pager.) <literal>\pset pager</> turns the ! pager on and off. Pager can also be set to <literal>always</>, ! which causes the pager to be always used. </para> </listitem> </varlistentry> --- 1718,1726 ---- When the pager is <literal>off</>, the pager is not used. When the pager is <literal>on</>, the pager is used only when appropriate, i.e. the output is to a terminal and will not fit on the screen. ! <literal>\pset pager</> turns the pager on and off. Pager can ! also be set to <literal>always</>, which causes the pager to be ! always used. </para> </listitem> </varlistentry> *************** *** 2734,2741 **** <listitem> <para> ! Used for the <literal>wrapped</> output format if ! <literal>\pset columns</> is zero. </para> </listitem> </varlistentry> --- 2734,2742 ---- <listitem> <para> ! If <literal>\pset columns</> is zero, controls the ! width for the <literal>wrapped</> format and width for determining ! if wide output requires the pager. </para> </listitem> </varlistentry> Index: src/bin/psql/print.c =================================================================== RCS file: /cvsroot/pgsql/src/bin/psql/print.c,v retrieving revision 1.101 diff -c -c -r1.101 print.c *** src/bin/psql/print.c 13 May 2008 00:14:11 -0000 1.101 --- src/bin/psql/print.c 16 May 2008 16:49:20 -0000 *************** *** 45,50 **** --- 45,52 ---- /* Local functions */ static int strlen_max_width(unsigned char *str, int *target_width, int encoding); + static void IsPagerNeeded(const printTableContent *cont, const int extra_lines, + FILE **fout, bool *is_pager); static void * *************** *** 394,400 **** * Print pretty boxes around cells. */ static void ! print_aligned_text(const printTableContent *cont, bool is_pager, FILE *fout) { bool opt_tuples_only = cont->opt->tuples_only; bool opt_numeric_locale = cont->opt->numericLocale; --- 396,402 ---- * Print pretty boxes around cells. */ static void ! print_aligned_text(const printTableContent *cont, FILE *fout) { bool opt_tuples_only = cont->opt->tuples_only; bool opt_numeric_locale = cont->opt->numericLocale; *************** *** 416,421 **** --- 418,425 ---- unsigned char **format_buf; unsigned int width_total; unsigned int total_header_width; + unsigned int extra_row_output_lines = 0; + unsigned int extra_output_lines = 0; const char * const *ptr; *************** *** 424,429 **** --- 428,434 ---- bool *header_done; /* Have all header lines been output? */ int *bytes_output; /* Bytes output for column value */ int output_columns = 0; /* Width of interactive console */ + bool is_pager = false; if (cancel_pressed) return; *************** *** 476,484 **** --- 481,494 ---- max_nl_lines[i] = nl_lines; if (bytes_required > max_bytes[i]) max_bytes[i] = bytes_required; + if (nl_lines > extra_row_output_lines) + extra_row_output_lines = nl_lines; width_header[i] = width; } + /* Add height of tallest header column */ + extra_output_lines += extra_row_output_lines; + extra_row_output_lines = 0; /* scan all cells, find maximum width, compute cell_count */ for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++) *************** *** 487,493 **** nl_lines, bytes_required; - /* Get width, ignore nl_lines */ pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding, &width, &nl_lines, &bytes_required); if (opt_numeric_locale && cont->aligns[i % col_count] == 'r') --- 497,502 ---- *************** *** 552,579 **** for (i = 0; i < col_count; i++) width_wrap[i] = max_width[i]; ! if (cont->opt->format == PRINT_WRAPPED) { ! /* ! * Choose target output width: \pset columns, or $COLUMNS, or ioctl ! */ ! if (cont->opt->columns > 0) ! output_columns = cont->opt->columns; ! else if ((fout == stdout && isatty(fileno(stdout))) || is_pager) ! { ! if (cont->opt->env_columns > 0) ! output_columns = cont->opt->env_columns; #ifdef TIOCGWINSZ ! else ! { ! struct winsize screen_size; ! ! if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1) ! output_columns = screen_size.ws_col; ! } ! #endif } /* * Optional optimized word wrap. Shrink columns with a high max/avg * ratio. Slighly bias against wider columns. (Increases chance a --- 561,588 ---- for (i = 0; i < col_count; i++) width_wrap[i] = max_width[i]; ! /* ! * Choose target output width: \pset columns, or $COLUMNS, or ioctl ! */ ! if (cont->opt->columns > 0) ! output_columns = cont->opt->columns; ! else if ((fout == stdout && isatty(fileno(stdout))) || is_pager) { ! if (cont->opt->env_columns > 0) ! output_columns = cont->opt->env_columns; #ifdef TIOCGWINSZ ! else ! { ! struct winsize screen_size; ! ! if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1) ! output_columns = screen_size.ws_col; } + #endif + } + if (cont->opt->format == PRINT_WRAPPED) + { /* * Optional optimized word wrap. Shrink columns with a high max/avg * ratio. Slighly bias against wider columns. (Increases chance a *************** *** 623,628 **** --- 632,680 ---- } } + /* If we wrapped beyond the display width, use the pager */ + if (!is_pager && output_columns > 0 && + (output_columns < total_header_width || output_columns < width_total)) + { + fout = PageOutput(INT_MAX, cont->opt->pager); /* force pager */ + is_pager = true; + } + + /* Check if newlines or our wrapping now need the pager */ + if (!is_pager) + { + /* scan all cells, find maximum width, compute cell_count */ + for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++) + { + int width, + nl_lines, + bytes_required; + + pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding, + &width, &nl_lines, &bytes_required); + if (opt_numeric_locale && cont->align[i % col_count] == 'r') + width += additional_numeric_locale_len(*ptr); + + /* + * A row can have both wrapping and newlines that cause + * it to display across multiple lines. We check + * for both cases below. + */ + if (width > 0 && width_wrap[i] && + (width-1) / width_wrap[i] + nl_lines > extra_row_output_lines) + extra_row_output_lines = (width-1) / width_wrap[i] + nl_lines; + + /* If last column, add tallest column height */ + if (i % col_count == col_count - 1) + { + /* Add height of tallest row */ + extra_output_lines += extra_row_output_lines; + extra_row_output_lines = 0; + } + } + IsPagerNeeded(cont, extra_output_lines, &fout, &is_pager); + } + /* time to output */ if (cont->opt->start_table) { *************** *** 882,887 **** --- 934,942 ---- for (i = 0; i < col_count; i++) free(format_buf[i]); free(format_buf); + + if (is_pager) + ClosePager(fout); } *************** *** 2115,2135 **** } /* ! * Use this to print just any table in the supported formats. */ void ! printTable(const printTableContent *cont, FILE *fout, FILE *flog) { ! FILE *output; ! bool is_pager = false; ! ! if (cancel_pressed) ! return; ! ! if (cont->opt->format == PRINT_NOTHING) ! return; ! ! if (fout == stdout) { int lines; --- 2170,2184 ---- } /* ! * IsPagerNeeded ! * ! * Setup pager if required */ void ! IsPagerNeeded(const printTableContent *cont, const int extra_lines, FILE **fout, ! bool *is_pager) { ! if (*fout == stdout) { int lines; *************** *** 2150,2207 **** lines++; } ! output = PageOutput(lines, cont->opt->pager); ! is_pager = (output != fout); } else ! output = fout; /* print the stuff */ if (flog) ! print_aligned_text(cont, is_pager, flog); switch (cont->opt->format) { case PRINT_UNALIGNED: if (cont->opt->expanded) ! print_unaligned_vertical(cont, output); else ! print_unaligned_text(cont, output); break; case PRINT_ALIGNED: case PRINT_WRAPPED: if (cont->opt->expanded) ! print_aligned_vertical(cont, output); else ! print_aligned_text(cont, is_pager, output); break; case PRINT_HTML: if (cont->opt->expanded) ! print_html_vertical(cont, output); else ! print_html_text(cont, output); break; case PRINT_LATEX: if (cont->opt->expanded) ! print_latex_vertical(cont, output); else ! print_latex_text(cont, output); break; case PRINT_TROFF_MS: if (cont->opt->expanded) ! print_troff_ms_vertical(cont, output); else ! print_troff_ms_text(cont, output); break; default: ! fprintf(stderr, _("invalid output format (internal error): %d"), cont->opt->format); exit(EXIT_FAILURE); } if (is_pager) ! ClosePager(output); } /* --- 2199,2277 ---- lines++; } ! *fout = PageOutput(lines + extra_lines, cont->opt->pager); ! *is_pager = (*fout != stdout); } else ! *is_pager = false; ! } ! ! /* ! * Use this to print just any table in the supported formats. ! */ ! void ! printTable(const printTableContent *cont, FILE *fout, FILE *flog) ! { ! bool is_pager = false; ! ! if (cancel_pressed) ! return; ! ! if (cont->opt->format == PRINT_NOTHING) ! return; ! ! /* print_aligned_text() handles the pager itself */ ! if ((cont->opt->format != PRINT_ALIGNED && ! cont->opt->format != PRINT_WRAPPED) || ! cont->opt->expanded) ! IsPagerNeeded(cont, 0, &fout, &is_pager); /* print the stuff */ if (flog) ! print_aligned_text(cont, flog); switch (cont->opt->format) { case PRINT_UNALIGNED: if (cont->opt->expanded) ! print_unaligned_vertical(cont, fout); else ! print_unaligned_text(cont, fout); break; case PRINT_ALIGNED: case PRINT_WRAPPED: if (cont->opt->expanded) ! print_aligned_vertical(cont, fout); else ! print_aligned_text(cont, fout); break; case PRINT_HTML: if (cont->opt->expanded) ! print_html_vertical(cont, fout); else ! print_html_text(cont, fout); break; case PRINT_LATEX: if (cont->opt->expanded) ! print_latex_vertical(cont, fout); else ! print_latex_text(cont, fout); break; case PRINT_TROFF_MS: if (cont->opt->expanded) ! print_troff_ms_vertical(cont, fout); else ! print_troff_ms_text(cont, fout); break; default: ! fprintf(stderr, _("invalid fout format (internal error): %d"), cont->opt->format); exit(EXIT_FAILURE); } if (is_pager) ! ClosePager(fout); } /*
-- Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-patches