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

Reply via email to