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,
