Skip to content

Commit 0e0776b

Browse files
committed
Rework wrap-width calculation in psql's print_aligned_vertical() function.
This area was rather heavily whacked around in 6513633 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.
1 parent 3690dc6 commit 0e0776b

File tree

3 files changed

+510
-153
lines changed

3 files changed

+510
-153
lines changed

src/bin/psql/print.c

Lines changed: 76 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,88 +1346,115 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
13461346
#endif
13471347
}
13481348

1349+
/*
1350+
* Calculate available width for data in wrapped mode
1351+
*/
13491352
if (cont->opt->format == PRINT_WRAPPED)
13501353
{
1351-
/*
1352-
* Separators width
1353-
*/
1354-
unsigned int width,
1355-
min_width,
1356-
swidth,
1357-
iwidth = 0;
1354+
unsigned int swidth,
1355+
rwidth = 0,
1356+
newdwidth;
13581357

13591358
if (opt_border == 0)
13601359
{
13611360
/*
1362-
* For border = 0, one space in the middle.
1361+
* For border = 0, one space in the middle. (If we discover we
1362+
* need to wrap, the spacer column will be replaced by a wrap
1363+
* marker, and we'll make room below for another wrap marker at
1364+
* the end of the line. But for now, assume no wrap is needed.)
13631365
*/
13641366
swidth = 1;
1367+
1368+
/* We might need a column for header newline markers, too */
1369+
if (hmultiline)
1370+
swidth++;
13651371
}
13661372
else if (opt_border == 1)
13671373
{
13681374
/*
1369-
* For border = 1, one for the pipe (|) in the middle between the
1370-
* two spaces.
1375+
* For border = 1, two spaces and a vrule in the middle. (As
1376+
* above, we might need one more column for a wrap marker.)
13711377
*/
13721378
swidth = 3;
1379+
1380+
/* We might need a column for left header newline markers, too */
1381+
if (hmultiline && (format == &pg_asciiformat_old))
1382+
swidth++;
13731383
}
13741384
else
1375-
1385+
{
13761386
/*
1377-
* For border = 2, two more for the pipes (|) at the beginning and
1378-
* at the end of the lines.
1387+
* For border = 2, two more for the vrules at the beginning and
1388+
* end of the lines, plus spacer columns adjacent to these. (We
1389+
* won't need extra columns for wrap/newline markers, we'll just
1390+
* repurpose the spacers.)
13791391
*/
13801392
swidth = 7;
1393+
}
13811394

1382-
if ((opt_border < 2) &&
1383-
((hmultiline &&
1384-
(format == &pg_asciiformat_old)) ||
1385-
(dmultiline &&
1386-
(format != &pg_asciiformat_old))))
1387-
iwidth++; /* for newline indicators */
1388-
1389-
min_width = hwidth + iwidth + swidth + 3;
1395+
/* Reserve a column for data newline indicators, too, if needed */
1396+
if (dmultiline &&
1397+
opt_border < 2 && format != &pg_asciiformat_old)
1398+
swidth++;
13901399

1391-
/*
1392-
* Record header width
1393-
*/
1400+
/* Determine width required for record header lines */
13941401
if (!opt_tuples_only)
13951402
{
1396-
/*
1397-
* Record number
1398-
*/
1399-
unsigned int rwidth = 1 + log10(cont->nrows);
1400-
1403+
rwidth = 1 + log10(cont->nrows);
14011404
if (opt_border == 0)
14021405
rwidth += 9; /* "* RECORD " */
14031406
else if (opt_border == 1)
14041407
rwidth += 12; /* "-[ RECORD ]" */
14051408
else
14061409
rwidth += 15; /* "+-[ RECORD ]-+" */
1410+
}
1411+
1412+
/* We might need to do the rest of the calculation twice */
1413+
for (;;)
1414+
{
1415+
unsigned int width,
1416+
min_width;
1417+
1418+
/* Total width required to not wrap data */
1419+
width = hwidth + swidth + dwidth;
14071420

1421+
/* Minimum acceptable width: room for just 3 columns of data */
1422+
min_width = hwidth + swidth + 3;
1423+
/* ... but not less than what the record header lines need */
14081424
if (rwidth > min_width)
14091425
min_width = rwidth;
1410-
}
14111426

1412-
/* Wrap to minimum width */
1413-
width = hwidth + iwidth + swidth + dwidth;
1414-
if ((width < min_width) || (output_columns < min_width))
1415-
width = min_width - hwidth - iwidth - swidth;
1416-
else if (output_columns > 0)
1427+
if (width < min_width || output_columns < min_width)
1428+
{
1429+
/* Set data width to match min_width */
1430+
newdwidth = min_width - hwidth - swidth;
1431+
}
1432+
else if (output_columns > 0)
1433+
{
1434+
/* Set data width to match output_columns */
1435+
newdwidth = output_columns - hwidth - swidth;
1436+
}
1437+
else
1438+
{
1439+
/* Use native data width */
1440+
newdwidth = dwidth;
1441+
}
14171442

14181443
/*
1419-
* Wrap to maximum width
1444+
* If we will need to wrap data and didn't already allocate a data
1445+
* newline/wrap marker column, do so and recompute.
14201446
*/
1421-
width = output_columns - hwidth - iwidth - swidth;
1422-
1423-
if ((width < dwidth) || (dheight > 1))
1424-
{
1425-
dmultiline = true;
1426-
if ((opt_border == 0) &&
1427-
(format != &pg_asciiformat_old))
1428-
width--; /* for wrap indicators */
1447+
if (newdwidth < dwidth && !dmultiline &&
1448+
opt_border < 2 && format != &pg_asciiformat_old)
1449+
{
1450+
dmultiline = true;
1451+
swidth++;
1452+
}
1453+
else
1454+
break;
14291455
}
1430-
dwidth = width;
1456+
1457+
dwidth = newdwidth;
14311458
}
14321459

14331460
/* print records */
@@ -1558,12 +1585,10 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
15581585
{
15591586
if (offset)
15601587
fputs(format->midvrule_wrap, fout);
1561-
else if (!dline)
1588+
else if (dline == 0)
15621589
fputs(dformat->midvrule, fout);
1563-
else if (dline)
1564-
fputs(format->midvrule_nl, fout);
15651590
else
1566-
fputs(format->midvrule_blank, fout);
1591+
fputs(format->midvrule_nl, fout);
15671592
}
15681593

15691594
/* Data */
@@ -1574,9 +1599,9 @@ print_aligned_vertical(const printTableContent *cont, FILE *fout)
15741599
swidth = dwidth;
15751600

15761601
/*
1577-
* Left spacer on wrap indicator
1602+
* Left spacer or wrap indicator
15781603
*/
1579-
fputs(!dcomplete && !offset ? " " : format->wrap_left, fout);
1604+
fputs(offset == 0 ? " " : format->wrap_left, fout);
15801605

15811606
/*
15821607
* Data text

0 commit comments

Comments
 (0)