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