Revise handling of oldstyle/newstyle functions per recent discussions
authorTom Lane
Mon, 20 Nov 2000 20:36:57 +0000 (20:36 +0000)
committerTom Lane
Mon, 20 Nov 2000 20:36:57 +0000 (20:36 +0000)
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.

52 files changed:
contrib/fulltextindex/README.fti
contrib/fulltextindex/fti.c
contrib/fulltextindex/fti.pl
contrib/fulltextindex/fti.sql.in
contrib/lo/lo.c
contrib/lo/lo.sql.in
contrib/noupdate/noup.c
contrib/noupdate/noup.sql.in
contrib/pgcrypto/pgcrypto.c
contrib/pgcrypto/pgcrypto.sql.in
contrib/soundex/soundex.c
contrib/soundex/soundex.sql.in
contrib/spi/autoinc.c
contrib/spi/autoinc.sql.in
contrib/spi/insert_username.c
contrib/spi/insert_username.sql.in
contrib/spi/moddatetime.c
contrib/spi/moddatetime.sql.in
contrib/spi/refint.c
contrib/spi/refint.sql.in
contrib/spi/timetravel.c
contrib/spi/timetravel.sql.in
doc/src/sgml/ref/create_function.sgml
doc/src/sgml/ref/create_language.sgml
doc/src/sgml/trigger.sgml
doc/src/sgml/xfunc.sgml
src/backend/catalog/pg_proc.c
src/backend/commands/define.c
src/backend/commands/remove.c
src/backend/commands/trigger.c
src/backend/utils/Gen_fmgrtab.sh
src/backend/utils/cache/lsyscache.c
src/backend/utils/fmgr/dfmgr.c
src/backend/utils/fmgr/fmgr.c
src/bin/scripts/createlang.sh
src/include/catalog/catversion.h
src/include/catalog/pg_language.h
src/include/fmgr.h
src/include/utils/fmgrtab.h
src/include/utils/lsyscache.h
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_handler.c
src/pl/tcl/pltcl.c
src/test/regress/input/create_function_1.source
src/test/regress/input/create_function_2.source
src/test/regress/input/misc.source
src/test/regress/output/create_function_1.source
src/test/regress/output/create_function_2.source
src/test/regress/output/misc.source
src/test/regress/regress.c
src/test/regress/sql/drop.sql
src/tutorial/funcs_new.c

index fdb6fcf3b10663d9b4ea6d442f9cbee5a52cbb75..10838db6912641d129643c6abff8025551523d1b 100644 (file)
@@ -57,7 +57,7 @@ sub-string will fit.
 The create the function that contains the trigger::
 
    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:
 
index a98fcd47dc7a86be4d71f0552f4d75021b5a198f..bb4636ff3e03937508f9e4b6281fe8809824201a 100644 (file)
@@ -17,7 +17,7 @@
    Example:
 
 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 index title_fti_idx on title_fti (string);
@@ -93,6 +93,8 @@ static int    nDeletePlans = 0;
 static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
 
 /***********************************************************************/
+PG_FUNCTION_INFO_V1(fti);
+
 Datum
 fti(PG_FUNCTION_ARGS)
 {
index 6b6d68e4900ac35412c907dbf977179817d74431..02bf057e94a6597ef584ea82272a649e9818426b 100644 (file)
@@ -29,7 +29,7 @@
 #
 #      create function fti() returns opaque as
 #          '/path/to/fti/file/fti.so'
-#      language 'newC';
+#      language 'C';
 #
 #      create trigger my_fti_trigger after update or insert or delete
 #          on mytable
index c0b3662ae592645680e25606a441cd3f7729a643..e0da2353c52447eb1b019fb516d827abf4842c21 100644 (file)
@@ -1,3 +1,3 @@
 create function fti() returns opaque as
    'MODULE_PATHNAME'
-   language 'newC';
\ No newline at end of file
+   language 'C';
\ No newline at end of file
index 386c2c2d2f76263abfd7c6584e2257954255d0e8..5de00ad5ca4bccca3f791feea61f26c11337c4ac 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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)
 /*
  * This handles the trigger that protects us from orphaned large objects
  */
