On lör, 2011-11-05 at 12:26 -0400, Noah Misch wrote:
> On Sat, Nov 05, 2011 at 04:53:56PM +0200, Peter Eisentraut wrote:
> > On fre, 2011-11-04 at 07:34 -0400, Noah Misch wrote:
> > > For "\pset format wrapped", we only use $COLUMNS when the output is a
> > > tty. I'm thinking it's best, although not terribly important, to
> > > apply the same rule to this feature.
> >
> > I think it does work that way. There is only one place where the
> > environment variable is queries, and it's used for both wrapped format
> > and expanded auto format.
>
> You're correct; given output to a non-tty and no use of \pset columns,
> output_columns always becomes zero. This makes wrapped format never wrap, but
> it makes expanded auto mode always expand. Would it be more consistent to
> never
> expand when output_columns == 0? That is, make these give the same output:
>
> psql -X -P expanded=auto -c "select 'a' as a"
> psql -X -P expanded=auto -c "select 'a' as a" | cat
>
> I just noticed: the help text for \x in slashUsage() will also need an update.
Here is an updated patch that addresses all the issues you pointed out.
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml
index d6941e0..01f57c4 100644
--- a/doc/src/sgml/ref/psql-ref.sgml
+++ b/doc/src/sgml/ref/psql-ref.sgml
@@ -1860,7 +1860,8 @@ lo_import 152801
<para>
Sets the target width for the <literal>wrapped</> format, and also
the width limit for determining whether output is wide enough to
- require the pager.
+ require the pager or switch to the vertical display in expanded auto
+ mode.
Zero (the default) causes the target width to be controlled by the
environment variable <envar>COLUMNS</>, or the detected screen width
if <envar>COLUMNS</> is not set.
@@ -1876,15 +1877,19 @@ lo_import 152801
<term><literal>expanded</literal> (or <literal>x</literal>)</term>
<listitem>
<para>
- If <replaceable class="parameter">value</replaceable> is specified
- it must be either <literal>on</literal> or <literal>off</literal>
- which will enable or disable expanded mode. If <replaceable
- class="parameter">value</replaceable> is omitted the command toggles
- between regular and expanded mode.
- When expanded mode is enabled, query results
- are displayed in two columns, with the column name on the left and
- the data on the right. This mode is useful if the data wouldn't fit
- on the screen in the normal <quote>horizontal</quote> mode.
+ If <replaceable class="parameter">value</replaceable> is specified it
+ must be either <literal>on</literal> or <literal>off</literal>, which
+ will enable or disable expanded mode, or <literal>auto</literal>.
+ If <replaceable class="parameter">value</replaceable> is omitted the
+ command toggles between the on and off settings. When expanded mode
+ is enabled, query results are displayed in two columns, with the
+ column name on the left and the data on the right. This mode is
+ useful if the data wouldn't fit on the screen in the
+ normal <quote>horizontal</quote> mode. In the auto setting, the
+ expanded mode is used whenever the query output is wider than the
+ screen, otherwise the regular mode is used. The auto setting is only
+ effective in the aligned and wrapped formats. In other formats, it
+ always behaves as if the expanded mode is off.
</para>
</listitem>
</varlistentry>
@@ -2326,10 +2331,10 @@ lo_import 152801
<varlistentry>
- <term><literal>\x</literal></term>
+ <term><literal>\x [ <replaceable class="parameter">on</replaceable> | <replaceable class="parameter">off</replaceable> | <replaceable class="parameter">auto</replaceable> ]</literal></term>
<listitem>
<para>
- Toggles expanded table formatting mode. As such it is equivalent to
+ Sets or toggles expanded table formatting mode. As such it is equivalent to
<literal>\pset expanded</literal>.
</para>
</listitem>
@@ -3197,7 +3202,8 @@ $endif
<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.
+ if wide output requires the pager or should be switched to the
+ vertical format in expanded auto mode.
</para>
</listitem>
</varlistentry>
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 2c38902..daaed66 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -1343,7 +1343,7 @@ exec_command(const char *cmd,
free(fname);
}
- /* \x -- toggle expanded table representation */
+ /* \x -- set or toggle expanded table representation */
else if (strcmp(cmd, "x") == 0)
{
char *opt = psql_scan_slash_option(scan_state,
@@ -2177,14 +2177,21 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
/* set expanded/vertical mode */
else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
{
- if (value)
+ if (value && pg_strcasecmp(value, "auto") == 0)
+ popt->topt.expanded = 2;
+ else if (value)
popt->topt.expanded = ParseVariableBool(value);
else
popt->topt.expanded = !popt->topt.expanded;
if (!quiet)
- printf(popt->topt.expanded
- ? _("Expanded display is on.\n")
- : _("Expanded display is off.\n"));
+ {
+ if (popt->topt.expanded == 1)
+ printf(_("Expanded display is on.\n"));
+ else if (popt->topt.expanded == 2)
+ printf(_("Expanded display is used automatically.\n"));
+ else
+ printf(_("Expanded display is off.\n"));
+ }
}
/* locale-aware numeric output */
@@ -2344,7 +2351,7 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
popt->topt.columns = atoi(value);
if (!quiet)
- printf(_("Target width for \"wrapped\" format is %d.\n"), popt->topt.columns);
+ printf(_("Target width is %d.\n"), popt->topt.columns);
}
else
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 53e4cd0..4649e94 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -242,8 +242,8 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\t [on|off] show only rows (currently %s)\n"),
ON(pset.popt.topt.tuples_only));
fprintf(output, _(" \\T [STRING] set HTML <table> tag attributes, or unset if none\n"));
- fprintf(output, _(" \\x [on|off] toggle expanded output (currently %s)\n"),
- ON(pset.popt.topt.expanded));
+ fprintf(output, _(" \\x [on|off|auto] toggle expanded output (currently %s)\n"),
+ pset.popt.topt.expanded == 2 ? "auto" : ON(pset.popt.topt.expanded));
fprintf(output, "\n");
fprintf(output, _("Connection\n"));
diff --git a/src/bin/psql/print.c b/src/bin/psql/print.c
index 0d18665..b19159d 100644
--- a/src/bin/psql/print.c
+++ b/src/bin/psql/print.c
@@ -122,9 +122,11 @@ const printTextFormat pg_utf8format =
/* 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,
+static void IsPagerNeeded(const printTableContent *cont, const int extra_lines, bool expanded,
FILE **fout, bool *is_pager);
+static void print_aligned_vertical(const printTableContent *cont, FILE *fout);
+
static void *
pg_local_malloc(size_t size)
@@ -713,6 +715,17 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
}
}
+ /*
+ * If in expanded auto mode, we have now calculated the expected width, so
+ * we can now escape to vertical mode if necessary.
+ */
+ if (cont->opt->expanded == 2 && output_columns > 0 &&
+ (output_columns < total_header_width || output_columns < width_total))
+ {
+ print_aligned_vertical(cont, fout);
+ return;
+ }
+
/* If we wrapped beyond the display width, use the pager */
if (!is_pager && fout == stdout && output_columns > 0 &&
(output_columns < total_header_width || output_columns < width_total))
@@ -756,7 +769,7 @@ print_aligned_text(const printTableContent *cont, FILE *fout)
extra_row_output_lines = 0;
}
}
- IsPagerNeeded(cont, extra_output_lines, &fout, &is_pager);
+ IsPagerNeeded(cont, extra_output_lines, false, &fout, &is_pager);
}
/* time to output */
@@ -1125,6 +1138,7 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
dformatsize = 0;
struct lineptr *hlineptr,
*dlineptr;
+ bool is_pager = false;
if (cancel_pressed)
return;
@@ -1139,6 +1153,13 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
return;
}
+ /*
+ * Deal with the pager here instead of in printTable(), because we could
+ * get here via print_aligned_text() in expanded auto mode, and so we have
+ * to recalcuate the pager requirement based on vertical output.
+ */
+ IsPagerNeeded(cont, 0, true, &fout, &is_pager);
+
/* Find the maximum dimensions for the headers */
for (i = 0; i < cont->ncolumns; i++)
{
@@ -1295,6 +1316,9 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
free(dlineptr->ptr);
free(hlineptr);
free(dlineptr);
+
+ if (is_pager)
+ ClosePager(fout);
}
@@ -2265,14 +2289,14 @@ printTableCleanup(printTableContent *const content)
* Setup pager if required
*/
static void
-IsPagerNeeded(const printTableContent *cont, const int extra_lines, FILE **fout,
+IsPagerNeeded(const printTableContent *cont, const int extra_lines, bool expanded, FILE **fout,
bool *is_pager)
{
if (*fout == stdout)
{
int lines;
- if (cont->opt->expanded)
+ if (expanded)
lines = (cont->ncolumns + 1) * cont->nrows;
else
lines = cont->nrows + 1;
@@ -2310,11 +2334,10 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
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_aligned_*() handles the pager themselves */
+ if (cont->opt->format != PRINT_ALIGNED &&
+ cont->opt->format != PRINT_WRAPPED)
+ IsPagerNeeded(cont, 0, (cont->opt->expanded == 1), &fout, &is_pager);
/* print the stuff */
@@ -2324,32 +2347,32 @@ printTable(const printTableContent *cont, FILE *fout, FILE *flog)
switch (cont->opt->format)
{
case PRINT_UNALIGNED:
- if (cont->opt->expanded)
+ if (cont->opt->expanded == 1)
print_unaligned_vertical(cont, fout);
else
print_unaligned_text(cont, fout);
break;
case PRINT_ALIGNED:
case PRINT_WRAPPED:
- if (cont->opt->expanded)
+ if (cont->opt->expanded == 1)
print_aligned_vertical(cont, fout);
else
print_aligned_text(cont, fout);
break;
case PRINT_HTML:
- if (cont->opt->expanded)
+ if (cont->opt->expanded == 1)
print_html_vertical(cont, fout);
else
print_html_text(cont, fout);
break;
case PRINT_LATEX:
- if (cont->opt->expanded)
+ if (cont->opt->expanded == 1)
print_latex_vertical(cont, fout);
else
print_latex_text(cont, fout);
break;
case PRINT_TROFF_MS:
- if (cont->opt->expanded)
+ if (cont->opt->expanded == 1)
print_troff_ms_vertical(cont, fout);
else
print_troff_ms_text(cont, fout);
diff --git a/src/bin/psql/print.h b/src/bin/psql/print.h
index 35bb4cd..bb20613 100644
--- a/src/bin/psql/print.h
+++ b/src/bin/psql/print.h
@@ -70,8 +70,8 @@ typedef struct printTextFormat
typedef struct printTableOpt
{
enum printFormat format; /* see enum above */
- bool expanded; /* expanded/vertical output (if supported by
- * output format) */
+ unsigned short int expanded;/* expanded/vertical output (if supported by
+ * output format); 0=no, 1=yes, 2=auto */
unsigned short int border; /* Print a border around the table. 0=none,
* 1=dividing lines, 2=full */
unsigned short int pager; /* use pager for output (if to stdout and
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers