Re: thousands comma numeric formatting in psql - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: thousands comma numeric formatting in psql
Date
Msg-id 200507100346.j6A3kb812714@candle.pha.pa.us
Whole thread Raw
In response to Re: thousands comma numeric formatting in psql  (Eugen Nedelcu <eugen@sifolt.ro>)
Responses Re: thousands comma numeric formatting in psql
List pgsql-patches
Eugen Nedelcu wrote:
> Hello,
>
> I have included my patch attached to this mail.
>
> I have made the changes to deal with locale settings from client
> environment. So now you can start psql like this:
>
> (export LC_ALL=ro_RO; psql -U user db)
>
> and have numeric formatting with '.' as thousands separator and
> ',' as decimal point, or
>
> (export LC_ALL=en_US; psql -U user db)
>
> and have numeric formatting with ',' as thousands separator and
> '.' as decimal point. This formatting is default when locale is 'C'
>
> You can set any locale and numeric formatting code will take it in
> consideration.
>
> This patch is for version 7.3.2. The steps for install is:
>
> 1) cp thousands_comma.diff $POSTGRES_DIR/src/bin/psql
> 2) cd $POSTGRES_DIR/src/bin/psql
> 3) patch -p0 < thousands_comma.diff
> 4) ../../../configure && make

I have heavily modified your patch and have applied it.  Instead of
using langinfo, I used a \pset variable numericsep. (We can talk about
adding langinfo detection later.)  By default, it is off, ''.  If you
set it to '.', the decimal marker will be ','.  This also allows
separators like ' ' too so numebers can appear as 100 000.

I have also added documentation.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.145
diff -c -c -r1.145 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml    14 Jun 2005 02:57:38 -0000    1.145
--- doc/src/sgml/ref/psql-ref.sgml    10 Jul 2005 03:24:16 -0000
***************
*** 1493,1498 ****
--- 1493,1510 ----
            </varlistentry>

            <varlistentry>
+           <term><literal>numericsep</literal></term>
+           <listitem>
+           <para>
+           Specifies the character separator between groups of three digits
+           to the left of the decimal marker.  The default is <literal>''</>
+           (none).  Setting this to a period also changes the decimal marker
+           to a comma.
+           </para>
+           </listitem>
+           </varlistentry>
+
+           <varlistentry>
            <term><literal>recordsep</literal></term>
            <listitem>
            <para>
Index: src/bin/psql/command.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.146
diff -c -c -r1.146 command.c
*** src/bin/psql/command.c    13 Jun 2005 06:36:22 -0000    1.146
--- src/bin/psql/command.c    10 Jul 2005 03:24:17 -0000
***************
*** 838,844 ****
      else if (strcmp(cmd, "x") == 0)
          success = do_pset("expanded", NULL, &pset.popt, quiet);

-
      /* \z -- list table rights (equivalent to \dp) */
      else if (strcmp(cmd, "z") == 0)
      {
--- 838,843 ----
***************
*** 1421,1426 ****
--- 1420,1436 ----
                     : _("Expanded display is off.\n"));
      }

