There is actualised version, for people who are interested on it. Minimally it should be sample of variadic "any" function for playing. Don't afraid, I don't plan to send it to commit fest.
regards Pavel 2009/9/10 Alvaro Herrera <alvhe...@commandprompt.com>: > 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 >
*** ./src/backend/utils/adt/varlena.c.orig 2009-09-10 18:10:05.243689073 +0200 --- ./src/backend/utils/adt/varlena.c 2009-09-10 22:00:53.594689873 +0200 *************** *** 3143,3145 **** --- 3143,3228 ---- PG_RETURN_INT32(result); } + + /* + * Format message - replace char % by parameter value + * + */ + Datum + pg_format_variadic(PG_FUNCTION_ARGS) + { + text *fmt; + StringInfo str; + char *cp; + int i = 1; + size_t len; + char *start_ptr, + *end_ptr; + + /* When format string is null, returns null */ + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); + + fmt = PG_GETARG_TEXT_PP(0); + str = makeStringInfo(); + len = VARSIZE_ANY_EXHDR(fmt); + start_ptr = VARDATA_ANY(fmt); + end_ptr = start_ptr + len - 1; + + for (cp = start_ptr; cp <= end_ptr; cp++) + { + if (cp[0] == '%') + { + Oid valtype; + Datum value; + Oid typoutput; + bool typIsVarlena; + + /* when cp is not pointer on last char, check %% */ + if (cp < end_ptr && cp[1] == '%') + { + appendStringInfoChar(str, cp[1]); + cp++; + continue; + } + + if (i >= PG_NARGS()) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("too few parameters"))); + + if (!PG_ARGISNULL(i)) + { + /* 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)); + } + else + appendStringInfoString(str, "NULL"); + i++; + } + else + appendStringInfoChar(str, cp[0]); + } + + /* check if all arguments are used */ + if (i != PG_NARGS()) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("too much parameters"))); + + PG_RETURN_TEXT_P(CStringGetTextDatum(str->data)); + } + + /* + * One parameter Format function - only wrapper + * We have to call variadic function, because we would to check format string. + */ + Datum + pg_format(PG_FUNCTION_ARGS) + { + return pg_format_variadic(fcinfo); + } *** ./src/include/catalog/pg_proc.h.orig 2009-09-10 20:07:24.288690736 +0200 --- ./src/include/catalog/pg_proc.h 2009-09-10 21:47:35.533684577 +0200 *************** *** 2679,2684 **** --- 2679,2689 ---- DATA(insert OID = 1768 ( to_char PGNSP PGUID 12 1 0 0 f f f t f s 2 0 25 "1186 25" _null_ _null_ _null_ _null_ interval_to_char _null_ _null_ _null_ )); DESCR("format interval to text"); + DATA(insert OID = 2336 ( format PGNSP PGUID 12 1 0 0 f f f t f s 1 0 25 "25" _null_ _null_ _null_ _null_ pg_format _null_ _null_ _null_ )); + DESCR("format message"); + DATA(insert OID = 2337 ( format PGNSP PGUID 12 1 0 2276 f f f t f s 2 0 25 "25 2276" "{25,2276}" "{i,v}" _null_ _null_ pg_format_variadic _null_ _null_ _null_ )); + DESCR("format message"); + DATA(insert OID = 1282 ( quote_ident PGNSP PGUID 12 1 0 0 f f f t f i 1 0 25 "25" _null_ _null_ _null_ _null_ quote_ident _null_ _null_ _null_ )); DESCR("quote an identifier for usage in a querystring"); DATA(insert OID = 1283 ( quote_literal PGNSP PGUID 12 1 0 0 f f f t f i 1 0 25 "25" _null_ _null_ _null_ _null_ quote_literal _null_ _null_ _null_ )); *** ./src/include/utils/builtins.h.orig 2009-09-10 19:06:12.706686814 +0200 --- ./src/include/utils/builtins.h 2009-09-10 19:07:29.538687017 +0200 *************** *** 712,717 **** --- 712,719 ---- extern Datum to_hex64(PG_FUNCTION_ARGS); extern Datum md5_text(PG_FUNCTION_ARGS); extern Datum md5_bytea(PG_FUNCTION_ARGS); + extern Datum pg_format_variadic(PG_FUNCTION_ARGS); + extern Datum pg_format(PG_FUNCTION_ARGS); extern Datum unknownin(PG_FUNCTION_ARGS); extern Datum unknownout(PG_FUNCTION_ARGS);
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers