diff options
author | Marc G. Fournier <scrappy@hub.org> | 1996-08-18 22:14:33 +0000 |
---|---|---|
committer | Marc G. Fournier <scrappy@hub.org> | 1996-08-18 22:14:33 +0000 |
commit | 9848d3655d44aa2e58d28fe9f93a94b2934eedc8 (patch) | |
tree | 059111c2156111b083ea668b84bc8b3481676fca /doc/man/create_function.l | |
parent | 1960a3b96573ad1ec73cd50255edde29cc80df88 (diff) | |
download | postgresql-9848d3655d44aa2e58d28fe9f93a94b2934eedc8.tar.gz postgresql-9848d3655d44aa2e58d28fe9f93a94b2934eedc8.zip |
Support Docs & Contrib
Diffstat (limited to 'doc/man/create_function.l')
-rw-r--r-- | doc/man/create_function.l | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/doc/man/create_function.l b/doc/man/create_function.l new file mode 100644 index 00000000000..2eaa148e119 --- /dev/null +++ b/doc/man/create_function.l @@ -0,0 +1,417 @@ +.\" This is -*-nroff-*- +.\" XXX standard disclaimer belongs here.... +.\" $Header: /cvsroot/pgsql/doc/man/Attic/create_function.l,v 1.1.1.1 1996/08/18 22:14:21 scrappy Exp $ +.TH "CREATE FUNCTION" SQL 11/05/95 Postgres95 Postgres95 +.SH "NAME" +create function \(em define a new function +.SH "SYNOPSIS" +.nf +\fBcreate function\fP function_name \fB(\fP + ([type1 {, type-n}]) + \fBreturns\fP type-r + \fBas\fP {'/full/path/to/objectfile' | 'sql-queries'} + \fBlanguage\fP {'c' \ 'sql' \ 'internal'} +.fi +.SH "DESCRIPTION" +With this command, a Postgres user can register a function with Postgres. +Subsequently, this user is treated as the owner of the function. +.PP +When defining a function with arguments, the input data types, +.IR type-1 , +.IR type-2 , +\&..., +.IR type-n , +and the return data type, +.IR type-r +must be specified, along with the language, which may be +.IR "\*(lqc\*(rq" +or +.IR "\*(lqsql\*(rq" . +or +.IR "\*(lqinternal\*(rq" . +(The +.IR "arg is" +clause may be left out if the function has no arguments, or +alternatively the argument list may be left empty.) +The input types may be base or complex types, or +.IR opaque . +.IR Opaque +indicates that the function accepts arguments of an +invalid type such as (char *). +The output type may be specified as a base type, complex type, +.IR "setof <type>", +or +.IR opaque . +The +.IR setof +modifier indicates that the function will return a set of items, +rather than a single item. +The +.IR as +clause of the command is treated differently for C and SQL +functions, as explained below. +.SH "C FUNCTIONS" +Functions written in C can be defined to Postgres, which will dynamically +load them into its address space. The loading happens either using +.IR load (l) +or automatically the first time the function is necessary for +execution. Repeated execution of a function will cause negligible +additional overhead, as the function will remain in a main memory +cache. +.PP +Internal functions are functions written in C which have been statically +linked into the postgres backend process. The +.BR as +clause must still be specified when defining an internal function but +the contents are ignored. +.SH "Writing C Functions" +The body of a C function following +.BR as +should be the +.BR "FULL PATH" +of the object code (.o file) for the function, bracketed by quotation +marks. (Postgres will not compile a function automatically \(em it must +be compiled before it is used in a +.BR "define function" +command.) +.PP +C functions with base type arguments can be written in a +straightforward fashion. The C equivalents of built-in Postgres types +are accessible in a C file if +.nf +\&.../src/backend/utils/builtins.h +.fi +is included as a header file. This can be achieved by having +.nf +\&#include <utils/builtins.h> +.fi +at the top of the C source file and by compiling all C files with the +following include options: +.nf +-I.../src/backend +-I.../src/backend/port/<portname> +-I.../src/backend/obj +.fi +before any \*(lq.c\*(rq programs in the +.IR cc +command line, e.g.: +.nf +cc -I.../src/backend \e + -I.../src/backend/port/<portname> \e + -I.../src/backend/obj \e + -c progname.c +.fi +where \*(lq...\*(rq is the path to the installed Postgres source tree and +\*(lq<portname>\*(rq is the name of the port for which the source tree +has been built. +.PP +The convention for passing arguments to and from the user's C +functions is to use pass-by-value for data types that are 32 bits (4 +bytes) or smaller, and pass-by-reference for data types that require +more than 32 bits. +.if t \{ +The following table gives the C type required for parameters in the C +functions that will be loaded into Postgres. The \*(lqDefined In\*(rq +column gives the actual header file (in the +.nf +\&.../src/backend +.fi +directory) that the equivalent C type is defined. However, if you +include \*(lqutils/builtins.h\*(rq, these files will automatically be +included. +.SH "Equivalent C Types for Built-In Postgres Types" +.PP +.TS +center; +l l l +l l l. +\fBBuilt-In Type\fP \fBC Type\fP \fBDefined In\fP +_ +abstime AbsoluteTime utils/nabstime.h +bool bool include/c.h +box (BOX *) utils/geo-decls.h +bytea (bytea *) include/postgres.h +char char N/A +char16 Char16 or (char16 *) include/postgres.h +cid CID include/postgres.h +int2 int2 include/postgres.h +int28 (int28 *) include/postgres.h +int4 int4 include/postgres.h +float4 float32 or (float4 *) include/c.h or include/postgres.h +float8 float64 or (float8 *) include/c.h or include/postgres.h +lseg (LSEG *) include/geo-decls.h +name (Name) include/postgres.h +oid oid include/postgres.h +oid8 (oid8 *) include/postgres.h +path (PATH *) utils/geo-decls.h +point (POINT *) utils/geo-decls.h +regproc regproc or REGPROC include/postgres.h +reltime RelativeTime utils/nabstime.h +text (text *) include/postgres.h +tid ItemPointer storage/itemptr.h +tinterval TimeInterval utils/nabstime.h +uint2 uint16 include/c.h +uint4 uint32 include/c.h +xid (XID *) include/postgres.h +.TE +\} +.PP +Complex arguments to C functions are passed into the C function as a +special C type, TUPLE, defined in +.nf +\&.../src/libpq/libpq-fe.h. +.fi +Given a variable +.IR t +of this type, the C function may extract attributes from the function +using the function call: +.nf +GetAttributeByName(t, "fieldname", &isnull) +.fi +where +.IR isnull +is a pointer to a +.IR bool , +which the function sets to +.IR true +if the field is null. The result of this function should be cast +appropriately as shown in the examples below. +.SH "Compiling Dynamically-Loaded C Functions" +.PP +Different operating systems require different procedures for compiling +C source files so that Postgres can load them dynamically. This section +discusses the required compiler and loader options on each system. +.PP +Under Linux ELF, object files can be generated by specifing the compiler +flag -fpic. +.PP +Under Ultrix, all object files that Postgres is expected to load +dynamically must be compiled using +.IR /bin/cc +with the \*(lq-G 0\*(rq option turned on. The object file name in the +.IR as +clause should end in \*(lq.o\*(rq. +.PP +Under HP-UX, DEC OSF/1, AIX and SunOS 4, all object files must be +turned into +.IR "shared libraries" +using the operating system's native object file loader, +.IR ld (1). +.PP +Under HP-UX, an object file must be compiled using the native HP-UX C +compiler, +.IR /bin/cc , +with both the \*(lq+z\*(rq and \*(lq+u\*(rq flags turned on. The +first flag turns the object file into \*(lqposition-independent +code\*(rq (PIC); the second flag removes some alignment restrictions +that the PA-RISC architecture normally enforces. The object file must +then be turned into a shared library using the HP-UX loader, +.IR /bin/ld . +The command lines to compile a C source file, \*(lqfoo.c\*(rq, look +like: +.nf +cc <other flags> +z +u -c foo.c +ld <other flags> -b -o foo.sl foo.o +.fi +The object file name in the +.BR as +clause should end in \*(lq.sl\*(rq. +.PP +An extra step is required under versions of HP-UX prior to 9.00. If +the Postgres header file +.nf +include/c.h +.fi +is not included in the source file, then the following line must also +be added at the top of every source file: +.nf +#pragma HP_ALIGN HPUX_NATURAL_S500 +.fi +However, this line must not appear in programs compiled under HP-UX +9.00 or later. +.PP +Under DEC OSF/1, an object file must be compiled and then turned +into a shared library using the OSF/1 loader, +.IR /bin/ld . +In this case, the command lines look like: +.nf +cc <other flags> -c foo.c +ld <other flags> -shared -expect_unresolved '*' -o foo.so foo.o +.fi +The object file name in the +.BR as +clause should end in \*(lq.so\*(rq. +.PP +Under SunOS 4, an object file must be compiled and then turned into a +shared library using the SunOS 4 loader, +.IR /bin/ld . +The command lines look like: +.nf +cc <other flags> -PIC -c foo.c +ld <other flags> -dc -dp -Bdynamic -o foo.so foo.o +.fi +The object file name in the +.BR as +clause should end in \*(lq.so\*(rq. +.PP +Under AIX, object files are compiled normally but building the shared +library requires a couple of steps. First, create the object file: +.nf +cc <other flags> -c foo.c +.fi +You must then create a symbol \*(lqexports\*(rq file for the object +file: +.nf +mkldexport foo.o `pwd` > foo.exp +.fi +Finally, you can create the shared library: +.nf +ld <other flags> -H512 -T512 -o foo.so -e _nostart \e + -bI:.../lib/postgres.exp -bE:foo.exp foo.o \e + -lm -lc 2>/dev/null +.fi +You should look at the Postgres User's Manual for an explanation of this +procedure. +.SH "SQL FUNCTIONS" +SQL functions execute an arbitrary list of SQL queries, returning +the results of the last query in the list. SQL functions in general +return sets. If their returntype is not specified as a +.IR setof , +then an arbitrary element of the last query's result will be returned. +.PP +The body of a SQL function following +.BR 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 +(i.e. \e\e"). +.PP +Arguments to the SQL function may be referenced in the queries using +a $n syntax: $1 refers to the first argument, $2 to the second, and so +on. If an argument is complex, then a \*(lqdot\*(rq notation may be +used to access attributes of the argument (e.g. \*(lq$1.emp\*(rq), or +to invoke functions via a nested-dot syntax. +.SH "EXAMPLES: C Functions" +The following command defines a C function, overpaid, of two basetype +arguments. +.nf +create function overpaid (float8, int4) returns bool + as '/usr/postgres/src/adt/overpaid.o' + language 'c' +.fi +The C file "overpaid.c" might look something like: +.nf +#include <utils/builtins.h> + +bool overpaid(salary, age) + float8 *salary; + int4 age; +{ + if (*salary > 200000.00) + return(TRUE); + if ((age < 30) & (*salary > 100000.00)) + return(TRUE); + return(FALSE); +} +.fi +The overpaid function can be used in a query, e.g: +.nf +select name from EMP where overpaid(salary, age) +.fi +One can also write this as a function of a single argument of type +EMP: +.nf +create function overpaid_2 (EMP) + returns bool + as '/usr/postgres/src/adt/overpaid_2.o' + language 'c' +.fi +The following query is now accepted: +.nf +select name from EMP where overpaid_2(EMP) +.fi +In this case, in the body of the overpaid_2 function, the fields in the EMP +record must be extracted. The C file "overpaid_2.c" might look +something like: +.nf +#include <utils/builtins.h> +#include <libpq-fe.h> + +bool overpaid_2(t) +TUPLE t; +{ + float8 *salary; + int4 age; + bool salnull, agenull; + + salary = (float8 *)GetAttributeByName(t, "salary", + &salnull); + age = (int4)GetAttributeByName(t, "age", &agenull); + if (!salnull && *salary > 200000.00) + return(TRUE); + if (!agenull && (age<30) && (*salary > 100000.00)) + return(TRUE); + return(FALSE) +} +.fi +.SH "EXAMPLES: SQL Functions" +To illustrate a simple SQL function, consider the following, +which might be used to debit a bank account: +.nf +create function TP1 (int4, float8) returns int4 + as 'update BANK set balance = BANK.balance - $2 + where BANK.acctountno = $1 + select(x = 1)' + language 'sql' +.fi +A user could execute this function to debit account 17 by $100.00 as +follows: +.nf +select (x = TP1( 17,100.0)) +.fi +The following more interesting examples take a single argument of type +EMP, and retrieve multiple results: +.nf +select function hobbies (EMP) returns set of HOBBIES + as 'select (HOBBIES.all) from HOBBIES + where $1.name = HOBBIES.person' + language 'sql' +.SH "SEE ALSO" +.PP +information(1), load(l), drop function(l). +.SH "NOTES" +.SH "Name Space Conflicts" +More than one function may be defined with the same name, as long as +the arguments they take are different. In other words, function names +can be +.IR overloaded . +A function may also have the same name as an attribute. In the case +that there is an ambiguity between a function on a complex type and +an attribute of the complex type, the attribute will always be used. +.SH "RESTRICTIONS" +The name of the C function must be a legal C function name, and the +name of the function in C code must be exactly the same as the name +used in +.BR "create function" . +There is a subtle implication of this restriction: while the +dynamic loading routines in most operating systems are more than +happy to allow you to load any number of shared libraries that +contain conflicting (identically-named) function names, they may +in fact botch the load in interesting ways. For example, if you +define a dynamically-loaded function that happens to have the +same name as a function built into Postgres, the DEC OSF/1 dynamic +loader causes Postgres to call the function within itself rather than +allowing Postgres to call your function. Hence, if you want your +function to be used on different architectures, we recommend that +you do not overload C function names. +.PP +There is a clever trick to get around the problem just described. +Since there is no problem overloading SQL functions, you can +define a set of C functions with different names and then define +a set of identically-named SQL function wrappers that take the +appropriate argument types and call the matching C function. +.PP +.IR opaque +cannot be given as an argument to a SQL function. +.SH "BUGS" +C functions cannot return a set of values. |