+PG_FUNCTION_INFO_V1(lo_manage);
+
 Datum
 lo_manage(PG_FUNCTION_ARGS)
 {
index 4aa75a60fe17ec9935e6eb411d829d178bcb90af..9b340b196f8425d0f46384421d6376d60f6c8a5f 100644 (file)
@@ -1,7 +1,7 @@
 --
 -- 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
@@ -44,7 +44,7 @@ create function lo(oid)
 create function lo_manage()
    returns opaque
    as 'MODULE_PATHNAME'
-   language 'newC';
+   language 'C';
 
 -- This allows us to map lo to oid
 --
index 5035e127be86c90c0e493f1e787135e1963d56ad..af857c41f6e33ebb9bc9ba2373b7547d71da42d5 100644 (file)
@@ -16,6 +16,8 @@ extern Datum noup(PG_FUNCTION_ARGS);
  * EXECUTE PROCEDURE noup ('col').
  */
 
+PG_FUNCTION_INFO_V1(noup);
+
 Datum
 noup(PG_FUNCTION_ARGS)
 {
index cc1e6fa146fce8cb2c4599588f1d6bc1725788f0..abf92837d1d626ab3b9e0c63abea97c410f289bc 100644 (file)
@@ -3,5 +3,4 @@ DROP FUNCTION noup ();
 CREATE FUNCTION noup ()
    RETURNS opaque
    AS 'MODULE_PATHNAME'
-   LANGUAGE 'newC'
-;
+   LANGUAGE 'C';
index 4897edb9d2542116655cfa5b01c5652791d9c488..e4978dea2daae700a2bf7e352493db54ecb38bac 100644 (file)
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * 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 
@@ -59,6 +59,8 @@ find_digest(pg_digest *hbuf, text *name, int silent);
 
 
 /* SQL function: hash(text, text) returns text */
+PG_FUNCTION_INFO_V1(digest);
+
 Datum
 digest(PG_FUNCTION_ARGS)
 {
@@ -95,6 +97,8 @@ digest(PG_FUNCTION_ARGS)
 }
 
 /* check if given hash exists */
+PG_FUNCTION_INFO_V1(digest_exists);
+
 Datum
 digest_exists(PG_FUNCTION_ARGS)
 {
index a30b3116e5e1c6b897cee32aa9fddbf261a37901..2059c0d8e5998081d76640bf0eff194377a952bd 100644 (file)
@@ -4,9 +4,9 @@
 
 CREATE FUNCTION digest(text, text) RETURNS text
   AS '@MODULE_FILENAME@',
-  'digest' LANGUAGE 'newC';
+  'digest' LANGUAGE 'C';
 
 CREATE FUNCTION digest_exists(text) RETURNS bool
   AS '@MODULE_FILENAME@',
-  'digest_exists' LANGUAGE 'newC';
+  'digest_exists' LANGUAGE 'C';
 
index f2acba403666a21e00ea57120a6de082e52212c0..f66cb21f2426517986a4b51972387775c7712e76 100644 (file)
@@ -1,4 +1,4 @@
-/* $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 "fmgr.h"
 #include "utils/builtins.h"
@@ -7,11 +7,9 @@
 #include 
 
 
-Datum
-text_soundex(PG_FUNCTION_ARGS);
+Datum text_soundex(PG_FUNCTION_ARGS);
 
-static void
-soundex(const char *instr, char *outstr);
+static void soundex(const char *instr, char *outstr);
 
 #define SOUNDEX_LEN 4
 
@@ -24,6 +22,8 @@ soundex(const char *instr, char *outstr);
 /*
  * SQL function: text_soundex(text) returns text
  */
+PG_FUNCTION_INFO_V1(text_soundex);
+
 Datum
 text_soundex(PG_FUNCTION_ARGS)
 {
@@ -36,6 +36,7 @@ text_soundex(PG_FUNCTION_ARGS)
 
    PG_RETURN_TEXT_P(_textin(outstr));
 }
+
 #endif /* not SOUNDEX_TEST */
 
 
index 4cb0ad0e4dbf2849d245d4ba169a16f9f8fb1e0e..4805694f9a6b5fca1b0584b412cf0ae8aa371b85 100644 (file)
@@ -1,5 +1,5 @@
 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
-  AS '@MODULE_FILENAME@', 'text_soundex' LANGUAGE 'newC';
+  AS '@MODULE_FILENAME@', 'text_soundex' LANGUAGE 'C';
index f8b86217e73b79115cef4017d32a4d013246dc12..8592ea7ed9bcdc112197b7286dcd136b3d7b8d82 100644 (file)
@@ -5,6 +5,8 @@
 
 extern Datum autoinc(PG_FUNCTION_ARGS);
 
+PG_FUNCTION_INFO_V1(autoinc);
+
 Datum
 autoinc(PG_FUNCTION_ARGS)
 {
index d587b567b37b33e85b1f144796c55b9dfd24c49b..367674294352dc28fedce86ff9b6490a45558764 100644 (file)
@@ -3,4 +3,4 @@ DROP FUNCTION autoinc();
 CREATE FUNCTION autoinc() 
    RETURNS opaque 
    AS 'MODULE_PATHNAME'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
index 978a873ec90dd67b7fe22009c560344b3e88d747..6bc31444200332ca913bb50c7a21c7f62d85ec2a 100644 (file)
@@ -12,6 +12,8 @@
 
 extern Datum   insert_username(PG_FUNCTION_ARGS);
 
+PG_FUNCTION_INFO_V1(insert_username);
+
 Datum
 insert_username(PG_FUNCTION_ARGS)
 {
index d60aebc1b0e73434b55de2872c85ea200c4fbb00..436fc88b73cdbe23da6899aa10da43a69a681e79 100644 (file)
@@ -3,4 +3,4 @@ DROP FUNCTION insert_username();
 CREATE FUNCTION insert_username() 
    RETURNS opaque 
    AS 'MODULE_PATHNAME'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
index 0229eb8f155015d9f06fd70a9a802a8e7fe543d3..73b151851888d29eb2d2ebdcf00a28dbe012a899 100644 (file)
@@ -17,6 +17,8 @@ OH, me, I'm Terry Mackintosh 
 
 extern Datum   moddatetime(PG_FUNCTION_ARGS);
 
+PG_FUNCTION_INFO_V1(moddatetime);
+
 Datum
 moddatetime(PG_FUNCTION_ARGS)
 {
index cfb7c3c508b0af84458ab44ddf5937fef565703b..d497900ecf19431fc5719307325d74f75121df0b 100644 (file)
@@ -3,4 +3,4 @@ DROP FUNCTION moddatetime();
 CREATE FUNCTION moddatetime() 
    RETURNS opaque 
    AS 'MODULE_PATHNAME'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
index 4bbe761573b9bdce64543df3b6d437a648e60385..d7a8d73c8e1e3e08a995e3d9ae73d82349640295 100644 (file)
@@ -36,6 +36,8 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
  * check_primary_key ('Fkey1', 'Fkey2', 'Ptable', 'Pkey1', 'Pkey2').
  */
 
+PG_FUNCTION_INFO_V1(check_primary_key);
+
 Datum
 check_primary_key(PG_FUNCTION_ARGS)
 {
@@ -216,6 +218,8 @@ check_primary_key(PG_FUNCTION_ARGS)
  * 'Ftable1', 'Fkey11', 'Fkey12', 'Ftable2', 'Fkey21', 'Fkey22').
  */
 
+PG_FUNCTION_INFO_V1(check_foreign_key);
+
 Datum
 check_foreign_key(PG_FUNCTION_ARGS)
 {
index 91448e8a2ed03e82cb68fc050427dc6d70a0cfdf..d193319d9d4bfaf37341feeb0704227a28eec61d 100644 (file)
@@ -4,11 +4,9 @@ DROP FUNCTION check_foreign_key ();
 CREATE FUNCTION check_primary_key ()
    RETURNS opaque
    AS 'MODULE_PATHNAME'
-   LANGUAGE 'newC'
-;
+   LANGUAGE 'C';
 
 CREATE FUNCTION check_foreign_key ()
    RETURNS opaque
    AS 'MODULE_PATHNAME'
-   LANGUAGE 'newC'
-;
+   LANGUAGE 'C';
index cd50cd84890696f69117eff6b8da16313f1e8017..41e7b092b32b7e63a0d7cb016e92311db75e8663 100644 (file)
@@ -47,6 +47,8 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
  * timetravel ('date_on', 'date_off').
  */
 
+PG_FUNCTION_INFO_V1(timetravel);
+
 Datum
 timetravel(PG_FUNCTION_ARGS)
 {
@@ -326,6 +328,8 @@ timetravel(PG_FUNCTION_ARGS)
  * set_timetravel (relname, on) --
  *                 turn timetravel for specified relation ON/OFF
  */
+PG_FUNCTION_INFO_V1(set_timetravel);
+
 Datum
 set_timetravel(PG_FUNCTION_ARGS)
 {
index 0de680cb39ad5427202d15023bd16684136de5c2..46912abf6d78588fd2237290c6eee0d2810bcf8d 100644 (file)
@@ -4,9 +4,9 @@ DROP FUNCTION set_timetravel(name, int4);
 CREATE FUNCTION timetravel() 
    RETURNS opaque 
    AS 'MODULE_PATHNAME'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 
 CREATE FUNCTION set_timetravel(name, int4) 
    RETURNS int4 
    AS 'MODULE_PATHNAME'
-   LANGUAGE 'newC' WITH (isStrict);
+   LANGUAGE 'C' WITH (isStrict);
index 20a7b6f8b039ba64e0d4825eb460436b9b4d659e..bb733b8df2e1124e0bf76dc32085abb47f2ed5ab 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -119,8 +119,7 @@ CREATE FUNCTION name ( [ 
       
        
    May be 'sql',
-   'C', 'newC',
-   'internal', 'newinternal',
+   'C', 'internal',
    or 'plname',
    where 'plname'
    is the name of a created procedural language. See
@@ -258,7 +257,7 @@ CREATE
    
 
    
-    Two internal or newinternal
+    Two internal
     functions cannot have the same C name without causing
     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
index 934b6cbaf9e139b96a6e5edce44e0be34b2ef0e3..f5e1c6ffa900ae4ccf581f5279ffe15b6be80166 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -163,7 +163,8 @@ ERROR:  PL handler function funcname
     
      
       In Postgres 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.
      
     
 
@@ -180,7 +181,7 @@ ERROR:  PL handler function funcname
    
 
    
-    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
     containing argument values and information about the called function,
     and it is expected to return a Datum result (and possibly set the
@@ -269,9 +270,7 @@ ERROR:  PL handler function funcname
    lanname   | lanispl | lanpltrusted | lanplcallfoid | lancompiler
 -------------+---------+--------------+---------------+-------------
  internal    | f       | f            |             0 | n/a
- newinternal | f       | f            |             0 | n/a
  C           | f       | f            |             0 | /bin/cc
- newC        | f       | f            |             0 | /bin/cc
  sql         | f       | f            |             0 | postgres
 
 
@@ -279,8 +278,9 @@ ERROR:  PL handler function funcname
 
    
     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.
+    The call handler cannot use the old-style 'C' function interface.
    
 
     
@@ -306,6 +306,8 @@ ERROR:  PL handler function funcname
 #include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 
+PG_FUNCTION_INFO_V1(plsample_call_handler);
+
 Datum
 plsample_call_handler(PG_FUNCTION_ARGS)
 {
@@ -344,7 +346,7 @@ plsample_call_handler(PG_FUNCTION_ARGS)
    
 CREATE FUNCTION plsample_call_handler () RETURNS opaque
     AS '/usr/local/pgsql/lib/plsample.so'
-    LANGUAGE 'newC';
+    LANGUAGE 'C';
 CREATE PROCEDURAL LANGUAGE 'plsample'
     HANDLER plsample_call_handler
     LANCOMPILER 'PL/Sample';
index 0b3442517c93a7be03c1ec2582b902215b9a3728..d248887a59941e78ec6b107d6756e5f5ee5d0c80 100644 (file)
@@ -22,7 +22,7 @@
    
     The trigger function must be created before the trigger is created as a
     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.
    
 
    
@@ -447,6 +447,8 @@ execution of Q) or after Q is done.
 
 extern Datum trigf(PG_FUNCTION_ARGS);
 
+PG_FUNCTION_INFO_V1(trigf);
+
 Datum
 trigf(PG_FUNCTION_ARGS)
 {
@@ -513,7 +515,7 @@ trigf(PG_FUNCTION_ARGS)
 
     
 create function trigf () returns opaque as 
-'...path_to_so' language 'newC';
+'...path_to_so' language 'C';
 
 create table ttest (x int4);
     
index d02718d53a7e8b4479114ddb078de2753b7d2415..f2dc29817460700a7a9006fd1e0f5c4ede7a156d 100644 (file)
@@ -1,5 +1,5 @@
 
 
  
@@ -339,9 +339,9 @@ SELECT clean_EMP();
    
 
    
-    There are two procedural languages available with the standard
-    Postgres distribution (PLTCL and PLSQL), and other
-    languages can be defined.
+    There are currently three procedural languages available in the standard
+    Postgres distribution (PLSQL, PLTCL and
+    PLPERL), and other languages can be defined.
     Refer to  for
     more information.
    
@@ -366,12 +366,7 @@ SELECT clean_EMP();
 
    
     Internal functions are declared in CREATE FUNCTION
-    with language name internal or
-    newinternal, 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
-    C and newC functions respectively;
-    see the next section for details.
+    with language name internal.
    
   
 
@@ -404,9 +399,9 @@ SELECT clean_EMP();
    
     The string which specifies the object file (the first string in the AS
     clause) should be the full path 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
-    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
     the command nm will print all of the link
     symbols in a dynamically loadable object.
@@ -422,11 +417,11 @@ SELECT clean_EMP();
 
    
     Two different calling conventions are currently used for C functions.
-    The "old style" (pre-Postgres-7.1) method
-    is selected by writing language name 'C' in the
-    CREATE FUNCTION command, while the "new style"
-    (7.1 and later) method is selecting by writing language name
-    'newC'.  Old-style functions are now deprecated
+    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.
    
@@ -484,7 +479,7 @@ SELECT clean_EMP();
     include/postgres.h
    
    
-    char
+    "char"
     char
     N/A
    
@@ -583,16 +578,6 @@ SELECT clean_EMP();
     TimeInterval
     utils/nabstime.h
    
-   
-    uint2
-    uint16
-    include/c.h
-   
-   
-    uint4
-    uint32
-    include/c.h
-   
    
     xid
     (XID *)
@@ -694,7 +679,7 @@ typedef struct {
     
 
     
-     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
      a  structure  in  C.  When manipulating 
      variable-length types, we must  be  careful  to  allocate  
@@ -721,12 +706,12 @@ memmove(destination->data, buffer, 40);
    
 
    
-    <span class="marked">Old-style</span> Calling Conventions for C-Language Functions
+    <span class="marked">Version-0</span> Calling Conventions for C-Language Functions
 
     
      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 "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
      careful to use the C representation of each SQL data type as shown
      above.
@@ -854,26 +839,39 @@ CREATE FUNCTION concat_text(text, text) RETURNS text
     
 
     
-     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
      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
-     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.
     
    
 
    
-    <span class="marked">New-style</span> Calling Conventions for C-Language Functions
+    <span class="marked">Version-1</span> Calling Conventions for C-Language Functions
 
     
-     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 a new-style function is always
+     of a version-1 function is always
      
                 Datum funcname(PG_FUNCTION_ARGS)
      
-     Each actual argument is fetched using a PG_GETARG_xxx() macro that
+     In addition, the macro call
+     
+                PG_FUNCTION_INFO_V1(funcname);
+     
+     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
+     required for dynamically-loaded functions.
+    
+
+    
+     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
      using a PG_RETURN_xxx() macro for the return type.
     
@@ -887,6 +885,8 @@ CREATE FUNCTION concat_text(text, text) RETURNS text
 #include "fmgr.h"
 
 /* By Value */
+
+PG_FUNCTION_INFO_V1(add_one);
          
 Datum
 add_one(PG_FUNCTION_ARGS)
@@ -898,6 +898,8 @@ add_one(PG_FUNCTION_ARGS)
 
 /* By Reference, Fixed Length */
 
+PG_FUNCTION_INFO_V1(add_one_float8);
+
 Datum
 add_one_float8(PG_FUNCTION_ARGS)
 {
@@ -907,6 +909,8 @@ add_one_float8(PG_FUNCTION_ARGS)
     PG_RETURN_FLOAT8(arg + 1.0);
 }
 
+PG_FUNCTION_INFO_V1(makepoint);
+
 Datum
 makepoint(PG_FUNCTION_ARGS)
 {
@@ -922,6 +926,8 @@ makepoint(PG_FUNCTION_ARGS)
 
 /* By Reference, Variable Length */
 
+PG_FUNCTION_INFO_V1(copytext);
+
 Datum
 copytext(PG_FUNCTION_ARGS)
 {
@@ -940,6 +946,8 @@ copytext(PG_FUNCTION_ARGS)
     PG_RETURN_TEXT_P(new_t);
 }
 
+PG_FUNCTION_INFO_V1(concat_text);
+
 Datum
 concat_text(PG_FUNCTION_ARGS)
 {
@@ -959,12 +967,11 @@ concat_text(PG_FUNCTION_ARGS)
 
     
      The CREATE FUNCTION commands are the same as
-     for the old-style equivalents, except that the language is specified
-     as 'newC' not 'C'.
+     for the old-style equivalents.
     
 
     
-     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
      improvements, because the macros can hide unnecessary detail.
      An example is that in coding add_one_float8, we no longer need to
@@ -973,11 +980,14 @@ concat_text(PG_FUNCTION_ARGS)
      to deal with fetching "toasted" (compressed or out-of-line) values.
      The old-style copytext and concat_text functions shown above are
      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.)
     
 
     
-     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
      (from either strict or non-strict functions), return "set" results,
      and implement trigger functions and procedural-language call handlers.
@@ -1026,7 +1036,9 @@ c_overpaid(TupleTableSlot *t, /* the current instance of EMP */
     return salary > 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
 c_overpaid(PG_FUNCTION_ARGS)
index 9d3ce5c50d6b084d1f880315cc797c3f2e290862..5d63ebf161652bc1ae2a254aa1452efb2d4f8b56 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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,
     * FUNCTION xyz AS '' LANGUAGE 'internal'.  To preserve some modicum
     * of backwards compatibility, accept an empty 'prosrc' value as
     * 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 ||
-       languageObjectId == NEWINTERNALlanguageId)
+   if (languageObjectId == INTERNALlanguageId)
    {
-       Oid         actualLangID;
-
        if (strlen(prosrc) == 0)
            prosrc = procedureName;
-       actualLangID = fmgr_internal_language(prosrc);
-       if (actualLangID == InvalidOid)
+       if (fmgr_internal_function(prosrc) == InvalidOid)
            elog(ERROR,
                 "ProcedureCreate: there is no builtin function named \"%s\"",
                 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
     * 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
     * called, but it seems friendlier to verify the library's validity
     * at CREATE FUNCTION time.
     */
 
-   if (languageObjectId == ClanguageId ||
-       languageObjectId == NEWClanguageId)
+   if (languageObjectId == ClanguageId)
    {
        /* If link symbol is specified as "-", substitute procedure name */
        if (strcmp(prosrc, "-") == 0)
            prosrc = procedureName;
-       (void) load_external_function(probin, prosrc);
+       (void) load_external_function(probin, prosrc, true);
+       (void) fetch_finfo_record(probin, prosrc);
    }
 
    /*
index 9d681a4a50fe2b6d814ed4df6963e1d986da94c4..63ccf32543fd8111688d8413cf8af69a7d14ab6a 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * 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
  *   The "DefineFoo" routines take the parse tree and pick out the
@@ -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 to upper case, or "newC", translate to that spelling.
+  translate to upper case.
 --------------------------------------------------------------------------*/
    int         i;
 
@@ -77,8 +77,6 @@ case_translate_language_name(const char *input, char *output)
 
    if (strcmp(output, "c") == 0)
        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,
 {
    Assert(as != NIL);
 
-   if (strcmp(languageName, "C") == 0 ||
-       strcmp(languageName, "newC") == 0)
+   if (strcmp(languageName, "C") == 0)
    {
 
        /*
@@ -230,8 +227,8 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
 
    char        languageName[NAMEDATALEN];
    /*
-    * name of language of function, with case adjusted: "C", "newC",
-    * "internal", "newinternal", "sql", etc.
+    * name of language of function, with case adjusted: "C",
+    * "internal", "sql", etc.
     */
 
    bool        returnsSet;
@@ -255,9 +252,7 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
     * Apply appropriate security checks depending on language.
     */
    if (strcmp(languageName, "C") == 0 ||
-       strcmp(languageName, "newC") == 0 ||
-       strcmp(languageName, "internal") == 0 ||
-       strcmp(languageName, "newinternal") == 0)
+       strcmp(languageName, "internal") == 0)
    {
        if (!superuser())
            elog(ERROR,
@@ -283,8 +278,8 @@ CreateFunction(ProcedureStmt *stmt, CommandDest dest)
        if (!HeapTupleIsValid(languageTuple))
            elog(ERROR,
                 "Unrecognized language specified in a CREATE FUNCTION: "
-                "'%s'.\n\tRecognized languages are sql, C, newC, "
-                "internal, newinternal, and created procedural languages.",
+                "'%s'.\n\tRecognized languages are sql, C, "
+                "internal, and created procedural languages.",
                 languageName);
 
        /* Check that this language is a PL */
index fdcd0e7e744846e0664b8117ffb0d94c3f5ce4a0..cb11b47a37c4c35f8a8d5c7bdff195c262cfd268 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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 */
    if (!HeapTupleIsValid(tup))
        func_error("RemoveFunction", functionName, nargs, argList, NULL);
 
-   if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId ||
-       ((Form_pg_proc) GETSTRUCT(tup))->prolang == NEWINTERNALlanguageId)
+   if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
    {
        /* "Helpful" notice when removing a builtin function ... */
        elog(NOTICE, "Removing built-in function \"%s\"", functionName);
index 22dfcac05244d438de49ed929f4c4bb2cd0be29b..cc31a0eb48bce75b705bb89662ca200f30cb8498 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * 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)
    funclang = ((Form_pg_proc) GETSTRUCT(tuple))->prolang;
    ReleaseSysCache(tuple);
 
-   if (funclang != ClanguageId &&
-       funclang != NEWClanguageId &&
-       funclang != INTERNALlanguageId &&
-       funclang != NEWINTERNALlanguageId)
+   if (funclang != ClanguageId && funclang != INTERNALlanguageId)
    {
        HeapTuple   langTup;
 
@@ -180,10 +177,10 @@ CreateTrigger(CreateTrigStmt *stmt)
                                 ObjectIdGetDatum(funclang),
                                 0, 0, 0);
        if (!HeapTupleIsValid(langTup))
-           elog(ERROR, "CreateTrigger: cache lookup for PL %u failed",
+           elog(ERROR, "CreateTrigger: cache lookup for language %u failed",
                 funclang);
        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);
    }
 
index 41a0bc3d712ee1a80a8a256d215e39e2487b58af..00f12e3e1f1cae4962125661dd2631f0295d6a1c 100644 (file)
@@ -9,7 +9,7 @@
 #
 #
 # 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
 
 #
 # 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
 # deal with preprocessor statements first (before we sort the
@@ -99,7 +99,6 @@ sed   -e 's/^.*OID[^=]*=[^0-9]*//' \
    -e 's/[     ]*).*$//' | \
 $AWK '
 /^#/       { print; next; }
-$4 == "11" { print; next; }
 $4 == "12" { print; next; }' > $CPPTMPFILE
 
 if [ $? -ne 0 ]; then
@@ -182,10 +181,6 @@ FuNkYfMgRsTuFf
 # Generate fmgr's built-in-function table.
 #
 # 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" <
 /*-------------------------------------------------------------------------
@@ -205,10 +200,6 @@ cat > "$$-$TABLEFILE" <
  * It has been GENERATED by $CMDNAME
  * 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
 # conditional expression instead.  Not all awks have conditional expressions.
 
 $AWK 'BEGIN {
-    Strict["t"] = "true"
-    Strict["f"] = "false"
-    OldStyle["11"] = "true"
-    OldStyle["12"] = "false"
+    Bool["t"] = "true"
+    Bool["f"] = "false"
 }
 { 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"
 
 if [ $? -ne 0 ]; then
index e07445837a5b83f42e32be173cb743f468ba8919..24b2cbada95dfaa5ec66538f087b222654c89c11 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * 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
  *   Eventually, the index information should go through here, too.
@@ -731,6 +731,27 @@ get_typalign(Oid typid)
 
 #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
  *
index 2dfddebd0a8731dc29191f35fcb77167d62b7955..ae8eb6785e58b58a3f338e8fc7e91fd5a6de1417 100644 (file)
@@ -8,20 +8,17 @@
  *
  *
  * 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 
 #include 
 
-#include "postgres.h"
-
-#include "catalog/pg_proc.h"
 #include "dynloader.h"
 #include "utils/dynamic_loader.h"
-#include "utils/builtins.h"
-#include "utils/syscache.h"
 
 
 /*
@@ -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)
 
 
+/*
+ * 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
-fmgr_dynamic(Oid functionId)
-{
-   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)
+load_external_function(char *filename, char *funcname,
+                      bool signalNotFound)
 {
    DynamicFileList *file_scanner;
    PGFunction  retval;
@@ -164,7 +122,7 @@ load_external_function(char *filename, char *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);
 
    return retval;
@@ -217,5 +175,5 @@ load_file(char *filename)
        }
    }
 
-   load_external_function(filename, (char *) NULL);
+   load_external_function(filename, (char *) NULL, false);
 }
index 5287615eea0fbcf491f6268dbbbf7dfbe9c2fe82..d4353a482460946b71f5a83f9532ec94aa244f21 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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 @@
 #include "executor/functions.h"
 #include "utils/builtins.h"
 #include "utils/fmgrtab.h"
+#include "utils/lsyscache.h"
 #include "utils/syscache.h"
 
 /*
@@ -42,7 +43,19 @@ typedef int32 ((*func_ptr) ());
 typedef char *((*func_ptr) ());
 #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_untrusted(PG_FUNCTION_ARGS);
 
@@ -104,9 +117,6 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
    const FmgrBuiltin *fbp;
    HeapTuple   procedureTuple;
    Form_pg_proc procedureStruct;
-   HeapTuple   languageTuple;
-   Form_pg_language languageStruct;
-   Oid         language;
    char       *prosrc;
 
    finfo->fn_oid = functionId;
@@ -120,16 +130,8 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
         */
        finfo->fn_nargs = fbp->nargs;
        finfo->fn_strict = fbp->strict;
-       finfo->fn_retset = false; /* assume no builtins return sets! */
-       if (fbp->oldstyle)
-       {
-           finfo->fn_addr = fmgr_oldstyle;
-           finfo->fn_extra = (void *) fbp->func;
-       }
-       else
-       {
-           finfo->fn_addr = fbp->func;
-       }
+       finfo->fn_retset = fbp->retset;
+       finfo->fn_addr = fbp->func;
        return;
    }
 
@@ -148,16 +150,15 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
 
    if (!procedureStruct->proistrusted)
    {
+       /* This isn't really supported anymore... */
        finfo->fn_addr = fmgr_untrusted;
        ReleaseSysCache(procedureTuple);
        return;
    }
 
-   language = procedureStruct->prolang;
-   switch (language)
+   switch (procedureStruct->prolang)
    {
        case INTERNALlanguageId:
-       case NEWINTERNALlanguageId:
            /*
             * For an ordinary builtin function, we should never get
             * here because the isbuiltin() search above will have
@@ -175,24 +176,12 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
                elog(ERROR, "fmgr_info: function %s not in internal table",
                     prosrc);
            pfree(prosrc);
-           if (fbp->oldstyle)
-           {
-               finfo->fn_addr = fmgr_oldstyle;
-               finfo->fn_extra = (void *) fbp->func;
-           }
-           else
-           {
-               finfo->fn_addr = fbp->func;
-           }
+           /* Should we check that nargs, strict, retset match the table? */
+           finfo->fn_addr = fbp->func;
            break;
 
        case ClanguageId:
-           finfo->fn_addr = fmgr_oldstyle;
-           finfo->fn_extra = (void *) fmgr_dynamic(functionId);
-           break;
-
-       case NEWClanguageId:
-           finfo->fn_addr = fmgr_dynamic(functionId);
+           fmgr_info_C_lang(finfo, procedureTuple);
            break;
 
        case SQLlanguageId:
@@ -200,92 +189,234 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
            break;
 
        default:
-           /*
-            * Might be a created procedural language; try to look it up.
-            */
-           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
+           fmgr_info_other_lang(finfo, procedureTuple);
+           break;
+   }
+
+   ReleaseSysCache(procedureTuple);
+}
+
+/*
+ * Special fmgr_info processing for C-language functions
+ */
+static void
+fmgr_info_C_lang(FmgrInfo *finfo, HeapTuple procedureTuple)
+{
+   Form_pg_proc procedureStruct = (Form_pg_proc) GETSTRUCT(procedureTuple);
+   Datum       prosrcattr,
+               probinattr;
+   char       *prosrcstring,
+              *probinstring;
+   PGFunction  user_fn;
+   Pg_finfo_record *inforec;
+   Oldstyle_fnextra *fnextra;
+   bool        isnull;
+   int         i;
+
+   /* Get prosrc and probin strings (link symbol and library filename) */
+   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",
-                    functionId, language);
+               fnextra->arg_toastable[i] =
+                   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;
    }
 
-   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
- * an internal function, return the OID of the function's language.
- * If the name is not known, return InvalidOid.
+ * Fetch and validate the information record for the given external function.
+ *
+ * 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
-fmgr_internal_language(const char *proname)
+fmgr_internal_function(const char *proname)
 {
    const FmgrBuiltin *fbp = fmgr_lookupByName(proname);
 
    if (fbp == NULL)
        return InvalidOid;
-   return fbp->oldstyle ? INTERNALlanguageId : NEWINTERNALlanguageId;
+   return fbp->foid;
 }
 
 
 /*
- * Handler for old-style internal and "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...
+ * Handler for old-style "C" language functions
  */
 static Datum
 fmgr_oldstyle(PG_FUNCTION_ARGS)
 {
-   char       *returnValue = NULL;
+   Oldstyle_fnextra *fnextra;
    int         n_arguments = fcinfo->nargs;
    int         i;
    bool        isnull;
    func_ptr    user_fn;
+   char       *returnValue;
 
    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
     * (peculiar, but that's the way it worked before, and after all this is
     * a backwards-compatibility wrapper).  Note, however, that we'll never
     * 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;
    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;
 
-   user_fn = (func_ptr) fcinfo->flinfo->fn_extra;
+   user_fn = fnextra->func;
 
    switch (n_arguments)
    {
@@ -411,6 +542,7 @@ fmgr_oldstyle(PG_FUNCTION_ARGS)
             */
            elog(ERROR, "fmgr_oldstyle: function %u: too many arguments (%d > %d)",
                 fcinfo->flinfo->fn_oid, n_arguments, 16);
+           returnValue = NULL; /* keep compiler quiet */
            break;
    }
 
index 3fc0a1b02fa4e06302b2e34d56fda8f537371385..02c27aaf90bb1bad2d3d843384ff43f2c2c586b7 100644 (file)
@@ -8,7 +8,7 @@
 #
 #
 # 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
 # ----------
 # 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
    echo "$CMDNAME: language installation failed" 1>&2
    exit 1
index e3f4c6ff8992f5fe5ff09ddbf4e90c615c0e4b9d..558feef575ba0f005f55ecdc182942b568be354d 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * 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 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 200011191
+#define CATALOG_VERSION_NO 200011201
 
 #endif
index 0d597d8c4daf82f28d6c0a733522434340e14dac..423f2e9470043e333e08d2421f034d102ee7f273 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * 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
  *   the genbki.sh script reads this file and generates .bki
@@ -63,18 +63,12 @@ typedef FormData_pg_language *Form_pg_language;
  * ----------------
  */
 
-DATA(insert OID = 11 ( internal f f 0 "n/a" ));
-DESCR("old-style built-in functions");
-#define INTERNALlanguageId 11
-DATA(insert OID = 12 ( newinternal f f 0 "n/a" ));
-DESCR("new-style built-in functions");
-#define NEWINTERNALlanguageId 12
+DATA(insert OID = 12 ( internal f f 0 "n/a" ));
+DESCR("Built-in functions");
+#define INTERNALlanguageId 12
 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
-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"));
 DESCR("SQL-language functions");
 #define SQLlanguageId 14
index 28634262bcc13a964342cb652a23bcfb1058dd93..08faf956299220e7f8f9bbc5f733bde600defe9b 100644 (file)
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * 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);
 #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
  *-------------------------------------------------------------------------
@@ -297,13 +334,14 @@ extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
 /*
  * 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
  */
-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);
 
 
index e6cfe519650c41689d569e3dcfdf34f3530ef0dd..9d46aeae694f0d66d390fe5b3423e55a24c8c3e4 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * 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
    const char *funcName;       /* C name of the function */
     short       nargs;         /* 0..FUNC_MAX_ARGS, or -1 if variable count */
     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 */
 } FmgrBuiltin;
 
index f8547baa884664b84bf093b7f3525d9b66871ae4..903e09aaf9cfc6a22cbb18b0a334fbe8c7432336 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * 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);
 extern int16 get_typlen(Oid typid);
 extern bool get_typbyval(Oid typid);
 extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
+extern char get_typstorage(Oid typid);
 extern Datum get_typdefault(Oid typid);
 
+#define TypeIsToastable(typid)  (get_typstorage(typid) != 'p')
+
 #endif  /* LSYSCACHE_H */
index 81a4cd75d4b968922eaf5ddec2f53bc109e90d66..0b2d7d4e4256ea2cc1a3f2f9ab6377ba922e64b5 100644 (file)
@@ -33,7 +33,7 @@
  *   ENHANCEMENTS, OR MODIFICATIONS.
  *
  * 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)
  *               call this function for execution of
  *               perl procedures.
  **********************************************************************/
+PG_FUNCTION_INFO_V1(plperl_call_handler);
 
 /* keep non-static */
 Datum
index 31788b0706106bce7c5ada6edce8616acedc7e7f..d9e208ee98b987aa544e09d3ba8aea3cd7e6f559 100644 (file)
@@ -3,7 +3,7 @@
  *           procedural language
  *
  * 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.
  *
@@ -66,6 +66,8 @@ static PLpgSQL_function *compiled_functions = NULL;
  * call this function for execution of PL/pgSQL procedures.
  * ----------
  */
+PG_FUNCTION_INFO_V1(plpgsql_call_handler);
+
 Datum
 plpgsql_call_handler(PG_FUNCTION_ARGS)
 {
index 8658cac3065322f0fbd0013a851fc2755f06fd78..94a67ef043303dfbac4c1df6622ed1583c026e58 100644 (file)
@@ -31,7 +31,7 @@
  *   ENHANCEMENTS, OR MODIFICATIONS.
  *
  * 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)
  *               call this function for execution of
  *               PL/Tcl procedures.
  **********************************************************************/
+PG_FUNCTION_INFO_V1(pltcl_call_handler);
 
 /* keep non-static */
 Datum
@@ -371,6 +372,12 @@ pltcl_call_handler(PG_FUNCTION_ARGS)
    return retval;
 }
 
+
+/*
+ * Alternate handler for unsafe functions
+ */
+PG_FUNCTION_INFO_V1(pltclu_call_handler);
+
 /* keep non-static */
 Datum
 pltclu_call_handler(PG_FUNCTION_ARGS)
index 0f82a3bea40a17596d7d19454cbdc3e77eaa782c..6d91674cd56d1c0e9ddf03c5cb1bb10d26432793 100644 (file)
@@ -15,30 +15,30 @@ CREATE FUNCTION widget_out(opaque)
 CREATE FUNCTION check_primary_key ()
    RETURNS opaque
    AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 
 CREATE FUNCTION check_foreign_key ()
    RETURNS opaque
    AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 
 CREATE FUNCTION autoinc ()
    RETURNS opaque
    AS '@abs_builddir@/../../../contrib/spi/autoinc@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 
 CREATE FUNCTION funny_dup17 ()
         RETURNS opaque
         AS '@abs_builddir@/regress@DLSUFFIX@'
-        LANGUAGE 'newC';
+        LANGUAGE 'C';
 
 CREATE FUNCTION ttdummy ()
         RETURNS opaque
         AS '@abs_builddir@/regress@DLSUFFIX@'
-        LANGUAGE 'newC';
+        LANGUAGE 'C';
 
 CREATE FUNCTION set_ttdummy (int4)
         RETURNS int4
         AS '@abs_builddir@/regress@DLSUFFIX@'
-        LANGUAGE 'newC';
+        LANGUAGE 'C';
 
index af6695764ac96dc12aba3658e103a42b8672df34..b1c0eab138608bf17232ed586a0b40a3a458a721 100644 (file)
@@ -30,28 +30,33 @@ CREATE FUNCTION user_relns()
 CREATE FUNCTION pt_in_widget(point, widget)
    RETURNS bool
    AS '@abs_builddir@/regress@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 
 CREATE FUNCTION overpaid(emp)
    RETURNS bool
    AS '@abs_builddir@/regress@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 
 CREATE FUNCTION boxarea(box)
    RETURNS float8
    AS '@abs_builddir@/regress@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 
 CREATE FUNCTION interpt_pp(path, path)
    RETURNS point
    AS '@abs_builddir@/regress@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 
 CREATE FUNCTION reverse_name(name)
    RETURNS name
    AS '@abs_builddir@/regress@DLSUFFIX@'
    LANGUAGE 'c';
 
+CREATE FUNCTION oldstyle_length(int4, text)
+   RETURNS int4
+   AS '@abs_builddir@/regress@DLSUFFIX@'
+   LANGUAGE 'c';
+
 --
 -- Function dynamic loading
 --
index 9e9ebdb75bc57a4ce51eba3cf1bc60e2dacd6fb2..dbb8df847090ba1185eba934c84fe9fd610546c4 100644 (file)
@@ -215,6 +215,19 @@ SELECT user_relns() AS user_relns
 --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
 --
index d3815a9aadde7ff392c2ce68a98e6f6c91ca9eb6..d075a61eb8a4df8f9485250acbd431a4e87fee34 100644 (file)
@@ -13,24 +13,24 @@ CREATE FUNCTION widget_out(opaque)
 CREATE FUNCTION check_primary_key ()
    RETURNS opaque
    AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 CREATE FUNCTION check_foreign_key ()
    RETURNS opaque
    AS '@abs_builddir@/../../../contrib/spi/refint@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 CREATE FUNCTION autoinc ()
    RETURNS opaque
    AS '@abs_builddir@/../../../contrib/spi/autoinc@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 CREATE FUNCTION funny_dup17 ()
         RETURNS opaque
         AS '@abs_builddir@/regress@DLSUFFIX@'
-        LANGUAGE 'newC';
+        LANGUAGE 'C';
 CREATE FUNCTION ttdummy ()
         RETURNS opaque
         AS '@abs_builddir@/regress@DLSUFFIX@'
-        LANGUAGE 'newC';
+        LANGUAGE 'C';
 CREATE FUNCTION set_ttdummy (int4)
         RETURNS int4
         AS '@abs_builddir@/regress@DLSUFFIX@'
-        LANGUAGE 'newC';
+        LANGUAGE 'C';
index def359de90fd9b144d56b51a8ac99075836a260e..a5f39a00bb00f2f7ae6174dc2977305181008cea 100644 (file)
@@ -23,23 +23,27 @@ CREATE FUNCTION user_relns()
 CREATE FUNCTION pt_in_widget(point, widget)
    RETURNS bool
    AS '@abs_builddir@/regress@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 CREATE FUNCTION overpaid(emp)
    RETURNS bool
    AS '@abs_builddir@/regress@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 CREATE FUNCTION boxarea(box)
    RETURNS float8
    AS '@abs_builddir@/regress@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 CREATE FUNCTION interpt_pp(path, path)
    RETURNS point
    AS '@abs_builddir@/regress@DLSUFFIX@'
-   LANGUAGE 'newC';
+   LANGUAGE 'C';
 CREATE FUNCTION reverse_name(name)
    RETURNS name
    AS '@abs_builddir@/regress@DLSUFFIX@'
    LANGUAGE 'c';
+CREATE FUNCTION oldstyle_length(int4, text)
+   RETURNS int4
+   AS '@abs_builddir@/regress@DLSUFFIX@'
+   LANGUAGE 'c';
 --
 -- Function dynamic loading
 --
index 144ad33f24220b59914f69a5d67ee91b8d2e4083..768dba5c3c7789af4804bbdfffe292f9d16fa9bc 100644 (file)
@@ -657,6 +657,24 @@ SELECT user_relns() AS user_relns
 
 --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
 --
 --
index 479527fc3fc862948764d5fa71e46fda60d3326c..bd65c4233da2922223d689393f47101c40b97954 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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              /* faked on sunos */
@@ -25,10 +25,13 @@ extern void regress_lseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
 extern Datum overpaid(PG_FUNCTION_ARGS);
 extern Datum boxarea(PG_FUNCTION_ARGS);
 extern char *reverse_name(char *string);
+extern int oldstyle_length(int n, text *t);
 
 /*
 ** Distance from a point to a path
 */
+PG_FUNCTION_INFO_V1(regress_dist_ptpath);
+
 Datum
 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
    two paths, and finds the min distance between any two lsegs */
+PG_FUNCTION_INFO_V1(regress_path_dist);
+
 Datum
 regress_path_dist(PG_FUNCTION_ARGS)
 {
@@ -129,6 +134,8 @@ POLYGON    *poly;
 }
 
 /* return the point where two paths intersect, or NULL if no intersection. */
+PG_FUNCTION_INFO_V1(interpt_pp);
+
 Datum
 interpt_pp(PG_FUNCTION_ARGS)
 {
@@ -182,6 +189,8 @@ Point      *pt2;
    lseg->m = point_sl(pt1, pt2);
 }
 
+PG_FUNCTION_INFO_V1(overpaid);
+
 Datum
 overpaid(PG_FUNCTION_ARGS)
 {
@@ -254,6 +263,8 @@ WIDGET     *widget;
    return result;
 }
 
+PG_FUNCTION_INFO_V1(pt_in_widget);
+
 Datum
 pt_in_widget(PG_FUNCTION_ARGS)
 {
@@ -265,6 +276,8 @@ pt_in_widget(PG_FUNCTION_ARGS)
 
 #define ABS(X) ((X) >= 0 ? (X) : -(X))
 
+PG_FUNCTION_INFO_V1(boxarea);
+
 Datum
 boxarea(PG_FUNCTION_ARGS)
 {
@@ -278,8 +291,7 @@ boxarea(PG_FUNCTION_ARGS)
 }
 
 char *
-reverse_name(string)
-char      *string;
+reverse_name(char *string)
 {
    int         i;
    int         len;
@@ -301,6 +313,20 @@ char      *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 "commands/trigger.h"  /* -"- and triggers */
 
@@ -312,6 +338,8 @@ static bool fd17b_recursion = true;
 static bool fd17a_recursion = true;
 extern Datum funny_dup17(PG_FUNCTION_ARGS);
 
+PG_FUNCTION_INFO_V1(funny_dup17);
+
 Datum
 funny_dup17(PG_FUNCTION_ARGS)
 {
@@ -428,6 +456,8 @@ extern Datum set_ttdummy(PG_FUNCTION_ARGS);
 static void *splan = NULL;
 static bool ttoff = false;
 
+PG_FUNCTION_INFO_V1(ttdummy);
+
 Datum
 ttdummy(PG_FUNCTION_ARGS)
 {
@@ -625,6 +655,8 @@ ttdummy(PG_FUNCTION_ARGS)
    return PointerGetDatum(rettuple);
 }
 
+PG_FUNCTION_INFO_V1(set_ttdummy);
+
 Datum
 set_ttdummy(PG_FUNCTION_ARGS)
 {
index 254c62100dc1829bcbb0c077bf4b8bec56f840a9..fc89483208e5bc5a2fdfe0f14d5c44fa51c7e7f1 100644 (file)
@@ -38,6 +38,7 @@ DROP FUNCTION interpt_pp(path,path);
 
 DROP FUNCTION reverse_name(name);
 
+DROP FUNCTION oldstyle_length(int4, text);
 
 --
 -- OPERATOR REMOVAL
index 0734e67a113d9b06c25ba5a325baeb9cec8013ff..20f609d5d2d88c7d84d05f990ad535bba827d90f 100644 (file)
@@ -30,6 +30,8 @@ Datum   c_overpaid(PG_FUNCTION_ARGS);
 
 /* By Value */
          
+PG_FUNCTION_INFO_V1(add_one);
+
 Datum
 add_one(PG_FUNCTION_ARGS)
 {
@@ -40,6 +42,8 @@ add_one(PG_FUNCTION_ARGS)
 
 /* By Reference, Fixed Length */
 
+PG_FUNCTION_INFO_V1(add_one_float8);
+
 Datum
 add_one_float8(PG_FUNCTION_ARGS)
 {
@@ -49,6 +53,8 @@ add_one_float8(PG_FUNCTION_ARGS)
     PG_RETURN_FLOAT8(arg + 1.0);
 }
 
+PG_FUNCTION_INFO_V1(makepoint);
+
 Datum
 makepoint(PG_FUNCTION_ARGS)
 {
@@ -64,6 +70,8 @@ makepoint(PG_FUNCTION_ARGS)
 
 /* By Reference, Variable Length */
 
+PG_FUNCTION_INFO_V1(copytext);
+
 Datum
 copytext(PG_FUNCTION_ARGS)
 {
@@ -82,6 +90,8 @@ copytext(PG_FUNCTION_ARGS)
     PG_RETURN_TEXT_P(new_t);
 }
 
+PG_FUNCTION_INFO_V1(concat_text);
+
 Datum
 concat_text(PG_FUNCTION_ARGS)
 {
@@ -99,6 +109,8 @@ concat_text(PG_FUNCTION_ARGS)
 
 /* Composite types */
 
+PG_FUNCTION_INFO_V1(c_overpaid);
+
 Datum
 c_overpaid(PG_FUNCTION_ARGS)
 {