mirror of
https://github.com/postgres/postgres.git
synced 2025-06-29 10:41:53 +03:00
Add documentation about calling version-1 C functions from C.
This topic wasn't really covered before, so fill in some details. Author: Florents Tselai <florents.tselai@gmail.com> Reviewed-by: Pavel Stehule <pavel.stehule@gmail.com> Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/90853055-5BBD-493D-91E5-721677C7C59B@gmail.com
This commit is contained in:
@ -2384,6 +2384,56 @@ PG_FUNCTION_INFO_V1(funcname);
|
|||||||
takes as its argument the actual value to return.
|
takes as its argument the actual value to return.
|
||||||
</para>
|
</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>
|
||||||
|
These convenience functions and similar ones can be found
|
||||||
|
in <filename>fmgr.h</filename>.
|
||||||
|
The <function>DirectFunctionCall<replaceable>n</replaceable></function>
|
||||||
|
family expect a C function name as their first argument. There are also
|
||||||
|
<function>OidFunctionCall<replaceable>n</replaceable></function> which
|
||||||
|
take the OID of the target function, and some other variants. All of
|
||||||
|
these expect the function's arguments to be supplied
|
||||||
|
as <type>Datum</type>s, and likewise they return <type>Datum</type>.
|
||||||
|
Note that neither arguments nor result are allowed to be NULL when
|
||||||
|
using these convenience functions.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For example, to call the <function>starts_with(text, text)</function>
|
||||||
|
function from C, you can search through the catalog and find out that
|
||||||
|
its C implementation is the
|
||||||
|
<function>Datum text_starts_with(PG_FUNCTION_ARGS)</function>
|
||||||
|
function. Typically you would
|
||||||
|
use <literal>DirectFunctionCall2(text_starts_with, ...)</literal> to
|
||||||
|
call such a function. However, <function>starts_with(text,
|
||||||
|
text)</function> requires collation information, so it will fail
|
||||||
|
with <quote>could not determine which collation to use for string
|
||||||
|
comparison</quote> if called that way. Instead you must
|
||||||
|
use <literal>DirectFunctionCall2Coll(text_starts_with, ...)</literal>
|
||||||
|
and provide the desired collation, which typically is just passed
|
||||||
|
through from <function>PG_GET_COLLATION()</function>, as shown in the
|
||||||
|
example below.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<filename>fmgr.h</filename> also supplies macros that facilitate
|
||||||
|
conversions between C types and <type>Datum</type>. For example to
|
||||||
|
turn <type>Datum</type> into <type>text*</type>, you can
|
||||||
|
use <function>DatumGetTextPP(X)</function>. While some types have macros
|
||||||
|
named like <function>TypeGetDatum(X)</function> for the reverse
|
||||||
|
conversion, <type>text*</type> does not; it's sufficient to use the
|
||||||
|
generic macro <function>PointerGetDatum(X)</function> for that.
|
||||||
|
If your extension defines additional types, it is usually convenient to
|
||||||
|
define similar macros for your types too.
|
||||||
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Here are some examples using the version-1 calling convention:
|
Here are some examples using the version-1 calling convention:
|
||||||
</para>
|
</para>
|
||||||
@ -2482,6 +2532,25 @@ concat_text(PG_FUNCTION_ARGS)
|
|||||||
memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);
|
memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);
|
||||||
PG_RETURN_TEXT_P(new_text);
|
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)
|
||||||
|
{
|
||||||
|
text *t1 = PG_GETARG_TEXT_PP(0);
|
||||||
|
text *t2 = PG_GETARG_TEXT_PP(1);
|
||||||
|
Oid collid = PG_GET_COLLATION();
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
result = DatumGetBool(DirectFunctionCall2Coll(text_starts_with,
|
||||||
|
collid,
|
||||||
|
PointerGetDatum(t1),
|
||||||
|
PointerGetDatum(t2)));
|
||||||
|
PG_RETURN_BOOL(result);
|
||||||
|
}
|
||||||
]]>
|
]]>
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
@ -2513,6 +2582,10 @@ CREATE FUNCTION copytext(text) RETURNS text
|
|||||||
CREATE FUNCTION concat_text(text, text) RETURNS text
|
CREATE FUNCTION concat_text(text, text) RETURNS text
|
||||||
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'concat_text'
|
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'concat_text'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION t_starts_with(text, text) RETURNS boolean
|
||||||
|
AS '<replaceable>DIRECTORY</replaceable>/funcs', 't_starts_with'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "postgres.h" /* general Postgres declarations */
|
#include "postgres.h" /* general Postgres declarations */
|
||||||
|
|
||||||
#include "executor/executor.h" /* for GetAttributeByName() */
|
#include "executor/executor.h" /* for GetAttributeByName() */
|
||||||
|
#include "utils/fmgrprotos.h" /* for text_starts_with() */
|
||||||
#include "utils/geo_decls.h" /* for point type */
|
#include "utils/geo_decls.h" /* for point type */
|
||||||
|
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
@ -102,6 +103,25 @@ concat_text(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_TEXT_P(new_text);
|
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)
|
||||||
|
{
|
||||||
|
text *t1 = PG_GETARG_TEXT_PP(0);
|
||||||
|
text *t2 = PG_GETARG_TEXT_PP(1);
|
||||||
|
Oid collid = PG_GET_COLLATION();
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
result = DatumGetBool(DirectFunctionCall2Coll(text_starts_with,
|
||||||
|
collid,
|
||||||
|
PointerGetDatum(t1),
|
||||||
|
PointerGetDatum(t2)));
|
||||||
|
PG_RETURN_BOOL(result);
|
||||||
|
}
|
||||||
|
|
||||||
/* Composite types */
|
/* Composite types */
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(c_overpaid);
|
PG_FUNCTION_INFO_V1(c_overpaid);
|
||||||
|
@ -123,16 +123,25 @@ SELECT * FROM EMP;
|
|||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
CREATE FUNCTION add_one(integer) RETURNS integer
|
CREATE FUNCTION add_one(integer) RETURNS integer
|
||||||
AS '_OBJWD_/funcs' LANGUAGE C;
|
AS '_OBJWD_/funcs' LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION add_one(double precision) RETURNS double precision
|
||||||
|
AS '_OBJWD_/funcs' LANGUAGE C STRICT;
|
||||||
|
|
||||||
CREATE FUNCTION makepoint(point, point) RETURNS point
|
CREATE FUNCTION makepoint(point, point) RETURNS point
|
||||||
AS '_OBJWD_/funcs' LANGUAGE C;
|
AS '_OBJWD_/funcs' LANGUAGE C STRICT;
|
||||||
|
|
||||||
CREATE FUNCTION copytext(text) RETURNS text
|
CREATE FUNCTION copytext(text) RETURNS text
|
||||||
AS '_OBJWD_/funcs' LANGUAGE C;
|
AS '_OBJWD_/funcs' LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION concat_text(text, text) RETURNS text
|
||||||
|
AS '_OBJWD_/funcs' LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION t_starts_with(text, text) RETURNS boolean
|
||||||
|
AS '_OBJWD_/funcs' LANGUAGE C STRICT;
|
||||||
|
|
||||||
CREATE FUNCTION c_overpaid(EMP, integer) RETURNS boolean
|
CREATE FUNCTION c_overpaid(EMP, integer) RETURNS boolean
|
||||||
AS '_OBJWD_/funcs' LANGUAGE C;
|
AS '_OBJWD_/funcs' LANGUAGE C STRICT;
|
||||||
|
|
||||||
SELECT add_one(3) AS four;
|
SELECT add_one(3) AS four;
|
||||||
|
|
||||||
@ -140,6 +149,8 @@ SELECT makepoint('(1,2)'::point, '(3,4)'::point ) AS newpoint;
|
|||||||
|
|
||||||
SELECT copytext('hello world!');
|
SELECT copytext('hello world!');
|
||||||
|
|
||||||
|
SELECT t_starts_with('foobar', 'foo');
|
||||||
|
|
||||||
SELECT name, c_overpaid(EMP, 1500) AS overpaid
|
SELECT name, c_overpaid(EMP, 1500) AS overpaid
|
||||||
FROM EMP
|
FROM EMP
|
||||||
WHERE name = 'Bill' or name = 'Sam';
|
WHERE name = 'Bill' or name = 'Sam';
|
||||||
@ -147,10 +158,13 @@ WHERE name = 'Bill' or name = 'Sam';
|
|||||||
-- remove functions that were created in this file
|
-- remove functions that were created in this file
|
||||||
|
|
||||||
DROP FUNCTION c_overpaid(EMP, integer);
|
DROP FUNCTION c_overpaid(EMP, integer);
|
||||||
|
DROP FUNCTION t_starts_with(text, text);
|
||||||
|
DROP FUNCTION concat_text(text, text);
|
||||||
DROP FUNCTION copytext(text);
|
DROP FUNCTION copytext(text);
|
||||||
DROP FUNCTION makepoint(point, point);
|
DROP FUNCTION makepoint(point, point);
|
||||||
|
DROP FUNCTION add_one(double precision);
|
||||||
DROP FUNCTION add_one(integer);
|
DROP FUNCTION add_one(integer);
|
||||||
--DROP FUNCTION clean_EMP();
|
DROP FUNCTION clean_EMP();
|
||||||
DROP FUNCTION high_pay();
|
DROP FUNCTION high_pay();
|
||||||
DROP FUNCTION new_emp();
|
DROP FUNCTION new_emp();
|
||||||
DROP FUNCTION add_em(integer, integer);
|
DROP FUNCTION add_em(integer, integer);
|
||||||
|
Reference in New Issue
Block a user