+     else if (strcmp(param, "numericsep") == 0)
+     {
+         if (value)
+         {
+             free(popt->topt.numericSep);
+             popt->topt.numericSep = pg_strdup(value);
+         }
+         if (!quiet)
+             printf(_("Numeric separator is \"%s\".\n"), popt->topt.numericSep);
+     }
+
      /* null display */
      else if (strcmp(param, "null") == 0)
      {
Index: src/bin/psql/help.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/help.c,v
retrieving revision 1.103
diff -c -c -r1.103 help.c
*** src/bin/psql/help.c    6 Jul 2005 03:14:48 -0000    1.103
--- src/bin/psql/help.c    10 Jul 2005 03:24:18 -0000
***************
*** 239,245 ****
      fprintf(output, _("  \\pset NAME [VALUE]\n"
                        "                 set table output option\n"
                        "                 (NAME := {format|border|expanded|fieldsep|footer|null|\n"
!     "                 recordsep|tuples_only|title|tableattr|pager})\n"));
      fprintf(output, _("  \\t             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"));
--- 239,245 ----
      fprintf(output, _("  \\pset NAME [VALUE]\n"
                        "                 set table output option\n"
                        "                 (NAME := {format|border|expanded|fieldsep|footer|null|\n"
!     "                 numericsep|recordsep|tuples_only|title|tableattr|pager})\n"));
      fprintf(output, _("  \\t             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"));
Index: src/bin/psql/print.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/print.c,v
retrieving revision 1.60
diff -c -c -r1.60 print.c
*** src/bin/psql/print.c    14 Jun 2005 22:15:57 -0000    1.60
--- src/bin/psql/print.c    10 Jul 2005 03:24:24 -0000
***************
*** 29,48 ****

  #include "mbprint.h"

  /*************************/
  /* Unaligned text         */
  /*************************/


  static void
! print_unaligned_text(const char *title, const char *const * headers,
!                   const char *const * cells, const char *const * footers,
!  const char *opt_fieldsep, const char *opt_recordsep, bool opt_barebones,
!                      FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const * ptr;
      bool        need_recordsep = false;

      if (!opt_fieldsep)
--- 29,135 ----

  #include "mbprint.h"

+ static int
+ num_numericseps(const char *my_str)
+ {
+     int old_len, dec_len, int_len;
+
+     if (my_str[0] == '-')
+         my_str++;
+
+     old_len = strlen(my_str);
+     dec_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
+
+     int_len = old_len - dec_len;
+     if (int_len % 3 != 0)
+         return int_len / 3;
+     else
+         return int_len / 3 - 1;    /* no leading separator */
+ }
+ static int
+ len_with_numericsep(const char *my_str)
+ {
+     return strlen(my_str) + num_numericseps(my_str);
+ }
+
+ static void
+ format_numericsep(char *my_str, char *numericsep)
+ {
+     int i, j, digits_before_sep, old_len, new_len, dec_len, int_len;
+     char *dec_point;
+     char *new_str;
+     char *dec_value;
+
+     if (strcmp(numericsep, ".") != 0)
+         dec_point = ".";
+     else
+         dec_point = ",";
+
+     if (my_str[0] == '-')
+         my_str++;
+
+     old_len = strlen(my_str);
+     dec_len = strchr(my_str, '.') ? strlen(strchr(my_str, '.')) : 0;
+     int_len = old_len - dec_len;
+     digits_before_sep = int_len % 3;
+
+     new_len = int_len + int_len / 3 + dec_len;
+     if (digits_before_sep == 0)
+         new_len--;    /* no leading separator */
+
+     new_str = malloc(new_len);
+     if (!new_str)
+     {
+         fprintf(stderr, _("out of memory\n"));
+         exit(EXIT_FAILURE);
+     }
+
+     for (i=0, j=0; ; i++, j++)
+     {
+         /* hit decimal point */
+         if (my_str[i] == '.')
+         {
+             new_str[j] = *dec_point;
+             new_str[j+1] = '\0';
+             dec_value = strchr(my_str, '.');
+             strcat(new_str, ++dec_value);
+             break;
+         }
+
+         /* end of string */
+         if (my_str[i] == '\0')
+         {
+             new_str[j] = '\0';
+             break;
+         }
+
+         /* add separator? */
+         if (i != 0 &&
+             (i - (digits_before_sep ? digits_before_sep : 3)) % 3 == 0)
+             new_str[j++] = *numericsep;
+
+         new_str[j] = my_str[i];
+     }
+
+     strcpy(my_str, new_str);
+     free(new_str);
+ }
+
  /*************************/
  /* Unaligned text         */
  /*************************/


  static void
! print_unaligned_text(const char *title, const char *const *headers,
!                      const char *const *cells, const char *const *footers,
!                      const char *opt_align, const char *opt_fieldsep,
!                      const char *opt_recordsep, bool opt_barebones,
!                      char *opt_numericsep, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const *ptr;
      bool        need_recordsep = false;

      if (!opt_fieldsep)
***************
*** 77,83 ****
              fputs(opt_recordsep, fout);
              need_recordsep = false;
          }
!         fputs(*ptr, fout);
          if ((i + 1) % col_count)
              fputs(opt_fieldsep, fout);
          else
--- 164,187 ----
              fputs(opt_recordsep, fout);
              need_recordsep = false;
          }
!         if ((opt_align[i % col_count] == 'r') && strlen(*ptr) > 0 &&
!             opt_numericsep != NULL && strlen(opt_numericsep) > 0)
!         {
!             char *my_cell = malloc(len_with_numericsep(*ptr));
!
!             if (!my_cell)
!             {
!                 fprintf(stderr, _("out of memory\n"));
!                 exit(EXIT_FAILURE);
!             }
!             strcpy(my_cell, *ptr);
!             format_numericsep(my_cell, opt_numericsep);
!             fputs(my_cell, fout);
!             free(my_cell);
!         }
!         else
!             fputs(*ptr, fout);
!
          if ((i + 1) % col_count)
              fputs(opt_fieldsep, fout);
          else
***************
*** 107,120 ****


  static void
! print_unaligned_vertical(const char *title, const char *const * headers,
!                   const char *const * cells, const char *const * footers,
!  const char *opt_fieldsep, const char *opt_recordsep, bool opt_barebones,
!                          FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const * ptr;

      if (!opt_fieldsep)
          opt_fieldsep = "";
--- 211,225 ----


  static void
! print_unaligned_vertical(const char *title, const char *const *headers,
!                          const char *const *cells,
!                          const char *const *footers, const char *opt_align,
!                          const char *opt_fieldsep, const char *opt_recordsep,
!                          bool opt_barebones, char *opt_numericsep, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const *ptr;

      if (!opt_fieldsep)
          opt_fieldsep = "";
***************
*** 141,147 ****

          fputs(headers[i % col_count], fout);
          fputs(opt_fieldsep, fout);
!         fputs(*ptr, fout);
      }

      /* print footers */
--- 246,268 ----

          fputs(headers[i % col_count], fout);
          fputs(opt_fieldsep, fout);
!         if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
!             opt_numericsep != NULL && strlen(opt_numericsep) > 0)
!         {
!             char *my_cell = malloc(len_with_numericsep(*ptr));
!
!             if (!my_cell)
!             {
!                 fprintf(stderr, _("out of memory\n"));
!                 exit(EXIT_FAILURE);
!             }
!             strcpy(my_cell, *ptr);
!             format_numericsep(my_cell, opt_numericsep);
!             fputs(my_cell, fout);
!             free(my_cell);
!         }
!         else
!             fputs(*ptr, fout);
      }

      /* print footers */
