Pavel Stehule escribió: > Please, try to compile and run sprintf function from attachment
There's a minor bug in the comparison to PG_NARGS() inside the loop, fixed in this version. The one problem I have with this is that if the format string does not contain any % (and thus there is no extra argument), it errors out: alvherre=# select text_format('ouch'); ERROR: function text_format(unknown) does not exist LÍNEA 1: select text_format('ouch'); ^ SUGERENCIA: No function matches the given name and argument types. You might need to add explicit type casts. AFAICS fixing this would require a second pg_proc entry for this function. alvherre=# select text_format('% was % at % and said % % times', 'Pavel'::text, 'here'::unknown, now(), row('a','b','c'), '{42}'::int[]); text_format ----------------------------------------------------------------------------- Pavel was here at 2009-09-10 13:12:09.054653-04 and said (a,b,c) {42} times (1 fila) -- Alvaro Herrera http://www.CommandPrompt.com/ PostgreSQL Replication, Consulting, Custom Development, 24x7 support
Index: src/backend/utils/adt/varlena.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/utils/adt/varlena.c,v retrieving revision 1.172 diff -c -p -r1.172 varlena.c *** src/backend/utils/adt/varlena.c 4 Aug 2009 16:08:36 -0000 1.172 --- src/backend/utils/adt/varlena.c 10 Sep 2009 17:06:16 -0000 *************** text_position_cleanup(TextPositionState *** 1175,1180 **** --- 1175,1242 ---- } } + Datum + text_format(PG_FUNCTION_ARGS) + { + char *fmt = text_to_cstring(PG_GETARG_TEXT_P(0)); + StringInfo str; + char *cp; + int i = 1; + + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); + + str = makeStringInfo(); + + for (cp = fmt; *cp; cp++) + { + if (cp[0] == '%') + { + if (cp[1] == '%') + { + appendStringInfoChar(str, cp[1]); + cp++; + continue; + } + + if (i >= PG_NARGS()) + ereport(ERROR, + (errmsg("too few parameters specified for the format string"))); + + if (PG_ARGISNULL(i)) + { + appendStringInfoString(str, "NULL"); + } + else + { + Oid valtype; + Datum value; + Oid typoutput; + bool typIsVarlena; + + /* append n-th value */ + value = PG_GETARG_DATUM(i); + valtype = get_fn_expr_argtype(fcinfo->flinfo, i); + + getTypeOutputInfo(valtype, &typoutput, &typIsVarlena); + appendStringInfoString(str, OidOutputFunctionCall(typoutput, value)); + } + i++; + } + else + appendStringInfoChar(str, cp[0]); + } + + if (i != PG_NARGS()) + ereport(ERROR, + (errmsg("too many parameters for the format string"))); + + pfree(fmt); + + PG_RETURN_TEXT_P(CStringGetTextDatum(str->data)); + } + + /* varstr_cmp() * Comparison function for text strings with given lengths. * Includes locale support, but must copy strings to temporary memory Index: src/include/catalog/pg_proc.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/include/catalog/pg_proc.h,v retrieving revision 1.550 diff -c -p -r1.550 pg_proc.h *** src/include/catalog/pg_proc.h 1 Sep 2009 02:54:52 -0000 1.550 --- src/include/catalog/pg_proc.h 10 Sep 2009 16:52:48 -0000 *************** DATA(insert OID = 1257 ( textlen PG *** 214,219 **** --- 214,221 ---- DESCR("length"); DATA(insert OID = 1258 ( textcat PGNSP PGUID 12 1 0 0 f f f t f i 2 0 25 "25 25" _null_ _null_ _null_ _null_ textcat _null_ _null_ _null_ )); DESCR("concatenate"); + DATA(insert OID = 1259 ( text_format PGNSP PGUID 12 1 0 2276 f f f t f i 2 0 25 "25 2276" "{25,2276}" "{i,v}" _null_ _null_ text_format _null_ _null_ _null_ )); + DESCR("format arguments, sprintf-style"); DATA(insert OID = 84 ( boolne PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "16 16" _null_ _null_ _null_ _null_ boolne _null_ _null_ _null_ )); DESCR("not equal"); Index: src/include/utils/builtins.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/include/utils/builtins.h,v retrieving revision 1.339 diff -c -p -r1.339 builtins.h *** src/include/utils/builtins.h 9 Sep 2009 19:00:09 -0000 1.339 --- src/include/utils/builtins.h 10 Sep 2009 16:35:34 -0000 *************** extern Datum text_substr(PG_FUNCTION_ARG *** 698,703 **** --- 698,704 ---- extern Datum text_substr_no_len(PG_FUNCTION_ARGS); extern Datum name_text(PG_FUNCTION_ARGS); extern Datum text_name(PG_FUNCTION_ARGS); + extern Datum text_format(PG_FUNCTION_ARGS); extern int varstr_cmp(char *arg1, int len1, char *arg2, int len2); extern List *textToQualifiedNameList(text *textval); extern bool SplitIdentifierString(char *rawstring, char separator,
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers