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
Best Regards,
Eugen
*** ./command.c.orig Fri Jan 24 07:23:55 2003
--- ./command.c Fri Jun 17 12:10:12 2005
***************
*** 817,822 ****
--- 817,827 ----
else if (strcmp(cmd, "x") == 0)
success = do_pset("expanded", NULL, &pset.popt, quiet);
+ /* thousands comma patch */
+ /* \n -- toggle numeric formating */
+ else if (strcmp(cmd, "n") == 0)
+ success = do_pset("numeric", NULL, &pset.popt, quiet);
+ /* thousands comma patch */
/* \z -- list table rights (equivalent to \dp) */
else if (strcmp(cmd, "z") == 0)
***************
*** 1780,1785 ****
--- 1785,1802 ----
: gettext("Expanded display is off.\n"));
}
+
+ /* thousands comma patch */
+ else if ((strcmp(param, "n") == 0) || (strcmp(param, "numeric") == 0))
+ {
+ popt->topt.numeric = !popt->topt.numeric;
+ if (!quiet)
+ printf(popt->topt.numeric
+ ? gettext("Numeric formating is on.\n")
+ : gettext("Numeric formating is off.\n"));
+ }
+ /* thousands comma patch */
+
/* null display */
else if (strcmp(param, "null") == 0)
{
*** ./help.c.orig Thu Oct 24 04:33:50 2002
--- ./help.c Fri Jun 17 12:42:41 2005
***************
*** 224,229 ****
--- 224,231 ----
ON(pset.popt.topt.expanded));
fprintf(output, _(" \\z [PATTERN] list table access privileges (same
as \\dp)\n"));
fprintf(output, _(" \\! [COMMAND] execute command in shell or start
interactive shell\n"));
+ fprintf(output, _(" \\n toggle numeric formating (currently
%s)\n"),
+ ON(pset.popt.topt.numeric));
if (output != stdout)
{
*** ./print.c.orig Fri Nov 1 17:12:19 2002
--- ./print.c Wed Jun 22 10:10:08 2005
***************
*** 19,24 ****
--- 19,114 ----
#include "mbprint.h"
+ /* thousands comma patch */
+ # include "langinfo.h"
+
+ int get_nr_delim (char *);
+ int get_new_l (char *);
+
+ int get_nr_delim (char *my_str)
+ {
+ int old_l,dec_l,int_l,k,nr_delim;
+ old_l = strlen(my_str);
+ dec_l = (strstr(my_str, ".") ? strlen(strstr(my_str, ".")) : 0);
+ if (my_str[0] == '-')
+ int_l = old_l - dec_l - 1;
+ else
+ int_l = old_l - dec_l;
+
+ k = int_l % 3;
+
+ if (k)
+ nr_delim = (int_l / 3);
+ else
+ nr_delim = (int_l / 3) - 1;
+
+ return nr_delim;
+ }
+
+ int get_new_l (char *my_str)
+ {
+ return (strlen(my_str) + get_nr_delim(my_str));
+ }
+
+ static void
+ thousands_comma(char *my_str)
+ {
+ int i,j,k,old_l,new_l,dec_l,int_l;
+
+ char *dec_point = nl_langinfo(__DECIMAL_POINT);
+ char *thou_sep;
+
+ if (!strcmp(dec_point, "")) dec_point = ".";
+ if (!strcmp(dec_point, "."))
+ thou_sep = ",";
+ else
+ thou_sep = ".";
+
+ if (my_str[0] == '-') my_str++;
+
+ old_l = strlen(my_str);
+ dec_l = (strstr(my_str, ".") ? strlen(strstr(my_str, ".")) : 0);
+ int_l = old_l - dec_l;
+ k = int_l % 3;
+
+ if (k)
+ new_l = int_l + (int_l / 3) + dec_l;
+ else
+ new_l = int_l + (int_l / 3) - 1 + dec_l;
+
+ char new_str[new_l];
+
+ for (i=0,j=0;;i++,j++)
+ {
+ if (my_str[i] == '.')
+ {
+ new_str[j] = *dec_point;
+ new_str[j+1] = '\0';
+ char *dec_value = strstr(my_str, ".");
+ strcat(new_str, ++dec_value);
+ break;
+ }
+
+ if (my_str[i] == '\0')
+ {
+ new_str[j] = '\0';
+ break;
+ }
+
+ if ((j - (k ? k : 3)) % 4)
+ new_str[j] = my_str[i];
+ else
+ {
+ new_str[j] = *thou_sep;
+ i--;
+ }
+ }
+
+ strcpy(my_str, new_str);
+ }
+
+ /* thousands comma patch */
+
/*************************/
/* Unaligned text */
/*************************/
***************
*** 26,33 ****
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;
--- 116,123 ----
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,
bool opt_numeric,
FILE *fout)
{
unsigned int col_count = 0;
***************
*** 67,73 ****
fputs(opt_recordsep, fout);
need_recordsep = false;
}
! fputs(*ptr, fout);
if ((i + 1) % col_count)
fputs(opt_fieldsep, fout);
else
--- 157,173 ----
fputs(opt_recordsep, fout);
need_recordsep = false;
}
! /* thousands comma patch */
! if ((opt_align[i % col_count] == 'r') && cells[i] != "" &&
opt_numeric)
! {
! char my_cell[get_new_l(cells[i])];
! strcpy(my_cell, *ptr);
! thousands_comma(my_cell);
! fputs(my_cell, fout);
! } else fputs(*ptr, fout);
! /* thousands comma patch */
!
! /* fputs(*ptr, fout); */
if ((i + 1) % col_count)
fputs(opt_fieldsep, fout);
else
***************
*** 98,105 ****
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;
--- 198,205 ----
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,
bool opt_numeric,
FILE *fout)
{
unsigned int col_count = 0;
***************
*** 131,137 ****
fputs(headers[i % col_count], fout);
fputs(opt_fieldsep, fout);
! fputs(*ptr, fout);
}
/* print footers */
--- 231,247 ----
fputs(headers[i % col_count], fout);
fputs(opt_fieldsep, fout);
! /* thousands comma patch */
! if ((opt_align[i % col_count] == 'r') && cells[i] != "" &&
opt_numeric)
! {
! char my_cell[get_new_l(cells[i])];
! strcpy(my_cell, *ptr);
! thousands_comma(my_cell);
! fputs(my_cell, fout);
! } else fputs(*ptr, fout);
! /* thousands comma patch */
!
! /* fputs(*ptr, fout); */
}
/* print footers */
***************
*** 190,200 ****
}
-
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,
FILE *fout)
{
--- 300,309 ----
}
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,
bool opt_numeric,
unsigned short int opt_border,
FILE *fout)
{
***************
*** 261,267 ****
for (i = 0, ptr = cells; *ptr; ptr++, i++)
{
! tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr));
if (tmp > widths[i % col_count])
widths[i % col_count] = tmp;
cell_w[i] = tmp;
--- 370,384 ----
for (i = 0, ptr = cells; *ptr; ptr++, i++)
{
! /* thousands comma patch */
! int nr_delim;
! if ((opt_align[i % col_count] == 'r') && cells[i] != "" &&
opt_numeric)
! nr_delim = get_nr_delim(cells[i]);
! else
! nr_delim = 0;
! /* thousands comma patch */
!
! tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr)) +
nr_delim;
if (tmp > widths[i % col_count])
widths[i % col_count] = tmp;
cell_w[i] = tmp;
***************
*** 343,350 ****
/* content */
if (opt_align[i % col_count] == 'r')
{
! fprintf(fout, "%*s%s",
! widths[i % col_count] - cell_w[i], "",
cells[i]);
}
else
{
--- 460,475 ----
/* content */
if (opt_align[i % col_count] == 'r')
{
! /* thousands comma patch */
! if (cells[i] != "" && opt_numeric)
! {
! char my_cell[cell_w[i]];
! strcpy(my_cell, cells[i]);
! thousands_comma(my_cell);
! fprintf(fout, "%*s%s", widths[i % col_count] -
cell_w[i], "", my_cell);
! } else
! fprintf(fout, "%*s%s", widths[i % col_count] -
cell_w[i], "", cells[i]);
! /* thousands comma patch */
}
else
{
***************
*** 392,399 ****
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,
FILE *fout)
{
unsigned int col_count = 0;
--- 517,524 ----
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, bool
opt_numeric, unsigned short int opt_border,
FILE *fout)
{
unsigned int col_count = 0;
***************
*** 447,453 ****
/* find longest data cell */
for (i = 0, ptr = cells; *ptr; ptr++, i++)
{
! if ((tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr))) >
dwidth)
dwidth = tmp;
cell_w[i] = tmp;
}
--- 572,586 ----
/* find longest data cell */
for (i = 0, ptr = cells; *ptr; ptr++, i++)
{
! /* thousands comma patch */
! int nr_delim;
! if ((opt_align[i % col_count] == 'r') && cells[i] != "" &&
opt_numeric)
! nr_delim = get_nr_delim(cells[i]);
! else
! nr_delim = 0;
! /* thousands comma patch */
!
! if ((tmp = pg_wcswidth((unsigned char *) *ptr, strlen(*ptr)) +
nr_delim) > dwidth)
dwidth = tmp;
cell_w[i] = tmp;
}
***************
*** 532,541 ****
--- 665,687 ----
else
fputs(" ", fout);
+ /* thousands comma patch */
+ char my_cell[cell_w[i]];
+ strcpy(my_cell, *ptr);
+ if ((opt_align[i % col_count] == 'r') && (my_cell != "") &&
opt_numeric)
+ thousands_comma(my_cell);
+ if (opt_border < 2)
+ fprintf(fout, "%s\n", my_cell);
+ else
+ fprintf(fout, "%-s%*s |\n", my_cell, dwidth -
cell_w[i], "");
+ /* thousands comma patch */
+
+ /*
if (opt_border < 2)
fprintf(fout, "%s\n", *ptr);
else
fprintf(fout, "%-s%*s |\n", *ptr, dwidth - cell_w[i],
"");
+ */
}
if (opt_border == 2)
***************
*** 598,604 ****
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)
{
--- 744,750 ----
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, bool opt_numeric, unsigned short
int opt_border,
const char *opt_table_attr,
FILE *fout)
{
***************
*** 646,652 ****
* whitespace? */
fputs(" ", fout);
else
! html_escaped_print(*ptr, fout);
fputs("</td>\n", fout);
if ((i + 1) % col_count == 0)
--- 792,808 ----
* whitespace? */
fputs(" ", fout);
else
! /* thousands comma patch */
! if ((opt_align[i % col_count] == 'r') && cells[i] != ""
&& opt_numeric)
! {
! char my_cell[get_new_l(cells[i])];
! strcpy(my_cell, *ptr);
! thousands_comma(my_cell);
! html_escaped_print(my_cell, fout);
! } else html_escaped_print(*ptr, fout);
! /* thousands comma patch */
!
! /* html_escaped_print(*ptr, fout); */
fputs("</td>\n", fout);
if ((i + 1) % col_count == 0)
***************
*** 672,678 ****
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)
{
--- 828,834 ----
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, bool opt_numeric, unsigned short
int opt_border,
const char *opt_table_attr,
FILE *fout)
{
***************
*** 718,724 ****
* whitespace? */
fputs(" ", fout);
else
! html_escaped_print(*ptr, fout);
fputs("</td>\n </tr>\n", fout);
}
--- 874,892 ----
* whitespace? */
fputs(" ", fout);
else
! { /* thousands comma patch */
! if ((opt_align[i % col_count] == 'r') && cells[i] != ""
&& opt_numeric)
! {
! char my_cell[get_new_l(cells[i])];
! strcpy(my_cell, *ptr);
! thousands_comma(my_cell);
! html_escaped_print(my_cell, fout);
! } else html_escaped_print(*ptr, fout);
! }
! /* thousands comma patch */
!
! /* html_escaped_print(*ptr, fout); */
!
fputs("</td>\n </tr>\n", fout);
}
***************
*** 1017,1037 ****
{
case PRINT_UNALIGNED:
if (opt->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 (opt->expanded)
! print_aligned_vertical(title, headers, cells,
footers, opt->tuples_only, border, output);
else
! print_aligned_text(title, headers, cells,
footers, align, opt->tuples_only, border, output);
break;
case PRINT_HTML:
if (opt->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:
if (opt->expanded)
--- 1185,1205 ----
{
case PRINT_UNALIGNED:
if (opt->expanded)
! print_unaligned_vertical(title, headers, cells,
footers, align, opt->fieldSep, opt->recordSep, opt->tuples_only, opt->numeric,
output);
else
! print_unaligned_text(title, headers, cells,
footers, align, opt->fieldSep, opt->recordSep, opt->tuples_only, opt->numeric,
output);
break;
case PRINT_ALIGNED:
if (opt->expanded)
! print_aligned_vertical(title, headers, cells,
footers, align, opt->tuples_only, opt->numeric, border, output);
else
! print_aligned_text(title, headers, cells,
footers, align, opt->tuples_only, opt->numeric, border, output);
break;
case PRINT_HTML:
if (opt->expanded)
! print_html_vertical(title, headers, cells,
footers, align, opt->tuples_only, opt->numeric, border, opt->tableAttr, output);
else
! print_html_text(title, headers, cells, footers,
align, opt->tuples_only, opt->numeric, border, opt->tableAttr, output);
break;
case PRINT_LATEX:
if (opt->expanded)
*** ./print.h.orig Wed Sep 4 23:31:36 2002
--- ./print.h Fri Jun 17 12:38:26 2005
***************
*** 26,31 ****
--- 26,34 ----
enum printFormat format; /* one of the above */
bool expanded; /* expanded/vertical output (if
supported
* by output
format) */
+ /* thousands comma patch */
+ bool numeric; /* numeric format */
+ /* thousands comma patch */
bool pager; /* use pager for output (if to
stdout and
* stdout is a
tty) */
bool tuples_only; /* don't output headers, row counts,
etc. */
*** ./startup.c.orig Sat Oct 19 01:05:36 2002
--- ./startup.c Fri Jun 17 12:54:43 2005
***************
*** 138,143 ****
--- 138,146 ----
pset.queryFout = stdout;
pset.popt.topt.border = 1;
pset.popt.topt.pager = true;
+ /* thousands comma patch */
+ pset.popt.topt.numeric = true;
+ /* thousands comma patch */
pset.popt.default_footer = true;
SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
---------------------------(end of broadcast)---------------------------
TIP 9: In versions below 8.0, the planner will ignore your desire to
choose an index scan if your joining column's datatypes do not
match