***************
*** 202,210 ****


  static void
! print_aligned_text(const char *title, const char *const * headers,
!                    const char *const * cells, const char *const * footers,
!                    const char *opt_align, bool opt_barebones,
                     unsigned short int opt_border, int encoding,
                     FILE *fout)
  {
--- 323,331 ----


  static void
! print_aligned_text(const char *title, const char *const *headers,
!                    const char *const *cells, const char *const *footers,
!                    const char *opt_align, bool opt_barebones, char *opt_numericsep,
                     unsigned short int opt_border, int encoding,
                     FILE *fout)
  {
***************
*** 216,222 ****
                  tmp;
      unsigned int *widths,
                  total_w;
!     const char *const * ptr;

      /* count columns */
      for (ptr = headers; *ptr; ptr++)
--- 337,343 ----
                  tmp;
      unsigned int *widths,
                  total_w;
!     const char *const *ptr;

      /* count columns */
      for (ptr = headers; *ptr; ptr++)
***************
*** 271,277 ****

      for (i = 0, ptr = cells; *ptr; ptr++, i++)
      {
!         tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr), encoding);
          if (tmp > widths[i % col_count])
              widths[i % col_count] = tmp;
          cell_w[i] = tmp;
--- 392,406 ----

      for (i = 0, ptr = cells; *ptr; ptr++, i++)
      {
!         int numericseps;
!
!         if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
!             opt_numericsep != NULL && strlen(opt_numericsep) > 0)
!             numericseps = num_numericseps(*ptr);
!         else
!             numericseps = 0;
!
!         tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr), encoding) + numericseps;
          if (tmp > widths[i % col_count])
              widths[i % col_count] = tmp;
          cell_w[i] = tmp;
