1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Remove support for version-0 calling conventions.

The V0 convention is failure prone because we've so far assumed that a
function is V0 if PG_FUNCTION_INFO_V1 is missing, leading to crashes
if a function was coded against the V1 interface.  V0 doesn't allow
proper NULL, SRF and toast handling.  V0 doesn't offer features that
V1 doesn't.

Thus remove V0 support and obsolete fmgr README contents relating to
it.

Author: Andres Freund, with contributions by Peter Eisentraut & Craig Ringer
Reviewed-By: Peter Eisentraut, Craig Ringer
Discussion: https://postgr.es/m/20161208213441.k3mbno4twhg2qf7g@alap3.anarazel.de
This commit is contained in:
Andres Freund
2017-03-29 13:16:49 -07:00
parent 389bb2818f
commit 5ded4bd214
10 changed files with 104 additions and 909 deletions

View File

@ -1610,14 +1610,10 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision
</para>
<para>
Two different calling conventions are currently used for C functions.
The newer <quote>version 1</quote> calling convention is indicated by writing
a <literal>PG_FUNCTION_INFO_V1()</literal> macro call for the function,
as illustrated below. Lack of such a macro indicates an old-style
(<quote>version 0</quote>) function. The language name specified in <command>CREATE FUNCTION</command>
is <literal>C</literal> in either case. Old-style functions are now deprecated
because of portability problems and lack of functionality, but they
are still supported for compatibility reasons.
Currently only one calling convention is used for C functions
(<quote>version 1</quote>). Support for that calling convention is
indicated by writing a <literal>PG_FUNCTION_INFO_V1()</literal> macro
call for the function, as illustrated below.
</para>
<sect2 id="xfunc-c-dynload">
@ -2137,160 +2133,6 @@ memcpy(destination->data, buffer, 40);
</para>
</sect2>
<sect2>
<title>Version 0 Calling Conventions</title>
<para>
We present the <quote>old style</quote> calling convention first &mdash; although
this approach is now deprecated, it's easier to get a handle on
initially. In the version-0 method, the arguments and result
of the C function are just declared in normal C style, but being
careful to use the C representation of each SQL data type as shown
above.
</para>
<para>
Here are some examples:
<programlisting><![CDATA[
#include "postgres.h"
#include <string.h>
#include "utils/geo_decls.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
/* by value */
int
add_one(int arg)
{
return arg + 1;
}
/* by reference, fixed length */
float8 *
add_one_float8(float8 *arg)
{
float8 *result = (float8 *) palloc(sizeof(float8));
*result = *arg + 1.0;
return result;
}
Point *
makepoint(Point *pointx, Point *pointy)
{
Point *new_point = (Point *) palloc(sizeof(Point));
new_point->x = pointx->x;
new_point->y = pointy->y;
return new_point;
}
/* by reference, variable length */
text *
copytext(text *t)
{
/*
* VARSIZE is the total size of the struct in bytes.
*/
text *new_t = (text *) palloc(VARSIZE(t));
SET_VARSIZE(new_t, VARSIZE(t));
/*
* VARDATA is a pointer to the data region of the struct.
*/
memcpy((void *) VARDATA(new_t), /* destination */
(void *) VARDATA(t), /* source */
VARSIZE(t) - VARHDRSZ); /* how many bytes */
return new_t;
}
text *
concat_text(text *arg1, text *arg2)
{
int32 new_text_size = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ;
text *new_text = (text *) palloc(new_text_size);
SET_VARSIZE(new_text, new_text_size);
memcpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1) - VARHDRSZ);
memcpy(VARDATA(new_text) + (VARSIZE(arg1) - VARHDRSZ),
VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
return new_text;
}
]]>
</programlisting>
</para>
<para>
Supposing that the above code has been prepared in file
<filename>funcs.c</filename> and compiled into a shared object,
we could define the functions to <productname>PostgreSQL</productname>
with commands like this:
<programlisting>
CREATE FUNCTION add_one(integer) RETURNS integer
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'add_one'
LANGUAGE C STRICT;
-- note overloading of SQL function name "add_one"
CREATE FUNCTION add_one(double precision) RETURNS double precision
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'add_one_float8'
LANGUAGE C STRICT;
CREATE FUNCTION makepoint(point, point) RETURNS point
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'makepoint'
LANGUAGE C STRICT;
CREATE FUNCTION copytext(text) RETURNS text
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'copytext'
LANGUAGE C STRICT;
CREATE FUNCTION concat_text(text, text) RETURNS text
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'concat_text'
LANGUAGE C STRICT;
</programlisting>
</para>
<para>
Here, <replaceable>DIRECTORY</replaceable> stands for the
directory of the shared library file (for instance the
<productname>PostgreSQL</productname> tutorial directory, which
contains the code for the examples used in this section).
(Better style would be to use just <literal>'funcs'</> in the
<literal>AS</> clause, after having added
<replaceable>DIRECTORY</replaceable> to the search path. In any
case, we can omit the system-specific extension for a shared
library, commonly <literal>.so</literal> or
<literal>.sl</literal>.)
</para>
<para>
Notice that we have specified the functions as <quote>strict</quote>,
meaning that
the system should automatically assume a null result if any input
value is null. By doing this, we avoid having to check for null inputs
in the function code. Without this, we'd have to check for null values
explicitly, by checking for a null pointer for each
pass-by-reference argument. (For pass-by-value arguments, we don't
even have a way to check!)
</para>
<para>
Although this calling convention is simple to use,
it is not very portable; on some architectures there are problems
with passing data types that are smaller than <type>int</type> this way. Also, there is
no simple way to return a null result, nor to cope with null arguments
in any way other than making the function strict. The version-1
convention, presented next, overcomes these objections.
</para>
</sect2>
<sect2>
<title>Version 1 Calling Conventions</title>
@ -2316,8 +2158,10 @@ PG_FUNCTION_INFO_V1(funcname);
<para>
In a version-1 function, each actual argument is fetched using a
<function>PG_GETARG_<replaceable>xxx</replaceable>()</function>
macro that corresponds to the argument's data type, and the
result is returned using a
macro that corresponds to the argument's data type. In non-strict
functions there needs to be a previous check about argument null-ness
using <function>PG_ARGNULL_<replaceable>xxx</replaceable>()</function>.
The result is returned using a
<function>PG_RETURN_<replaceable>xxx</replaceable>()</function>
macro for the return type.
<function>PG_GETARG_<replaceable>xxx</replaceable>()</function>
@ -2328,7 +2172,7 @@ PG_FUNCTION_INFO_V1(funcname);
</para>
<para>
Here we show the same functions as above, coded in version-1 style:
Here are some examples using the version-1 calling convention:
<programlisting><![CDATA[
#include "postgres.h"
@ -2427,27 +2271,67 @@ concat_text(PG_FUNCTION_ARGS)
}
]]>
</programlisting>
<para>
Supposing that the above code has been prepared in file
<filename>funcs.c</filename> and compiled into a shared object,
we could define the functions to <productname>PostgreSQL</productname>
with commands like this:
<programlisting>
CREATE FUNCTION add_one(integer) RETURNS integer
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'add_one'
LANGUAGE C STRICT;
-- note overloading of SQL function name "add_one"
CREATE FUNCTION add_one(double precision) RETURNS double precision
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'add_one_float8'
LANGUAGE C STRICT;
CREATE FUNCTION makepoint(point, point) RETURNS point
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'makepoint'
LANGUAGE C STRICT;
CREATE FUNCTION copytext(text) RETURNS text
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'copytext'
LANGUAGE C STRICT;
CREATE FUNCTION concat_text(text, text) RETURNS text
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'concat_text'
LANGUAGE C STRICT;
</programlisting>
<para>
Here, <replaceable>DIRECTORY</replaceable> stands for the
directory of the shared library file (for instance the
<productname>PostgreSQL</productname> tutorial directory, which
contains the code for the examples used in this section).
(Better style would be to use just <literal>'funcs'</> in the
<literal>AS</> clause, after having added
<replaceable>DIRECTORY</replaceable> to the search path. In any
case, we can omit the system-specific extension for a shared
library, commonly <literal>.so</literal>.)
</para>
<para>
The <command>CREATE FUNCTION</command> commands are the same as
for the version-0 equivalents.
Notice that we have specified the functions as <quote>strict</quote>,
meaning that
the system should automatically assume a null result if any input
value is null. By doing this, we avoid having to check for null inputs
in the function code. Without this, we'd have to check for null values
explicitly, using PG_ARGISNULL().
</para>
<para>
At first glance, the version-1 coding conventions might appear to
be just pointless obscurantism. They do, however, offer a number
of improvements, because the macros can hide unnecessary detail.
An example is that in coding <function>add_one_float8</>, we no longer need to
be aware that <type>float8</type> is a pass-by-reference type. Another
example is that the <literal>GETARG</> macros for variable-length types allow
for more efficient fetching of <quote>toasted</quote> (compressed or
At first glance, the version-1 coding conventions might appear to be just
pointless obscurantism, over using plain <literal>C</> calling
conventions. They do however allow to deal with <literal>NULL</>able
arguments/return values, and <quote>toasted</quote> (compressed or
out-of-line) values.
</para>
<para>
One big improvement in version-1 functions is better handling of null
inputs and results. The macro <function>PG_ARGISNULL(<replaceable>n</>)</function>
The macro <function>PG_ARGISNULL(<replaceable>n</>)</function>
allows a function to test whether each input is null. (Of course, doing
this is only necessary in functions not declared <quote>strict</>.)
As with the
@ -2461,7 +2345,7 @@ concat_text(PG_FUNCTION_ARGS)
</para>
<para>
Other options provided in the new-style interface are two
Other options provided by the version-1 interface are two
variants of the
<function>PG_GETARG_<replaceable>xxx</replaceable>()</function>
macros. The first of these,
@ -2493,9 +2377,7 @@ concat_text(PG_FUNCTION_ARGS)
to return set results (<xref linkend="xfunc-c-return-set">) and
implement trigger functions (<xref linkend="triggers">) and
procedural-language call handlers (<xref
linkend="plhandler">). Version-1 code is also more
portable than version-0, because it does not break restrictions
on function call protocol in the C standard. For more details
linkend="plhandler">). For more details
see <filename>src/backend/utils/fmgr/README</filename> in the
source distribution.
</para>
@ -2630,7 +2512,7 @@ SELECT name, c_overpaid(emp, 1500) AS overpaid
WHERE name = 'Bill' OR name = 'Sam';
</programlisting>
Using call conventions version 0, we can define
Using the version-1 calling conventions, we can define
<function>c_overpaid</> as:
<programlisting><![CDATA[
@ -2641,31 +2523,6 @@ SELECT name, c_overpaid(emp, 1500) AS overpaid
PG_MODULE_MAGIC;
#endif
bool
c_overpaid(HeapTupleHeader t, /* the current row of emp */
int32 limit)
{
bool isnull;
int32 salary;
salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull));
if (isnull)
return false;
return salary > limit;
}
]]>
</programlisting>
In version-1 coding, the above would look like this:
<programlisting><![CDATA[
#include "postgres.h"
#include "executor/executor.h" /* for GetAttributeByName() */
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(c_overpaid);
Datum