]> granicus.if.org Git - postgresql/commitdiff
Rework wrap-width calculation in psql's print_aligned_vertical() function.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 30 Nov 2015 22:53:32 +0000 (17:53 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 30 Nov 2015 22:53:32 +0000 (17:53 -0500)
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.

src/bin/psql/print.c
src/test/regress/expected/psql.out
src/test/regress/sql/psql.sql

index ad4350e1fe0a7f10b37331492f9d3c3aca34235d..b53e81be37924d7e302ab6c815ed7105ec07ed5e 100644 (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.
+                        * 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.)
                         */
                        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;
+               /* Reserve a column for data newline indicators, too, if needed */
+               if (dmultiline &&
+                       opt_border < 2 && format != &pg_asciiformat_old)
+                       swidth++;
 
-               /*
-                * Record header width
-                */
+               /* Determine width required for record header lines */
                if (!opt_tuples_only)
                {
-                       /*
-                        * Record number
-                        */
-                       unsigned int rwidth = 1 + log10(cont->nrows);
-
+                       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
index d6f4f4831db77c8ba5d67385217582ba6339ef08..371cef3cd7d39d6a352b4d862fb950a3fb5ba328 100644 (file)
@@ -1186,7 +1186,7 @@ execute q;
 (10 rows)
 
 \pset expanded on
-\pset columns 20
+\pset columns 30
 \pset border 0
 \pset format unaligned
 execute q;
@@ -1254,115 +1254,420 @@ execute q;
 
 \pset format wrapped
 execute q;
-* Record 1        
+* Record 1                  
 0123456789abcdef xx
-0123456789       yy.
-                .yy.
-                .yy.
-                .yy.
-                .yy.
-                .yy.
-                .yy.
-                .yy.
-                .yy
-* Record 2        
-0123456789abcdef xx.
-                .xx
-0123456789       yy.
-                .yy.
-                .yy.
-                .yy.
-                .yy.
-                .yy.
-                .yy.
-                .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.
+0123456789       yyyyyyyyyyyy.
+                .yyyyyy
+* Record 2                  
+0123456789abcdef xxxx
+0123456789       yyyyyyyyyyyy.
+                .yyyy
+* Record 3                  
+0123456789abcdef xxxxxx
+0123456789       yyyyyyyyyyyy.
                 .yy
-* Record 7        
-0123456789abcdef xx.
-                .xx.
-                .xx.
-                .xx.
-                .xx.
-                .xx.
+* Record 4                  
+0123456789abcdef xxxxxxxx
+0123456789       yyyyyyyyyyyy
+* Record 5                  
+0123456789abcdef xxxxxxxxxx
+0123456789       yyyyyyyyyy
+* Record 6                  
+0123456789abcdef xxxxxxxxxxxx
+0123456789       yyyyyyyy
+* Record 7                  
+0123456789abcdef xxxxxxxxxxxx.
                 .xx
-0123456789       yy.
-                .yy.
+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
+\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       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 8        
-0123456789abcdef xx.
-                .xx.
-                .xx.
-                .xx.
-                .xx.
-                .xx.
-                .xx.
+* Record 4         
+0123456789abcdef xxx.
+                .xxx.
                 .xx
-0123456789       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 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       
 
index b93764a68498d445ce4b9bb9d234d0e3b27c7aaf..2f81380e226d93f311ce892c5396fcfc4f758e39 100644 (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