***************
*** 351,358 ****
          /* content */
          if (opt_align[i % col_count] == 'r')
          {
!             fprintf(fout, "%*s%s",
!                     widths[i % col_count] - cell_w[i], "", cells[i]);
          }
          else
          {
--- 480,501 ----
          /* content */
          if (opt_align[i % col_count] == 'r')
          {
!             if (strlen(*ptr) > 0 && opt_numericsep != NULL && strlen(opt_numericsep) > 0)
!             {
!                 char *my_cell = malloc(cell_w[i]);
!
!                 if (!my_cell)
!                 {
!                     fprintf(stderr, _("out of memory\n"));
!                     exit(EXIT_FAILURE);
!                 }
!                 strcpy(my_cell, *ptr);
!                 format_numericsep(my_cell, opt_numericsep);
!                 fprintf(fout, "%*s%s", widths[i % col_count] - cell_w[i], "", my_cell);
!                 free(my_cell);
!             }
!             else
!                 fprintf(fout, "%*s%s", widths[i % col_count] - cell_w[i], "", *ptr);
          }
          else
          {
***************
*** 406,419 ****


  static void
! print_aligned_vertical(const char *title, const char *const * headers,
!                   const char *const * cells, const char *const * footers,
!                        bool opt_barebones, unsigned short int opt_border,
                         int encoding, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int record = 1;
!     const char *const * ptr;
      unsigned int i,
                  tmp = 0,
                  hwidth = 0,
--- 549,563 ----


  static void
! print_aligned_vertical(const char *title, const char *const *headers,
!                        const char *const *cells, const char *const *footers,
!                        const char *opt_align, bool opt_barebones,
!                        char *opt_numericsep, unsigned short int opt_border,
                         int encoding, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int record = 1;
!     const char *const *ptr;
      unsigned int i,
                  tmp = 0,
                  hwidth = 0,
***************
*** 471,477 ****
      /* find longest data cell */
      for (i = 0, ptr = cells; *ptr; ptr++, i++)
      {
!         tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr), encoding);
          if (tmp > dwidth)
              dwidth = tmp;
          cell_w[i] = tmp;
--- 615,629 ----
      /* find longest data cell */
      for (i = 0, ptr = cells; *ptr; ptr++, i++)
      {
!         int numericseps;
!
!         if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
!             opt_numericsep != NULL && strlen(opt_numericsep) > 0)
!             numericseps = num_numericseps(*ptr);
!         else
!             numericseps = 0;
!
!         tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr), encoding) + numericseps;
          if (tmp > dwidth)
              dwidth = tmp;
          cell_w[i] = tmp;
***************
*** 556,565 ****
          else
              fputs(" ", fout);

!         if (opt_border < 2)
!             fprintf(fout, "%s\n", *ptr);
!         else
!             fprintf(fout, "%-s%*s |\n", *ptr, dwidth - cell_w[i], "");
      }

      if (opt_border == 2)
--- 708,731 ----
          else
              fputs(" ", fout);

