public inbox for [email protected]
help / color / mirror / Atom feedFrom: Florents Tselai <[email protected]>
To: PostgreSQL Hackers <[email protected]>
Subject: [PATCH] Add some documentation on how to call internal functions
Date: Thu, 12 Sep 2024 12:41:42 +0300
Message-ID: <[email protected]> (raw)
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.
[0] https://github.com/Florents-Tselai/postgres/pull/1/commits/1651b7bb68e0f9c2b61e1462367295d846d253ec

Attachments:
[application/octet-stream] 0001-Add-some-documentation-on-how-to-call-internal-funct.patch (3.1K, ../[email protected]/3-0001-Add-some-documentation-on-how-to-call-internal-funct.patch)
download | inline diff:
From 1651b7bb68e0f9c2b61e1462367295d846d253ec Mon Sep 17 00:00:00 2001
From: Florents Tselai <[email protected]>
Date: Thu, 12 Sep 2024 12:23:13 +0300
Subject: [PATCH] Add some documentation on how to call internal functions
---
doc/src/sgml/xfunc.sgml | 51 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index af7864a1b5..eb26120def 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -2384,6 +2384,36 @@ PG_FUNCTION_INFO_V1(funcname);
takes as its argument the actual value to return.
</para>
+ <para>
+ To call another version-1 function, you can use
+ <function>DirectFunctionCall<replaceable>n</replaceable>(func, arg1,...,argn)</function>.
+ 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.
+ </para>
+
+ <para>
+ Different flavors of similar macros can be found in <filename>fmgr.h</filename>.
+ The main point though is that they expect a C function name to call as their first argument
+ (or its <literal>Oid</literal> in some cases),
+ and actual arguments should be supplied as <literal>Datum</literal>s.
+ They always return <literal>Datum</literal>.
+ </para>
+
+ <para>
+ For example, to call the <function>starts_with(text, text) </function> from C,
+ you can search through the catalog and find out that its C implementation is based on the
+ <function>Datum text_starts_with(PG_FUNCTION_ARGS)</function> function.
+ </para>
+
+ <para>
+ In <filename>fmgr.h</filename> there are also available macros the facilitate conversions
+ between C types and <literal>Datum</literal>.
+ For example to turn <literal>text*</literal> into <literal>Datum</literal>,
+ you can use <function>DatumGetTextPP(X)</function>.
+ If your extension defines additional types,
+ it is usually convenient to define similar macros for these types too.
+ </para>
+
<para>
Here are some examples using the version-1 calling convention:
</para>
@@ -2482,6 +2512,23 @@ concat_text(PG_FUNCTION_ARGS)
memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);
PG_RETURN_TEXT_P(new_text);
}
+
+/* A wrapper around starts_with(text, text) */
+
+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);
+}
]]>
</programlisting>
@@ -2513,6 +2560,10 @@ CREATE FUNCTION copytext(text) RETURNS text
CREATE FUNCTION concat_text(text, text) RETURNS text
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'concat_text'
LANGUAGE C STRICT;
+
+CREATE FUNCTION t_starts_with(text, text) RETURNS boolean
+ AS '<replaceable>DIRECTORY</replaceable>/funcs', 't_starts_with'
+ LANGUAGE C STRICT;
</programlisting>
<para>
--
2.39.3 (Apple Git-146)
view thread (2+ messages)
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: [PATCH] Add some documentation on how to call internal functions
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox