Make 8.3.x psql print tab characters as an appropriate number of spaces,
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 29 May 2008 19:34:44 +0000 (19:34 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 29 May 2008 19:34:44 +0000 (19:34 +0000)
rather than "\x09".  Before 8.3 we just printed tabs as-is, leading to poor
formatting of subsequent columns, but consensus is that "\x09" is not an
improvement over that.  Back-patch of fix that's already in HEAD.

src/bin/psql/mbprint.c
src/bin/psql/mbprint.h
src/test/regress/expected/prepare.out

index 794561b54c3c6316063d0c12b0128e6876198be2..85c3a249e2fe83260ca47997d23c4dcd9726e902 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2008, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/mbprint.c,v 1.29 2008/01/01 19:45:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/mbprint.c,v 1.29.2.1 2008/05/29 19:34:43 tgl Exp $
  *
  * XXX this file does not really belong in psql/.  Perhaps move to libpq?
  * It also seems that the mbvalidate function is redundant with existing
@@ -204,13 +204,16 @@ pg_wcswidth(const unsigned char *pwcs, size_t len, int encoding)
 /*
  * pg_wcssize takes the given string in the given encoding and returns three
  * values:
- *       result_width: Width in display character of longest line in string
- *       result_hieght: Number of lines in display output
- *       result_format_size: Number of bytes required to store formatted representation of string
+ *       result_width: Width in display characters of the longest line in string
+ *       result_height: Number of lines in display output
+ *       result_format_size: Number of bytes required to store formatted
+ *             representation of string
+ *
+ * This MUST be kept in sync with pg_wcsformat!
  */
-int
-pg_wcssize(unsigned char *pwcs, size_t len, int encoding, int *result_width,
-                  int *result_height, int *result_format_size)
+void
+pg_wcssize(unsigned char *pwcs, size_t len, int encoding,
+                  int *result_width, int *result_height, int *result_format_size)
 {
        int                     w,
                                chlen = 0,
@@ -241,6 +244,14 @@ pg_wcssize(unsigned char *pwcs, size_t len, int encoding, int *result_width,
                                linewidth += 2;
                                format_size += 2;
                        }
+                       else if (*pwcs == '\t')         /* Tab */
+                       {
+                               do
+                               {
+                                       linewidth++;
+                                       format_size++;
+                               } while (linewidth % 8 != 0);
+                       }
                        else if (w < 0)         /* Other control char */
                        {
                                linewidth += 4;
@@ -266,7 +277,7 @@ pg_wcssize(unsigned char *pwcs, size_t len, int encoding, int *result_width,
        }
        if (linewidth > width)
                width = linewidth;
-       format_size += 1;
+       format_size += 1;               /* For NUL char */
 
        /* Set results */
        if (result_width)
@@ -275,10 +286,14 @@ pg_wcssize(unsigned char *pwcs, size_t len, int encoding, int *result_width,
                *result_height = height;
        if (result_format_size)
                *result_format_size = format_size;
-
-       return width;
 }
 
+/*
+ *  Format a string into one or more "struct lineptr" lines.
+ *  lines[i].ptr == NULL indicates the end of the array.
+ *
+ * This MUST be kept in sync with pg_wcssize!
+ */
 void
 pg_wcsformat(unsigned char *pwcs, size_t len, int encoding,
                         struct lineptr * lines, int count)
@@ -304,7 +319,7 @@ pg_wcsformat(unsigned char *pwcs, size_t len, int encoding,
                                linewidth = 0;
                                lines++;
                                count--;
-                               if (count == 0)
+                               if (count <= 0)
                                        exit(1);        /* Screwup */
 
                                lines->ptr = ptr;
@@ -315,6 +330,14 @@ pg_wcsformat(unsigned char *pwcs, size_t len, int encoding,
                                linewidth += 2;
                                ptr += 2;
                        }
+                       else if (*pwcs == '\t')         /* Tab */
+                       {
+                               do
+                               {
+                                       *ptr++ = ' ';
+                                       linewidth++;
+                               } while (linewidth % 8 != 0);
+                       }
                        else if (w < 0)         /* Other control char */
                        {
                                sprintf((char *) ptr, "\\x%02X", *pwcs);
@@ -332,14 +355,14 @@ pg_wcsformat(unsigned char *pwcs, size_t len, int encoding,
                        if (encoding == PG_UTF8)
                                sprintf((char *) ptr, "\\u%04X", utf2ucs(pwcs));
                        else
-
+                       {
                                /*
                                 * This case cannot happen in the current code because only
                                 * UTF-8 signals multibyte control characters. But we may need
                                 * to support it at some stage
                                 */
                                sprintf((char *) ptr, "\\u????");
-
+                       }
                        ptr += 6;
                        linewidth += 6;
                }
index 61e723cbaef6823b110e08db6b2259939270d13f..664f3e738c52c4afa7cf5b73a3b619936e092dd0 100644 (file)
@@ -1,4 +1,4 @@
-/* $PostgreSQL: pgsql/src/bin/psql/mbprint.h,v 1.11 2006/10/04 00:30:06 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/bin/psql/mbprint.h,v 1.11.4.1 2008/05/29 19:34:43 tgl Exp $ */
 #ifndef MBPRINT_H
 #define MBPRINT_H
 
@@ -13,6 +13,7 @@ extern unsigned char *mbvalidate(unsigned char *pwcs, int encoding);
 
 extern int     pg_wcswidth(const unsigned char *pwcs, size_t len, int encoding);
 extern void pg_wcsformat(unsigned char *pwcs, size_t len, int encoding, struct lineptr * lines, int count);
-extern int     pg_wcssize(unsigned char *pwcs, size_t len, int encoding, int *width, int *height, int *format_size);
+extern void pg_wcssize(unsigned char *pwcs, size_t len, int encoding,
+                                          int *width, int *height, int *format_size);
 
 #endif   /* MBPRINT_H */
index 35e1befcbb49998f803d72d14fb3ed2e0916fc19..9e5f397810c5a008176592018f7138f90f859e59 100644 (file)
@@ -152,22 +152,22 @@ PREPARE q7(unknown) AS
     SELECT * FROM road WHERE thepath = $1;
 SELECT name, statement, parameter_types FROM pg_prepared_statements
     ORDER BY name;
- name |                            statement                            |                    parameter_types                     
-------+-----------------------------------------------------------------+--------------------------------------------------------
- q2   | PREPARE q2(text) AS                                             | {text}
-      : \x09SELECT datname, datistemplate, datallowconn                   
-      : \x09FROM pg_database WHERE datname = $1;                          
- q3   | PREPARE q3(text, int, float, boolean, oid, smallint) AS         | {text,integer,"double precision",boolean,oid,smallint}
-      : \x09SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR      
-      : \x09ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int)   
-      : \x09ORDER BY unique1;                                             
- q5   | PREPARE q5(int, text) AS                                        | {integer,text}
-      : \x09SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2       
-      : \x09ORDER BY unique1;                                             
- q6   | PREPARE q6 AS                                                   | {integer,name}
-      :     SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;     
- q7   | PREPARE q7(unknown) AS                                          | {path}
-      :     SELECT * FROM road WHERE thepath = $1;                        
+ name |                              statement                              |                    parameter_types                     
+------+---------------------------------------------------------------------+--------------------------------------------------------
+ q2   | PREPARE q2(text) AS                                                 | {text}
+      :         SELECT datname, datistemplate, datallowconn                   
+      :         FROM pg_database WHERE datname = $1;                          
+ q3   | PREPARE q3(text, int, float, boolean, oid, smallint) AS             | {text,integer,"double precision",boolean,oid,smallint}
+      :         SELECT * FROM tenk1 WHERE string4 = $1 AND (four = $2 OR      
+      :         ten = $3::bigint OR true = $4 OR oid = $5 OR odd = $6::int)   
+      :         ORDER BY unique1;                                             
+ q5   | PREPARE q5(int, text) AS                                            | {integer,text}
+      :         SELECT * FROM tenk1 WHERE unique1 = $1 OR stringu1 = $2       
+      :         ORDER BY unique1;                                             
+ q6   | PREPARE q6 AS                                                       | {integer,name}
+      :     SELECT * FROM tenk1 WHERE unique1 = $1 AND stringu1 = $2;         
+ q7   | PREPARE q7(unknown) AS                                              | {path}
+      :     SELECT * FROM road WHERE thepath = $1;                            
 (5 rows)
 
 -- test DEALLOCATE ALL;