]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix numericlocale psql option when used with a null string and latex and troff
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 1 Mar 2010 20:56:06 +0000 (20:56 +0000)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 1 Mar 2010 20:56:06 +0000 (20:56 +0000)
formats; a null string must not be formatted as a numeric. The more exotic
formats latex and troff also incorrectly formatted all strings as numerics
when numericlocale was on.

Backpatch to 8.1 where numericlocale option was added.

This fixes bug #5355 reported by Andy Lester.

src/bin/psql/print.c

index f256212ec5d5473f790e91888a8a1a7a959c3fe5..1115ba9de6705464047b1c4025cc8d7fc7d9e67f 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2006, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.90 2006/10/04 00:30:06 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/print.c,v 1.90.2.1 2010/03/01 20:56:06 heikki Exp $
  *
  * Note: we include postgres.h not postgres_fe.h so that we can include
  * catalog/pg_type.h, and thereby have access to INT4OID and similar macros.
@@ -181,7 +181,6 @@ print_unaligned_text(const char *title, const char *const * headers,
        const char *opt_fieldsep = opt->fieldSep;
        const char *opt_recordsep = opt->recordSep;
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned int col_count = 0;
        unsigned int i;
        const char *const * ptr;
@@ -231,15 +230,7 @@ print_unaligned_text(const char *title, const char *const * headers,
                        if (cancel_pressed)
                                break;
                }
-               if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
-               {
-                       char       *my_cell = format_numeric_locale(*ptr);
-
-                       fputs(my_cell, fout);
-                       free(my_cell);
-               }
-               else
-                       fputs(*ptr, fout);
+               fputs(*ptr, fout);
 
                if ((i + 1) % col_count)
                        fputs(opt_fieldsep, fout);
@@ -278,7 +269,6 @@ print_unaligned_vertical(const char *title, const char *const * headers,
        const char *opt_fieldsep = opt->fieldSep;
        const char *opt_recordsep = opt->recordSep;
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned int col_count = 0;
        unsigned int i;
        const char *const * ptr;
@@ -324,15 +314,7 @@ print_unaligned_vertical(const char *title, const char *const * headers,
 
                fputs(headers[i % col_count], fout);
                fputs(opt_fieldsep, fout);
-               if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
-               {
-                       char       *my_cell = format_numeric_locale(*ptr);
-
-                       fputs(my_cell, fout);
-                       free(my_cell);
-               }
-               else
-                       fputs(*ptr, fout);
+               fputs(*ptr, fout);
 
                if ((i + 1) % col_count)
                        fputs(opt_recordsep, fout);
@@ -405,7 +387,6 @@ print_aligned_text(const char *title, const char *const * headers,
                                   FILE *fout)
 {
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned short int opt_border = opt->border;
        int                     encoding = opt->encoding;
        unsigned int col_count = 0;
@@ -478,18 +459,11 @@ print_aligned_text(const char *title, const char *const * headers,
 
        for (i = 0, ptr = cells; *ptr; ptr++, i++)
        {
-               int                     numeric_locale_len;
                int                     height,
                                        space;
 
-               if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
-                       numeric_locale_len = additional_numeric_locale_len(*ptr);
-               else
-                       numeric_locale_len = 0;
-
                /* Get width, ignore height */
                pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding, &tmp, &height, &space);
-               tmp += numeric_locale_len;
                if (tmp > widths[i % col_count])
                        widths[i % col_count] = tmp;
                if (height > heights[i % col_count])
@@ -655,25 +629,9 @@ print_aligned_text(const char *title, const char *const * headers,
                                        /* content */
                                        if (opt_align[j] == 'r')
                                        {
-                                               if (opt_numeric_locale)
-                                               {
-                                                       /*
-                                                        * Assumption: This code used only on strings
-                                                        * without multibyte characters, otherwise
-                                                        * this_line->width < strlen(this_ptr) and we get
-                                                        * an overflow
-                                                        */
-                                                       char       *my_cell = format_numeric_locale((char *) this_line->ptr);
-
-                                                       fprintf(fout, "%*s%s",
-                                                                       (int) (widths[i % col_count] - strlen(my_cell)), "",
-                                                                       my_cell);
-                                                       free(my_cell);
-                                               }
-                                               else
-                                                       fprintf(fout, "%*s%s",
-                                                                       widths[j] - this_line->width, "",
-                                                                       this_line->ptr);
+                                               fprintf(fout, "%*s%s",
+                                                               widths[j] - this_line->width, "",
+                                                               this_line->ptr);
                                        }
                                        else
                                                fprintf(fout, "%-s%*s", this_line->ptr,
@@ -743,7 +701,6 @@ print_aligned_vertical(const char *title, const char *const * headers,
                                           FILE *fout)
 {
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned short int opt_border = opt->border;
        int                     encoding = opt->encoding;
        unsigned int col_count = 0;
@@ -800,17 +757,10 @@ print_aligned_vertical(const char *title, const char *const * headers,
        /* find longest data cell */
        for (i = 0, ptr = cells; *ptr; ptr++, i++)
        {
-               int                     numeric_locale_len;
                int                     height,
                                        fs;
 
-               if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
-                       numeric_locale_len = additional_numeric_locale_len(*ptr);
-               else
-                       numeric_locale_len = 0;
-
                pg_wcssize((unsigned char *) *ptr, strlen(*ptr), encoding, &tmp, &height, &fs);
-               tmp += numeric_locale_len;
                if (tmp > dwidth)
                        dwidth = tmp;
                if (height > dheight)
@@ -925,25 +875,11 @@ print_aligned_vertical(const char *title, const char *const * headers,
 
                        if (!dcomplete)
                        {
-                               if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
-                               {
-                                       char       *my_cell = format_numeric_locale((char *) dlineptr[line_count].ptr);
-
-                                       if (opt_border < 2)
-                                               fprintf(fout, "%s\n", my_cell);
-                                       else
-                                               fprintf(fout, "%-s%*s |\n", my_cell,
-                                                               (int) (dwidth - strlen(my_cell)), "");
-                                       free(my_cell);
-                               }
+                               if (opt_border < 2)
+                                       fprintf(fout, "%s\n", dlineptr[line_count].ptr);
                                else
-                               {
-                                       if (opt_border < 2)
-                                               fprintf(fout, "%s\n", dlineptr[line_count].ptr);
-                                       else
-                                               fprintf(fout, "%-s%*s |\n", dlineptr[line_count].ptr,
-                                                               dwidth - dlineptr[line_count].width, "");
-                               }
+                                       fprintf(fout, "%-s%*s |\n", dlineptr[line_count].ptr,
+                                                       dwidth - dlineptr[line_count].width, "");
 
                                if (line_count == dheight - 1 || !dlineptr[line_count + 1].ptr)
                                        dcomplete = 1;
@@ -1037,7 +973,6 @@ print_html_text(const char *title, const char *const * headers,
                                FILE *fout)
 {
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned short int opt_border = opt->border;
        const char *opt_table_attr = opt->tableAttr;
        unsigned int col_count = 0;
@@ -1094,13 +1029,6 @@ print_html_text(const char *title, const char *const * headers,
                /* is string only whitespace? */
                if ((*ptr)[strspn(*ptr, " \t")] == '\0')
                        fputs("&nbsp; ", fout);
-               else if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
-               {
-                       char       *my_cell = format_numeric_locale(*ptr);
-
-                       html_escaped_print(my_cell, fout);
-                       free(my_cell);
-               }
                else
                        html_escaped_print(*ptr, fout);
 
@@ -1138,7 +1066,6 @@ print_html_vertical(const char *title, const char *const * headers,
                                        FILE *fout)
 {
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned short int opt_border = opt->border;
        const char *opt_table_attr = opt->tableAttr;
        unsigned int col_count = 0;
@@ -1192,13 +1119,6 @@ print_html_vertical(const char *title, const char *const * headers,
                /* is string only whitespace? */
                if ((*ptr)[strspn(*ptr, " \t")] == '\0')
                        fputs("&nbsp; ", fout);
-               else if (opt_align[i % col_count] == 'r' && opt_numeric_locale)
-               {
-                       char       *my_cell = format_numeric_locale(*ptr);
-
-                       html_escaped_print(my_cell, fout);
-                       free(my_cell);
-               }
                else
                        html_escaped_print(*ptr, fout);
 
@@ -1276,7 +1196,6 @@ print_latex_text(const char *title, const char *const * headers,
                                 FILE *fout)
 {
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned short int opt_border = opt->border;
        unsigned int col_count = 0;
        unsigned int i;
@@ -1340,15 +1259,7 @@ print_latex_text(const char *title, const char *const * headers,
        /* print cells */
        for (i = 0, ptr = cells; *ptr; i++, ptr++)
        {
-               if (opt_numeric_locale)
-               {
-                       char       *my_cell = format_numeric_locale(*ptr);
-
-                       latex_escaped_print(my_cell, fout);
-                       free(my_cell);
-               }
-               else
-                       latex_escaped_print(*ptr, fout);
+               latex_escaped_print(*ptr, fout);
 
                if ((i + 1) % col_count == 0)
                {
@@ -1389,7 +1300,6 @@ print_latex_vertical(const char *title, const char *const * headers,
                                         FILE *fout)
 {
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned short int opt_border = opt->border;
        unsigned int col_count = 0;
        unsigned long record = opt->prior_records + 1;
@@ -1469,15 +1379,7 @@ print_latex_vertical(const char *title, const char *const * headers,
                {
                        for (ptr = footers; *ptr; ptr++)
                        {
-                               if (opt_numeric_locale)
-                               {
-                                       char       *my_cell = format_numeric_locale(*ptr);
-
-                                       latex_escaped_print(my_cell, fout);
-                                       free(my_cell);
-                               }
-                               else
-                                       latex_escaped_print(*ptr, fout);
+                               latex_escaped_print(*ptr, fout);
                                fputs(" \\\\\n", fout);
                        }
                }
@@ -1516,7 +1418,6 @@ print_troff_ms_text(const char *title, const char *const * headers,
                                        FILE *fout)
 {
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned short int opt_border = opt->border;
        unsigned int col_count = 0;
        unsigned int i;
@@ -1575,15 +1476,7 @@ print_troff_ms_text(const char *title, const char *const * headers,
        /* print cells */
        for (i = 0, ptr = cells; *ptr; i++, ptr++)
        {
-               if (opt_numeric_locale)
-               {
-                       char       *my_cell = format_numeric_locale(*ptr);
-
-                       troff_ms_escaped_print(my_cell, fout);
-                       free(my_cell);
-               }
-               else
-                       troff_ms_escaped_print(*ptr, fout);
+               troff_ms_escaped_print(*ptr, fout);
 
                if ((i + 1) % col_count == 0)
                {
@@ -1619,7 +1512,6 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
                                                FILE *fout)
 {
        bool            opt_tuples_only = opt->tuples_only;
-       bool            opt_numeric_locale = opt->numericLocale;
        unsigned short int opt_border = opt->border;
        unsigned int col_count = 0;
        unsigned long record = opt->prior_records + 1;
@@ -1704,15 +1596,7 @@ print_troff_ms_vertical(const char *title, const char *const * headers,
 
                troff_ms_escaped_print(headers[i % col_count], fout);
                fputc('\t', fout);
-               if (opt_numeric_locale)
-               {
-                       char       *my_cell = format_numeric_locale(*ptr);
-
-                       troff_ms_escaped_print(my_cell, fout);
-                       free(my_cell);
-               }
-               else
-                       troff_ms_escaped_print(*ptr, fout);
+               troff_ms_escaped_print(*ptr, fout);
 
                fputc('\n', fout);
        }
@@ -1930,6 +1814,7 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
        int                     ncells;
        const char **headers;
        const char **cells;
+       bool       *cellmustfree = NULL;
        char      **footers;
        char       *align;
        int                     i;
@@ -1946,6 +1831,33 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
                headers[i] = (char *) mbvalidate((unsigned char *) PQfname(result, i),
                                                                                 opt->topt.encoding);
 
+       /* set alignment */
+       align = pg_local_calloc(nfields + 1, sizeof(*align));
+
+       for (i = 0; i < nfields; i++)
+       {
+               Oid                     ftype = PQftype(result, i);
+
+               switch (ftype)
+               {
+                       case INT2OID:
+                       case INT4OID:
+                       case INT8OID:
+                       case FLOAT4OID:
+                       case FLOAT8OID:
+                       case NUMERICOID:
+                       case OIDOID:
+                       case XIDOID:
+                       case CIDOID:
+                       case CASHOID:
+                               align[i] = 'r';
+                               break;
+                       default:
+                               align[i] = 'l';
+                               break;
+               }
+       }
+
        /* set cells */
        ncells = PQntuples(result) * nfields;
        cells = pg_local_calloc(ncells + 1, sizeof(*cells));
@@ -1955,9 +1867,25 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
                if (PQgetisnull(result, i / nfields, i % nfields))
                        cells[i] = opt->nullPrint ? opt->nullPrint : "";
                else
+               {
                        cells[i] = (char *)
                                mbvalidate((unsigned char *) PQgetvalue(result, i / nfields, i % nfields),
                                                   opt->topt.encoding);
+
+                       if (align[i % nfields] == 'r' && opt->topt.numericLocale)
+                       {
+                               cells[i] = format_numeric_locale(cells[i]);
+
+                               /*
+                                * format_numeric_locale() returns a malloc'd string, 
+                                * remember that it needs to be freed.
+                                */
+                               if (cellmustfree == NULL)
+                                       cellmustfree = pg_local_calloc(ncells + 1, sizeof(bool));
+
+                               cellmustfree[i] = true;
+                       }
+               }
        }
 
        /* set footers */
@@ -1979,39 +1907,21 @@ printQuery(const PGresult *result, const printQueryOpt *opt, FILE *fout, FILE *f
        else
                footers = NULL;
 
-       /* set alignment */
-       align = pg_local_calloc(nfields + 1, sizeof(*align));
-
-       for (i = 0; i < nfields; i++)
-       {
-               Oid                     ftype = PQftype(result, i);
-
-               switch (ftype)
-               {
-                       case INT2OID:
-                       case INT4OID:
-                       case INT8OID:
-                       case FLOAT4OID:
-                       case FLOAT8OID:
-                       case NUMERICOID:
-                       case OIDOID:
-                       case XIDOID:
-                       case CIDOID:
-                       case CASHOID:
-                               align[i] = 'r';
-                               break;
-                       default:
-                               align[i] = 'l';
-                               break;
-               }
-       }
-
        /* call table printer */
        printTable(opt->title, headers, cells,
                           (const char *const *) footers,
                           align, &opt->topt, fout, flog);
 
        free(headers);
+       if (cellmustfree)
+       {
+               for (i = 0; i < ncells; i++)
+               {
+                       if (cellmustfree[i])
+                               free((char *) cells[i]);
+               }
+               free(cellmustfree);
+       }
        free(cells);
        if (footers)
        {