!         {
!             char *my_cell = malloc(cell_w[i]);
!
!             if (!my_cell)
!             {
!                 fprintf(stderr, _("out of memory\n"));
!                 exit(EXIT_FAILURE);
!             }
!             strcpy(my_cell, *ptr);
!             if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
!                 opt_numericsep != NULL && strlen(opt_numericsep) > 0)
!                 format_numericsep(my_cell, opt_numericsep);
!             if (opt_border < 2)
!                 puts(my_cell);
!             else
!                 fprintf(fout, "%-s%*s |\n", my_cell, dwidth - cell_w[i], "");
!             free(my_cell);
!         }
      }

      if (opt_border == 2)
***************
*** 637,651 ****


  static void
! print_html_text(const char *title, const char *const * headers,
!                 const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
!                 const char *opt_table_attr,
!                 FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const * ptr;

      fprintf(fout, "<table border=\"%d\"", opt_border);
      if (opt_table_attr)
--- 803,817 ----


  static void
! print_html_text(const char *title, const char *const *headers,
!                 const char *const *cells, const char *const *footers,
!                 const char *opt_align, bool opt_barebones,
!                 char *opt_numericsep, unsigned short int opt_border,
!                 const char *opt_table_attr, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const *ptr;

      fprintf(fout, "<table border=\"%d\"", opt_border);
      if (opt_table_attr)
***************
*** 683,693 ****
              fputs("  <tr valign=\"top\">\n", fout);

          fprintf(fout, "    <td align=\"%s\">", opt_align[(i) % col_count] == 'r' ? "right" : "left");
!         if ((*ptr)[strspn(*ptr, " \t")] == '\0')        /* is string only
!                                                          * whitespace? */
              fputs("  ", fout);
          else
              html_escaped_print(*ptr, fout);
          fputs("</td>\n", fout);

          if ((i + 1) % col_count == 0)
--- 849,875 ----
              fputs("  <tr valign=\"top\">\n", fout);

          fprintf(fout, "    <td align=\"%s\">", opt_align[(i) % col_count] == 'r' ? "right" : "left");
!         /* is string only whitespace? */
!         if ((*ptr)[strspn(*ptr, " \t")] == '\0')
              fputs("  ", fout);
+         else if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
+                  opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+         {
+             char *my_cell = malloc(len_with_numericsep(*ptr));
+
+             if (!my_cell)
+             {
+                 fprintf(stderr, _("out of memory\n"));
+                 exit(EXIT_FAILURE);
+             }
+             strcpy(my_cell, *ptr);
+             format_numericsep(my_cell, opt_numericsep);
+             html_escaped_print(my_cell, fout);
+             free(my_cell);
+         }
          else
              html_escaped_print(*ptr, fout);
+
          fputs("</td>\n", fout);

          if ((i + 1) % col_count == 0)
***************
*** 714,729 ****


  static void
! print_html_vertical(const char *title, const char *const * headers,
!                   const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
!                     const char *opt_table_attr,
!                     FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
      unsigned int record = 1;
!     const char *const * ptr;

      fprintf(fout, "<table border=\"%d\"", opt_border);
      if (opt_table_attr)
--- 896,911 ----


  static void
! print_html_vertical(const char *title, const char *const *headers,
!                   const char *const *cells, const char *const *footers,
!                   const char *opt_align, bool opt_barebones,
!                   char *opt_numericsep, unsigned short int opt_border,
!                   const char *opt_table_attr, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
      unsigned int record = 1;
!     const char *const *ptr;

      fprintf(fout, "<table border=\"%d\"", opt_border);
      if (opt_table_attr)
***************
*** 758,768 ****
          fputs("</th>\n", fout);

          fprintf(fout, "    <td align=\"%s\">", opt_align[i % col_count] == 'r' ? "right" : "left");
!         if ((*ptr)[strspn(*ptr, " \t")] == '\0')        /* is string only
!                                                          * whitespace? */
              fputs("  ", fout);
          else
              html_escaped_print(*ptr, fout);
          fputs("</td>\n  </tr>\n", fout);
      }

--- 940,966 ----
          fputs("</th>\n", fout);

          fprintf(fout, "    <td align=\"%s\">", opt_align[i % col_count] == 'r' ? "right" : "left");
!         /* is string only whitespace? */
!         if ((*ptr)[strspn(*ptr, " \t")] == '\0')
              fputs("  ", fout);
+         else if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 &&
+             opt_numericsep != NULL && strlen(opt_numericsep) > 0)
+         {
+             char *my_cell = malloc(len_with_numericsep(*ptr));
+
+             if (!my_cell)
+             {
+                 fprintf(stderr, _("out of memory\n"));
+                 exit(EXIT_FAILURE);
+             }
+             strcpy(my_cell, *ptr);
+             format_numericsep(my_cell, opt_numericsep);
+             html_escaped_print(my_cell, fout);
+             free(my_cell);
+         }
          else
              html_escaped_print(*ptr, fout);
+
          fputs("</td>\n  </tr>\n", fout);
      }

***************
*** 829,842 ****


  static void
! print_latex_text(const char *title, const char *const * headers,
!                  const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
!                  FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const * ptr;


      /* print title */
--- 1027,1040 ----


  static void
! print_latex_text(const char *title, const char *const *headers,
!                  const char *const *cells, const char *const *footers,
!                  const char *opt_align, bool opt_barebones,
!                  unsigned short int opt_border, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const *ptr;


      /* print title */
***************
*** 921,934 ****


  static void
! print_latex_vertical(const char *title, const char *const * headers,
!                   const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
!                      FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const * ptr;
      unsigned int record = 1;

      (void) opt_align;            /* currently unused parameter */
--- 1119,1132 ----


  static void
! print_latex_vertical(const char *title, const char *const *headers,
!                   const char *const *cells, const char *const *footers,
!                   const char *opt_align, bool opt_barebones,
!                   unsigned short int opt_border, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const *ptr;
      unsigned int record = 1;

      (void) opt_align;            /* currently unused parameter */
***************
*** 1027,1040 ****


  static void
! print_troff_ms_text(const char *title, const char *const * headers,
!                  const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
!                  FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const * ptr;


      /* print title */
--- 1225,1238 ----


  static void
! print_troff_ms_text(const char *title, const char *const *headers,
!                  const char *const *cells, const char *const *footers,
!                  const char *opt_align, bool opt_barebones,
!                  unsigned short int opt_border, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const *ptr;


      /* print title */
***************
*** 1111,1124 ****


  static void
! print_troff_ms_vertical(const char *title, const char *const * headers,
!                   const char *const * cells, const char *const * footers,
! const char *opt_align, bool opt_barebones, unsigned short int opt_border,
!                      FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const * ptr;
      unsigned int record = 1;
          unsigned short current_format = 0; /* 0=none, 1=header, 2=body */

--- 1309,1322 ----


  static void
! print_troff_ms_vertical(const char *title, const char *const *headers,
!                   const char *const *cells, const char *const *footers,
!                   const char *opt_align, bool opt_barebones,
!                   unsigned short int opt_border, FILE *fout)
  {
      unsigned int col_count = 0;
      unsigned int i;
!     const char *const *ptr;
      unsigned int record = 1;
          unsigned short current_format = 0; /* 0=none, 1=header, 2=body */

***************
*** 1263,1271 ****

  void
  printTable(const char *title,
!            const char *const * headers,
!            const char *const * cells,
!            const char *const * footers,
             const char *align,
             const printTableOpt *opt, FILE *fout, FILE *flog)
  {
--- 1461,1469 ----

  void
  printTable(const char *title,
!            const char *const *headers,
!            const char *const *cells,
!            const char *const *footers,
             const char *align,
             const printTableOpt *opt, FILE *fout, FILE *flog)
  {
***************
*** 1298,1304 ****
          int            col_count = 0,
                      row_count = 0,
                      lines;
!         const char *const * ptr;

          /* rough estimate of columns and rows */
          if (headers)
--- 1496,1502 ----
          int            col_count = 0,
                      row_count = 0,
                      lines;
!         const char *const *ptr;

          /* rough estimate of columns and rows */
          if (headers)
***************
*** 1325,1362 ****
      /* print the stuff */

      if (flog)
!         print_aligned_text(title, headers, cells, footers, align, opt->tuples_only, border, opt->encoding, flog);

      switch (opt->format)
      {
          case PRINT_UNALIGNED:
              if (use_expanded)
!                 print_unaligned_vertical(title, headers, cells, footers,
                                           opt->fieldSep, opt->recordSep,
!                                          opt->tuples_only, output);
              else
!                 print_unaligned_text(title, headers, cells, footers,
                                       opt->fieldSep, opt->recordSep,
!                                      opt->tuples_only, output);
              break;
          case PRINT_ALIGNED:
              if (use_expanded)
!                 print_aligned_vertical(title, headers, cells, footers,
!                                        opt->tuples_only, border,
                                         opt->encoding, output);
              else
!                 print_aligned_text(title, headers, cells, footers,
!                                    align, opt->tuples_only,
                                     border, opt->encoding, output);
              break;
          case PRINT_HTML:
              if (use_expanded)
!                 print_html_vertical(title, headers, cells, footers,
!                                     align, opt->tuples_only,
                                      border, opt->tableAttr, output);
              else
                  print_html_text(title, headers, cells, footers,
!                                 align, opt->tuples_only, border,
                                  opt->tableAttr, output);
              break;
          case PRINT_LATEX:
--- 1523,1560 ----
      /* print the stuff */

      if (flog)
!         print_aligned_text(title, headers, cells, footers, align, opt->tuples_only, opt->numericSep, border,
opt->encoding,flog); 

      switch (opt->format)
      {
          case PRINT_UNALIGNED:
              if (use_expanded)
!                 print_unaligned_vertical(title, headers, cells, footers, align,
                                           opt->fieldSep, opt->recordSep,
!                                          opt->tuples_only, opt->numericSep, output);
              else
!                 print_unaligned_text(title, headers, cells, footers, align,
                                       opt->fieldSep, opt->recordSep,
!                                      opt->tuples_only, opt->numericSep, output);
              break;
          case PRINT_ALIGNED:
              if (use_expanded)
!                 print_aligned_vertical(title, headers, cells, footers, align,
!                                        opt->tuples_only, opt->numericSep, border,
                                         opt->encoding, output);
              else
!                 print_aligned_text(title, headers, cells, footers, align,
!                                    opt->tuples_only, opt->numericSep,
                                     border, opt->encoding, output);
              break;
          case PRINT_HTML:
              if (use_expanded)
!                 print_html_vertical(title, headers, cells, footers, align,
!                                     opt->tuples_only, opt->numericSep,
                                      border, opt->tableAttr, output);
              else
                  print_html_text(title, headers, cells, footers,
!                                 align, opt->tuples_only, opt->numericSep, border,
                                  opt->tableAttr, output);
              break;
          case PRINT_LATEX:
Index: src/bin/psql/print.h
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/print.h,v
retrieving revision 1.25
diff -c -c -r1.25 print.h
*** src/bin/psql/print.h    14 Jun 2005 02:57:41 -0000    1.25
--- src/bin/psql/print.h    10 Jul 2005 03:24:24 -0000
***************
*** 40,45 ****
--- 40,46 ----
      char       *fieldSep;        /* field separator for unaligned text mode */
      char       *recordSep;        /* record separator for unaligned text
                                   * mode */
+     char       *numericSep;        /* numeric units separator */
      char       *tableAttr;        /* attributes for HTML <table ...> */
      int            encoding;        /* character encoding */
      bool        normal_query;    /* are we presenting the results of a

pgsql-patches by date:

Previous
From: Stephan Szabo
Date:
Subject: Re: patch: garbage error strings in libpq
Next
From: Bruce Momjian
Date:
Subject: Re: [patch 1/2] Add implementation of SHA256/384/512