> 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.



Reply via email to