From 5ded4bd21403e143dd3eb66b92d52732fdac1945 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Wed, 29 Mar 2017 13:16:49 -0700 Subject: 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 --- doc/src/sgml/xfunc.sgml | 269 ++++++++++++------------------------------------ 1 file changed, 63 insertions(+), 206 deletions(-) (limited to 'doc/src') diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 94a7ad747da..e6313ddd59d 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1610,14 +1610,10 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision - Two different calling conventions are currently used for C functions. - The newer version 1 calling convention is indicated by writing - a PG_FUNCTION_INFO_V1() macro call for the function, - as illustrated below. Lack of such a macro indicates an old-style - (version 0) function. The language name specified in CREATE FUNCTION - is C 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 + (version 1). Support for that calling convention is + indicated by writing a PG_FUNCTION_INFO_V1() macro + call for the function, as illustrated below. @@ -2137,160 +2133,6 @@ memcpy(destination->data, buffer, 40); - - Version 0 Calling Conventions - - - We present the old style calling convention first — 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. - - - - Here are some examples: - - -#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; -} -]]> - - - - - Supposing that the above code has been prepared in file - funcs.c and compiled into a shared object, - we could define the functions to PostgreSQL - with commands like this: - - -CREATE FUNCTION add_one(integer) RETURNS integer - AS 'DIRECTORY/funcs', 'add_one' - LANGUAGE C STRICT; - --- note overloading of SQL function name "add_one" -CREATE FUNCTION add_one(double precision) RETURNS double precision - AS 'DIRECTORY/funcs', 'add_one_float8' - LANGUAGE C STRICT; - -CREATE FUNCTION makepoint(point, point) RETURNS point - AS 'DIRECTORY/funcs', 'makepoint' - LANGUAGE C STRICT; - -CREATE FUNCTION copytext(text) RETURNS text - AS 'DIRECTORY/funcs', 'copytext' - LANGUAGE C STRICT; - -CREATE FUNCTION concat_text(text, text) RETURNS text - AS 'DIRECTORY/funcs', 'concat_text' - LANGUAGE C STRICT; - - - - - Here, DIRECTORY stands for the - directory of the shared library file (for instance the - PostgreSQL tutorial directory, which - contains the code for the examples used in this section). - (Better style would be to use just 'funcs' in the - AS clause, after having added - DIRECTORY to the search path. In any - case, we can omit the system-specific extension for a shared - library, commonly .so or - .sl.) - - - - Notice that we have specified the functions as strict, - 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!) - - - - 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 int 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. - - - Version 1 Calling Conventions @@ -2316,8 +2158,10 @@ PG_FUNCTION_INFO_V1(funcname); In a version-1 function, each actual argument is fetched using a PG_GETARG_xxx() - 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 PG_ARGNULL_xxx(). + The result is returned using a PG_RETURN_xxx() macro for the return type. PG_GETARG_xxx() @@ -2328,7 +2172,7 @@ PG_FUNCTION_INFO_V1(funcname); - Here we show the same functions as above, coded in version-1 style: + Here are some examples using the version-1 calling convention: + + + Supposing that the above code has been prepared in file + funcs.c and compiled into a shared object, + we could define the functions to PostgreSQL + with commands like this: + + +CREATE FUNCTION add_one(integer) RETURNS integer + AS 'DIRECTORY/funcs', 'add_one' + LANGUAGE C STRICT; + +-- note overloading of SQL function name "add_one" +CREATE FUNCTION add_one(double precision) RETURNS double precision + AS 'DIRECTORY/funcs', 'add_one_float8' + LANGUAGE C STRICT; + +CREATE FUNCTION makepoint(point, point) RETURNS point + AS 'DIRECTORY/funcs', 'makepoint' + LANGUAGE C STRICT; + +CREATE FUNCTION copytext(text) RETURNS text + AS 'DIRECTORY/funcs', 'copytext' + LANGUAGE C STRICT; + +CREATE FUNCTION concat_text(text, text) RETURNS text + AS 'DIRECTORY/funcs', 'concat_text' + LANGUAGE C STRICT; + + + + Here, DIRECTORY stands for the + directory of the shared library file (for instance the + PostgreSQL tutorial directory, which + contains the code for the examples used in this section). + (Better style would be to use just 'funcs' in the + AS clause, after having added + DIRECTORY to the search path. In any + case, we can omit the system-specific extension for a shared + library, commonly .so.) - The CREATE FUNCTION commands are the same as - for the version-0 equivalents. + Notice that we have specified the functions as strict, + 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(). - 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 add_one_float8, we no longer need to - be aware that float8 is a pass-by-reference type. Another - example is that the GETARG macros for variable-length types allow - for more efficient fetching of toasted (compressed or + At first glance, the version-1 coding conventions might appear to be just + pointless obscurantism, over using plain C calling + conventions. They do however allow to deal with NULLable + arguments/return values, and toasted (compressed or out-of-line) values. - One big improvement in version-1 functions is better handling of null - inputs and results. The macro PG_ARGISNULL(n) + The macro PG_ARGISNULL(n) allows a function to test whether each input is null. (Of course, doing this is only necessary in functions not declared strict.) As with the @@ -2461,7 +2345,7 @@ concat_text(PG_FUNCTION_ARGS) - Other options provided in the new-style interface are two + Other options provided by the version-1 interface are two variants of the PG_GETARG_xxx() macros. The first of these, @@ -2493,9 +2377,7 @@ concat_text(PG_FUNCTION_ARGS) to return set results () and implement trigger functions () and procedural-language call handlers (). 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 src/backend/utils/fmgr/README in the source distribution. @@ -2630,7 +2512,7 @@ SELECT name, c_overpaid(emp, 1500) AS overpaid WHERE name = 'Bill' OR name = 'Sam'; - Using call conventions version 0, we can define + Using the version-1 calling conventions, we can define c_overpaid as: limit; -} -]]> - - - In version-1 coding, the above would look like this: - -