> On 9 Oct 2024, at 2:57 PM, Pavel Stehule <pavel.steh...@gmail.com> wrote: > > Hi > > I am checking this patch > > čt 12. 9. 2024 v 11:42 odesílatel Florents Tselai <florents.tse...@gmail.com > <mailto:florents.tse...@gmail.com>> napsal: >> Hi, >> >> The documentation on extending using C functions, >> leaves a blank on how to call other internal Postgres functions. >> This can leave first-timers hanging. >> >> I think it’d be helpful to spend some paragraphs on discussing the >> DirectFunctionCall API. >> >> Here’s an attempt (also a PR[0]). >> >> Here’s the relevant HTML snippet for convenience: >> To call another version-1 function, you can use DirectFunctionCalln(func, >> arg1,...,argn). This is particularly useful when you want to call functions >> defined in the standard internal library, by using an interface similar to >> their SQL signature. >> >> Different flavors of similar macros can be found in fmgr.h. The main point >> though is that they expect a C function name to call as their first argument >> (or its Oid in some cases), and actual arguments should be supplied as >> Datums. They always return Datum. >> >> For example, to call the starts_with(text, text) from C, you can search >> through the catalog and find out that its C implementation is based on the >> Datum text_starts_with(PG_FUNCTION_ARGS) function. >> >> In fmgr.h there are also available macros the facilitate conversions between >> C types and Datum. For example to turn text* into Datum, you can use >> DatumGetTextPP(X). If your extension defines additional types, it is usually >> convenient to define similar macros for these types too. >> >> I’ve also added the below example function: >> >> PG_FUNCTION_INFO_V1(t_starts_with); >> >> Datum >> t_starts_with(PG_FUNCTION_ARGS) >> { >> Datum t1 = PG_GETARG_DATUM(0); >> Datum t2 = PG_GETARG_DATUM(1); >> bool bool_res; >> >> Datum datum_res = DirectFunctionCall2(text_starts_with, t1, t2); >> bool_res = DatumGetBool(datum_res); >> >> PG_RETURN_BOOL(bool_res); >> } >> PS1: I was not sure if src/tutorial is still relevant with this part of the >> documentation. >> If so, it needs updating too. >> > > I have few points > > 1. I am missing warning so NULL is not supported by DirectFunctionCall - on > input and on output. Any argument should not be null, and the result should > not be null.
You’re right. > > 2. The example looks little bit not consistent > > I propose > > Text *t1 = PG_GETARG_TEXT_PP(0); > Text *t2 = PG_GETARG_TEXT_PP(1); > bool result; > > result = DatumGetBool( > DirectFunctionCall2(text_starts_with, > PointerGetDatum(t1), > PointerGetDatum(t2)); > > PG_RETURN_BOOL(result); > > > or > > Datum t1 = PG_GETARG_DATUM(0); > Datum t2 = PG_GETARG_DATUM(1); > Datum result; > > result = DirectFunctionCall2(text_starts_with, t1, t2); > > PG_RETURN_DATUM(result); > > Both examples can show some interesting patterns (maybe can be used both) The example can be extended a bit more. I like your first proposal. My primary purpose with this patch is to show explicitly how one goes from SQL types, to Datum and/or char*/text if necessary, use some internal C function (even if it doesn’t have an SQL equivalent). and then return back an SQL type. So, simply GET_ARG_DATUM() and then PG_RETURN_DATUM() defeats the purpose.