From 0813fcbc08e7f519e30a3ffece80ff2e2fa84508 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 24 Aug 2000 23:36:29 +0000 Subject: [PATCH] Documentation updates to reflect TOAST and new-style fmgr. --- doc/src/sgml/array.sgml | 10 +- doc/src/sgml/datatype.sgml | 32 ++- doc/src/sgml/ref/create_function.sgml | 115 +++++--- doc/src/sgml/ref/create_language.sgml | 29 +- doc/src/sgml/ref/create_table.sgml | 10 +- doc/src/sgml/ref/create_type.sgml | 74 +++-- doc/src/sgml/xfunc.sgml | 381 ++++++++++++++++++++------ 7 files changed, 474 insertions(+), 177 deletions(-) diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml index aa7ecdc711..d579dd4979 100644 --- a/doc/src/sgml/array.sgml +++ b/doc/src/sgml/array.sgml @@ -130,10 +130,12 @@ UPDATE sal_emp SET pay_by_quarter[1:2] = '{27000,27000}' - It is not currently possible to resize an array value except by - complete replacement; for example, we couldn't change a four- - element array value to a five-element value with a single - assignment to array[5]. + An array can be enlarged by assigning to an element adjacent to + those already present, or by assigning to a slice that is adjacent + to or overlaps the data already present. Currently, this is only + allowed for one-dimensional arrays, not multidimensional arrays. + For example, if an array value currently has 4 elements, it will + have five elements after an update that assigns to array[5]. diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index 2b03cdeffc..9026d23e8c 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -1,5 +1,5 @@ @@ -42,7 +42,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.33 2000/08/23 05:59:01 th Postgres Type - SQL92 or SQL3 Type + SQL92 or SQL99 Type Description @@ -80,7 +80,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.33 2000/08/23 05:59:01 th decimal decimal(p,s) - exact numeric for p <= 9, s = 0 + exact numeric with selectable precision float4 @@ -135,7 +135,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.33 2000/08/23 05:59:01 th numeric numeric(p,s) - exact numeric for p == 9, s = 0 + exact numeric with selectable precision path @@ -157,6 +157,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.33 2000/08/23 05:59:01 th unique id for indexing and cross-reference + + text + + variable-length character string + time time [ without time zone ] @@ -234,7 +239,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.33 2000/08/23 05:59:01 th Postgres has features at the forefront of ORDBMS development. In addition to - SQL3 conformance, substantial portions + SQL99 conformance, substantial portions of SQL92 are also supported. Although we strive for SQL92 compliance, there are some aspects of the standard @@ -275,7 +280,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.33 2000/08/23 05:59:01 th Numeric Types - Numeric types consist of two- and four-byte integers, four- and eight-byte + Numeric types consist of two-, four-, and eight-byte integers, + four- and eight-byte floating point numbers and fixed-precision decimals. @@ -297,7 +303,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.33 2000/08/23 05:59:01 th decimal variable User-specified precision - ~8000 digits + no limit float4 @@ -327,7 +333,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.33 2000/08/23 05:59:01 th int8 8 bytes Very large range fixed-precision - +/- > 18 decimal places + ~18 decimal places numeric @@ -354,7 +360,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.33 2000/08/23 05:59:01 th The int8 type may not be available on all platforms since - it relies on compiler support for this. + it relies on compiler support for eight-byte integers. @@ -483,7 +489,7 @@ CREATE TABLE tablename ( - char + "char" 1 byte SQL92-compatible Single character @@ -502,7 +508,7 @@ CREATE TABLE tablename ( varchar(n) - (4+n) bytes + (4+x) bytes SQL92-compatible Variable-length with limit @@ -1359,10 +1365,10 @@ January 8 04:05:06 1999 PST Postgres supports bool as - the SQL3 boolean type. + the SQL99 boolean type. bool can have one of only two states: 'true' or 'false'. A third state, 'unknown', is not - implemented and is not suggested in SQL3; + implemented and is not suggested in SQL99; NULL is an effective substitute. bool can be used in any boolean expression, and boolean expressions diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml index f46e9796ee..2d185fa759 100644 --- a/doc/src/sgml/ref/create_function.sgml +++ b/doc/src/sgml/ref/create_function.sgml @@ -1,5 +1,5 @@ @@ -31,7 +31,7 @@ CREATE FUNCTION name ( [ name ( [ ftype [, ...] ] ) RETURNS rtype AS obj_file , link_symbol - LANGUAGE 'C' + LANGUAGE 'langname' [ WITH ( attribute [, ...] ) ] @@ -57,11 +57,11 @@ CREATE FUNCTION name ( [ ftype - The data type of function arguments. + The data type(s) of the function's arguments, if any. The input types may be base or complex types, or opaque. opaque indicates that the function - accepts arguments of an invalid type such as char *. + accepts arguments of a non-SQL type such as char *. @@ -84,14 +84,7 @@ CREATE FUNCTION name ( [ An optional piece of information about the function, used for - optimization. The only attribute currently supported is - iscachable. - iscachable indicates that the function always - returns the same result when given the same input values (i.e., - it does not do database lookups or otherwise use information not - directly present in its parameter list). The optimizer uses - iscachable to know whether it is safe to - pre-evaluate a call of the function. + optimization. See below for details. @@ -115,8 +108,8 @@ CREATE FUNCTION name ( [ obj_file is the name of the file containing the dynamically loadable object, and link_symbol, is the object's link - symbol which is the same as the name of the function in the C + class="parameter">link_symbol is the object's link + symbol, that is the name of the function in the C language source code. @@ -125,8 +118,9 @@ CREATE FUNCTION name ( [ langname - may be 'C', 'sql', - 'internal' + may be 'sql', + 'C', 'newC', + 'internal', 'newinternal', or 'plname', where 'plname' is the name of a created procedural language. See @@ -175,11 +169,57 @@ CREATE CREATE FUNCTION allows a Postgres user to register a function - with a database. Subsequently, this user is considered the + with the database. Subsequently, this user is considered the owner of the function. - + + + 2000-08-24 + + + Function Attributes + + + + The following items may appear in the WITH clause: + + + + iscachable + + + iscachable indicates that the function always + returns the same result when given the same argument values (i.e., + it does not do database lookups or otherwise use information not + directly present in its parameter list). The optimizer uses + iscachable to know whether it is safe to + pre-evaluate a call of the function. + + + + + + isstrict + + + isstrict indicates that the function always + returns NULL whenever any of its arguments are NULL. If this + attribute is specified, the function is not executed when there + are NULL arguments; instead a NULL result is assumed automatically. + When isstrict is not specified, the function will + be called for NULL inputs. It is then the function author's + responsibility to check for NULLs if necessary and respond + appropriately. + + + + + + + + + 2000-03-25 @@ -200,26 +240,25 @@ CREATE to remove user-defined functions. - - Postgres allows function "overloading"; - that is, the same name can be used for several different functions - so long as they have distinct argument types. This facility must - be used with caution for internal and - C-language functions, however. - - The full SQL92 type syntax is allowed for input arguments and return value. However, some details of the type specification (e.g. the precision field for numeric types) are the responsibility of the underlying function implementation and are silently swallowed - (e.g. not recognized or + (i.e., not recognized or enforced) by the CREATE FUNCTION command. - Two internal + Postgres allows function "overloading"; + that is, the same name can be used for several different functions + so long as they have distinct argument types. This facility must + be used with caution for internal and C-language functions, however. + + + + Two internal or newinternal 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 @@ -229,18 +268,14 @@ CREATE - When overloading SQL functions with C-language functions, give - each C-language instance of the function a distinct name, and use + Similarly, when overloading SQL function names with multiple C-language + functions, give + each C-language instance of the function a distinct name, then use the alternative form of the AS clause in the - CREATE FUNCTION syntax to ensure that - overloaded SQL functions names are resolved to the correct - dynamically linked objects. + CREATE FUNCTION syntax to select the appropriate + C-language implementation of each overloaded SQL function. - - - A C function cannot return a set of values. - @@ -291,7 +326,7 @@ CREATE TABLE product ( function is implemented by a dynamically loaded object that was compiled from C source. For Postgres to find a type conversion function automatically, the sql function has - to have the same name as the return type, and overloading is + to have the same name as the return type, and so overloading is unavoidable. The function name is overloaded by using the second form of the AS clause in the SQL definition: @@ -324,7 +359,7 @@ Point * complex_to_point (Complex *z) Compatibility - + 2000-03-25 @@ -338,7 +373,7 @@ Point * complex_to_point (Complex *z) - + 2000-03-25 diff --git a/doc/src/sgml/ref/create_language.sgml b/doc/src/sgml/ref/create_language.sgml index e8e84a6239..7e95f4310b 100644 --- a/doc/src/sgml/ref/create_language.sgml +++ b/doc/src/sgml/ref/create_language.sgml @@ -1,5 +1,5 @@ @@ -48,8 +48,7 @@ CREATE [ TRUSTED ] PROCEDURAL LANGUAGE 'langname< this keyword is omitted when registering the language, only users with the Postgres superuser privilege can use - this language to create new functions - (like the 'C' language). + this language to create new functions. @@ -222,6 +221,11 @@ ERROR: PL handler function funcnameflinfo->fn_extra is made to point at memory that will live at least until the end of the current query, since an FmgrInfo data structure could be kept that long. + One way to do this is to allocate the extra data in the memory context + specified by flinfo->fn_mcxt; such data will + normally have the same lifespan as the FmgrInfo itself. But the handler + could also choose to use a longer-lived context so that it can cache + function definition information across queries. @@ -262,20 +266,21 @@ ERROR: PL handler function funcname - Since the call handler for a procedural language must be - registered with Postgres in the 'C' language, - it inherits - all the capabilities and restrictions of 'C' functions. + The call handler for a procedural language must normally be written + in C and registered as 'newinternal' or 'newC' language, depending + on whether it is linked into the backend or dynamically loaded. diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index 41037655c6..8a56bae48b 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -1,5 +1,5 @@ @@ -248,11 +248,9 @@ ERROR: DEFAULT: type mismatched The new table is created as a heap with no initial data. - A table can have no more than 1600 columns (realistically, - this is limited by the fact that tuple sizes must - be less than 8192 bytes), but this limit may be configured - lower at some sites. A table cannot have the same name as - a system catalog table. + A table can have no more than 1600 columns (in practice, the + effective limit is lower because of tuple-length constraints). + A table cannot have the same name as a system catalog table. diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml index 2bdcacba5d..19ddabea50 100644 --- a/doc/src/sgml/ref/create_type.sgml +++ b/doc/src/sgml/ref/create_type.sgml @@ -1,5 +1,5 @@ @@ -24,11 +24,16 @@ Postgres documentation CREATE TYPE typename ( INPUT = input_function, OUTPUT = output_function - , INTERNALLENGTH = { internallength | VARIABLE } [ , EXTERNALLENGTH = { externallength | VARIABLE } ] + , INTERNALLENGTH = { internallength | VARIABLE } + [ , EXTERNALLENGTH = { externallength | VARIABLE } ] [ , DEFAULT = "default" ] [ , ELEMENT = element ] [ , DELIMITER = delimiter ] [ , SEND = send_function ] [ , RECEIVE = receive_function ] - [ , PASSEDBYVALUE ] ) + [ , PASSEDBYVALUE ] + [ , ALIGNMENT = alignment ] + [ , STORAGE = storage ] +) @@ -64,7 +69,7 @@ CREATE TYPE typename ( INPUT = externallength - A literal value, which specifies the external length of + A literal value, which specifies the external (displayed) length of the new type. @@ -86,7 +91,8 @@ CREATE TYPE typename ( INPUT = output_function - The name of a function, created by CREATE FUNCTION, which + The name of a function, created by + CREATE FUNCTION, which converts data from its internal form to a form suitable for display. @@ -107,7 +113,7 @@ CREATE TYPE typename ( INPUT = delimiter - The delimiter character for the array. + The delimiter character for the array elements. @@ -116,8 +122,8 @@ CREATE TYPE typename ( INPUT = default - The default text to be displayed to indicate "data - not present" + The default value for the datatype. Usually this is omitted, + so that the default is NULL. @@ -141,6 +147,29 @@ CREATE TYPE typename ( INPUT = + + + alignment + + + Storage alignment requirement of the datatype. If specified, must + be 'int4' or 'double'; + the default is 'int4'. + + + + + + storage + + + Storage technique for the datatype. If specified, must + be 'plain', 'external', + 'extended', or 'main'; + the default is 'plain'. + + + @@ -267,6 +296,24 @@ CREATE more than four bytes. + + The storage keyword + allows selection of TOAST storage method for variable-length datatypes + (only plain is allowed for fixed-length types). + plain disables TOAST for the datatype: it will always + be stored in-line and not compressed. + extended is full TOAST capability: the system will + first try to compress a long data value, and will move the value out of + the main table row if it's still too long. + external allows the value to be moved out of the main + table, but the system will not try to compress it. + main allows compression, but discourages moving the + value out of the main table. (Data items with this storage method may + still be moved out of the main table if there is no other way to make + a row fit, but they will be kept in the main table preferentially over + extended and external items.) + + For new base types, a user can define operators, functions and aggregates using the appropriate facilities described @@ -283,17 +330,6 @@ CREATE - - Large Object Types - - A "regular" Postgres type can only be 8192 bytes in - length. If you need a larger type you must create a Large - Object type. The interface for these types is discussed - at length in the - PostgreSQL Programmer's Guide. - The length of all large object types is always VARIABLE. - - diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 23db3819c7..1bc1f41f6f 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,5 +1,5 @@ @@ -64,10 +64,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.18 2000/08/21 17:22:36 tgl E The body of a SQL function following AS - should be a list of queries separated by whitespace characters and - bracketed within quotation marks. Note that quotation marks used in - the queries must be escaped, by preceding them with two - backslashes. + should be a list of queries separated by semicolons and + bracketed within single-quote marks. Note that quote marks used in + the queries must be escaped, by preceding them with a backslash. @@ -100,7 +99,7 @@ LANGUAGE 'sql'; follows: -select (x = TP1( 17,100.0)); +select TP1( 17,100.0); @@ -109,7 +108,7 @@ select (x = TP1( 17,100.0)); EMP, and retrieves multiple results: -select function hobbies (EMP) returns set of HOBBIES +create function hobbies (EMP) returns setof HOBBIES as 'select HOBBIES.* from HOBBIES where $1.name = HOBBIES.person' language 'sql'; @@ -140,10 +139,9 @@ SELECT one() AS answer; - Notice that we defined a target list for the function - (with the name RESULT), but the target list of the - query that invoked the function overrode the function's - target list. Hence, the result is labelled answer + Notice that we defined a column name for the function's result + (with the name RESULT), but this column name is not visible + outside the function. Hence, the result is labelled answer instead of one. @@ -204,7 +202,7 @@ WHERE EMP.cubicle ~= '(2,1)'::point; return composite types, we must first introduce the function notation for projecting attributes. The simple way to explain this is that we can usually use the - notation attribute(class) and class.attribute interchangably: + notations attribute(class) and class.attribute interchangably: -- @@ -252,17 +250,16 @@ LANGUAGE 'sql'; The target list order must be exactly the same as that in which the attributes appear in the CREATE - TABLE statement (or when you execute a .* query). + TABLE statement that defined the composite type. - You must typecast the expressions (using ::) very carefully - or you will see the following error: - + You must typecast the expressions (using ::) to match the + composite type's definition, or you will get errors like this: -NOTICE::function declared to return type EMP does not retrieve (EMP.*) +ERROR: function declared to return emp returns varchar instead of text at column 1 @@ -366,6 +363,16 @@ SELECT clean_EMP(); but a user could use CREATE FUNCTION to create additional alias names for an internal function. + + + 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. + @@ -373,50 +380,59 @@ SELECT clean_EMP(); Functions written in C can be compiled into dynamically loadable - objects, and used to implement user-defined SQL functions. The - first time the user defined function is called inside the backend, - the dynamic loader loads the function's object code into memory, - and links the function with the running - Postgres executable. The SQL syntax - for CREATE FUNCTION - links the SQL function - to the C source function in one of two ways. If the SQL function - has the same name as the C source function the first form of the - statement is used. The string argument in the AS clause is the - full pathname of the file that contains the dynamically loadable - compiled object. If the name of the C function is different from the - desired name of the SQL function, then the second form is used. In this - form the AS clause takes two string arguments, the first is the - full pathname of the dynamically loadable object file, and the - second is the link symbol that the dynamic loader should search - for. This link symbol is just the function name in the C source - code. + objects (also called shared libraries), and used to implement user-defined + SQL functions. The first time a user-defined function in a particular + loadable object file is called in a backend session, + the dynamic loader loads that object file into memory so that the + function can be called. The CREATE FUNCTION + for a user-defined function must therefore specify two pieces of + information for the function: the name of the loadable + object file, and the C name (link symbol) of the specific function to call + within that object file. If the C name is not explicitly specified then + it is assumed to be the same as the SQL function name. - After it is used for the first time, a dynamically loaded, user + After it is used for the first time, a dynamically loaded user function is retained in memory, and future calls to the function - only incur the small overhead of a symbol table lookup. + in the same session will only incur the small overhead of a symbol table + lookup. - The string which specifies the object file (the string in the AS + 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 - link symbol is used 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 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. - (Postgres will not compile a function - automatically; it must be compiled before it is used in a CREATE - FUNCTION command. See below for additional information.) + + + + Postgres will not compile a function + automatically; it must be compiled before it is used in a CREATE + FUNCTION command. See below for additional information. + + + + + + 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 + because of portability problems and lack of functionality, but they + are still supported for compatibility reasons. - C Language Functions on Base Types + Base Types in C-Language Functions The following table gives the C type required for parameters in the C @@ -484,7 +500,7 @@ SELECT clean_EMP(); int2 - int2 + int2 or int16 include/postgres.h @@ -494,7 +510,7 @@ SELECT clean_EMP(); int4 - int4 + int4 or int32 include/postgres.h @@ -654,6 +670,12 @@ typedef struct Only pointers to such types can be used when passing them in and out of Postgres functions. + To return a value of such a type, allocate the right amount of + memory with palloc(), fill in the allocated memory, + and return a pointer to it. + + + Finally, all variable-length types must also be passed by reference. All variable-length types must begin with a length field of exactly 4 bytes, and all data to @@ -694,8 +716,24 @@ memmove(destination->data, buffer, 40); Now that we've gone over all of the possible structures - for base types, we can show some examples of real functions. - Suppose funcs.c look like: + for base types, we can show some examples of real functions. + + + + + Old-style 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 + of the C function are just declared in normal C style, but being + careful to use the C representation of each SQL data type as shown + above. + + + + Here are some examples: #include <string.h> @@ -706,13 +744,23 @@ memmove(destination->data, buffer, 40); int add_one(int arg) { - return(arg + 1); + return arg + 1; } /* By Reference, Fixed Length */ +float8 * +add_one_float8(float8 *arg) +{ + float8 *result = (float8 *) palloc(sizeof(float8)); + + *result = *arg + 1.0; + + return result; +} + Point * -makepoint(Point *pointx, Point *pointy ) +makepoint(Point *pointx, Point *pointy) { Point *new_point = (Point *) palloc(sizeof(Point)); @@ -731,15 +779,14 @@ copytext(text *t) * VARSIZE is the total size of the struct in bytes. */ text *new_t = (text *) palloc(VARSIZE(t)); - memset(new_t, 0, VARSIZE(t)); - VARSIZE(new_t) = VARSIZE(t); + VARATT_SIZEP(new_t) = VARSIZE(t); /* * VARDATA is a pointer to the data region of the struct. */ memcpy((void *) VARDATA(new_t), /* destination */ (void *) VARDATA(t), /* source */ - VARSIZE(t)-VARHDRSZ); /* how many bytes */ - return(new_t); + VARSIZE(t)-VARHDRSZ); /* how many bytes */ + return new_t; } text * @@ -749,40 +796,197 @@ concat_text(text *arg1, text *arg2) text *new_text = (text *) palloc(new_text_size); memset((void *) new_text, 0, new_text_size); - VARSIZE(new_text) = new_text_size; + VARATT_SIZEP(new_text) = new_text_size; strncpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1)-VARHDRSZ); strncat(VARDATA(new_text), VARDATA(arg2), VARSIZE(arg2)-VARHDRSZ); - return (new_text); + return new_text; } - On OSF/1 we would type: + Supposing that the above code has been prepared in file + funcs.c and compiled into a shared object, + we could define the functions to Postgres + with commands like this: CREATE FUNCTION add_one(int4) RETURNS int4 - AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c'; + AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c' + WITH (isStrict); + +-- note overloading of SQL function name add_one() +CREATE FUNCTION add_one(float8) RETURNS float8 + AS 'PGROOT/tutorial/funcs.so', + 'add_one_float8' + LANGUAGE 'c' WITH (isStrict); CREATE FUNCTION makepoint(point, point) RETURNS point - AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c'; - -CREATE FUNCTION concat_text(text, text) RETURNS text - AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c'; + AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c' + WITH (isStrict); CREATE FUNCTION copytext(text) RETURNS text - AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c'; + AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c' + WITH (isStrict); + +CREATE FUNCTION concat_text(text, text) RETURNS text + AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c' + WITH (isStrict); - On other systems, we might have to make the filename - end in .sl (to indicate that it's a shared library). + Here PGROOT stands for the full path to + the Postgres source tree. Note that + depending on your system, the filename for a shared object might + not end in .so, but in .sl + or something else; adapt accordingly. + + + + Notice that we have specified the functions as "strict", meaning that + the system should automatically assume a NULL result if any input + value is NULL. By doing this, we avoid having to check for NULL inputs + in the function code. Without this, we'd have to check for NULLs + explicitly, for example by checking for a null pointer for each + pass-by-reference argument. (For pass-by-value arguments, we don't + even have a way to check!) + + + + Although this old-style 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 + convention, presented next, overcomes these objections. - C Language Functions on Composite Types + New-style Calling Conventions for C-Language Functions + + + The new-style 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 + + Datum funcname(PG_FUNCTION_ARGS) + + 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. + + + + Here we show the same functions as above, coded in new style: + + +#include <string.h> +#include "postgres.h" +#include "fmgr.h" + +/* By Value */ + +Datum +add_one(PG_FUNCTION_ARGS) +{ + int32 arg = PG_GETARG_INT32(0); + + PG_RETURN_INT32(arg + 1); +} + +/* By Reference, Fixed Length */ + +Datum +add_one_float8(PG_FUNCTION_ARGS) +{ + /* The macros for FLOAT8 hide its pass-by-reference nature */ + float8 arg = PG_GETARG_FLOAT8(0); + + PG_RETURN_FLOAT8(arg + 1.0); +} + +Datum +makepoint(PG_FUNCTION_ARGS) +{ + Point *pointx = PG_GETARG_POINT_P(0); + Point *pointy = PG_GETARG_POINT_P(1); + Point *new_point = (Point *) palloc(sizeof(Point)); + + new_point->x = pointx->x; + new_point->y = pointy->y; + + PG_RETURN_POINT_P(new_point); +} + +/* By Reference, Variable Length */ + +Datum +copytext(PG_FUNCTION_ARGS) +{ + text *t = PG_GETARG_TEXT_P(0); + /* + * VARSIZE is the total size of the struct in bytes. + */ + text *new_t = (text *) palloc(VARSIZE(t)); + VARATT_SIZEP(new_t) = VARSIZE(t); + /* + * VARDATA is a pointer to the data region of the struct. + */ + memcpy((void *) VARDATA(new_t), /* destination */ + (void *) VARDATA(t), /* source */ + VARSIZE(t)-VARHDRSZ); /* how many bytes */ + PG_RETURN_TEXT_P(new_t); +} + +Datum +concat_text(PG_FUNCTION_ARGS) +{ + text *arg1 = PG_GETARG_TEXT_P(0); + text *arg2 = PG_GETARG_TEXT_P(1); + int32 new_text_size = VARSIZE(arg1) + VARSIZE(arg2) - VARHDRSZ; + text *new_text = (text *) palloc(new_text_size); + + memset((void *) new_text, 0, new_text_size); + VARATT_SIZEP(new_text) = new_text_size; + strncpy(VARDATA(new_text), VARDATA(arg1), VARSIZE(arg1)-VARHDRSZ); + strncat(VARDATA(new_text), VARDATA(arg2), VARSIZE(arg2)-VARHDRSZ); + PG_RETURN_TEXT_P(new_text); +} + + + + + The CREATE FUNCTION commands are the same as + for the old-style equivalents, except that the language is specified + as 'newC' not 'C'. + + + + At first glance, the new-style 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 + be aware that float8 is a pass-by-reference type. Another example + is that the GETARG macros for variable-length types hide the need + 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. + + + + The new-style 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. + For more details see src/backend/utils/fmgr/README. + + + + + Composite Types in C-Language Functions Composite types do not have a fixed layout like C @@ -811,14 +1015,33 @@ CREATE FUNCTION copytext(text) RETURNS text bool c_overpaid(TupleTableSlot *t, /* the current instance of EMP */ - int4 limit) + int32 limit) { - bool isnull = false; - int4 salary; - salary = (int4) GetAttributeByName(t, "salary", &isnull); + bool isnull; + int32 salary; + + salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull)); if (isnull) return (false); - return(salary > limit); + return salary > limit; +} + +/* In new-style coding, the above would look like this: */ + +Datum +c_overpaid(PG_FUNCTION_ARGS) +{ + TupleTableSlot *t = (TupleTableSlot *) PG_GETARG_POINTER(0); + int32 limit = PG_GETARG_INT32(1); + bool isnull; + int32 salary; + + salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull)); + if (isnull) + PG_RETURN_BOOL(false); + /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary */ + + PG_RETURN_BOOL(salary > limit); } @@ -827,20 +1050,12 @@ c_overpaid(TupleTableSlot *t, /* the current instance of EMP */ GetAttributeByName is the Postgres system function that returns attributes out of the current instance. It has - three arguments: the argument of type TUPLE passed into + three arguments: the argument of type TupleTableSlot* passed into the function, the name of the desired attribute, and a - return parameter that describes whether the attribute - is null. GetAttributeByName will - align data properly so you can cast its return value to - the desired type. For example, if you have an attribute - name which is of the type name, the GetAttributeByName - call would look like: - - -char *str; -... -str = (char *) GetAttributeByName(t, "name", &isnull) - + return parameter that tells whether the attribute + is null. GetAttributeByName returns a Datum + value that you can convert to the proper datatype by using the + appropriate DatumGetXXX() macro.