Rework wrap-width calculation in psql's print_aligned_vertical() function.

This area was rather heavily whacked around in 6513633b9 and follow-on
commits, and it was showing it, because the logic to calculate the
allowable data width in wrapped expanded mode had only the vaguest
relationship to the logic that was actually printing the data.  It was
not very close to being right about the conditions requiring overhead
columns to be added.  Aside from being wrong, it was pretty unreadable
and under-commented.  Rewrite it so it corresponds to what the printing
code actually does.

In passing, remove a couple of dead tests in the printing logic, too.

Per a complaint from Jeff Janes, though this doesn't look much like his
patch because it fixes a number of other corner-case bogosities too.
One such fix that's visible in the regression test results is that
although the code was attempting to enforce a minimum data width of
3 columns, it sometimes left less space than that available.
This commit is contained in:
Tom Lane 2015-11-30 17:53:32 -05:00
parent 3690dc6b03
commit 0e0776bc99
3 changed files with 514 additions and 157 deletions

View File

@ -1346,88 +1346,115 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
#endif
}
/*
* Calculate available width for data in wrapped mode
*/
if (cont->opt->format == PRINT_WRAPPED)
{
/*
* Separators width
*/
unsigned int width,
min_width,
swidth,
iwidth = 0;
unsigned int swidth,
rwidth = 0,
newdwidth;
if (opt_border == 0)
{
/*
* For border = 0, one space in the middle.
* For border = 0, one space in the middle. (If we discover we
* need to wrap, the spacer column will be replaced by a wrap
* marker, and we'll make room below for another wrap marker at
* the end of the line. But for now, assume no wrap is needed.)
*/
swidth = 1;
/* We might need a column for header newline markers, too */
if (hmultiline)
swidth++;
}
else if (opt_border == 1)
{
/*
* For border = 1, one for the pipe (|) in the middle between the
* two spaces.
* For border = 1, two spaces and a vrule in the middle. (As
* above, we might need one more column for a wrap marker.)
*/
swidth = 3;
/* We might need a column for left header newline markers, too */
if (hmultiline && (format == &pg_asciiformat_old))
swidth++;
}
else
/*
* For border = 2, two more for the pipes (|) at the beginning and
* at the end of the lines.
*/
swidth = 7;
if ((opt_border < 2) &&
((hmultiline &&
(format == &pg_asciiformat_old)) ||
(dmultiline &&
(format != &pg_asciiformat_old))))
iwidth++; /* for newline indicators */
min_width = hwidth + iwidth + swidth + 3;
/*
* Record header width
*/
if (!opt_tuples_only)
{
/*
* Record number
* For border = 2, two more for the vrules at the beginning and
* end of the lines, plus spacer columns adjacent to these. (We
* won't need extra columns for wrap/newline markers, we'll just
* repurpose the spacers.)
*/
unsigned int rwidth = 1 + log10(cont->nrows);
swidth = 7;
}
/* Reserve a column for data newline indicators, too, if needed */
if (dmultiline &&
opt_border < 2 && format != &pg_asciiformat_old)
swidth++;
/* Determine width required for record header lines */
if (!opt_tuples_only)
{
rwidth = 1 + log10(cont->nrows);
if (opt_border == 0)
rwidth += 9; /* "* RECORD " */
else if (opt_border == 1)
rwidth += 12; /* "-[ RECORD ]" */
else
rwidth += 15; /* "+-[ RECORD ]-+" */
}
/* We might need to do the rest of the calculation twice */
for (;;)
{
unsigned int width,
min_width;
/* Total width required to not wrap data */
width = hwidth + swidth + dwidth;
/* Minimum acceptable width: room for just 3 columns of data */
min_width = hwidth + swidth + 3;
/* ... but not less than what the record header lines need */
if (rwidth > min_width)
min_width = rwidth;
}
/* Wrap to minimum width */
width = hwidth + iwidth + swidth + dwidth;
if ((width < min_width) || (output_columns < min_width))
width = min_width - hwidth - iwidth - swidth;
else if (output_columns > 0)
if (width < min_width || output_columns < min_width)
{
/* Set data width to match min_width */
newdwidth = min_width - hwidth - swidth;
}
else if (output_columns > 0)
{
/* Set data width to match output_columns */
newdwidth = output_columns - hwidth - swidth;
}
else
{
/* Use native data width */
newdwidth = dwidth;
}
/*
* Wrap to maximum width
* If we will need to wrap data and didn't already allocate a data
* newline/wrap marker column, do so and recompute.
*/
width = output_columns - hwidth - iwidth - swidth;
if ((width < dwidth) || (dheight > 1))
{
dmultiline = true;
if ((opt_border == 0) &&
(format != &pg_asciiformat_old))
width--; /* for wrap indicators */
if (newdwidth < dwidth && !dmultiline &&
opt_border < 2 && format != &pg_asciiformat_old)
{
dmultiline = true;
swidth++;
}
else
break;
}
dwidth = width;
dwidth = newdwidth;
}
/* print records */
@ -1558,12 +1585,10 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
{
if (offset)
fputs(format->midvrule_wrap, fout);
else if (!dline)
else if (dline == 0)
fputs(dformat->midvrule, fout);
else if (dline)
fputs(format->midvrule_nl, fout);
else
fputs(format->midvrule_blank, fout);
fputs(format->midvrule_nl, fout);
}
/* Data */
@ -1574,9 +1599,9 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
swidth = dwidth;
/*
* Left spacer on wrap indicator
* Left spacer or wrap indicator
*/
fputs(!dcomplete && !offset ? " " : format->wrap_left, fout);
fputs(offset == 0 ? " " : format->wrap_left, fout);
/*
* Data text

View File

@ -1185,6 +1185,338 @@ execute q;
+--------------------+-----------------+
(10 rows)
\pset expanded on
\pset columns 30
\pset border 0
\pset format unaligned
execute q;
0123456789abcdef|xx
0123456789|yyyyyyyyyyyyyyyyyy
0123456789abcdef|xxxx
0123456789|yyyyyyyyyyyyyyyy
0123456789abcdef|xxxxxx
0123456789|yyyyyyyyyyyyyy
0123456789abcdef|xxxxxxxx
0123456789|yyyyyyyyyyyy
0123456789abcdef|xxxxxxxxxx
0123456789|yyyyyyyyyy
0123456789abcdef|xxxxxxxxxxxx
0123456789|yyyyyyyy
0123456789abcdef|xxxxxxxxxxxxxx
0123456789|yyyyyy
0123456789abcdef|xxxxxxxxxxxxxxxx
0123456789|yyyy
0123456789abcdef|xxxxxxxxxxxxxxxxxx
0123456789|yy
0123456789abcdef|xxxxxxxxxxxxxxxxxxxx
0123456789|
\pset format aligned
execute q;
* Record 1
0123456789abcdef xx
0123456789 yyyyyyyyyyyyyyyyyy
* Record 2
0123456789abcdef xxxx
0123456789 yyyyyyyyyyyyyyyy
* Record 3
0123456789abcdef xxxxxx
0123456789 yyyyyyyyyyyyyy
* Record 4
0123456789abcdef xxxxxxxx
0123456789 yyyyyyyyyyyy
* Record 5
0123456789abcdef xxxxxxxxxx
0123456789 yyyyyyyyyy
* Record 6
0123456789abcdef xxxxxxxxxxxx
0123456789 yyyyyyyy
* Record 7
0123456789abcdef xxxxxxxxxxxxxx
0123456789 yyyyyy
* Record 8
0123456789abcdef xxxxxxxxxxxxxxxx
0123456789 yyyy
* Record 9
0123456789abcdef xxxxxxxxxxxxxxxxxx
0123456789 yy
* Record 10
0123456789abcdef xxxxxxxxxxxxxxxxxxxx
0123456789
\pset format wrapped
execute q;
* Record 1
0123456789abcdef xx
0123456789 yyyyyyyyyyyy.
.yyyyyy
* Record 2
0123456789abcdef xxxx
0123456789 yyyyyyyyyyyy.
.yyyy
* Record 3
0123456789abcdef xxxxxx
0123456789 yyyyyyyyyyyy.
.yy
* Record 4
0123456789abcdef xxxxxxxx
0123456789 yyyyyyyyyyyy
* Record 5
0123456789abcdef xxxxxxxxxx
0123456789 yyyyyyyyyy
* Record 6
0123456789abcdef xxxxxxxxxxxx
0123456789 yyyyyyyy
* Record 7
0123456789abcdef xxxxxxxxxxxx.
.xx
0123456789 yyyyyy
* Record 8
0123456789abcdef xxxxxxxxxxxx.
.xxxx
0123456789 yyyy
* Record 9
0123456789abcdef xxxxxxxxxxxx.
.xxxxxx
0123456789 yy
* Record 10
0123456789abcdef xxxxxxxxxxxx.
.xxxxxxxx
0123456789
\pset border 1
\pset format unaligned
execute q;
0123456789abcdef|xx
0123456789|yyyyyyyyyyyyyyyyyy
0123456789abcdef|xxxx
0123456789|yyyyyyyyyyyyyyyy
0123456789abcdef|xxxxxx
0123456789|yyyyyyyyyyyyyy
0123456789abcdef|xxxxxxxx
0123456789|yyyyyyyyyyyy
0123456789abcdef|xxxxxxxxxx
0123456789|yyyyyyyyyy
0123456789abcdef|xxxxxxxxxxxx
0123456789|yyyyyyyy
0123456789abcdef|xxxxxxxxxxxxxx
0123456789|yyyyyy
0123456789abcdef|xxxxxxxxxxxxxxxx
0123456789|yyyy
0123456789abcdef|xxxxxxxxxxxxxxxxxx
0123456789|yy
0123456789abcdef|xxxxxxxxxxxxxxxxxxxx
0123456789|
\pset format aligned
execute q;
-[ RECORD 1 ]----+---------------------
0123456789abcdef | xx
0123456789 | yyyyyyyyyyyyyyyyyy
-[ RECORD 2 ]----+---------------------
0123456789abcdef | xxxx
0123456789 | yyyyyyyyyyyyyyyy
-[ RECORD 3 ]----+---------------------
0123456789abcdef | xxxxxx
0123456789 | yyyyyyyyyyyyyy
-[ RECORD 4 ]----+---------------------
0123456789abcdef | xxxxxxxx
0123456789 | yyyyyyyyyyyy
-[ RECORD 5 ]----+---------------------
0123456789abcdef | xxxxxxxxxx
0123456789 | yyyyyyyyyy
-[ RECORD 6 ]----+---------------------
0123456789abcdef | xxxxxxxxxxxx
0123456789 | yyyyyyyy
-[ RECORD 7 ]----+---------------------
0123456789abcdef | xxxxxxxxxxxxxx
0123456789 | yyyyyy
-[ RECORD 8 ]----+---------------------
0123456789abcdef | xxxxxxxxxxxxxxxx
0123456789 | yyyy
-[ RECORD 9 ]----+---------------------
0123456789abcdef | xxxxxxxxxxxxxxxxxx
0123456789 | yy
-[ RECORD 10 ]---+---------------------
0123456789abcdef | xxxxxxxxxxxxxxxxxxxx
0123456789 |
\pset format wrapped
execute q;
-[ RECORD 1 ]----+-----------
0123456789abcdef | xx
0123456789 | yyyyyyyyyy.
|.yyyyyyyy
-[ RECORD 2 ]----+-----------
0123456789abcdef | xxxx
0123456789 | yyyyyyyyyy.
|.yyyyyy
-[ RECORD 3 ]----+-----------
0123456789abcdef | xxxxxx
0123456789 | yyyyyyyyyy.
|.yyyy
-[ RECORD 4 ]----+-----------
0123456789abcdef | xxxxxxxx
0123456789 | yyyyyyyyyy.
|.yy
-[ RECORD 5 ]----+-----------
0123456789abcdef | xxxxxxxxxx
0123456789 | yyyyyyyyyy
-[ RECORD 6 ]----+-----------
0123456789abcdef | xxxxxxxxxx.
|.xx
0123456789 | yyyyyyyy
-[ RECORD 7 ]----+-----------
0123456789abcdef | xxxxxxxxxx.
|.xxxx
0123456789 | yyyyyy
-[ RECORD 8 ]----+-----------
0123456789abcdef | xxxxxxxxxx.
|.xxxxxx
0123456789 | yyyy
-[ RECORD 9 ]----+-----------
0123456789abcdef | xxxxxxxxxx.
|.xxxxxxxx
0123456789 | yy
-[ RECORD 10 ]---+-----------
0123456789abcdef | xxxxxxxxxx.
|.xxxxxxxxxx
0123456789 |
\pset border 2
\pset format unaligned
execute q;
0123456789abcdef|xx
0123456789|yyyyyyyyyyyyyyyyyy
0123456789abcdef|xxxx
0123456789|yyyyyyyyyyyyyyyy
0123456789abcdef|xxxxxx
0123456789|yyyyyyyyyyyyyy
0123456789abcdef|xxxxxxxx
0123456789|yyyyyyyyyyyy
0123456789abcdef|xxxxxxxxxx
0123456789|yyyyyyyyyy
0123456789abcdef|xxxxxxxxxxxx
0123456789|yyyyyyyy
0123456789abcdef|xxxxxxxxxxxxxx
0123456789|yyyyyy
0123456789abcdef|xxxxxxxxxxxxxxxx
0123456789|yyyy
0123456789abcdef|xxxxxxxxxxxxxxxxxx
0123456789|yy
0123456789abcdef|xxxxxxxxxxxxxxxxxxxx
0123456789|
\pset format aligned
execute q;
+-[ RECORD 1 ]-----+----------------------+
| 0123456789abcdef | xx |
| 0123456789 | yyyyyyyyyyyyyyyyyy |
+-[ RECORD 2 ]-----+----------------------+
| 0123456789abcdef | xxxx |
| 0123456789 | yyyyyyyyyyyyyyyy |
+-[ RECORD 3 ]-----+----------------------+
| 0123456789abcdef | xxxxxx |
| 0123456789 | yyyyyyyyyyyyyy |
+-[ RECORD 4 ]-----+----------------------+
| 0123456789abcdef | xxxxxxxx |
| 0123456789 | yyyyyyyyyyyy |
+-[ RECORD 5 ]-----+----------------------+
| 0123456789abcdef | xxxxxxxxxx |
| 0123456789 | yyyyyyyyyy |
+-[ RECORD 6 ]-----+----------------------+
| 0123456789abcdef | xxxxxxxxxxxx |
| 0123456789 | yyyyyyyy |
+-[ RECORD 7 ]-----+----------------------+
| 0123456789abcdef | xxxxxxxxxxxxxx |
| 0123456789 | yyyyyy |
+-[ RECORD 8 ]-----+----------------------+
| 0123456789abcdef | xxxxxxxxxxxxxxxx |
| 0123456789 | yyyy |
+-[ RECORD 9 ]-----+----------------------+
| 0123456789abcdef | xxxxxxxxxxxxxxxxxx |
| 0123456789 | yy |
+-[ RECORD 10 ]----+----------------------+
| 0123456789abcdef | xxxxxxxxxxxxxxxxxxxx |
| 0123456789 | |
+------------------+----------------------+
\pset format wrapped
execute q;
+-[ RECORD 1 ]-----+---------+
| 0123456789abcdef | xx |
| 0123456789 | yyyyyyy.|
| |.yyyyyyy.|
| |.yyyy |
+-[ RECORD 2 ]-----+---------+
| 0123456789abcdef | xxxx |
| 0123456789 | yyyyyyy.|
| |.yyyyyyy.|
| |.yy |
+-[ RECORD 3 ]-----+---------+
| 0123456789abcdef | xxxxxx |
| 0123456789 | yyyyyyy.|
| |.yyyyyyy |
+-[ RECORD 4 ]-----+---------+
| 0123456789abcdef | xxxxxxx.|
| |.x |
| 0123456789 | yyyyyyy.|
| |.yyyyy |
+-[ RECORD 5 ]-----+---------+
| 0123456789abcdef | xxxxxxx.|
| |.xxx |
| 0123456789 | yyyyyyy.|
| |.yyy |
+-[ RECORD 6 ]-----+---------+
| 0123456789abcdef | xxxxxxx.|
| |.xxxxx |
| 0123456789 | yyyyyyy.|
| |.y |
+-[ RECORD 7 ]-----+---------+
| 0123456789abcdef | xxxxxxx.|
| |.xxxxxxx |
| 0123456789 | yyyyyy |
+-[ RECORD 8 ]-----+---------+
| 0123456789abcdef | xxxxxxx.|
| |.xxxxxxx.|
| |.xx |
| 0123456789 | yyyy |
+-[ RECORD 9 ]-----+---------+
| 0123456789abcdef | xxxxxxx.|
| |.xxxxxxx.|
| |.xxxx |
| 0123456789 | yy |
+-[ RECORD 10 ]----+---------+
| 0123456789abcdef | xxxxxxx.|
| |.xxxxxxx.|
| |.xxxxxx |
| 0123456789 | |
+------------------+---------+
\pset expanded on
\pset columns 20
\pset border 0
@ -1254,115 +1586,88 @@ execute q;
\pset format wrapped
execute q;
* Record 1
* Record 1
0123456789abcdef xx
0123456789 yy.
.yy.
.yy.
.yy.
.yy.
.yy.
.yy.
.yy.
0123456789 yyy.
.yyy.
.yyy.
.yyy.
.yyy.
.yyy
* Record 2
0123456789abcdef xxx.
.x
0123456789 yyy.
.yyy.
.yyy.
.yyy.
.yyy.
.y
* Record 3
0123456789abcdef xxx.
.xxx
0123456789 yyy.
.yyy.
.yyy.
.yyy.
.yy
* Record 2
0123456789abcdef xx.
* Record 4
0123456789abcdef xxx.
.xxx.
.xx
0123456789 yy.
.yy.
.yy.
.yy.
.yy.
.yy.
.yy.
0123456789 yyy.
.yyy.
.yyy.
.yyy
* Record 5
0123456789abcdef xxx.
.xxx.
.xxx.
.x
0123456789 yyy.
.yyy.
.yyy.
.y
* Record 6
0123456789abcdef xxx.
.xxx.
.xxx.
.xxx
0123456789 yyy.
.yyy.
.yy
* Record 3
0123456789abcdef xx.
.xx.
.xx
0123456789 yy.
.yy.
.yy.
.yy.
.yy.
.yy.
.yy
* Record 4
0123456789abcdef xx.
.xx.
.xx.
.xx
0123456789 yy.
.yy.
.yy.
.yy.
.yy.
.yy
* Record 5
0123456789abcdef xx.
.xx.
.xx.
.xx.
.xx
0123456789 yy.
.yy.
.yy.
.yy.
.yy
* Record 6
0123456789abcdef xx.
.xx.
.xx.
.xx.
.xx.
.xx
0123456789 yy.
.yy.
.yy.
.yy
* Record 7
0123456789abcdef xx.
.xx.
.xx.
.xx.
.xx.
.xx.
.xx
0123456789 yy.
.yy.
.yy
* Record 8
0123456789abcdef xx.
.xx.
.xx.
.xx.
.xx.
.xx.
.xx.
.xx
0123456789 yy.
.yy
* Record 9
0123456789abcdef xx.
.xx.
.xx.
.xx.
.xx.
.xx.
.xx.
.xx.
* Record 7
0123456789abcdef xxx.
.xxx.
.xxx.
.xxx.
.xx
0123456789 yyy.
.yyy
* Record 8
0123456789abcdef xxx.
.xxx.
.xxx.
.xxx.
.xxx.
.x
0123456789 yyy.
.y
* Record 9
0123456789abcdef xxx.
.xxx.
.xxx.
.xxx.
.xxx.
.xxx
0123456789 yy
* Record 10
0123456789abcdef xx.
.xx.
.xx.
.xx.
.xx.
.xx.
.xx.
.xx.
.xx.
* Record 10
0123456789abcdef xxx.
.xxx.
.xxx.
.xxx.
.xxx.
.xxx.
.xx
0123456789

View File

@ -193,6 +193,33 @@ execute q;
\pset format wrapped
execute q;
\pset expanded on
\pset columns 30
\pset border 0
\pset format unaligned
execute q;
\pset format aligned
execute q;
\pset format wrapped
execute q;
\pset border 1
\pset format unaligned
execute q;
\pset format aligned
execute q;
\pset format wrapped
execute q;
\pset border 2
\pset format unaligned
execute q;
\pset format aligned
execute q;
\pset format wrapped
execute q;
\pset expanded on
\pset columns 20