[PATCHES] pgcrypto BYTE_ORDER fix for stable branches
Recently was uncovered that pgcrypto does not include right header file to get BYTE_ORDER define on Cygwin and MINGW, and the missing define does not result in build failures, but random combinations of little and big-endian code sections. This patch adds missing sys/param.h include for md5.c, sha1.c and rijndael.c plus also check to catch undefined BYTE_ORDER. The patch applies cleanly and is tested on branches for versions 7.2, 7.3, 7.4 and 8.0. There are also no failures on buildfarm for HEAD, where this patch is already included. -- marko Index: contrib/pgcrypto/md5.c === RCS file: /opt/arc/cvs2/pgsql/contrib/pgcrypto/md5.c,v retrieving revision 1.9 diff -u -c -r1.9 md5.c *** contrib/pgcrypto/md5.c 29 Nov 2001 19:40:37 - 1.9 --- contrib/pgcrypto/md5.c 13 Jul 2005 14:14:07 - *** *** 31,40 */ #include "postgres.h" - #include "px.h" #include "md5.h" #define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s #define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z))) --- 31,47 */ #include "postgres.h" + #include + + #include "px.h" #include "md5.h" + /* sanity check */ + #if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) + #error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN + #endif + #define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s #define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z))) Index: contrib/pgcrypto/rijndael.c === RCS file: /opt/arc/cvs2/pgsql/contrib/pgcrypto/rijndael.c,v retrieving revision 1.9 diff -u -c -r1.9 rijndael.c *** contrib/pgcrypto/rijndael.c 5 Sep 2002 21:08:26 - 1.9 --- contrib/pgcrypto/rijndael.c 13 Jul 2005 14:15:43 - *** *** 38,48 */ ! #include #include "px.h" #include "rijndael.h" #define PRE_CALC_TABLES #define LARGE_TABLES --- 38,56 */ ! #include "postgres.h" ! ! #include ! #include "px.h" #include "rijndael.h" + /* sanity check */ + #if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) + #error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN + #endif + #define PRE_CALC_TABLES #define LARGE_TABLES Index: contrib/pgcrypto/sha1.c === RCS file: /opt/arc/cvs2/pgsql/contrib/pgcrypto/sha1.c,v retrieving revision 1.11 diff -u -c -r1.11 sha1.c *** contrib/pgcrypto/sha1.c 29 Nov 2001 19:40:37 - 1.11 --- contrib/pgcrypto/sha1.c 13 Jul 2005 14:15:05 - *** *** 36,53 */ #include "postgres.h" #include "px.h" #include "sha1.h" /* sanity check */ ! #if BYTE_ORDER != BIG_ENDIAN ! #if BYTE_ORDER != LITTLE_ENDIAN ! #define unsupported 1 #endif - #endif - - #ifndef unsupported /* constant table */ static uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; --- 36,52 */ #include "postgres.h" + + #include + #include "px.h" #include "sha1.h" /* sanity check */ ! #if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN) ! #error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN #endif /* constant table */ static uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; *** *** 347,350 #endif } - #endif /* unsupported */ --- 346,348 ---(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
[PATCHES] Final cleanup of SQL:1999 references
This doc patch replaces all inappropriate references to SQL:1999 when it is used as if it were the latest (and/or still valid) SQL standard. SQL:2003 is used in its place. Best Regards, Simon Riggs Index: array.sgml === RCS file: /projects/cvsroot/pgsql/doc/src/sgml/array.sgml,v retrieving revision 1.43 diff -c -c -r1.43 array.sgml *** array.sgml 6 Feb 2005 20:59:30 - 1.43 --- array.sgml 12 Jul 2005 20:31:31 - *** *** 63,69 ! An alternative syntax, which conforms to the SQL:1999 standard, may be used for one-dimensional arrays. pay_by_quarter could have been defined as: --- 63,69 ! An alternative syntax, which conforms to the SQL:2003 standard, may be used for one-dimensional arrays. pay_by_quarter could have been defined as: Index: ddl.sgml === RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ddl.sgml,v retrieving revision 1.41 diff -c -c -r1.41 ddl.sgml *** ddl.sgml 13 Jun 2005 02:40:01 - 1.41 --- ddl.sgml 12 Jul 2005 20:31:33 - *** *** 1122,1128 In previous versions of PostgreSQL, the default behavior was not to include child tables in queries. This was ! found to be error prone and is also in violation of the SQL:1999 standard. Under the old syntax, to get the sub-tables you append * to the table name. For example --- 1122,1128 In previous versions of PostgreSQL, the default behavior was not to include child tables in queries. This was ! found to be error prone and is also in violation of the SQL:2003 standard. Under the old syntax, to get the sub-tables you append * to the table name. For example Index: ecpg.sgml === RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v retrieving revision 1.64 diff -c -c -r1.64 ecpg.sgml *** ecpg.sgml 20 May 2005 12:36:48 - 1.64 --- ecpg.sgml 12 Jul 2005 20:31:35 - *** *** 1146,1153 The fields sqlca.sqlstate and sqlca.sqlcode are two different schemes that provide error codes. Both are specified in the SQL standard, but ! SQLCODE has been marked deprecated in the 1992 ! edition of the standard and has been dropped in the 1999 edition. Therefore, new applications are strongly encouraged to use SQLSTATE. --- 1146,1153 The fields sqlca.sqlstate and sqlca.sqlcode are two different schemes that provide error codes. Both are specified in the SQL standard, but ! SQLCODE has been marked deprecated in SQL-92 ! edition of the standard and has been dropped in later editions. Therefore, new applications are strongly encouraged to use SQLSTATE. Index: errcodes.sgml === RCS file: /projects/cvsroot/pgsql/doc/src/sgml/errcodes.sgml,v retrieving revision 1.13 diff -c -c -r1.13 errcodes.sgml *** errcodes.sgml 26 Jun 2005 19:16:04 - 1.13 --- errcodes.sgml 12 Jul 2005 20:31:36 - *** *** 127,133 Class 02 ! No Data — this is also a warning class per SQL:1999 --- 127,133 Class 02 ! No Data — this is also a warning class per SQL:2003 Index: func.sgml === RCS file: /projects/cvsroot/pgsql/doc/src/sgml/func.sgml,v retrieving revision 1.260 diff -c -c -r1.260 func.sgml *** func.sgml 26 Jun 2005 22:05:35 - 1.260 --- func.sgml 12 Jul 2005 20:31:59 - *** *** 2515,2522 There are three separate approaches to pattern matching provided by PostgreSQL: the traditional SQL LIKE operator, the ! more recent SIMILAR TO operator (added in ! SQL:1999), and POSIX-style regular expressions. Additionally, a pattern matching function, substring, is available, using either SIMILAR TO-style or POSIX-style regular --- 2515,2522 There are three separate approaches to pattern matching provided by PostgreSQL: the traditional SQL LIKE operator, the ! more recent SIMILAR TO operator (part of ! SQL:2003), and POSIX-style regular expressions. Additionally, a pattern matching function, substring, is available, using either SIMILAR TO-style or POSIX-style regular Index: sql.sgml === RCS file: /projects/cvsroot/pgsql/doc/src/sgml/sql.sgml,v retrieving revision 1.36 diff -c -c -r1.36 sql.sgml *** sql.sgml 28 Apr 2005 21:47:09 - 1.36 --- sql.sgml 12 Jul 2005 20:31:59 - *** *** 98,105 is under development. It is planned to make SQL a Turing-complete language, i.e. all computable queries (e.g. recursive queries)
[PATCHES] PL/PGSQL: Dynamic Record Introspection
Hi all, I needed introspection capabilities for record types to write more generic trigger procedures in PL/PGSQL. With the following patch it's possible to - extract all field names of a record into an array - extract field count of a record - address a single field of a record with a variable containing the field name (additional to the usual record.fieldname notation where the fieldname is hardcoded). The syntax is - record%NFIELDS gives the number of fields in the record - record%FIELDNAMES gives the array of the field names - record%scalarvariable extracts the field whose name is equal to the contents of scalarvariable The patch is nonintrusive in the sense that it only adds things with one exception: In function exec_eval_datum(), file pl_exec.c, line 3557 (after the patch) I chose to convert the record field values to TEXT if the caller does not require a certain type (expectedtypeid == InvalidOid). Additionally, I cast the value from the record field type if the destination Datum is of different type. As far as I can see, this does no harm because in most cases the expectedtypeid is correctly set. I just wanted to avoid that if it is not set, the returned datum is of a more restrictive type than TEXT. The patch is against a HEAD checkout from 07/12/05 The output comes from difforig. Test code for the patch can be extracted from an example I put into plpgsql.sgml Here is a summary of things that get patched by the file: - add three new special parsing functions to pl_comp.c (plpgsql_parse_wordpercentword, plpgsql_parse_wordnfields, plpgsql_parse_wordfieldnames). - modify PLpgSQL_recfield in plpgsql.h to either hold a conventional field name (record.fieldname) or a dno for the variable (record%variable). - add two PLPGSQL_DTYPEs for the two new % notations - modify "case PLPGSQL_DTYPE_RECFIELD:" in exec_eval_datum() and exec_assign_value() to deal with index strings from a variable - add "case PLPGSQL_DTYPE_RECFIELDNAMES" and "case PLPGSQL_DTYPE_NRECFIELD" to exec_eval_datum() to evaluate %FIELDNAMES and %NFIELDS expressions. - update plpgsql.sgml in the docs directory Please notify me if I can be of further assistance. Regards Titus *** ./doc/src/sgml/plpgsql.sgml.origThu Jul 14 00:49:33 2005 --- ./doc/src/sgml/plpgsql.sgml Thu Jul 14 01:15:41 2005 *** *** 867,872 --- 867,941 + To obtain the values of the fields the record is made up of, + the record variable can be qualified with the column or field + name. This can be done either literally with the usual dot notation + or the column name for indexing the record can be taken out of a scalar + variable. The syntax for this notation is Record_variable%IndexVariable. + To get information about the column fields, two special + notations exist that return all column names as an array (RecordVariable%FIELDNAMES) + and the count of fields stored in a record (RecordVariable%NFIELDS). + Thus, the RECORD can be viewed + as an associative array that allows for introspection of it's contents. + This feature is especially useful for writing generic triggers that + operate on records with unknown structure. + Here is an example that operates on the predefined record NEW in + a trigger procedure: + + CREATE OR REPLACE FUNCTION show_associative_records() RETURNS TRIGGER AS $ztt_u$ + DECLARE + wmsgTEXT; + column TEXT; + colcontent TEXT; + colnamesTEXT[]; + colnINT4; + coliINT4; + testint8INT8; + BEGIN + -- get the number of fields + coln := NEW%NFIELDS; + RAISE NOTICE 'Record type has % fields', coln; + + -- obtain an array with all field names of the record + colnames := NEW%FIELDNAMES; + RAISE NOTICE 'All column names of test record: %', colnames; + + -- show field names and contents of record + coli := 1; + LOOP + column := colnames[coli]; + colcontent := NEW%column; + IF colcontent IS NULL + THEN + colcontent := ''; + END IF; + RAISE NOTICE 'column name % of NEW: value %', column, colcontent; + coli := coli + 1; + EXIT WHEN coli > coln; + END LOOP; + + -- get a single record field value indexed by the contents of the variable "column" + -- raises an error if the record does not have the field name from "column" + column := 'SomeFieldNameInYourRecord'; + -- testint8 will contain NULL if the value of this column + -- has a different type and cannot be casted to int8! + -- use a TEXT
[PATCHES] A minor patch to mark xml/xslt functions immutable
Immutability is obvious, because xml procession result depends on the document and request solely. Couldn't use it for indexes w/o that flag. --- /root/pgxml.sql.in Sat Jul 9 21:41:33 2005 +++ /usr/ports/databases/postgresql-contrib/work/postgresql-8.0.3/contrib/xml2/p gxml.sql.in Sat Jul 9 21:41:36 2005 @@ -1,31 +1,31 @@ --SQL for XML parser -CREATE OR REPLACE FUNCTION xml_valid(text) RETURNS bool +CREATE OR REPLACE FUNCTION xml_valid(text) RETURNS bool IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); -CREATE OR REPLACE FUNCTION xml_encode_special_chars(text) RETURNS text +CREATE OR REPLACE FUNCTION xml_encode_special_chars(text) RETURNS text IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); -CREATE OR REPLACE FUNCTION xpath_string(text,text) RETURNS text +CREATE OR REPLACE FUNCTION xpath_string(text,text) RETURNS text IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); -CREATE OR REPLACE FUNCTION xpath_nodeset(text,text,text,text) RETURNS text +CREATE OR REPLACE FUNCTION xpath_nodeset(text,text,text,text) RETURNS text IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); -CREATE OR REPLACE FUNCTION xpath_number(text,text) RETURNS float4 +CREATE OR REPLACE FUNCTION xpath_number(text,text) RETURNS float4 IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); -CREATE OR REPLACE FUNCTION xpath_bool(text,text) RETURNS boolean +CREATE OR REPLACE FUNCTION xpath_bool(text,text) RETURNS boolean IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); -- List function -CREATE OR REPLACE FUNCTION xpath_list(text,text,text) RETURNS text +CREATE OR REPLACE FUNCTION xpath_list(text,text,text) RETURNS text IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); -CREATE OR REPLACE FUNCTION xpath_list(text,text) RETURNS text +CREATE OR REPLACE FUNCTION xpath_list(text,text) RETURNS text IMMUTABLE AS 'SELECT xpath_list($1,$2,'','')' language 'SQL' WITH (isStrict); @@ -33,16 +33,16 @@ -- Wrapper functions for nodeset where no tags needed. -CREATE OR REPLACE FUNCTION xpath_nodeset(text,text) RETURNS text AS +CREATE OR REPLACE FUNCTION xpath_nodeset(text,text) RETURNS text IMMUTABLE AS 'SELECT xpath_nodeset($1,$2,,)' language 'SQL' WITH (isStrict); -CREATE OR REPLACE FUNCTION xpath_nodeset(text,text,text) RETURNS text AS +CREATE OR REPLACE FUNCTION xpath_nodeset(text,text,text) RETURNS text IMMUTABLE AS 'SELECT xpath_nodeset($1,$2,,$3)' language 'SQL' WITH (isStrict); -- Table function -CREATE OR REPLACE FUNCTION xpath_table(text,text,text,text,text) RETURNS setof record +CREATE OR REPLACE FUNCTION xpath_table(text,text,text,text,text) RETURNS setof record IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); @@ -51,10 +51,10 @@ -- XSLT support. -CREATE OR REPLACE FUNCTION xslt_process(text,text,text) RETURNS text +CREATE OR REPLACE FUNCTION xslt_process(text,text,text) RETURNS text IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); -- the function checks for the correct argument count -CREATE OR REPLACE FUNCTION xslt_process(text,text) RETURNS text +CREATE OR REPLACE FUNCTION xslt_process(text,text) RETURNS text IMMUTABLE AS 'MODULE_PATHNAME' LANGUAGE 'c' WITH (isStrict); ---(end of broadcast)--- TIP 5: don't forget to increase your free space map settings
Re: [PATCHES] PL/PGSQL: Dynamic Record Introspection
Titus von Boxberg wrote: With the following patch it's possible to - extract all field names of a record into an array - extract field count of a record - address a single field of a record with a variable containing the field name (additional to the usual record.fieldname notation where the fieldname is hardcoded). I wonder if this is the right syntax. record%identifier is doing something fundamentally different from record.identifier, but the syntax doesn't make that clear. I don't have any concrete suggestions for improvement, mind you... :) Test code for the patch can be extracted from an example I put into plpgsql.sgml Can you supply some proper regression tests, please? i.e. patch sql/plpgsql.sql and expected/plpgsql.out in src/test/regress A few minor comments from skimming the patch: *** *** 995,1001 new = palloc(sizeof(PLpgSQL_recfield)); new->dtype = PLPGSQL_DTYPE_RECFIELD; ! new->fieldname = pstrdup(cp[1]); new->recparentno = ns->itemno; plpgsql_adddatum((PLpgSQL_datum *) new); --- 995,1002 new = palloc(sizeof(PLpgSQL_recfield)); new->dtype = PLPGSQL_DTYPE_RECFIELD; ! new->fieldindex.fieldname = strdup(cp[1]); ! new->fieldindex_flag = RECFIELD_USE_FIELDNAME; new->recparentno = ns->itemno; plpgsql_adddatum((PLpgSQL_datum *) new); Should be pstrdup(). *** *** 1101,1107 new = palloc(sizeof(PLpgSQL_recfield)); new->dtype = PLPGSQL_DTYPE_RECFIELD; ! new->fieldname = pstrdup(cp[2]); new->recparentno = ns->itemno; plpgsql_adddatum((PLpgSQL_datum *) new); --- 1102,1109 new = palloc(sizeof(PLpgSQL_recfield)); new->dtype = PLPGSQL_DTYPE_RECFIELD; ! new->fieldindex.fieldname = strdup(cp[2]); ! new->fieldindex_flag = RECFIELD_USE_FIELDNAME; new->recparentno = ns->itemno; plpgsql_adddatum((PLpgSQL_datum *) new); Ibid. + switch (ns1->itemtype) + { + case PLPGSQL_NSTYPE_REC: + { + PLpgSQL_recfieldproperties *new; + + new = malloc(sizeof(PLpgSQL_recfieldproperties)); + new->dtype = PLPGSQL_DTYPE_NRECFIELD; + new->recparentno = ns1->itemno; + plpgsql_adddatum((PLpgSQL_datum *) new); + plpgsql_yylval.scalar = (PLpgSQL_datum *) new; + ret = T_SCALAR;/* ??? */ + break; Should be palloc(). + return ret; + } /* plpgsql_parse_wordnfields */ The Postgres convention is not to include comments like this. + case PLPGSQL_NSTYPE_REC: + { + PLpgSQL_recfieldproperties *new; + + new = malloc(sizeof(PLpgSQL_recfieldproperties)); + new->dtype = PLPGSQL_DTYPE_RECFIELDNAMES; + new->recparentno = ns1->itemno; + plpgsql_adddatum((PLpgSQL_datum *) new); + plpgsql_yylval.scalar = (PLpgSQL_datum *) new; + ret = T_SCALAR;/* ??? */ + break; + } Should be palloc(). ! /* construct_array copies data; free temp elem array */ ! #if 0 ! for ( fc = 0; fc < tfc; ++fc ) ! pfree(DatumGetPointer(arrayelems[fc]); ! pfree(arrayelems); ! #endif Unexplained #if 0 blocks aren't good. -Neil ---(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
Re: [PATCHES] Final cleanup of SQL:1999 references
Simon Riggs wrote: This doc patch replaces all inappropriate references to SQL:1999 when it is used as if it were the latest (and/or still valid) SQL standard. Applied, thanks. -Neil ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [PATCHES] PL/PGSQL: Dynamic Record Introspection
good idea. it's what can eliminate not neccessery using plperl. I would to see it in plpgsql. regards Pavel On Thu, 14 Jul 2005, Titus von Boxberg wrote: > Hi all, > > I needed introspection capabilities for record types to write more generic > trigger procedures in PL/PGSQL. > > With the following patch it's possible to > - extract all field names of a record into an array > - extract field count of a record > - address a single field of a record with a variable >containing the field name (additional to the usual record.fieldname >notation where the fieldname is hardcoded). > > The syntax is > - record%NFIELDS gives the number of fields in the record > - record%FIELDNAMES gives the array of the field names > - record%scalarvariable extracts the field whose name >is equal to the contents of scalarvariable > > > > The patch is nonintrusive in the sense that it only adds things > with one exception: > In function exec_eval_datum(), file pl_exec.c, line 3557 (after the patch) > I chose to convert the record field values to TEXT if the caller does > not require a certain type (expectedtypeid == InvalidOid). > Additionally, I cast the value from the record field type if > the destination Datum is of different type. > > As far as I can see, this does no harm because in most cases > the expectedtypeid is correctly set. I just wanted to avoid that > if it is not set, the returned datum is of a more restrictive type > than TEXT. > > > > The patch is against a HEAD checkout from 07/12/05 > The output comes from difforig. > > Test code for the patch can be extracted from an example I put into > plpgsql.sgml > > > > Here is a summary of things that get patched by the file: > - add three new special parsing functions to pl_comp.c >(plpgsql_parse_wordpercentword, plpgsql_parse_wordnfields, >plpgsql_parse_wordfieldnames). > - modify PLpgSQL_recfield in plpgsql.h to either hold >a conventional field name (record.fieldname) or a dno >for the variable (record%variable). > - add two PLPGSQL_DTYPEs for the two new % notations > - modify "case PLPGSQL_DTYPE_RECFIELD:" >in exec_eval_datum() and exec_assign_value() >to deal with index strings from a variable > - add "case PLPGSQL_DTYPE_RECFIELDNAMES" >and "case PLPGSQL_DTYPE_NRECFIELD" >to exec_eval_datum() to evaluate %FIELDNAMES >and %NFIELDS expressions. > - update plpgsql.sgml in the docs directory > > > > Please notify me if I can be of further assistance. > > Regards > Titus > ---(end of broadcast)--- TIP 4: Have you searched our list archives? http://archives.postgresql.org
Re: [PATCHES] thousands comma numeric formatting in psql
Thanks, fixed, and applied. I also centralized the malloc into a function. We could use pg_malloc, but that doesn't export out to /scripts, where this is shared. We will fix that some day, but not right now. --- Eugen Nedelcu wrote: > On Mon, Jul 11, 2005 at 11:37:17PM -0400, Bruce Momjian wrote: > > > > Did you do a 'make clean' before testing? I can't reproduce any failure > > here. Can you supply a number that is failing, like this: > > > > SELECT 100; > > > > --- > > > > The bug is in the following code: > > new_str = malloc(new_len) and every one of > char *my_cell = malloc() > > Ring a bell? > > The corect form is: > > new_str = malloc(new_len + 1), > char *my_cell = malloc( + 1) > > because of the null character that must terminate the string (\0) > > The error apears of course randomly (more probably for a query which > returns many rows) > > Regarding locale aproach, it is trivial to replace langinfo with > localeconv: > > struct lconv *l = localeconv(); > char *dec_point = l->decimal_point; > > instead of: > > #include langinfo.h > char *dec_point = nl_langinfo(__DECIMAL_POINT); > > I used langinfo because in linux libc it is considered > "The Elegant and Fast Way" of using locale and conforms with > X/Open portability guide that every modern Unix follows > (Solaris, Linux, latest FreeBSD). > > Regarding locale vs. \pset numericsep, for me it doesn't matter > which one is used. I consider the patch very usefull, and I think > that other guys that use psql daily for working with financial data > will appreciate it too. > > With a quick setting like \pset numericsep ',' all my numeric fields > will appear in easy readable form. I must underline that to_char is > a backend function and we talk here about a little psql feature which > makes life a little easier (for me at least). > -- 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: src/bin/psql/print.c === RCS file: /cvsroot/pgsql/src/bin/psql/print.c,v retrieving revision 1.63 diff -c -c -r1.63 print.c *** src/bin/psql/print.c10 Jul 2005 15:53:42 - 1.63 --- src/bin/psql/print.c14 Jul 2005 06:44:10 - *** *** 29,34 --- 29,48 #include "mbprint.h" + static void * + pg_local_malloc(size_t size) + { + void *tmp; + + tmp = malloc(size); + if (!tmp) + { + psql_error("out of memory\n"); + exit(EXIT_FAILURE); + } + return tmp; + } + static int num_numericseps(const char *my_str) { *** *** 46,51 --- 60,66 else return int_len / 3 - 1; /* no leading separator */ } + static int len_with_numericsep(const char *my_str) { *** *** 77,88 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++) { --- 92,98 if (digits_before_sep == 0) new_len--; /* no leading separator */ ! new_str = pg_local_malloc(new_len + 1); for (i=0, j=0; ; i++, j++) { *** *** 167,179 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); --- 177,184 if ((opt_align[i % col_count] == 'r') && strlen(*ptr) > 0 && opt_numericsep != NULL && strlen(opt_numericsep) > 0) { ! char *my_cell = pg_local_malloc(len_with_numericsep(*ptr) + 1); strcpy(my_cell, *ptr); format_numericsep(my_cell, opt_numericsep); fputs(my_cell, fout); *** *** 249,261 if ((opt_align[i % col_count] == 'r') && strlen(*ptr) != 0 && opt_numeri