Commit 5bb2300b authored by Tom Lane's avatar Tom Lane

Revise handling of oldstyle/newstyle functions per recent discussions

in pghackers list.  Support for oldstyle internal functions is gone
(no longer needed, since conversion is complete) and pg_language entry
'internal' now implies newstyle call convention.  pg_language entry
'newC' is gone; both old and newstyle dynamically loaded C functions
are now called language 'C'.  A newstyle function must be identified
by an associated info routine.  See src/backend/utils/fmgr/README.
parent 99198ac6
...@@ -57,7 +57,7 @@ sub-string will fit. ...@@ -57,7 +57,7 @@ sub-string will fit.
The create the function that contains the trigger:: The create the function that contains the trigger::
create function fti() returns opaque as create function fti() returns opaque as
'/path/to/fti.so' language 'newC'; '/path/to/fti.so' language 'C';
And finally define the trigger on the 'cds' table: And finally define the trigger on the 'cds' table:
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
Example: Example:
create function fti() returns opaque as create function fti() returns opaque as
'/home/boekhold/src/postgresql-6.2/contrib/fti/fti.so' language 'newC'; '/home/boekhold/src/postgresql-6.2/contrib/fti/fti.so' language 'C';
create table title_fti (string varchar(25), id oid); create table title_fti (string varchar(25), id oid);
create index title_fti_idx on title_fti (string); create index title_fti_idx on title_fti (string);
...@@ -93,6 +93,8 @@ static int nDeletePlans = 0; ...@@ -93,6 +93,8 @@ static int nDeletePlans = 0;
static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans); static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
/***********************************************************************/ /***********************************************************************/
PG_FUNCTION_INFO_V1(fti);
Datum Datum
fti(PG_FUNCTION_ARGS) fti(PG_FUNCTION_ARGS)
{ {
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
# #
# create function fti() returns opaque as # create function fti() returns opaque as
# '/path/to/fti/file/fti.so' # '/path/to/fti/file/fti.so'
# language 'newC'; # language 'C';
# #
# create trigger my_fti_trigger after update or insert or delete # create trigger my_fti_trigger after update or insert or delete
# on mytable # on mytable
......
create function fti() returns opaque as create function fti() returns opaque as
'MODULE_PATHNAME' 'MODULE_PATHNAME'
language 'newC'; language 'C';
\ No newline at end of file \ No newline at end of file
/* /*
* PostgreSQL type definitions for managed LargeObjects. * PostgreSQL type definitions for managed LargeObjects.
* *
* $Id: lo.c,v 1.4 2000/06/09 01:10:58 tgl Exp $ * $Id: lo.c,v 1.5 2000/11/20 20:36:55 tgl Exp $
* *
*/ */
...@@ -140,6 +140,8 @@ lo(Oid oid) ...@@ -140,6 +140,8 @@ lo(Oid oid)
/* /*
* This handles the trigger that protects us from orphaned large objects * This handles the trigger that protects us from orphaned large objects
*/ */
PG_FUNCTION_INFO_V1(lo_manage);
Datum Datum
lo_manage(PG_FUNCTION_ARGS) lo_manage(PG_FUNCTION_ARGS)
{ {
......
-- --
-- PostgreSQL code for LargeObjects -- PostgreSQL code for LargeObjects
-- --
-- $Id: lo.sql.in,v 1.4 2000/06/19 13:53:42 momjian Exp $ -- $Id: lo.sql.in,v 1.5 2000/11/20 20:36:55 tgl Exp $
-- --
-- --
-- Create the data type -- Create the data type
...@@ -44,7 +44,7 @@ create function lo(oid) ...@@ -44,7 +44,7 @@ create function lo(oid)
create function lo_manage() create function lo_manage()
returns opaque returns opaque
as 'MODULE_PATHNAME' as 'MODULE_PATHNAME'
language 'newC'; language 'C';
-- This allows us to map lo to oid -- This allows us to map lo to oid
-- --
......
...@@ -16,6 +16,8 @@ extern Datum noup(PG_FUNCTION_ARGS); ...@@ -16,6 +16,8 @@ extern Datum noup(PG_FUNCTION_ARGS);
* EXECUTE PROCEDURE noup ('col'). * EXECUTE PROCEDURE noup ('col').
*/ */
PG_FUNCTION_INFO_V1(noup);
Datum Datum
noup(PG_FUNCTION_ARGS) noup(PG_FUNCTION_ARGS)
{ {
......
...@@ -3,5 +3,4 @@ DROP FUNCTION noup (); ...@@ -3,5 +3,4 @@ DROP FUNCTION noup ();
CREATE FUNCTION noup () CREATE FUNCTION noup ()
RETURNS opaque RETURNS opaque
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'newC' LANGUAGE 'C';
;
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: pgcrypto.c,v 1.1 2000/10/31 13:11:28 petere Exp $ * $Id: pgcrypto.c,v 1.2 2000/11/20 20:36:56 tgl Exp $
*/ */
#include <postgres.h> #include <postgres.h>
...@@ -59,6 +59,8 @@ find_digest(pg_digest *hbuf, text *name, int silent); ...@@ -59,6 +59,8 @@ find_digest(pg_digest *hbuf, text *name, int silent);
/* SQL function: hash(text, text) returns text */ /* SQL function: hash(text, text) returns text */
PG_FUNCTION_INFO_V1(digest);
Datum Datum
digest(PG_FUNCTION_ARGS) digest(PG_FUNCTION_ARGS)
{ {
...@@ -95,6 +97,8 @@ digest(PG_FUNCTION_ARGS) ...@@ -95,6 +97,8 @@ digest(PG_FUNCTION_ARGS)
} }
/* check if given hash exists */ /* check if given hash exists */
PG_FUNCTION_INFO_V1(digest_exists);
Datum Datum
digest_exists(PG_FUNCTION_ARGS) digest_exists(PG_FUNCTION_ARGS)
{ {
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
CREATE FUNCTION digest(text, text) RETURNS text CREATE FUNCTION digest(text, text) RETURNS text
AS '@MODULE_FILENAME@', AS '@MODULE_FILENAME@',
'digest' LANGUAGE 'newC'; 'digest' LANGUAGE 'C';
CREATE FUNCTION digest_exists(text) RETURNS bool CREATE FUNCTION digest_exists(text) RETURNS bool
AS '@MODULE_FILENAME@', AS '@MODULE_FILENAME@',
'digest_exists' LANGUAGE 'newC'; 'digest_exists' LANGUAGE 'C';
/* $Header: /cvsroot/pgsql/contrib/soundex/Attic/soundex.c,v 1.7 2000/10/04 19:25:34 petere Exp $ */ /* $Header: /cvsroot/pgsql/contrib/soundex/Attic/soundex.c,v 1.8 2000/11/20 20:36:57 tgl Exp $ */
#include "postgres.h" #include "postgres.h"
#include "fmgr.h" #include "fmgr.h"
#include "utils/builtins.h" #include "utils/builtins.h"
...@@ -7,11 +7,9 @@ ...@@ -7,11 +7,9 @@
#include <stdio.h> #include <stdio.h>
Datum Datum text_soundex(PG_FUNCTION_ARGS);
text_soundex(PG_FUNCTION_ARGS);
static void static void soundex(const char *instr, char *outstr);
soundex(const char *instr, char *outstr);
#define SOUNDEX_LEN 4 #define SOUNDEX_LEN 4
...@@ -24,6 +22,8 @@ soundex(const char *instr, char *outstr); ...@@ -24,6 +22,8 @@ soundex(const char *instr, char *outstr);
/* /*
* SQL function: text_soundex(text) returns text * SQL function: text_soundex(text) returns text
*/ */
PG_FUNCTION_INFO_V1(text_soundex);
Datum Datum
text_soundex(PG_FUNCTION_ARGS) text_soundex(PG_FUNCTION_ARGS)
{ {
...@@ -36,6 +36,7 @@ text_soundex(PG_FUNCTION_ARGS) ...@@ -36,6 +36,7 @@ text_soundex(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(_textin(outstr)); PG_RETURN_TEXT_P(_textin(outstr));
} }
#endif /* not SOUNDEX_TEST */ #endif /* not SOUNDEX_TEST */
......
CREATE FUNCTION text_soundex(text) RETURNS text CREATE FUNCTION text_soundex(text) RETURNS text
AS '@MODULE_FILENAME@', 'text_soundex' LANGUAGE 'newC'; AS '@MODULE_FILENAME@', 'text_soundex' LANGUAGE 'C';
CREATE FUNCTION soundex(text) RETURNS text CREATE FUNCTION soundex(text) RETURNS text
AS '@MODULE_FILENAME@', 'text_soundex' LANGUAGE 'newC'; AS '@MODULE_FILENAME@', 'text_soundex' LANGUAGE 'C';
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
extern Datum autoinc(PG_FUNCTION_ARGS); extern Datum autoinc(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(autoinc);
Datum Datum
autoinc(PG_FUNCTION_ARGS) autoinc(PG_FUNCTION_ARGS)
{ {
......
...@@ -3,4 +3,4 @@ DROP FUNCTION autoinc(); ...@@ -3,4 +3,4 @@ DROP FUNCTION autoinc();
CREATE FUNCTION autoinc() CREATE FUNCTION autoinc()
RETURNS opaque RETURNS opaque
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'newC'; LANGUAGE 'C';
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
extern Datum insert_username(PG_FUNCTION_ARGS); extern Datum insert_username(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(insert_username);
Datum Datum
insert_username(PG_FUNCTION_ARGS) insert_username(PG_FUNCTION_ARGS)
{ {
......
...@@ -3,4 +3,4 @@ DROP FUNCTION insert_username(); ...@@ -3,4 +3,4 @@ DROP FUNCTION insert_username();
CREATE FUNCTION insert_username() CREATE FUNCTION insert_username()
RETURNS opaque RETURNS opaque
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'newC'; LANGUAGE 'C';
...@@ -17,6 +17,8 @@ OH, me, I'm Terry Mackintosh <terry@terrym.com> ...@@ -17,6 +17,8 @@ OH, me, I'm Terry Mackintosh <terry@terrym.com>
extern Datum moddatetime(PG_FUNCTION_ARGS); extern Datum moddatetime(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(moddatetime);
Datum Datum
moddatetime(PG_FUNCTION_ARGS) moddatetime(PG_FUNCTION_ARGS)
{ {
......
...@@ -3,4 +3,4 @@ DROP FUNCTION moddatetime(); ...@@ -3,4 +3,4 @@ DROP FUNCTION moddatetime();
CREATE FUNCTION moddatetime() CREATE FUNCTION moddatetime()
RETURNS opaque RETURNS opaque
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'newC'; LANGUAGE 'C';
...@@ -36,6 +36,8 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans); ...@@ -36,6 +36,8 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
* check_primary_key ('Fkey1', 'Fkey2', 'Ptable', 'Pkey1', 'Pkey2'). * check_primary_key ('Fkey1', 'Fkey2', 'Ptable', 'Pkey1', 'Pkey2').
*/ */
PG_FUNCTION_INFO_V1(check_primary_key);
Datum Datum
check_primary_key(PG_FUNCTION_ARGS) check_primary_key(PG_FUNCTION_ARGS)
{ {
...@@ -216,6 +218,8 @@ check_primary_key(PG_FUNCTION_ARGS) ...@@ -216,6 +218,8 @@ check_primary_key(PG_FUNCTION_ARGS)
* 'Ftable1', 'Fkey11', 'Fkey12', 'Ftable2', 'Fkey21', 'Fkey22'). * 'Ftable1', 'Fkey11', 'Fkey12', 'Ftable2', 'Fkey21', 'Fkey22').
*/ */
PG_FUNCTION_INFO_V1(check_foreign_key);
Datum Datum
check_foreign_key(PG_FUNCTION_ARGS) check_foreign_key(PG_FUNCTION_ARGS)
{ {
......
...@@ -4,11 +4,9 @@ DROP FUNCTION check_foreign_key (); ...@@ -4,11 +4,9 @@ DROP FUNCTION check_foreign_key ();
CREATE FUNCTION check_primary_key () CREATE FUNCTION check_primary_key ()
RETURNS opaque RETURNS opaque
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'newC' LANGUAGE 'C';
;
CREATE FUNCTION check_foreign_key () CREATE FUNCTION check_foreign_key ()
RETURNS opaque RETURNS opaque
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'newC' LANGUAGE 'C';
;
...@@ -47,6 +47,8 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans); ...@@ -47,6 +47,8 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
* timetravel ('date_on', 'date_off'). * timetravel ('date_on', 'date_off').
*/ */
PG_FUNCTION_INFO_V1(timetravel);
Datum Datum
timetravel(PG_FUNCTION_ARGS) timetravel(PG_FUNCTION_ARGS)
{ {
...@@ -326,6 +328,8 @@ timetravel(PG_FUNCTION_ARGS) ...@@ -326,6 +328,8 @@ timetravel(PG_FUNCTION_ARGS)
* set_timetravel (relname, on) -- * set_timetravel (relname, on) --
* turn timetravel for specified relation ON/OFF * turn timetravel for specified relation ON/OFF
*/ */
PG_FUNCTION_INFO_V1(set_timetravel);
Datum Datum
set_timetravel(PG_FUNCTION_ARGS) set_timetravel(PG_FUNCTION_ARGS)
{ {
......
...@@ -4,9 +4,9 @@ DROP FUNCTION set_timetravel(name, int4); ...@@ -4,9 +4,9 @@ DROP FUNCTION set_timetravel(name, int4);
CREATE FUNCTION timetravel() CREATE FUNCTION timetravel()
RETURNS opaque RETURNS opaque
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION set_timetravel(name, int4) CREATE FUNCTION set_timetravel(name, int4)
RETURNS int4 RETURNS int4
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'newC' WITH (isStrict); LANGUAGE 'C' WITH (isStrict);
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.19 2000/11/02 19:26:44 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.20 2000/11/20 20:36:46 tgl Exp $
Postgres documentation Postgres documentation
--> -->
...@@ -119,8 +119,7 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab ...@@ -119,8 +119,7 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab
<listitem> <listitem>
<para> <para>
May be '<literal>sql</literal>', May be '<literal>sql</literal>',
'<literal>C</literal>', '<literal>newC</literal>', '<literal>C</literal>', '<literal>internal</literal>',
'<literal>internal</literal>', '<literal>newinternal</literal>',
or '<replaceable class="parameter">plname</replaceable>', or '<replaceable class="parameter">plname</replaceable>',
where '<replaceable class="parameter">plname</replaceable>' where '<replaceable class="parameter">plname</replaceable>'
is the name of a created procedural language. See is the name of a created procedural language. See
...@@ -258,7 +257,7 @@ CREATE ...@@ -258,7 +257,7 @@ CREATE
</para> </para>
<para> <para>
Two <literal>internal</literal> or <literal>newinternal</literal> Two <literal>internal</literal>
functions cannot have the same C name without causing functions cannot have the same C name without causing
errors at link time. To get around that, give them different C names errors at link time. To get around that, give them different C names
(for example, use the argument types as part of the C names), then (for example, use the argument types as part of the C names), then
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.13 2000/11/04 21:04:54 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.14 2000/11/20 20:36:46 tgl Exp $
Postgres documentation Postgres documentation
--> -->
...@@ -163,7 +163,8 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable ...@@ -163,7 +163,8 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
<note> <note>
<para> <para>
In <productname>Postgres</productname> 7.1 and later, call handlers In <productname>Postgres</productname> 7.1 and later, call handlers
must adhere to the "new style" function manager interface. must adhere to the "version 1" function manager interface, not the
old-style interface.
</para> </para>
</note> </note>
...@@ -180,7 +181,7 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable ...@@ -180,7 +181,7 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
</para> </para>
<para> <para>
The call handler is called in the same way as any other new-style The call handler is called in the same way as any other
function: it receives a pointer to a FunctionCallInfoData struct function: it receives a pointer to a FunctionCallInfoData struct
containing argument values and information about the called function, containing argument values and information about the called function,
and it is expected to return a Datum result (and possibly set the and it is expected to return a Datum result (and possibly set the
...@@ -269,9 +270,7 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable ...@@ -269,9 +270,7 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
lanname | lanispl | lanpltrusted | lanplcallfoid | lancompiler lanname | lanispl | lanpltrusted | lanplcallfoid | lancompiler
-------------+---------+--------------+---------------+------------- -------------+---------+--------------+---------------+-------------
internal | f | f | 0 | n/a internal | f | f | 0 | n/a
newinternal | f | f | 0 | n/a
C | f | f | 0 | /bin/cc C | f | f | 0 | /bin/cc
newC | f | f | 0 | /bin/cc
sql | f | f | 0 | postgres sql | f | f | 0 | postgres
</computeroutput> </computeroutput>
</programlisting> </programlisting>
...@@ -279,8 +278,9 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable ...@@ -279,8 +278,9 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
<para> <para>
The call handler for a procedural language must normally be written The call handler for a procedural language must normally be written
in C and registered as 'newinternal' or 'newC' language, depending in C and registered as 'internal' or 'C' language, depending
on whether it is linked into the backend or dynamically loaded. on whether it is linked into the backend or dynamically loaded.
The call handler cannot use the old-style 'C' function interface.
</para> </para>
<para> <para>
...@@ -306,6 +306,8 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable ...@@ -306,6 +306,8 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
PG_FUNCTION_INFO_V1(plsample_call_handler);
Datum Datum
plsample_call_handler(PG_FUNCTION_ARGS) plsample_call_handler(PG_FUNCTION_ARGS)
{ {
...@@ -344,7 +346,7 @@ plsample_call_handler(PG_FUNCTION_ARGS) ...@@ -344,7 +346,7 @@ plsample_call_handler(PG_FUNCTION_ARGS)
<programlisting> <programlisting>
CREATE FUNCTION plsample_call_handler () RETURNS opaque CREATE FUNCTION plsample_call_handler () RETURNS opaque
AS '/usr/local/pgsql/lib/plsample.so' AS '/usr/local/pgsql/lib/plsample.so'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE PROCEDURAL LANGUAGE 'plsample' CREATE PROCEDURAL LANGUAGE 'plsample'
HANDLER plsample_call_handler HANDLER plsample_call_handler
LANCOMPILER 'PL/Sample'; LANCOMPILER 'PL/Sample';
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
<para> <para>
The trigger function must be created before the trigger is created as a The trigger function must be created before the trigger is created as a
function taking no arguments and returning opaque. If the function is function taking no arguments and returning opaque. If the function is
written in C, it must follow the "new style" function manager interface. written in C, it must use the "version 1" function manager interface.
</para> </para>
<para> <para>
...@@ -447,6 +447,8 @@ execution of Q) or after Q is done. ...@@ -447,6 +447,8 @@ execution of Q) or after Q is done.
extern Datum trigf(PG_FUNCTION_ARGS); extern Datum trigf(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(trigf);
Datum Datum
trigf(PG_FUNCTION_ARGS) trigf(PG_FUNCTION_ARGS)
{ {
...@@ -513,7 +515,7 @@ trigf(PG_FUNCTION_ARGS) ...@@ -513,7 +515,7 @@ trigf(PG_FUNCTION_ARGS)
<programlisting> <programlisting>
create function trigf () returns opaque as create function trigf () returns opaque as
'...path_to_so' language 'newC'; '...path_to_so' language 'C';
create table ttest (x int4); create table ttest (x int4);
</programlisting> </programlisting>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.22 2000/10/23 00:46:06 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.23 2000/11/20 20:36:47 tgl Exp $
--> -->
<chapter id="xfunc"> <chapter id="xfunc">
...@@ -339,9 +339,9 @@ SELECT clean_EMP(); ...@@ -339,9 +339,9 @@ SELECT clean_EMP();
</para> </para>
<para> <para>
There are two procedural languages available with the standard There are currently three procedural languages available in the standard
<productname>Postgres</productname> distribution (PLTCL and PLSQL), and other <productname>Postgres</productname> distribution (PLSQL, PLTCL and
languages can be defined. PLPERL), and other languages can be defined.
Refer to <xref linkend="xplang-title" endterm="xplang-title"> for Refer to <xref linkend="xplang-title" endterm="xplang-title"> for
more information. more information.
</para> </para>
...@@ -366,12 +366,7 @@ SELECT clean_EMP(); ...@@ -366,12 +366,7 @@ SELECT clean_EMP();
<para> <para>
Internal functions are declared in <command>CREATE FUNCTION</command> Internal functions are declared in <command>CREATE FUNCTION</command>
with language name <literal>internal</literal> or with language name <literal>internal</literal>.
<literal>newinternal</literal>, depending on whether they follow the
old (pre-7.1) or new (7.1 and later) function call conventions.
The details of the call conventions are the same as for
<literal>C</literal> and <literal>newC</literal> functions respectively;
see the next section for details.
</para> </para>
</sect1> </sect1>
...@@ -404,9 +399,9 @@ SELECT clean_EMP(); ...@@ -404,9 +399,9 @@ SELECT clean_EMP();
<para> <para>
The string which specifies the object file (the first string in the AS The string which specifies the object file (the first string in the AS
clause) should be the <emphasis>full path</emphasis> of the object clause) should be the <emphasis>full path</emphasis> of the object
code file for the function, bracketed by quotation marks. If a code file for the function, bracketed by single quote marks. If a
link symbol is given in the AS clause, the link symbol should also be link symbol is given in the AS clause, the link symbol should also be
bracketed by single quotation marks, and should be exactly the bracketed by single quote marks, and should be exactly the
same as the name of the function in the C source code. On Unix systems same as the name of the function in the C source code. On Unix systems
the command <command>nm</command> will print all of the link the command <command>nm</command> will print all of the link
symbols in a dynamically loadable object. symbols in a dynamically loadable object.
...@@ -422,11 +417,11 @@ SELECT clean_EMP(); ...@@ -422,11 +417,11 @@ SELECT clean_EMP();
<para> <para>
Two different calling conventions are currently used for C functions. Two different calling conventions are currently used for C functions.
The "old style" (pre-<productname>Postgres</productname>-7.1) method The newer "version 1" calling convention is indicated by writing
is selected by writing language name '<literal>C</literal>' in the a <literal>PG_FUNCTION_INFO_V1()</literal> macro call for the function,
<command>CREATE FUNCTION</command> command, while the "new style" as illustrated below. Lack of such a macro indicates an old-style
(7.1 and later) method is selecting by writing language name ("version 0") function. The language name specified in CREATE FUNCTION
'<literal>newC</literal>'. Old-style functions are now deprecated is 'C' in either case. Old-style functions are now deprecated
because of portability problems and lack of functionality, but they because of portability problems and lack of functionality, but they
are still supported for compatibility reasons. are still supported for compatibility reasons.
</para> </para>
...@@ -484,7 +479,7 @@ SELECT clean_EMP(); ...@@ -484,7 +479,7 @@ SELECT clean_EMP();
<entry>include/postgres.h</entry> <entry>include/postgres.h</entry>
</row> </row>
<row> <row>
<entry>char</entry> <entry>"char"</entry>
<entry>char</entry> <entry>char</entry>
<entry>N/A</entry> <entry>N/A</entry>
</row> </row>
...@@ -583,16 +578,6 @@ SELECT clean_EMP(); ...@@ -583,16 +578,6 @@ SELECT clean_EMP();
<entry>TimeInterval</entry> <entry>TimeInterval</entry>
<entry>utils/nabstime.h</entry> <entry>utils/nabstime.h</entry>
</row> </row>
<row>
<entry>uint2</entry>
<entry>uint16</entry>
<entry>include/c.h</entry>
</row>
<row>
<entry>uint4</entry>
<entry>uint32</entry>
<entry>include/c.h</entry>
</row>
<row> <row>
<entry>xid</entry> <entry>xid</entry>
<entry>(XID *)</entry> <entry>(XID *)</entry>
...@@ -694,7 +679,7 @@ typedef struct { ...@@ -694,7 +679,7 @@ typedef struct {
</para> </para>
<para> <para>
Obviously, the data field is not long enough to hold Obviously, the data field shown here is not long enough to hold
all possible strings; it's impossible to declare such all possible strings; it's impossible to declare such
a structure in <acronym>C</acronym>. When manipulating a structure in <acronym>C</acronym>. When manipulating
variable-length types, we must be careful to allocate variable-length types, we must be careful to allocate
...@@ -721,12 +706,12 @@ memmove(destination-&gt;data, buffer, 40); ...@@ -721,12 +706,12 @@ memmove(destination-&gt;data, buffer, 40);
</sect2> </sect2>
<sect2> <sect2>
<title>Old-style Calling Conventions for C-Language Functions</title> <title>Version-0 Calling Conventions for C-Language Functions</title>
<para> <para>
We present the "old style" calling convention first --- although We present the "old style" calling convention first --- although
this approach is now deprecated, it's easier to get a handle on this approach is now deprecated, it's easier to get a handle on
initially. In the "old style" method, the arguments and result initially. In the version-0 method, the arguments and result
of the C function are just declared in normal C style, but being 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 careful to use the C representation of each SQL data type as shown
above. above.
...@@ -854,26 +839,39 @@ CREATE FUNCTION concat_text(text, text) RETURNS text ...@@ -854,26 +839,39 @@ CREATE FUNCTION concat_text(text, text) RETURNS text
</para> </para>
<para> <para>
Although this old-style calling convention is simple to use, Although this calling convention is simple to use,
it is not very portable; on some architectures there are problems it is not very portable; on some architectures there are problems
with passing smaller-than-int data types this way. Also, there is with passing smaller-than-int data types this way. Also, there is
no simple way to return a NULL result, nor to cope with NULL arguments no simple way to return a NULL result, nor to cope with NULL arguments
in any way other than making the function strict. The new-style in any way other than making the function strict. The version-1
convention, presented next, overcomes these objections. convention, presented next, overcomes these objections.
</para> </para>
</sect2> </sect2>
<sect2> <sect2>
<title>New-style Calling Conventions for C-Language Functions</title> <title>Version-1 Calling Conventions for C-Language Functions</title>
<para> <para>
The new-style calling convention relies on macros to suppress most The version-1 calling convention relies on macros to suppress most
of the complexity of passing arguments and results. The C declaration of the complexity of passing arguments and results. The C declaration
of a new-style function is always of a version-1 function is always
<programlisting> <programlisting>
Datum funcname(PG_FUNCTION_ARGS) Datum funcname(PG_FUNCTION_ARGS)
</programlisting> </programlisting>
Each actual argument is fetched using a PG_GETARG_xxx() macro that In addition, the macro call
<programlisting>
PG_FUNCTION_INFO_V1(funcname);
</programlisting>
must appear in the same source file (conventionally it's written
just before the function itself). This macro call is not needed
for "internal"-language functions, since Postgres currently assumes
all internal functions are version-1. However, it is
<emphasis>required</emphasis> for dynamically-loaded functions.
</para>
<para>
In a version-1 function,
each actual argument is fetched using a PG_GETARG_xxx() macro that
corresponds to the argument's datatype, and the result is returned corresponds to the argument's datatype, and the result is returned
using a PG_RETURN_xxx() macro for the return type. using a PG_RETURN_xxx() macro for the return type.
</para> </para>
...@@ -887,6 +885,8 @@ CREATE FUNCTION concat_text(text, text) RETURNS text ...@@ -887,6 +885,8 @@ CREATE FUNCTION concat_text(text, text) RETURNS text
#include "fmgr.h" #include "fmgr.h"
/* By Value */ /* By Value */
PG_FUNCTION_INFO_V1(add_one);
Datum Datum
add_one(PG_FUNCTION_ARGS) add_one(PG_FUNCTION_ARGS)
...@@ -898,6 +898,8 @@ add_one(PG_FUNCTION_ARGS) ...@@ -898,6 +898,8 @@ add_one(PG_FUNCTION_ARGS)
/* By Reference, Fixed Length */ /* By Reference, Fixed Length */
PG_FUNCTION_INFO_V1(add_one_float8);
Datum Datum
add_one_float8(PG_FUNCTION_ARGS) add_one_float8(PG_FUNCTION_ARGS)
{ {
...@@ -907,6 +909,8 @@ add_one_float8(PG_FUNCTION_ARGS) ...@@ -907,6 +909,8 @@ add_one_float8(PG_FUNCTION_ARGS)
PG_RETURN_FLOAT8(arg + 1.0); PG_RETURN_FLOAT8(arg + 1.0);
} }
PG_FUNCTION_INFO_V1(makepoint);
Datum Datum
makepoint(PG_FUNCTION_ARGS) makepoint(PG_FUNCTION_ARGS)
{ {
...@@ -922,6 +926,8 @@ makepoint(PG_FUNCTION_ARGS) ...@@ -922,6 +926,8 @@ makepoint(PG_FUNCTION_ARGS)
/* By Reference, Variable Length */ /* By Reference, Variable Length */
PG_FUNCTION_INFO_V1(copytext);
Datum Datum
copytext(PG_FUNCTION_ARGS) copytext(PG_FUNCTION_ARGS)
{ {
...@@ -940,6 +946,8 @@ copytext(PG_FUNCTION_ARGS) ...@@ -940,6 +946,8 @@ copytext(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(new_t); PG_RETURN_TEXT_P(new_t);
} }
PG_FUNCTION_INFO_V1(concat_text);
Datum Datum
concat_text(PG_FUNCTION_ARGS) concat_text(PG_FUNCTION_ARGS)
{ {
...@@ -959,12 +967,11 @@ concat_text(PG_FUNCTION_ARGS) ...@@ -959,12 +967,11 @@ concat_text(PG_FUNCTION_ARGS)
<para> <para>
The <command>CREATE FUNCTION</command> commands are the same as The <command>CREATE FUNCTION</command> commands are the same as
for the old-style equivalents, except that the language is specified for the old-style equivalents.
as '<literal>newC</literal>' not '<literal>C</literal>'.
</para> </para>
<para> <para>
At first glance, the new-style coding conventions may appear to be At first glance, the version-1 coding conventions may appear to be
just pointless obscurantism. However, they do offer a number of just pointless obscurantism. However, they do offer a number of
improvements, because the macros can hide unnecessary detail. improvements, because the macros can hide unnecessary detail.
An example is that in coding add_one_float8, we no longer need to An example is that in coding add_one_float8, we no longer need to
...@@ -973,11 +980,14 @@ concat_text(PG_FUNCTION_ARGS) ...@@ -973,11 +980,14 @@ concat_text(PG_FUNCTION_ARGS)
to deal with fetching "toasted" (compressed or out-of-line) values. to deal with fetching "toasted" (compressed or out-of-line) values.
The old-style copytext and concat_text functions shown above are The old-style copytext and concat_text functions shown above are
actually wrong in the presence of toasted values, because they don't actually wrong in the presence of toasted values, because they don't
call pg_detoast_datum() on their inputs. call pg_detoast_datum() on their inputs. (The handler for old-style
dynamically-loaded functions currently takes care of this detail,
but it does so less efficiently than is possible for a version-1
function.)
</para> </para>
<para> <para>
The new-style function call conventions also make it possible to The version-1 function call conventions also make it possible to
test for NULL inputs to a non-strict function, return a NULL result test for NULL inputs to a non-strict function, return a NULL result
(from either strict or non-strict functions), return "set" results, (from either strict or non-strict functions), return "set" results,
and implement trigger functions and procedural-language call handlers. and implement trigger functions and procedural-language call handlers.
...@@ -1026,7 +1036,9 @@ c_overpaid(TupleTableSlot *t, /* the current instance of EMP */ ...@@ -1026,7 +1036,9 @@ c_overpaid(TupleTableSlot *t, /* the current instance of EMP */
return salary &gt; limit; return salary &gt; limit;
} }
/* In new-style coding, the above would look like this: */ /* In version-1 coding, the above would look like this: */
PG_FUNCTION_INFO_V1(c_overpaid);
Datum Datum
c_overpaid(PG_FUNCTION_ARGS) c_overpaid(PG_FUNCTION_ARGS)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.50 2000/11/16 22:30:17 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.51 2000/11/20 20:36:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -229,50 +229,35 @@ ProcedureCreate(char *procedureName, ...@@ -229,50 +229,35 @@ ProcedureCreate(char *procedureName,
* FUNCTION xyz AS '' LANGUAGE 'internal'. To preserve some modicum * FUNCTION xyz AS '' LANGUAGE 'internal'. To preserve some modicum
* of backwards compatibility, accept an empty 'prosrc' value as * of backwards compatibility, accept an empty 'prosrc' value as
* meaning the supplied SQL function name. * meaning the supplied SQL function name.
*
* XXX: we could treat "internal" and "newinternal" language specs
* as equivalent, and take the actual language ID from the table of
* known builtin functions. Is that a better idea than making the
* user specify the right thing? Not sure.
*/ */
if (languageObjectId == INTERNALlanguageId || if (languageObjectId == INTERNALlanguageId)
languageObjectId == NEWINTERNALlanguageId)
{ {
Oid actualLangID;
if (strlen(prosrc) == 0) if (strlen(prosrc) == 0)
prosrc = procedureName; prosrc = procedureName;
actualLangID = fmgr_internal_language(prosrc); if (fmgr_internal_function(prosrc) == InvalidOid)
if (actualLangID == InvalidOid)
elog(ERROR, elog(ERROR,
"ProcedureCreate: there is no builtin function named \"%s\"", "ProcedureCreate: there is no builtin function named \"%s\"",
prosrc); prosrc);
if (actualLangID != languageObjectId)
elog(ERROR,
"ProcedureCreate: \"%s\" is not %s internal function",
prosrc,
((languageObjectId == INTERNALlanguageId) ?
"an old-style" : "a new-style"));
} }
/* /*
* If this is a dynamically loadable procedure, make sure that the * If this is a dynamically loadable procedure, make sure that the
* library file exists, is loadable, and contains the specified link * library file exists, is loadable, and contains the specified link
* symbol. * symbol. Also check for a valid function information record.
* *
* We used to perform these checks only when the function was first * We used to perform these checks only when the function was first
* called, but it seems friendlier to verify the library's validity * called, but it seems friendlier to verify the library's validity
* at CREATE FUNCTION time. * at CREATE FUNCTION time.
*/ */
if (languageObjectId == ClanguageId || if (languageObjectId == ClanguageId)
languageObjectId == NEWClanguageId)
{ {
/* If link symbol is specified as "-", substitute procedure name */ /* If link symbol is specified as "-", substitute procedure name */
if (strcmp(prosrc, "-") == 0) if (strcmp(prosrc, "-") == 0)
prosrc = procedureName; prosrc = procedureName;
(void) load_external_function(probin, prosrc); (void) load_external_function(probin, prosrc, true);
(void) fetch_finfo_record(probin, prosrc);
} }
/* /*
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.48 2000/11/16 22:30:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.49 2000/11/20 20:36:47 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -66,7 +66,7 @@ case_translate_language_name(const char *input, char *output) ...@@ -66,7 +66,7 @@ case_translate_language_name(const char *input, char *output)
{ {
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
Translate the input language name to lower case, except if it's "C", Translate the input language name to lower case, except if it's "C",
translate to upper case, or "newC", translate to that spelling. translate to upper case.
--------------------------------------------------------------------------*/ --------------------------------------------------------------------------*/
int i; int i;
...@@ -77,8 +77,6 @@ case_translate_language_name(const char *input, char *output) ...@@ -77,8 +77,6 @@ case_translate_language_name(const char *input, char *output)
if (strcmp(output, "c") == 0) if (strcmp(output, "c") == 0)
output[0] = 'C'; output[0] = 'C';
else if (strcmp(output, "newc") == 0)
output[3] = 'C';
} }
...@@ -183,8 +181,7 @@ interpret_AS_clause(const char *languageName, const List *as, ...@@ -183,8 +181,7 @@ interpret_AS_clause(const char *languageName, const List *as,
{ {
Assert(as != NIL); Assert(as != NIL);
if (strcmp(languageName, "C") == 0 || if (strcmp(languageName, "C") == 0)
strcmp(languageName, "newC") == 0)
{ {
/* /*
...@@ -230,8 +227,8 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) ...@@ -230,8 +227,8 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
char languageName[NAMEDATALEN]; char languageName[NAMEDATALEN];
/* /*
* name of language of function, with case adjusted: "C", "newC", * name of language of function, with case adjusted: "C",
* "internal", "newinternal", "sql", etc. * "internal", "sql", etc.
*/ */
bool returnsSet; bool returnsSet;
...@@ -255,9 +252,7 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) ...@@ -255,9 +252,7 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
* Apply appropriate security checks depending on language. * Apply appropriate security checks depending on language.
*/ */
if (strcmp(languageName, "C") == 0 || if (strcmp(languageName, "C") == 0 ||
strcmp(languageName, "newC") == 0 || strcmp(languageName, "internal") == 0)
strcmp(languageName, "internal") == 0 ||
strcmp(languageName, "newinternal") == 0)
{ {
if (!superuser()) if (!superuser())
elog(ERROR, elog(ERROR,
...@@ -283,8 +278,8 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest) ...@@ -283,8 +278,8 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
if (!HeapTupleIsValid(languageTuple)) if (!HeapTupleIsValid(languageTuple))
elog(ERROR, elog(ERROR,
"Unrecognized language specified in a CREATE FUNCTION: " "Unrecognized language specified in a CREATE FUNCTION: "
"'%s'.\n\tRecognized languages are sql, C, newC, " "'%s'.\n\tRecognized languages are sql, C, "
"internal, newinternal, and created procedural languages.", "internal, and created procedural languages.",
languageName); languageName);
/* Check that this language is a PL */ /* Check that this language is a PL */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.55 2000/11/16 22:30:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.56 2000/11/20 20:36:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -344,8 +344,7 @@ RemoveFunction(char *functionName, /* function name to be removed */ ...@@ -344,8 +344,7 @@ RemoveFunction(char *functionName, /* function name to be removed */
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
func_error("RemoveFunction", functionName, nargs, argList, NULL); func_error("RemoveFunction", functionName, nargs, argList, NULL);
if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId || if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
((Form_pg_proc) GETSTRUCT(tup))->prolang == NEWINTERNALlanguageId)
{ {
/* "Helpful" notice when removing a builtin function ... */ /* "Helpful" notice when removing a builtin function ... */
elog(NOTICE, "Removing built-in function \"%s\"", functionName); elog(NOTICE, "Removing built-in function \"%s\"", functionName);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.80 2000/11/16 22:30:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.81 2000/11/20 20:36:47 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -169,10 +169,7 @@ CreateTrigger(CreateTrigStmt *stmt) ...@@ -169,10 +169,7 @@ CreateTrigger(CreateTrigStmt *stmt)
funclang = ((Form_pg_proc) GETSTRUCT(tuple))->prolang; funclang = ((Form_pg_proc) GETSTRUCT(tuple))->prolang;
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
if (funclang != ClanguageId && if (funclang != ClanguageId && funclang != INTERNALlanguageId)
funclang != NEWClanguageId &&
funclang != INTERNALlanguageId &&
funclang != NEWINTERNALlanguageId)
{ {
HeapTuple langTup; HeapTuple langTup;
...@@ -180,10 +177,10 @@ CreateTrigger(CreateTrigStmt *stmt) ...@@ -180,10 +177,10 @@ CreateTrigger(CreateTrigStmt *stmt)
ObjectIdGetDatum(funclang), ObjectIdGetDatum(funclang),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(langTup)) if (!HeapTupleIsValid(langTup))
elog(ERROR, "CreateTrigger: cache lookup for PL %u failed", elog(ERROR, "CreateTrigger: cache lookup for language %u failed",
funclang); funclang);
if (((Form_pg_language) GETSTRUCT(langTup))->lanispl == false) if (((Form_pg_language) GETSTRUCT(langTup))->lanispl == false)
elog(ERROR, "CreateTrigger: only builtin, C and PL functions are supported"); elog(ERROR, "CreateTrigger: only internal, C and PL functions are supported");
ReleaseSysCache(langTup); ReleaseSysCache(langTup);
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.17 2000/07/13 16:07:06 petere Exp $ # $Header: /cvsroot/pgsql/src/backend/utils/Attic/Gen_fmgrtab.sh,v 1.18 2000/11/20 20:36:48 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -82,7 +82,7 @@ trap 'echo "Caught signal." ; cleanup ; exit 1' 1 2 15 ...@@ -82,7 +82,7 @@ trap 'echo "Caught signal." ; cleanup ; exit 1' 1 2 15
# #
# Generate the file containing raw pg_proc tuple data # Generate the file containing raw pg_proc tuple data
# (but only for "internal" and "newinternal" language procedures...). # (but only for "internal" language procedures...).
# #
# Unlike genbki.sh, which can run through cpp last, we have to # Unlike genbki.sh, which can run through cpp last, we have to
# deal with preprocessor statements first (before we sort the # deal with preprocessor statements first (before we sort the
...@@ -99,7 +99,6 @@ sed -e 's/^.*OID[^=]*=[^0-9]*//' \ ...@@ -99,7 +99,6 @@ sed -e 's/^.*OID[^=]*=[^0-9]*//' \
-e 's/[ ]*).*$//' | \ -e 's/[ ]*).*$//' | \
$AWK ' $AWK '
/^#/ { print; next; } /^#/ { print; next; }
$4 == "11" { print; next; }
$4 == "12" { print; next; }' > $CPPTMPFILE $4 == "12" { print; next; }' > $CPPTMPFILE
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
...@@ -182,10 +181,6 @@ FuNkYfMgRsTuFf ...@@ -182,10 +181,6 @@ FuNkYfMgRsTuFf
# Generate fmgr's built-in-function table. # Generate fmgr's built-in-function table.
# #
# Print out the function declarations, then the table that refers to them. # Print out the function declarations, then the table that refers to them.
# NB: the function declarations are bogus in the case of old-style functions,
# although they should be correct for new-style. Therefore we need to compile
# this table definition as a separate C file that won't need to include any
# "real" declarations for those functions!
# #
cat > "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF cat > "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
...@@ -205,10 +200,6 @@ cat > "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF ...@@ -205,10 +200,6 @@ cat > "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF
* It has been GENERATED by $CMDNAME * It has been GENERATED by $CMDNAME
* from $INFILE * from $INFILE
* *
* We lie here to cc about the return type and arguments of old-style
* builtin functions; all ld cares about is the fact that it
* will need to resolve an external function reference.
*
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -237,13 +228,11 @@ FuNkYfMgRtAbStUfF ...@@ -237,13 +228,11 @@ FuNkYfMgRtAbStUfF
# conditional expression instead. Not all awks have conditional expressions. # conditional expression instead. Not all awks have conditional expressions.
$AWK 'BEGIN { $AWK 'BEGIN {
Strict["t"] = "true" Bool["t"] = "true"
Strict["f"] = "false" Bool["f"] = "false"
OldStyle["11"] = "true"
OldStyle["12"] = "false"
} }
{ printf (" { %d, \"%s\", %d, %s, %s, %s },\n"), \ { printf (" { %d, \"%s\", %d, %s, %s, %s },\n"), \
$1, $(NF-1), $9, Strict[$8], OldStyle[$4], $(NF-1) $1, $(NF-1), $9, Bool[$8], Bool[$10], $(NF-1)
}' $RAWFILE >> "$$-$TABLEFILE" }' $RAWFILE >> "$$-$TABLEFILE"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.47 2000/11/16 22:30:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.48 2000/11/20 20:36:49 tgl Exp $
* *
* NOTES * NOTES
* Eventually, the index information should go through here, too. * Eventually, the index information should go through here, too.
...@@ -731,6 +731,27 @@ get_typalign(Oid typid) ...@@ -731,6 +731,27 @@ get_typalign(Oid typid)
#endif #endif
char
get_typstorage(Oid typid)
{
HeapTuple tp;
tp = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid),
0, 0, 0);
if (HeapTupleIsValid(tp))
{
Form_pg_type typtup = (Form_pg_type) GETSTRUCT(tp);
char result;
result = typtup->typstorage;
ReleaseSysCache(tp);
return result;
}
else
return 'p';
}
/* /*
* get_typdefault * get_typdefault
* *
......
...@@ -8,20 +8,17 @@ ...@@ -8,20 +8,17 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.45 2000/11/16 22:30:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.46 2000/11/20 20:36:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h"
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "postgres.h"
#include "catalog/pg_proc.h"
#include "dynloader.h" #include "dynloader.h"
#include "utils/dynamic_loader.h" #include "utils/dynamic_loader.h"
#include "utils/builtins.h"
#include "utils/syscache.h"
/* /*
...@@ -46,55 +43,16 @@ static DynamicFileList *file_tail = (DynamicFileList *) NULL; ...@@ -46,55 +43,16 @@ static DynamicFileList *file_tail = (DynamicFileList *) NULL;
#define SAME_INODE(A,B) ((A).st_ino == (B).inode && (A).st_dev == (B).device) #define SAME_INODE(A,B) ((A).st_ino == (B).inode && (A).st_dev == (B).device)
/*
* Load the specified dynamic-link library file, and look for a function
* named funcname in it. If the function is not found, we raise an error
* if signalNotFound is true, else return (PGFunction) NULL. Note that
* errors in loading the library will provoke elog regardless of
* signalNotFound.
*/
PGFunction PGFunction
fmgr_dynamic(Oid functionId) load_external_function(char *filename, char *funcname,
{ bool signalNotFound)
HeapTuple procedureTuple;
Form_pg_proc procedureStruct;
char *proname,
*prosrcstring,
*probinstring;
Datum prosrcattr,
probinattr;
PGFunction user_fn;
bool isnull;
procedureTuple = SearchSysCache(PROCOID,
ObjectIdGetDatum(functionId),
0, 0, 0);
if (!HeapTupleIsValid(procedureTuple))
elog(ERROR, "fmgr_dynamic: function %u: cache lookup failed",
functionId);
procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
proname = NameStr(procedureStruct->proname);
prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple,
Anum_pg_proc_prosrc, &isnull);
if (isnull)
elog(ERROR, "fmgr: Could not extract prosrc for %u from pg_proc",
functionId);
prosrcstring = DatumGetCString(DirectFunctionCall1(textout, prosrcattr));
probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
Anum_pg_proc_probin, &isnull);
if (isnull)
elog(ERROR, "fmgr: Could not extract probin for %u from pg_proc",
functionId);
probinstring = DatumGetCString(DirectFunctionCall1(textout, probinattr));
user_fn = load_external_function(probinstring, prosrcstring);
pfree(prosrcstring);
pfree(probinstring);
ReleaseSysCache(procedureTuple);
return user_fn;
}
PGFunction
load_external_function(char *filename, char *funcname)
{ {
DynamicFileList *file_scanner; DynamicFileList *file_scanner;
PGFunction retval; PGFunction retval;
...@@ -164,7 +122,7 @@ load_external_function(char *filename, char *funcname) ...@@ -164,7 +122,7 @@ load_external_function(char *filename, char *funcname)
retval = pg_dlsym(file_scanner->handle, funcname); retval = pg_dlsym(file_scanner->handle, funcname);
if (retval == (PGFunction) NULL) if (retval == (PGFunction) NULL && signalNotFound)
elog(ERROR, "Can't find function %s in file %s", funcname, filename); elog(ERROR, "Can't find function %s in file %s", funcname, filename);
return retval; return retval;
...@@ -217,5 +175,5 @@ load_file(char *filename) ...@@ -217,5 +175,5 @@ load_file(char *filename)
} }
} }
load_external_function(filename, (char *) NULL); load_external_function(filename, (char *) NULL, false);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.47 2000/11/16 22:30:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.48 2000/11/20 20:36:49 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "executor/functions.h" #include "executor/functions.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fmgrtab.h" #include "utils/fmgrtab.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h" #include "utils/syscache.h"
/* /*
...@@ -42,7 +43,19 @@ typedef int32 ((*func_ptr) ()); ...@@ -42,7 +43,19 @@ typedef int32 ((*func_ptr) ());
typedef char *((*func_ptr) ()); typedef char *((*func_ptr) ());
#endif #endif
/*
* For an oldstyle function, fn_extra points to a record like this:
*/
typedef struct
{
func_ptr func; /* Address of the oldstyle function */
bool arg_toastable[FUNC_MAX_ARGS]; /* is n'th arg of a toastable
* datatype? */
} Oldstyle_fnextra;
static void fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple);
static void fmgr_info_other_lang(FmgrInfo *finfo, HeapTuple procedureTuple);
static Datum fmgr_oldstyle(PG_FUNCTION_ARGS); static Datum fmgr_oldstyle(PG_FUNCTION_ARGS);
static Datum fmgr_untrusted(PG_FUNCTION_ARGS); static Datum fmgr_untrusted(PG_FUNCTION_ARGS);
...@@ -104,9 +117,6 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) ...@@ -104,9 +117,6 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
const FmgrBuiltin *fbp; const FmgrBuiltin *fbp;
HeapTuple procedureTuple; HeapTuple procedureTuple;
Form_pg_proc procedureStruct; Form_pg_proc procedureStruct;
HeapTuple languageTuple;
Form_pg_language languageStruct;
Oid language;
char *prosrc; char *prosrc;
finfo->fn_oid = functionId; finfo->fn_oid = functionId;
...@@ -120,16 +130,8 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) ...@@ -120,16 +130,8 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
*/ */
finfo->fn_nargs = fbp->nargs; finfo->fn_nargs = fbp->nargs;
finfo->fn_strict = fbp->strict; finfo->fn_strict = fbp->strict;
finfo->fn_retset = false; /* assume no builtins return sets! */ finfo->fn_retset = fbp->retset;
if (fbp->oldstyle) finfo->fn_addr = fbp->func;
{
finfo->fn_addr = fmgr_oldstyle;
finfo->fn_extra = (void *) fbp->func;
}
else
{
finfo->fn_addr = fbp->func;
}
return; return;
} }
...@@ -148,16 +150,15 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) ...@@ -148,16 +150,15 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
if (!procedureStruct->proistrusted) if (!procedureStruct->proistrusted)
{ {
/* This isn't really supported anymore... */
finfo->fn_addr = fmgr_untrusted; finfo->fn_addr = fmgr_untrusted;
ReleaseSysCache(procedureTuple); ReleaseSysCache(procedureTuple);
return; return;
} }
language = procedureStruct->prolang; switch (procedureStruct->prolang)
switch (language)
{ {
case INTERNALlanguageId: case INTERNALlanguageId:
case NEWINTERNALlanguageId:
/* /*
* For an ordinary builtin function, we should never get * For an ordinary builtin function, we should never get
* here because the isbuiltin() search above will have * here because the isbuiltin() search above will have
...@@ -175,24 +176,12 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) ...@@ -175,24 +176,12 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
elog(ERROR, "fmgr_info: function %s not in internal table", elog(ERROR, "fmgr_info: function %s not in internal table",
prosrc); prosrc);
pfree(prosrc); pfree(prosrc);
if (fbp->oldstyle) /* Should we check that nargs, strict, retset match the table? */
{ finfo->fn_addr = fbp->func;
finfo->fn_addr = fmgr_oldstyle;
finfo->fn_extra = (void *) fbp->func;
}
else
{
finfo->fn_addr = fbp->func;
}
break; break;
case ClanguageId: case ClanguageId:
finfo->fn_addr = fmgr_oldstyle; fmgr_info_C_lang(finfo, procedureTuple);
finfo->fn_extra = (void *) fmgr_dynamic(functionId);
break;
case NEWClanguageId:
finfo->fn_addr = fmgr_dynamic(functionId);
break; break;
case SQLlanguageId: case SQLlanguageId:
...@@ -200,92 +189,234 @@ fmgr_info(Oid functionId, FmgrInfo *finfo) ...@@ -200,92 +189,234 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
break; break;
default: default:
/* fmgr_info_other_lang(finfo, procedureTuple);
* Might be a created procedural language; try to look it up. break;
*/ }
languageTuple = SearchSysCache(LANGOID,
ObjectIdGetDatum(language), ReleaseSysCache(procedureTuple);
0, 0, 0); }
if (!HeapTupleIsValid(languageTuple))
elog(ERROR, "fmgr_info: cache lookup for language %u failed", /*
language); * Special fmgr_info processing for C-language functions
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); */
if (languageStruct->lanispl) static void
{ fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
FmgrInfo plfinfo; {
Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
fmgr_info(languageStruct->lanplcallfoid, &plfinfo); Datum prosrcattr,
finfo->fn_addr = plfinfo.fn_addr; probinattr;
/* char *prosrcstring,
* If lookup of the PL handler function produced nonnull *probinstring;
* fn_extra, complain --- it must be an oldstyle function! PGFunction user_fn;
* We no longer support oldstyle PL handlers. Pg_finfo_record *inforec;
*/ Oldstyle_fnextra *fnextra;
if (plfinfo.fn_extra != NULL) bool isnull;
elog(ERROR, "fmgr_info: language %u has old-style handler", int i;
language);
} /* Get prosrc and probin strings (link symbol and library filename) */
else prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple,
Anum_pg_proc_prosrc, &isnull);
if (isnull)
elog(ERROR, "fmgr: Could not extract prosrc for %u from pg_proc",
finfo->fn_oid);
prosrcstring = DatumGetCString(DirectFunctionCall1(textout, prosrcattr));
probinattr = SysCacheGetAttr(PROCOID, procedureTuple,
Anum_pg_proc_probin, &isnull);
if (isnull)
elog(ERROR, "fmgr: Could not extract probin for %u from pg_proc",
finfo->fn_oid);
probinstring = DatumGetCString(DirectFunctionCall1(textout, probinattr));
/* Look up the function itself */
user_fn = load_external_function(probinstring, prosrcstring, true);
/* Get the function information record (real or default) */
inforec = fetch_finfo_record(probinstring, prosrcstring);
switch (inforec->api_version)
{
case 0:
/* Old style: need to use a handler */
finfo->fn_addr = fmgr_oldstyle;
/* OK to use palloc here because fn_mcxt is CurrentMemoryContext */
fnextra = (Oldstyle_fnextra *) palloc(sizeof(Oldstyle_fnextra));
finfo->fn_extra = (void *) fnextra;
MemSet(fnextra, 0, sizeof(Oldstyle_fnextra));
fnextra->func = (func_ptr) user_fn;
for (i = 0; i < procedureStruct->pronargs; i++)
{ {
elog(ERROR, "fmgr_info: function %u: unsupported language %u", fnextra->arg_toastable[i] =
functionId, language); TypeIsToastable(procedureStruct->proargtypes[i]);
} }
ReleaseSysCache(languageTuple); break;
case 1:
/* New style: call directly */
finfo->fn_addr = user_fn;
break;
default:
/* Shouldn't get here if fetch_finfo_record did its job */
elog(ERROR, "Unknown function API version %d",
inforec->api_version);
break; break;
} }
ReleaseSysCache(procedureTuple); pfree(prosrcstring);
pfree(probinstring);
} }
/*
* Special fmgr_info processing for other-language functions
*/
static void
fmgr_info_other_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
{
Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
Oid language = procedureStruct->prolang;
HeapTuple languageTuple;
Form_pg_language languageStruct;
languageTuple = SearchSysCache(LANGOID,
ObjectIdGetDatum(language),
0, 0, 0);
if (!HeapTupleIsValid(languageTuple))
elog(ERROR, "fmgr_info: cache lookup for language %u failed",
language);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
if (languageStruct->lanispl)
{
FmgrInfo plfinfo;
fmgr_info(languageStruct->lanplcallfoid, &plfinfo);
finfo->fn_addr = plfinfo.fn_addr;
/*
* If lookup of the PL handler function produced nonnull
* fn_extra, complain --- it must be an oldstyle function!
* We no longer support oldstyle PL handlers.
*/
if (plfinfo.fn_extra != NULL)
elog(ERROR, "fmgr_info: language %u has old-style handler",
language);
}
else
{
elog(ERROR, "fmgr_info: function %u: unsupported language %u",
finfo->fn_oid, language);
}
ReleaseSysCache(languageTuple);
}
/* /*
* Specialized lookup routine for pg_proc.c: given the alleged name of * Fetch and validate the information record for the given external function.
* an internal function, return the OID of the function's language. *
* If the name is not known, return InvalidOid. * If no info function exists for the given name, it is not an error.
* Instead we return a default info record for a version-0 function.
* We want to raise an error here only if the info function returns
* something bogus.
*
* This function is broken out of fmgr_info_C_lang() so that ProcedureCreate()
* can validate the information record for a function not yet entered into
* pg_proc.
*/
Pg_finfo_record *
fetch_finfo_record(char *filename, char *funcname)
{
char *infofuncname;
PGFInfoFunction infofunc;
Pg_finfo_record *inforec;
static Pg_finfo_record default_inforec = { 0 };
/* Compute name of info func */
infofuncname = (char *) palloc(strlen(funcname) + 10);
sprintf(infofuncname, "pg_finfo_%s", funcname);
/* Try to look up the info function */
infofunc = (PGFInfoFunction) load_external_function(filename,
infofuncname,
false);
if (infofunc == (PGFInfoFunction) NULL)
{
/* Not found --- assume version 0 */
pfree(infofuncname);
return &default_inforec;
}
/* Found, so call it */
inforec = (*infofunc)();
/* Validate result as best we can */
if (inforec == NULL)
elog(ERROR, "Null result from %s", infofuncname);
switch (inforec->api_version)
{
case 0:
case 1:
/* OK, no additional fields to validate */
break;
default:
elog(ERROR, "Unknown version %d reported by %s",
inforec->api_version, infofuncname);
break;
}
pfree(infofuncname);
return inforec;
}
/*
* Specialized lookup routine for ProcedureCreate(): given the alleged name
* of an internal function, return the OID of the function.
* If the name is not recognized, return InvalidOid.
*/ */
Oid Oid
fmgr_internal_language(const char *proname) fmgr_internal_function(const char *proname)
{ {
const FmgrBuiltin *fbp = fmgr_lookupByName(proname); const FmgrBuiltin *fbp = fmgr_lookupByName(proname);
if (fbp == NULL) if (fbp == NULL)
return InvalidOid; return InvalidOid;
return fbp->oldstyle ? INTERNALlanguageId : NEWINTERNALlanguageId; return fbp->foid;
} }
/* /*
* Handler for old-style internal and "C" language functions * Handler for old-style "C" language functions
*
* We expect fmgr_info to have placed the old-style function's address
* in fn_extra of *flinfo. This is a bit of a hack since fn_extra is really
* void * which might be a different size than a pointer to function, but
* it will work on any machine that our old-style call interface works on...
*/ */
static Datum static Datum
fmgr_oldstyle(PG_FUNCTION_ARGS) fmgr_oldstyle(PG_FUNCTION_ARGS)
{ {
char *returnValue = NULL; Oldstyle_fnextra *fnextra;
int n_arguments = fcinfo->nargs; int n_arguments = fcinfo->nargs;
int i; int i;
bool isnull; bool isnull;
func_ptr user_fn; func_ptr user_fn;
char *returnValue;
if (fcinfo->flinfo == NULL || fcinfo->flinfo->fn_extra == NULL) if (fcinfo->flinfo == NULL || fcinfo->flinfo->fn_extra == NULL)
elog(ERROR, "Internal error: fmgr_oldstyle received NULL function pointer"); elog(ERROR, "Internal error: fmgr_oldstyle received NULL pointer");
fnextra = (Oldstyle_fnextra *) fcinfo->flinfo->fn_extra;
/* /*
* Result is NULL if any argument is NULL, but we still call the function * Result is NULL if any argument is NULL, but we still call the function
* (peculiar, but that's the way it worked before, and after all this is * (peculiar, but that's the way it worked before, and after all this is
* a backwards-compatibility wrapper). Note, however, that we'll never * a backwards-compatibility wrapper). Note, however, that we'll never
* get here with NULL arguments if the function is marked strict. * get here with NULL arguments if the function is marked strict.
*
* We also need to detoast any TOAST-ed inputs, since it's unlikely that
* an old-style function knows about TOASTing.
*/ */
isnull = false; isnull = false;
for (i = 0; i < n_arguments; i++) for (i = 0; i < n_arguments; i++)
isnull |= PG_ARGISNULL(i); {
if (PG_ARGISNULL(i))
isnull = true;
else if (fnextra->arg_toastable[i])
fcinfo->arg[i] = PointerGetDatum(PG_DETOAST_DATUM(fcinfo->arg[i]));
}
fcinfo->isnull = isnull; fcinfo->isnull = isnull;
user_fn = (func_ptr) fcinfo->flinfo->fn_extra; user_fn = fnextra->func;
switch (n_arguments) switch (n_arguments)
{ {
...@@ -411,6 +542,7 @@ fmgr_oldstyle(PG_FUNCTION_ARGS) ...@@ -411,6 +542,7 @@ fmgr_oldstyle(PG_FUNCTION_ARGS)
*/ */
elog(ERROR, "fmgr_oldstyle: function %u: too many arguments (%d > %d)", elog(ERROR, "fmgr_oldstyle: function %u: too many arguments (%d > %d)",
fcinfo->flinfo->fn_oid, n_arguments, 16); fcinfo->flinfo->fn_oid, n_arguments, 16);
returnValue = NULL; /* keep compiler quiet */
break; break;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createlang.sh,v 1.19 2000/11/13 23:37:53 momjian Exp $ # $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createlang.sh,v 1.20 2000/11/20 20:36:50 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -259,7 +259,7 @@ fi ...@@ -259,7 +259,7 @@ fi
# ---------- # ----------
# Create the call handler and the language # Create the call handler and the language
# ---------- # ----------
$PSQL "CREATE FUNCTION $handler () RETURNS OPAQUE AS '$PGLIB/${object}$DLSUFFIX' LANGUAGE 'newC'" $PSQL "CREATE FUNCTION $handler () RETURNS OPAQUE AS '$PGLIB/${object}$DLSUFFIX' LANGUAGE 'C'"
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
echo "$CMDNAME: language installation failed" 1>&2 echo "$CMDNAME: language installation failed" 1>&2
exit 1 exit 1
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: catversion.h,v 1.61 2000/11/20 05:18:40 vadim Exp $ * $Id: catversion.h,v 1.62 2000/11/20 20:36:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200011191 #define CATALOG_VERSION_NO 200011201
#endif #endif
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: pg_language.h,v 1.11 2000/05/28 17:56:16 tgl Exp $ * $Id: pg_language.h,v 1.12 2000/11/20 20:36:50 tgl Exp $
* *
* NOTES * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -63,18 +63,12 @@ typedef FormData_pg_language *Form_pg_language; ...@@ -63,18 +63,12 @@ typedef FormData_pg_language *Form_pg_language;
* ---------------- * ----------------
*/ */
DATA(insert OID = 11 ( internal f f 0 "n/a" )); DATA(insert OID = 12 ( internal f f 0 "n/a" ));
DESCR("old-style built-in functions"); DESCR("Built-in functions");
#define INTERNALlanguageId 11 #define INTERNALlanguageId 12
DATA(insert OID = 12 ( newinternal f f 0 "n/a" ));
DESCR("new-style built-in functions");
#define NEWINTERNALlanguageId 12
DATA(insert OID = 13 ( "C" f f 0 "/bin/cc" )); DATA(insert OID = 13 ( "C" f f 0 "/bin/cc" ));
DESCR("Dynamically-loaded old-style C functions"); DESCR("Dynamically-loaded C functions");
#define ClanguageId 13 #define ClanguageId 13
DATA(insert OID = 10 ( "newC" f f 0 "/bin/cc" ));
DESCR("Dynamically-loaded new-style C functions");
#define NEWClanguageId 10
DATA(insert OID = 14 ( "sql" f f 0 "postgres")); DATA(insert OID = 14 ( "sql" f f 0 "postgres"));
DESCR("SQL-language functions"); DESCR("SQL-language functions");
#define SQLlanguageId 14 #define SQLlanguageId 14
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: fmgr.h,v 1.10 2000/08/24 03:29:11 tgl Exp $ * $Id: fmgr.h,v 1.11 2000/11/20 20:36:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -208,6 +208,43 @@ extern struct varlena * pg_detoast_datum_copy(struct varlena * datum); ...@@ -208,6 +208,43 @@ extern struct varlena * pg_detoast_datum_copy(struct varlena * datum);
#define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x) #define PG_RETURN_VARCHAR_P(x) PG_RETURN_POINTER(x)
/*-------------------------------------------------------------------------
* Support for detecting call convention of dynamically-loaded functions
*
* Dynamically loaded functions may use either the version-1 ("new style")
* or version-0 ("old style") calling convention. Version 1 is the call
* convention defined in this header file; version 0 is the old "plain C"
* convention. A version-1 function must be accompanied by the macro call
*
* PG_FUNCTION_INFO_V1(function_name);
*
* Note that internal functions do not need this decoration since they are
* assumed to be version-1.
*
*-------------------------------------------------------------------------
*/
typedef struct
{
int api_version; /* specifies call convention version number */
/* More fields may be added later, for version numbers > 1. */
} Pg_finfo_record;
/* Expected signature of an info function */
typedef Pg_finfo_record * (*PGFInfoFunction) (void);
/* Macro to build an info function associated with the given function name */
#define PG_FUNCTION_INFO_V1(funcname) \
extern Pg_finfo_record * CppConcat(pg_finfo_,funcname) (void); \
Pg_finfo_record * \
CppConcat(pg_finfo_,funcname) (void) \
{ \
static Pg_finfo_record my_finfo = { 1 }; \
return &my_finfo; \
}
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* Support routines and macros for callers of fmgr-compatible functions * Support routines and macros for callers of fmgr-compatible functions
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
...@@ -297,13 +334,14 @@ extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2, ...@@ -297,13 +334,14 @@ extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
/* /*
* Routines in fmgr.c * Routines in fmgr.c
*/ */
extern Oid fmgr_internal_language(const char *proname); extern Pg_finfo_record *fetch_finfo_record(char *filename, char *funcname);
extern Oid fmgr_internal_function(const char *proname);
/* /*
* Routines in dfmgr.c * Routines in dfmgr.c
*/ */
extern PGFunction fmgr_dynamic(Oid functionId); extern PGFunction load_external_function(char *filename, char *funcname,
extern PGFunction load_external_function(char *filename, char *funcname); bool signalNotFound);
extern void load_file(char *filename); extern void load_file(char *filename);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: fmgrtab.h,v 1.13 2000/05/28 17:56:20 tgl Exp $ * $Id: fmgrtab.h,v 1.14 2000/11/20 20:36:51 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -28,7 +28,7 @@ typedef struct ...@@ -28,7 +28,7 @@ typedef struct
const char *funcName; /* C name of the function */ const char *funcName; /* C name of the function */
short nargs; /* 0..FUNC_MAX_ARGS, or -1 if variable count */ short nargs; /* 0..FUNC_MAX_ARGS, or -1 if variable count */
bool strict; /* T if function is "strict" */ bool strict; /* T if function is "strict" */
bool oldstyle; /* T if function uses old fmgr interface */ bool retset; /* T if function returns a set */
PGFunction func; /* pointer to compiled function */ PGFunction func; /* pointer to compiled function */
} FmgrBuiltin; } FmgrBuiltin;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: lsyscache.h,v 1.27 2000/11/16 22:30:49 tgl Exp $ * $Id: lsyscache.h,v 1.28 2000/11/20 20:36:51 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -39,6 +39,9 @@ extern char *get_rel_name(Oid relid); ...@@ -39,6 +39,9 @@ extern char *get_rel_name(Oid relid);
extern int16 get_typlen(Oid typid); extern int16 get_typlen(Oid typid);
extern bool get_typbyval(Oid typid); extern bool get_typbyval(Oid typid);
extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval); extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
extern char get_typstorage(Oid typid);
extern Datum get_typdefault(Oid typid); extern Datum get_typdefault(Oid typid);
#define TypeIsToastable(typid) (get_typstorage(typid) != 'p')
#endif /* LSYSCACHE_H */ #endif /* LSYSCACHE_H */
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
* ENHANCEMENTS, OR MODIFICATIONS. * ENHANCEMENTS, OR MODIFICATIONS.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.15 2000/11/16 22:30:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.16 2000/11/20 20:36:51 tgl Exp $
* *
**********************************************************************/ **********************************************************************/
...@@ -258,6 +258,7 @@ plperl_init_safe_interp(void) ...@@ -258,6 +258,7 @@ plperl_init_safe_interp(void)
* call this function for execution of * call this function for execution of
* perl procedures. * perl procedures.
**********************************************************************/ **********************************************************************/
PG_FUNCTION_INFO_V1(plperl_call_handler);
/* keep non-static */ /* keep non-static */
Datum Datum
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.5 2000/05/29 01:59:14 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.6 2000/11/20 20:36:52 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -66,6 +66,8 @@ static PLpgSQL_function *compiled_functions = NULL; ...@@ -66,6 +66,8 @@ static PLpgSQL_function *compiled_functions = NULL;
* call this function for execution of PL/pgSQL procedures. * call this function for execution of PL/pgSQL procedures.
* ---------- * ----------
*/ */
PG_FUNCTION_INFO_V1(plpgsql_call_handler);
Datum Datum
plpgsql_call_handler(PG_FUNCTION_ARGS) plpgsql_call_handler(PG_FUNCTION_ARGS)
{ {
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
* ENHANCEMENTS, OR MODIFICATIONS. * ENHANCEMENTS, OR MODIFICATIONS.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.29 2000/11/16 22:30:52 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.30 2000/11/20 20:36:52 tgl Exp $
* *
**********************************************************************/ **********************************************************************/
...@@ -325,6 +325,7 @@ pltcl_init_load_unknown(void) ...@@ -325,6 +325,7 @@ pltcl_init_load_unknown(void)
* call this function for execution of * call this function for execution of
* PL/Tcl procedures. * PL/Tcl procedures.
**********************************************************************/ **********************************************************************/
PG_FUNCTION_INFO_V1(pltcl_call_handler);
/* keep non-static */ /* keep non-static */
Datum Datum
...@@ -371,6 +372,12 @@ pltcl_call_handler(PG_FUNCTION_ARGS) ...@@ -371,6 +372,12 @@ pltcl_call_handler(PG_FUNCTION_ARGS)
return retval; return retval;
} }
/*
* Alternate handler for unsafe functions
*/
PG_FUNCTION_INFO_V1(pltclu_call_handler);
/* keep non-static */ /* keep non-static */
Datum Datum
pltclu_call_handler(PG_FUNCTION_ARGS) pltclu_call_handler(PG_FUNCTION_ARGS)
......
...@@ -15,30 +15,30 @@ CREATE FUNCTION widget_out(opaque) ...@@ -15,30 +15,30 @@ CREATE FUNCTION widget_out(opaque)
CREATE FUNCTION check_primary_key () CREATE FUNCTION check_primary_key ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@' AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION check_foreign_key () CREATE FUNCTION check_foreign_key ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@' AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION autoinc () CREATE FUNCTION autoinc ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/../../../contrib/spi/autoinc@DLSUFFIX@' AS '@abs_builddir@/../../../contrib/spi/autoinc@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION funny_dup17 () CREATE FUNCTION funny_dup17 ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION ttdummy () CREATE FUNCTION ttdummy ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION set_ttdummy (int4) CREATE FUNCTION set_ttdummy (int4)
RETURNS int4 RETURNS int4
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
...@@ -30,28 +30,33 @@ CREATE FUNCTION user_relns() ...@@ -30,28 +30,33 @@ CREATE FUNCTION user_relns()
CREATE FUNCTION pt_in_widget(point, widget) CREATE FUNCTION pt_in_widget(point, widget)
RETURNS bool RETURNS bool
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION overpaid(emp) CREATE FUNCTION overpaid(emp)
RETURNS bool RETURNS bool
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION boxarea(box) CREATE FUNCTION boxarea(box)
RETURNS float8 RETURNS float8
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION interpt_pp(path, path) CREATE FUNCTION interpt_pp(path, path)
RETURNS point RETURNS point
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION reverse_name(name) CREATE FUNCTION reverse_name(name)
RETURNS name RETURNS name
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'c'; LANGUAGE 'c';
CREATE FUNCTION oldstyle_length(int4, text)
RETURNS int4
AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'c';
-- --
-- Function dynamic loading -- Function dynamic loading
-- --
......
...@@ -215,6 +215,19 @@ SELECT user_relns() AS user_relns ...@@ -215,6 +215,19 @@ SELECT user_relns() AS user_relns
--SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))) AS equip_name; --SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))) AS equip_name;
--
-- check that old-style C functions work properly with TOASTed values
--
create table oldstyle_test(i int4, t text);
insert into oldstyle_test values(null,null);
insert into oldstyle_test values(0,'12');
insert into oldstyle_test values(1000,'12');
insert into oldstyle_test values(0, repeat('x', 50000));
select i, length(t), octet_length(t), oldstyle_length(i,t) from oldstyle_test;
drop table oldstyle_test;
-- --
-- functional joins -- functional joins
-- --
......
...@@ -13,24 +13,24 @@ CREATE FUNCTION widget_out(opaque) ...@@ -13,24 +13,24 @@ CREATE FUNCTION widget_out(opaque)
CREATE FUNCTION check_primary_key () CREATE FUNCTION check_primary_key ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@' AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION check_foreign_key () CREATE FUNCTION check_foreign_key ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@' AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION autoinc () CREATE FUNCTION autoinc ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/../../../contrib/spi/autoinc@DLSUFFIX@' AS '@abs_builddir@/../../../contrib/spi/autoinc@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION funny_dup17 () CREATE FUNCTION funny_dup17 ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION ttdummy () CREATE FUNCTION ttdummy ()
RETURNS opaque RETURNS opaque
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION set_ttdummy (int4) CREATE FUNCTION set_ttdummy (int4)
RETURNS int4 RETURNS int4
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
...@@ -23,23 +23,27 @@ CREATE FUNCTION user_relns() ...@@ -23,23 +23,27 @@ CREATE FUNCTION user_relns()
CREATE FUNCTION pt_in_widget(point, widget) CREATE FUNCTION pt_in_widget(point, widget)
RETURNS bool RETURNS bool
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION overpaid(emp) CREATE FUNCTION overpaid(emp)
RETURNS bool RETURNS bool
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION boxarea(box) CREATE FUNCTION boxarea(box)
RETURNS float8 RETURNS float8
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION interpt_pp(path, path) CREATE FUNCTION interpt_pp(path, path)
RETURNS point RETURNS point
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'newC'; LANGUAGE 'C';
CREATE FUNCTION reverse_name(name) CREATE FUNCTION reverse_name(name)
RETURNS name RETURNS name
AS '@abs_builddir@/regress@DLSUFFIX@' AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'c'; LANGUAGE 'c';
CREATE FUNCTION oldstyle_length(int4, text)
RETURNS int4
AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'c';
-- --
-- Function dynamic loading -- Function dynamic loading
-- --
......
...@@ -657,6 +657,24 @@ SELECT user_relns() AS user_relns ...@@ -657,6 +657,24 @@ SELECT user_relns() AS user_relns
--SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))) AS equip_name; --SELECT name(equipment(hobby_construct(text 'skywalking', text 'mer'))) AS equip_name;
-- --
-- check that old-style C functions work properly with TOASTed values
--
create table oldstyle_test(i int4, t text);
insert into oldstyle_test values(null,null);
insert into oldstyle_test values(0,'12');
insert into oldstyle_test values(1000,'12');
insert into oldstyle_test values(0, repeat('x', 50000));
select i, length(t), octet_length(t), oldstyle_length(i,t) from oldstyle_test;
i | length | octet_length | oldstyle_length
------+--------+--------------+-----------------
| | |
0 | 2 | 2 | 2
1000 | 2 | 2 | 1002
0 | 50000 | 581 | 50000
(4 rows)
drop table oldstyle_test;
--
-- functional joins -- functional joins
-- --
-- --
......
/* /*
* $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.44 2000/08/24 23:34:11 tgl Exp $ * $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.45 2000/11/20 20:36:53 tgl Exp $
*/ */
#include <float.h> /* faked on sunos */ #include <float.h> /* faked on sunos */
...@@ -25,10 +25,13 @@ extern void regress_lseg_construct(LSEG *lseg, Point *pt1, Point *pt2); ...@@ -25,10 +25,13 @@ extern void regress_lseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
extern Datum overpaid(PG_FUNCTION_ARGS); extern Datum overpaid(PG_FUNCTION_ARGS);
extern Datum boxarea(PG_FUNCTION_ARGS); extern Datum boxarea(PG_FUNCTION_ARGS);
extern char *reverse_name(char *string); extern char *reverse_name(char *string);
extern int oldstyle_length(int n, text *t);
/* /*
** Distance from a point to a path ** Distance from a point to a path
*/ */
PG_FUNCTION_INFO_V1(regress_dist_ptpath);
Datum Datum
regress_dist_ptpath(PG_FUNCTION_ARGS) regress_dist_ptpath(PG_FUNCTION_ARGS)
{ {
...@@ -69,6 +72,8 @@ regress_dist_ptpath(PG_FUNCTION_ARGS) ...@@ -69,6 +72,8 @@ regress_dist_ptpath(PG_FUNCTION_ARGS)
/* this essentially does a cartesian product of the lsegs in the /* this essentially does a cartesian product of the lsegs in the
two paths, and finds the min distance between any two lsegs */ two paths, and finds the min distance between any two lsegs */
PG_FUNCTION_INFO_V1(regress_path_dist);
Datum Datum
regress_path_dist(PG_FUNCTION_ARGS) regress_path_dist(PG_FUNCTION_ARGS)
{ {
...@@ -129,6 +134,8 @@ POLYGON *poly; ...@@ -129,6 +134,8 @@ POLYGON *poly;
} }
/* return the point where two paths intersect, or NULL if no intersection. */ /* return the point where two paths intersect, or NULL if no intersection. */
PG_FUNCTION_INFO_V1(interpt_pp);
Datum Datum
interpt_pp(PG_FUNCTION_ARGS) interpt_pp(PG_FUNCTION_ARGS)
{ {
...@@ -182,6 +189,8 @@ Point *pt2; ...@@ -182,6 +189,8 @@ Point *pt2;
lseg->m = point_sl(pt1, pt2); lseg->m = point_sl(pt1, pt2);
} }
PG_FUNCTION_INFO_V1(overpaid);
Datum Datum
overpaid(PG_FUNCTION_ARGS) overpaid(PG_FUNCTION_ARGS)
{ {
...@@ -254,6 +263,8 @@ WIDGET *widget; ...@@ -254,6 +263,8 @@ WIDGET *widget;
return result; return result;
} }
PG_FUNCTION_INFO_V1(pt_in_widget);
Datum Datum
pt_in_widget(PG_FUNCTION_ARGS) pt_in_widget(PG_FUNCTION_ARGS)
{ {
...@@ -265,6 +276,8 @@ pt_in_widget(PG_FUNCTION_ARGS) ...@@ -265,6 +276,8 @@ pt_in_widget(PG_FUNCTION_ARGS)
#define ABS(X) ((X) >= 0 ? (X) : -(X)) #define ABS(X) ((X) >= 0 ? (X) : -(X))
PG_FUNCTION_INFO_V1(boxarea);
Datum Datum
boxarea(PG_FUNCTION_ARGS) boxarea(PG_FUNCTION_ARGS)
{ {
...@@ -278,8 +291,7 @@ boxarea(PG_FUNCTION_ARGS) ...@@ -278,8 +291,7 @@ boxarea(PG_FUNCTION_ARGS)
} }
char * char *
reverse_name(string) reverse_name(char *string)
char *string;
{ {
int i; int i;
int len; int len;
...@@ -301,6 +313,20 @@ char *string; ...@@ -301,6 +313,20 @@ char *string;
return new_string; return new_string;
} }
/* This rather silly function is just to test that oldstyle functions
* work correctly on toast-able inputs.
*/
int
oldstyle_length(int n, text *t)
{
int len = 0;
if (t)
len = VARSIZE(t) - VARHDRSZ;
return n + len;
}
#include "executor/spi.h" /* this is what you need to work with SPI */ #include "executor/spi.h" /* this is what you need to work with SPI */
#include "commands/trigger.h" /* -"- and triggers */ #include "commands/trigger.h" /* -"- and triggers */
...@@ -312,6 +338,8 @@ static bool fd17b_recursion = true; ...@@ -312,6 +338,8 @@ static bool fd17b_recursion = true;
static bool fd17a_recursion = true; static bool fd17a_recursion = true;
extern Datum funny_dup17(PG_FUNCTION_ARGS); extern Datum funny_dup17(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(funny_dup17);
Datum Datum
funny_dup17(PG_FUNCTION_ARGS) funny_dup17(PG_FUNCTION_ARGS)
{ {
...@@ -428,6 +456,8 @@ extern Datum set_ttdummy(PG_FUNCTION_ARGS); ...@@ -428,6 +456,8 @@ extern Datum set_ttdummy(PG_FUNCTION_ARGS);
static void *splan = NULL; static void *splan = NULL;
static bool ttoff = false; static bool ttoff = false;
PG_FUNCTION_INFO_V1(ttdummy);
Datum Datum
ttdummy(PG_FUNCTION_ARGS) ttdummy(PG_FUNCTION_ARGS)
{ {
...@@ -625,6 +655,8 @@ ttdummy(PG_FUNCTION_ARGS) ...@@ -625,6 +655,8 @@ ttdummy(PG_FUNCTION_ARGS)
return PointerGetDatum(rettuple); return PointerGetDatum(rettuple);
} }
PG_FUNCTION_INFO_V1(set_ttdummy);
Datum Datum
set_ttdummy(PG_FUNCTION_ARGS) set_ttdummy(PG_FUNCTION_ARGS)
{ {
......
...@@ -38,6 +38,7 @@ DROP FUNCTION interpt_pp(path,path); ...@@ -38,6 +38,7 @@ DROP FUNCTION interpt_pp(path,path);
DROP FUNCTION reverse_name(name); DROP FUNCTION reverse_name(name);
DROP FUNCTION oldstyle_length(int4, text);
-- --
-- OPERATOR REMOVAL -- OPERATOR REMOVAL
......
...@@ -30,6 +30,8 @@ Datum c_overpaid(PG_FUNCTION_ARGS); ...@@ -30,6 +30,8 @@ Datum c_overpaid(PG_FUNCTION_ARGS);
/* By Value */ /* By Value */
PG_FUNCTION_INFO_V1(add_one);
Datum Datum
add_one(PG_FUNCTION_ARGS) add_one(PG_FUNCTION_ARGS)
{ {
...@@ -40,6 +42,8 @@ add_one(PG_FUNCTION_ARGS) ...@@ -40,6 +42,8 @@ add_one(PG_FUNCTION_ARGS)
/* By Reference, Fixed Length */ /* By Reference, Fixed Length */
PG_FUNCTION_INFO_V1(add_one_float8);
Datum Datum
add_one_float8(PG_FUNCTION_ARGS) add_one_float8(PG_FUNCTION_ARGS)
{ {
...@@ -49,6 +53,8 @@ add_one_float8(PG_FUNCTION_ARGS) ...@@ -49,6 +53,8 @@ add_one_float8(PG_FUNCTION_ARGS)
PG_RETURN_FLOAT8(arg + 1.0); PG_RETURN_FLOAT8(arg + 1.0);
} }
PG_FUNCTION_INFO_V1(makepoint);
Datum Datum
makepoint(PG_FUNCTION_ARGS) makepoint(PG_FUNCTION_ARGS)
{ {
...@@ -64,6 +70,8 @@ makepoint(PG_FUNCTION_ARGS) ...@@ -64,6 +70,8 @@ makepoint(PG_FUNCTION_ARGS)
/* By Reference, Variable Length */ /* By Reference, Variable Length */
PG_FUNCTION_INFO_V1(copytext);
Datum Datum
copytext(PG_FUNCTION_ARGS) copytext(PG_FUNCTION_ARGS)
{ {
...@@ -82,6 +90,8 @@ copytext(PG_FUNCTION_ARGS) ...@@ -82,6 +90,8 @@ copytext(PG_FUNCTION_ARGS)
PG_RETURN_TEXT_P(new_t); PG_RETURN_TEXT_P(new_t);
} }
PG_FUNCTION_INFO_V1(concat_text);
Datum Datum
concat_text(PG_FUNCTION_ARGS) concat_text(PG_FUNCTION_ARGS)
{ {
...@@ -99,6 +109,8 @@ concat_text(PG_FUNCTION_ARGS) ...@@ -99,6 +109,8 @@ concat_text(PG_FUNCTION_ARGS)
/* Composite types */ /* Composite types */
PG_FUNCTION_INFO_V1(c_overpaid);
Datum Datum
c_overpaid(PG_FUNCTION_ARGS) c_overpaid(PG_FUNCTION_ARGS)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment