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 <[email protected]>:
> 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 ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers