Commit f2f43efb authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Complete merge of all old man page information.

lisp.sgml is a placeholder for Eric Marsden's upcoming contribution.
catalogs.sgml is not yet marked up or integrated.
 It should perhaps become an appendix.
parent a27512e6
.\" This is -*-nroff-*-
.\" XXX standard disclaimer belongs here....
.\" $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.1 1999/07/22 15:11:03 thomas Exp $
.TH "SYSTEM CATALOGS" INTRO 03/13/94 PostgreSQL PostgreSQL
.SH "Section 7 - System Catalogs"
.de LS
.PP
.if n .ta 5 +13 +13
.if t .ta 0.5i +1.3i +1.3i
.in 0
.nf
..
.de LE
.fi
.in
..
.SH "DESCRIPTION"
In this
section we list each of the attributes of the system catalogs and
define their meanings.
.SH "CLASS/TYPE SYSTEM CATALOGS"
These catalogs form the core of the extensibility system:
.LS
\fBname\fP \fBshared/local\fP \fBdescription\fP
pg_aggregate local aggregate functions
pg_am local access methods
pg_amop local operators usable with specific access methods
pg_amproc local procedures used with specific access methods
pg_attribute local class attributes
pg_class local classes
pg_index local secondary indices
pg_inherits local class inheritance hierarchy
pg_language local procedure implementation languages
pg_opclass local operator classes
pg_operator local query language operators
pg_proc local procedures (functions)
pg_type local data types
.LE
.SH "ENTITIES"
These catalogs deal with identification of entities known throughout
the site:
.LS
\fBname\fP \fBshared/local\fP \fBdescription\fP
pg_database shared current databases
pg_group shared user groups
pg_shadow shared valid users
.LE
.SH "RULE SYSTEM CATALOGS"
.LS
\fBname\fP \fBshared/local\fP \fBdescription\fP
pg_listener local processes waiting on alerters
pg_prs2plans local instance system procedures
pg_prs2rule local instance system rules
pg_prs2stub local instance system ``stubs''
pg_rewrite local rewrite system information
.LE
.SH "LARGE OBJECT CATALOGS"
.PP
These catalogs are specific to the Inversion file system and large
objects in general:
.LS
\fBname\fP \fBshared/local\fP \fBdescription\fP
pg_lobj local description of a large object
pg_naming local Inversion name space mapping
pg_platter local jukebox platter inventory
pg_plmap local jukebox platter extent map
.LE
.SH "INTERNAL CATALOGS"
.PP
These catalogs are internal classes that are not stored as normal
heaps and cannot be accessed through normal means (attempting to do so
causes an error).
.LS
\fBname\fP \fBshared/local\fP \fBdescription\fP
pg_log shared transaction commit/rollback log
pg_magic shared magic constant
pg_time shared commit/rollback times
pg_variable shared special variable values
.LE
.PP
There are several other classes defined with \*(lqpg_\*(rq names.
Aside from those that end in \*(lqind\*(rq (secondary indices), these
are all obsolete or otherwise deprecated.
.SH "CLASS/TYPE SYSTEM CATALOGS"
.PP
The following catalogs relate to the class/type system.
.nf M
/*
* aggregates
*
* see DEFINE AGGREGATE for an explanation of transition functions
*/
pg_aggregate
NameData aggname /* aggregate name (e.g., "count") */
oid aggowner /* usesysid of creator */
regproc aggtransfn1 /* first transition function */
regproc aggtransfn2 /* second transition function */
regproc aggfinalfn /* final function */
oid aggbasetype /* type of data on which aggregate
operates */
oid aggtranstype1 /* type returned by aggtransfn1 */
oid aggtranstype2 /* type returned by aggtransfn2 */
oid aggfinaltype /* type returned by aggfinalfn */
text agginitval1 /* external format of initial
(starting) value of aggtransfn1 */
text agginitval2 /* external format of initial
(starting) value of aggtransfn2 */
.fi
.nf M
pg_am
NameData amname /* access method name */
oid amowner /* usesysid of creator */
char amkind /* - deprecated */
/* originally:
h=hashed
o=ordered
s=special */
int2 amstrategies /* total NUMBER of strategies by which
we can traverse/search this AM */
int2 amsupport /* total NUMBER of support functions
that this AM uses */
regproc amgettuple /* "next valid tuple" function */
regproc aminsert /* "insert this tuple" function */
regproc amdelete /* "delete this tuple" function */
regproc amgetattr /* - deprecated */
regproc amsetlock /* - deprecated */
regproc amsettid /* - deprecated */
regproc amfreetuple /* - deprecated */
regproc ambeginscan /* "start new scan" function */
regproc amrescan /* "restart this scan" function */
regproc amendscan /* "end this scan" function */
regproc ammarkpos /* "mark current scan position"
function */
regproc amrestrpos /* "restore marked scan position"
function */
regproc amopen /* - deprecated */
regproc amclose /* - deprecated */
regproc ambuild /* "build new index" function */
regproc amcreate /* - deprecated */
regproc amdestroy /* - deprecated */
.fi
.nf M
pg_amop
oid amopid /* access method with which this
operator be used */
oid amopclaid /* operator class with which this
operator can be used */
oid amopopr /* the operator */
int2 amopstrategy /* traversal/search strategy number
to which this operator applies */
regproc amopselect /* function to calculate the operator
selectivity */
regproc amopnpages /* function to calculate the number of
pages that will be examined */
.fi
.nf M
pg_amproc
oid amid /* access method with which this
procedure is associated */
oid amopclaid /* operator class with which this
operator can be used */
oid amproc /* the procedure */
int2 amprocnum /* support function number to which
this operator applies */
.fi
.nf M
pg_class
NameData relname /* class name */
oid relowner /* usesysid of owner */
oid relam /* access method */
int4 relpages /* # of 8KB pages */
int4 reltuples /* # of instances */
abstime relexpires /* time after which instances are
deleted from non-archival storage */
reltime relpreserved /* timespan after which instances are
deleted from non-archival storage */
bool relhasindex /* does the class have a secondary
index? */
bool relisshared /* is the class shared or local? */
char relkind /* type of relation:
i=index
r=relation (heap)
s=special
u=uncatalogued (temporary) */
char relarch /* archive mode:
h=heavy
l=light
n=none */
int2 relnatts /* current # of non-system
attributes */
int2 relsmgr /* storage manager:
0=magnetic disk
1=sony WORM jukebox
2=main memory */
int28 relkey /* - unused */
oid8 relkeyop /* - unused */
aclitem relacl[1] /* access control lists */
.fi
.nf M
pg_attribute
oid attrelid /* class containing this attribute */
NameData attname /* attribute name */
oid atttypid /* attribute type */
oid attdefrel /* - deprecated */
int4 attnvals /* - deprecated */
oid atttyparg /* - deprecated */
int2 attlen /* attribute length, in bytes
-1=variable */
int2 attnum /* attribute number
>0=user attribute
<0=system attribute */
int2 attbound /* - deprecated */
bool attbyval /* type passed by value? */
bool attcanindex /* - deprecated */
oid attproc /* - deprecated */
int4 attnelems /* # of array dimensions */
int4 attcacheoff /* cached offset into tuple */
bool attisset /* is attribute set-valued? */
.fi
.nf M
pg_inherits
oid inhrel /* child class */
oid inhparent /* parent class */
int4 inhseqno /* - deprecated */
.fi
.nf M
oid indexrelid /* oid of secondary index class */
oid indrelid /* oid of indexed heap class */
oid indproc /* function to compute index key from
attribute(s) in heap
0=not a functional index */
int28 indkey /* attribute numbers of key
attribute(s) */
oid8 indclass /* opclass of each key */
bool indisclustered /* is the index clustered?
- unused */
bool indisarchived /* is the index archival?
- unused */
text indpred /* query plan for partial index
predicate */
.fi
.nf M
pg_type
NameData typname /* type name */
oid typowner /* usesysid of owner */
int2 typlen /* length in internal form
-1=variable-length */
int2 typprtlen /* length in external form */
bool typbyval /* type passed by value? */
char typtype /* kind of type:
c=catalog (composite)
b=base */
bool typisdefined /* defined or still a shell? */
char typdelim /* delimiter for array external form */
oid typrelid /* class (if composite) */
oid typelem /* type of each array element */
regproc typinput /* external-internal conversion
function */
regproc typoutput /* internal-external conversion
function */
regproc typreceive /* client-server conversion function */
regproc typsend /* server-client conversion function */
text typdefault /* default value */
.fi
.nf M
pg_operator
NameData oprname /* operator name */
oid oprowner /* usesysid of owner */
int2 oprprec /* - deprecated */
char oprkind /* kind of operator:
b=binary
l=left unary
r=right unary */
bool oprisleft /* is operator left/right associative? */
bool oprcanhash /* is operator usable for hashjoin? */
oid oprleft /* left operand type */
oid oprright /* right operand type */
oid oprresult /* result type */
oid oprcom /* commutator operator */
oid oprnegate /* negator operator */
oid oprlsortop /* sort operator for left operand */
oid oprrsortop /* sort operator for right operand */
regproc oprcode /* function implementing this operator */
regproc oprrest /* function to calculate operator
restriction selectivity */
regproc oprjoin /* function to calculate operator
join selectivity */
.fi
.nf M
pg_opclass
NameData opcname /* operator class name */
.fi
.nf M
pg_proc
NameData proname /* function name */
oid proowner /* usesysid of owner */
oid prolang /* function implementation language */
bool proisinh /* - deprecated */
bool proistrusted /* run in server or untrusted function
process? */
bool proiscachable /* can the function return values be
cached? */
int2 pronargs /* # of arguments */
bool proretset /* does the function return a set?
- unused */
oid prorettype /* return type */
oid8 proargtypes /* argument types */
int4 probyte_pct /* % of argument size (in bytes) that
needs to be examined in order to
compute the function */
int4 properbyte_cpu /* sensitivity of the function's
running time to the size of its
inputs */
int4 propercall_cpu /* overhead of the function's
invocation (regardless of input
size) */
int4 prooutin_ratio /* size of the function's output as a
percentage of the size of the input */
text prosrc /* function definition:
INTERNAL function: actual C name of function
C function: currently, this field is unused
SQL function: text of query(s)
PL function: text in procedural language */
bytea probin /* path to object file (C functions only) */
.fi
.nf M
pg_language
NameData lanname /* language name */
text lancompiler /* - deprecated */
.fi
.SH "ENTITIES"
.nf M
pg_database
NameData datname /* database name */
oid datdba /* usesysid of database administrator */
text datpath /* directory of database under
$PGDATA */
.fi
.nf M
pg_group
NameData groname /* group name */
int2 grosysid /* group's UNIX group id */
int2 grolist[1] /* list of usesysids of group members */
.fi
.nf M
pg_shadow
NameData usename /* user's name */
int2 usesysid /* user's UNIX user id */
bool usecreatedb /* can user create databases? */
bool usetrace /* can user set trace flags? */
bool usesuper /* can user be POSTGRES superuser? */
bool usecatupd /* can user update catalogs? */
.fi
.SH "RULE SYSTEM CATALOGS"
.nf M
pg_listener
NameData relname /* class for which asynchronous
notification is desired */
int4 listenerpid /* process id of server corresponding
to a frontend program waiting for
asynchronous notification */
int4 notification /* whether an event notification for
this process id still pending */
.fi
.nf M
pg_prs2rule
NameData prs2name /* rule name */
char prs2eventtype /* rule event type:
R=retrieve
U=update (replace)
A=append
D=delete */
oid prs2eventrel /* class to which event applies */
int2 prs2eventattr /* attribute to which event applies */
float8 necessary /* - deprecated */
float8 sufficient /* - deprecated */
text prs2text /* text of original rule definition */
.fi
.nf M
pg_prs2plans
oid prs2ruleid /* prs2rule instance for which this
plan is used */
int2 prs2planno /* plan number (one rule may invoke
multiple plans) */
text prs2code /* external representation of the plan */
.fi
.nf M
pg_prs2stub
oid prs2relid /* class to which this rule applies */
bool prs2islast /* is this the last stub fragment? */
int4 prs2no /* stub fragment number */
stub prs2stub /* stub fragment */
.fi
.nf M
pg_rewrite
NameData rulename /* rule name */
char ev_type /* event type:
RETRIEVE, REPLACE, APPEND, DELETE
codes are parser-dependent (!?) */
oid ev_class /* class to which this rule applies */
int2 ev_attr /* attribute to which this rule applies */
bool is_instead /* is this an "instead" rule? */
text ev_qual /* qualification with which to modify
(rewrite) the plan that triggered this
rule */
text action /* parse tree of action */
.fi
.SH "LARGE OBJECT CATALOGS"
.nf M
pg_lobj
oid ourid /* 'ourid' from pg_naming that
identifies this object in the
Inversion file system namespace */
int4 objtype /* storage type code:
0=Inversion
1=Unix
2=External
3=Jaquith */
bytea object_descripto/* opaque object-handle structure */
.fi
.nf M
pg_naming
NameData filename /* filename component */
oid ourid /* random oid used to identify this
instance in other instances (can't
use the actual oid for obscure
reasons */
oid parentid /* pg_naming instance of parent
Inversion file system directory */
.fi
.nf M
pg_platter
NameData plname /* platter name */
int4 plstart /* the highest OCCUPIED extent */
.fi
.nf M
pg_plmap
oid plid /* platter (in pg_platter) on which
this extent (of blocks) resides */
oid pldbid /* database of the class to which this
extent (of blocks) belongs */
oid plrelid /* class to which this extend (of
blocks) belongs */
int4 plblkno /* starting block number within the
class */
int4 ploffset /* offset within the platter at which
this extent begins */
int4 plextentsz /* length of this extent */
.fi
<Chapter Id="dfunc"> <chapter id="dfunc">
<Title>Linking Dynamically-Loaded Functions</Title> <title id="dfunc-title">Linking Dynamically-Loaded Functions</title>
<Para> <!--
.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.
-->
<para>
After you have created and registered a user-defined After you have created and registered a user-defined
function, your work is essentially done. <ProductName>Postgres</ProductName>, function, your work is essentially done. <productname>Postgres</productname>,
however, must load the object code (e.g., a <FileName>.o</FileName> file, or however, must load the object code (e.g., a <filename>.o</filename> file, or
a shared library) that implements your function. As a shared library) that implements your function. As
previously mentioned, <ProductName>Postgres</ProductName> loads your code at previously mentioned, <productname>Postgres</productname> loads your code at
runtime, as required. In order to allow your code to be runtime, as required. In order to allow your code to be
dynamically loaded, you may have to compile and dynamically loaded, you may have to compile and
link-edit it in a special way. This section briefly link-edit it in a special way. This section briefly
describes how to perform the compilation and describes how to perform the compilation and
link-editing required before you can load your user-defined link-editing required before you can load your user-defined
functions into a running <ProductName>Postgres</ProductName> server. Note that functions into a running <productname>Postgres</productname> server. Note that
this process has changed as of Version 4.2. this process has changed as of Version 4.2.
<Tip> <tip>
<Para> <para>
The old <ProductName>Postgres</ProductName> dynamic The old <productname>Postgres</productname> dynamic
loading mechanism required loading mechanism required
in-depth knowledge in terms of executable format, placement in-depth knowledge in terms of executable format, placement
and alignment of executable instructions within memory, etc. and alignment of executable instructions within memory, etc.
on the part of the person writing the dynamic loader. Such on the part of the person writing the dynamic loader. Such
loaders tended to be slow and buggy. As of Version 4.2, the loaders tended to be slow and buggy. As of Version 4.2, the
<ProductName>Postgres</ProductName> dynamic loading mechanism has been rewritten to use <productname>Postgres</productname> dynamic loading mechanism has been rewritten to use
the dynamic loading mechanism provided by the operating the dynamic loading mechanism provided by the operating
system. This approach is generally faster, more reliable and system. This approach is generally faster, more reliable and
more portable than our previous dynamic loading mechanism. more portable than our previous dynamic loading mechanism.
...@@ -30,58 +129,59 @@ The reason for this is that nearly all modern versions of ...@@ -30,58 +129,59 @@ The reason for this is that nearly all modern versions of
UNIX use a dynamic loading mechanism to implement shared UNIX use a dynamic loading mechanism to implement shared
libraries and must therefore provide a fast and reliable libraries and must therefore provide a fast and reliable
mechanism. On the other hand, the object file must be mechanism. On the other hand, the object file must be
postprocessed a bit before it can be loaded into <ProductName>Postgres</ProductName>. We postprocessed a bit before it can be loaded into <productname>Postgres</productname>. We
hope that the large increase in speed and reliability will hope that the large increase in speed and reliability will
make up for the slight decrease in convenience. make up for the slight decrease in convenience.
</para> </para>
</Tip> </tip>
</para> </para>
<para> <para>
You should expect to read (and reread, and re-reread) the You should expect to read (and reread, and re-reread) the
manual pages for the C compiler, cc(1), and the link manual pages for the C compiler, cc(1), and the link
editor, ld(1), if you have specific questions. In editor, ld(1), if you have specific questions. In
addition, the regression test suites in the directory addition, the regression test suites in the directory
<FileName>PGROOT/src/regress</FileName> contain several <filename>PGROOT/src/regress</filename> contain several
working examples of this process. If you copy what these working examples of this process. If you copy what these
tests do, you should not have any problems. tests do, you should not have any problems.
The following terminology will be used below: The following terminology will be used below:
<ItemizedList> <itemizedlist>
<ListItem> <listitem>
<Para> <para>
<FirstTerm>Dynamic loading</FirstTerm> <firstterm>Dynamic loading</firstterm>
is what <ProductName>Postgres</ProductName> does to an object file. The is what <productname>Postgres</productname> does to an object file. The
object file is copied into the running <ProductName>Postgres</ProductName> object file is copied into the running <productname>Postgres</productname>
server and the functions and variables within the server and the functions and variables within the
file are made available to the functions within file are made available to the functions within
the <ProductName>Postgres</ProductName> process. <ProductName>Postgres</ProductName> does this using the <productname>Postgres</productname> process.
<productname>Postgres</productname> does this using
the dynamic loading mechanism provided by the the dynamic loading mechanism provided by the
operating system. operating system.
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
<FirstTerm>Loading and link editing</FirstTerm> <firstterm>Loading and link editing</firstterm>
is what you do to an object file in order to produce is what you do to an object file in order to produce
another kind of object file (e.g., an executable another kind of object file (e.g., an executable
program or a shared library). You perform program or a shared library). You perform
this using the link editing program, ld(1). this using the link editing program, ld(1).
</Para> </para>
</ListItem> </listitem>
</ItemizedList> </itemizedlist>
</Para> </para>
<Para> <para>
The following general restrictions and notes also apply The following general restrictions and notes also apply
to the discussion below: to the discussion below:
<ItemizedList> <itemizedlist>
<ListItem> <listitem>
<Para> <para>
Paths given to the create function command must be Paths given to the create function command must be
absolute paths (i.e., start with "/") that refer to absolute paths (i.e., start with "/") that refer to
directories visible on the machine on which the directories visible on the machine on which the
<ProductName>Postgres</ProductName> server is running. <productname>Postgres</productname> server is running.
<Tip> <tip>
<Para> <para>
Relative paths do in fact work, Relative paths do in fact work,
but are relative to but are relative to
the directory where the database resides (which is generally the directory where the database resides (which is generally
...@@ -89,45 +189,45 @@ invisible to the frontend application). Obviously, it makes ...@@ -89,45 +189,45 @@ invisible to the frontend application). Obviously, it makes
no sense to make the path relative to the directory in which no sense to make the path relative to the directory in which
the user started the frontend application, since the server the user started the frontend application, since the server
could be running on a completely different machine! could be running on a completely different machine!
</Para> </para>
</Tip> </tip>
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
The <ProductName>Postgres</ProductName> user must be able to traverse the path The <productname>Postgres</productname> user must be able to traverse the path
given to the create function command and be able to given to the create function command and be able to
read the object file. This is because the <ProductName>Postgres</ProductName> read the object file. This is because the <productname>Postgres</productname>
server runs as the <ProductName>Postgres</ProductName> user, not as the user server runs as the <productname>Postgres</productname> user, not as the user
who starts up the frontend process. (Making the who starts up the frontend process. (Making the
file or a higher-level directory unreadable and/or file or a higher-level directory unreadable and/or
unexecutable by the "postgres" user is an extremely unexecutable by the "postgres" user is an extremely
common mistake.) common mistake.)
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
Symbol names defined within object files must not Symbol names defined within object files must not
conflict with each other or with symbols defined in conflict with each other or with symbols defined in
<ProductName>Postgres</ProductName>. <productname>Postgres</productname>.
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
The GNU C compiler usually does not provide the special The GNU C compiler usually does not provide the special
options that are required to use the operating options that are required to use the operating
system's dynamic loader interface. In such cases, system's dynamic loader interface. In such cases,
the C compiler that comes with the operating system the C compiler that comes with the operating system
must be used. must be used.
</Para> </para>
</ListItem> </listitem>
</ItemizedList> </itemizedlist>
</para> </para>
<Sect1> <sect1>
<Title><Acronym>ULTRIX</Acronym></Title> <title><acronym>ULTRIX</acronym></title>
<Para> <para>
It is very easy to build dynamically-loaded object It is very easy to build dynamically-loaded object
files under ULTRIX. ULTRIX does not have any shared library files under ULTRIX. ULTRIX does not have any shared library
mechanism and hence does not place any restrictions on mechanism and hence does not place any restrictions on
...@@ -138,42 +238,42 @@ The GNU C compiler usually does not provide the special ...@@ -138,42 +238,42 @@ The GNU C compiler usually does not provide the special
produce each object file with the option -G 0. (Notice produce each object file with the option -G 0. (Notice
that that's the numeral ``0'' and not the letter that that's the numeral ``0'' and not the letter
``O''). For example, ``O''). For example,
<ProgramListing> <programlisting>
# simple ULTRIX example # simple ULTRIX example
% cc -G 0 -c foo.c % cc -G 0 -c foo.c
</ProgramListing> </programlisting>
produces an object file called foo.o that can then be produces an object file called foo.o that can then be
dynamically loaded into <ProductName>Postgres</ProductName>. dynamically loaded into <productname>Postgres</productname>.
No additional loading or link-editing must be performed. No additional loading or link-editing must be performed.
</Para> </para>
</Sect1> </sect1>
<Sect1> <sect1>
<Title><Acronym>DEC OSF/1</Acronym></Title> <title><acronym>DEC OSF/1</acronym></title>
<Para> <para>
Under DEC OSF/1, you can take any simple object file Under DEC OSF/1, you can take any simple object file
and produce a shared object file by running the ld command and produce a shared object file by running the ld command
over it with the correct options. The commands to over it with the correct options. The commands to
do this look like: do this look like:
<ProgramListing> <programlisting>
# simple DEC OSF/1 example # simple DEC OSF/1 example
% cc -c foo.c % cc -c foo.c
% ld -shared -expect_unresolved '*' -o foo.so foo.o % ld -shared -expect_unresolved '*' -o foo.so foo.o
</ProgramListing> </programlisting>
The resulting shared object file can then be loaded The resulting shared object file can then be loaded
into <ProductName>Postgres</ProductName>. When specifying the object file name to into <productname>Postgres</productname>. When specifying the object file name to
the create function command, one must give it the name the create function command, one must give it the name
of the shared object file (ending in .so) rather than of the shared object file (ending in .so) rather than
the simple object file. the simple object file.
<Tip> <tip>
<Para> <para>
Actually, <ProductName>Postgres</ProductName> does not care Actually, <productname>Postgres</productname> does not care
what you name the what you name the
file as long as it is a shared object file. If you prefer file as long as it is a shared object file. If you prefer
to name your shared object files with the extension .o, this to name your shared object files with the extension .o, this
is fine with <ProductName>Postgres</ProductName> is fine with <productname>Postgres</productname>
so long as you make sure that the correct so long as you make sure that the correct
file name is given to the create function command. In file name is given to the create function command. In
other words, you must simply be consistent. However, from a other words, you must simply be consistent. However, from a
...@@ -183,19 +283,20 @@ files have been made into shared object files and which have ...@@ -183,19 +283,20 @@ files have been made into shared object files and which have
not. For example, it's very hard to write Makefiles to do not. For example, it's very hard to write Makefiles to do
the link-editing automatically if both the object file and the link-editing automatically if both the object file and
the shared object file end in .o! the shared object file end in .o!
</Para> </para>
</Tip> </tip>
If the file you specify is If the file you specify is
not a shared object, the backend will hang! not a shared object, the backend will hang!
</Para> </para>
</Sect1> </sect1>
<Sect1> <sect1>
<Title> <title>
<Acronym>SunOS 4.x</Acronym>, <Acronym>Solaris 2.x</Acronym> and <Acronym>HP-UX</Acronym></Title> <acronym>SunOS 4.x</acronym>, <acronym>Solaris 2.x</acronym> and
<acronym>HP-UX</acronym></title>
<Para> <para>
Under SunOS 4.x, Solaris 2.x and HP-UX, the simple Under SunOS 4.x, Solaris 2.x and HP-UX, the simple
object file must be created by compiling the source object file must be created by compiling the source
file with special compiler flags and a shared library file with special compiler flags and a shared library
...@@ -209,44 +310,61 @@ If the file you specify is ...@@ -209,44 +310,61 @@ If the file you specify is
into a shared library using the HP-UX link editor with into a shared library using the HP-UX link editor with
the -b option. This sounds complicated but is actually the -b option. This sounds complicated but is actually
very simple, since the commands to do it are just: very simple, since the commands to do it are just:
<ProgramListing> <programlisting>
# simple HP-UX example # simple HP-UX example
% cc +z +u -c foo.c % cc +z +u -c foo.c
% ld -b -o foo.sl foo.o % ld -b -o foo.sl foo.o
</ProgramListing> </programlisting>
</Para> </para>
<Para> <para>
As with the .so files mentioned in the last subsection, As with the .so files mentioned in the last subsection,
the create function command must be told which file is the create function command must be told which file is
the correct file to load (i.e., you must give it the the correct file to load (i.e., you must give it the
location of the shared library, or .sl file). location of the shared library, or .sl file).
Under SunOS 4.x, the commands look like: Under SunOS 4.x, the commands look like:
<ProgramListing> <programlisting>
# simple SunOS 4.x example # simple SunOS 4.x example
% cc -PIC -c foo.c % cc -PIC -c foo.c
% ld -dc -dp -Bdynamic -o foo.so foo.o % ld -dc -dp -Bdynamic -o foo.so foo.o
</ProgramListing> </programlisting>
and the equivalent lines under Solaris 2.x are: and the equivalent lines under Solaris 2.x are:
<ProgramListing> <programlisting>
# simple Solaris 2.x example # simple Solaris 2.x example
% cc -K PIC -c foo.c % cc -K PIC -c foo.c
% ld -G -Bdynamic -o foo.so foo.o % ld -G -Bdynamic -o foo.so foo.o
</ProgramListing> </programlisting>
or or
<ProgramListing> <programlisting>
# simple Solaris 2.x example # simple Solaris 2.x example
% gcc -fPIC -c foo.c % gcc -fPIC -c foo.c
% ld -G -Bdynamic -o foo.so foo.o % ld -G -Bdynamic -o foo.so foo.o
</ProgramListing> </programlisting>
</Para> </para>
<Para> <para>
When linking shared libraries, you may have to specify When linking shared libraries, you may have to specify
some additional shared libraries (typically system some additional shared libraries (typically system
libraries, such as the C and math libraries) on your ld libraries, such as the C and math libraries) on your ld
command line. command line.
</Para> </para>
</Sect1> </sect1>
</Chapter> </chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
sgml-local-ecat-files:nil
End:
-->
<Chapter Id="extend"> <chapter id="extend">
<Title>Extending <Acronym>SQL</Acronym>: An Overview</Title> <title>Extending <acronym>SQL</acronym>: An Overview</title>
<Para> <para>
In the sections that follow, we will discuss how you In the sections that follow, we will discuss how you
can extend the <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> query language by adding: can extend the <productname>Postgres</productname>
<ItemizedList Mark="bullet" Spacing="compact"> <acronym>SQL</acronym> query language by adding:
<ListItem>
<Para> <itemizedlist spacing="compact" mark="bullet">
<listitem>
<para>
functions functions
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
types types
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
operators operators
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
aggregates aggregates
</Para> </para>
</ListItem> </listitem>
</ItemizedList> </itemizedlist>
</Para> </para>
<Sect1> <sect1>
<Title>How Extensibility Works</Title> <title>How Extensibility Works</title>
<Para> <para>
<ProductName>Postgres</ProductName> is extensible because its operation is <productname>Postgres</productname> is extensible because its operation is
catalog-driven. If you are familiar with standard catalog-driven. If you are familiar with standard
relational systems, you know that they store information relational systems, you know that they store information
about databases, tables, columns, etc., in what are about databases, tables, columns, etc., in what are
commonly known as system catalogs. (Some systems call commonly known as system catalogs. (Some systems call
this the data dictionary). The catalogs appear to the this the data dictionary). The catalogs appear to the
user as classes, like any other, but the <Acronym>DBMS</Acronym> stores user as classes, like any other, but the <acronym>DBMS</acronym> stores
its internal bookkeeping in them. One key difference its internal bookkeeping in them. One key difference
between <ProductName>Postgres</ProductName> and standard relational systems is between <productname>Postgres</productname> and standard relational systems is
that <ProductName>Postgres</ProductName> stores much more information in its that <productname>Postgres</productname> stores much more information in its
catalogs -- not only information about tables and columns, catalogs -- not only information about tables and columns,
but also information about its types, functions, access but also information about its types, functions, access
methods, and so on. These classes can be modified by methods, and so on. These classes can be modified by
the user, and since <ProductName>Postgres</ProductName> bases its internal operation the user, and since <productname>Postgres</productname> bases its internal operation
on these classes, this means that <ProductName>Postgres</ProductName> can be on these classes, this means that <productname>Postgres</productname> can be
extended by users. By comparison, conventional extended by users. By comparison, conventional
database systems can only be extended by changing hardcoded database systems can only be extended by changing hardcoded
procedures within the <Acronym>DBMS</Acronym> or by loading modules procedures within the <acronym>DBMS</acronym> or by loading modules
specially-written by the <Acronym>DBMS</Acronym> vendor. specially-written by the <acronym>DBMS</acronym> vendor.
</Para> </para>
<Para>
<ProductName>Postgres</ProductName> is also unlike most other data managers in <para>
that the server can incorporate user-written code into <productname>Postgres</productname> is also unlike most other data managers in
itself through dynamic loading. That is, the user can that the server can incorporate user-written code into
specify an object code file (e.g., a compiled .o file itself through dynamic loading. That is, the user can
or shared library) that implements a new type or function specify an object code file (e.g., a compiled .o file
and <ProductName>Postgres</ProductName> will load it as required. Code written or shared library) that implements a new type or function
in <Acronym>SQL</Acronym> are even more trivial to add to the server. and <productname>Postgres</productname> will load it as required. Code written
This ability to modify its operation "on the fly" makes in <acronym>SQL</acronym> are even more trivial to add to the server.
<ProductName>Postgres</ProductName> uniquely suited for rapid prototyping of new This ability to modify its operation "on the fly" makes
applications and storage structures. <productname>Postgres</productname> uniquely suited for rapid prototyping of new
</Para> applications and storage structures.
</Sect1> </para>
</sect1>
<Sect1>
<Title>The <ProductName>Postgres</ProductName> Type System</Title> <sect1>
<title>The <productname>Postgres</productname> Type System</title>
<Para>
The <ProductName>Postgres</ProductName> type system can be broken down in several ways. <para>
Types are divided into base types and composite types. The <productname>Postgres</productname> type system
Base types are those, like <FirstTerm>int4</FirstTerm>, that are implemented can be broken down in several ways.
in a language such as <ProductName>C</ProductName>. They generally correspond to Types are divided into base types and composite types.
what are often known as "abstract data types"; <ProductName>Postgres</ProductName> Base types are those, like <firstterm>int4</firstterm>, that are implemented
can only operate on such types through methods provided in a language such as <productname>C</productname>. They generally correspond to
by the user and only understands the behavior of such what are often known as "abstract data types"; <productname>Postgres</productname>
types to the extent that the user describes them. can only operate on such types through methods provided
Composite types are created whenever the user creates a by the user and only understands the behavior of such
class. EMP is an example of a composite type. types to the extent that the user describes them.
</Para> Composite types are created whenever the user creates a
<Para> class. EMP is an example of a composite type.
<ProductName>Postgres</ProductName> stores these types in only one way (within the </para>
file that stores all instances of the class) but the
user can "look inside" at the attributes of these types <para>
from the query language and optimize their retrieval by <productname>Postgres</productname> stores these types
(for example) defining indices on the attributes. in only one way (within the
<ProductName>Postgres</ProductName> base types are further divided into built-in file that stores all instances of the class) but the
types and user-defined types. Built-in types (like user can "look inside" at the attributes of these types
<FirstTerm>int4</FirstTerm>) are those that are compiled into the system. from the query language and optimize their retrieval by
User-defined types are those created by the user in the (for example) defining indices on the attributes.
manner to be described below. <productname>Postgres</productname> base types are further
</Para> divided into built-in
</Sect1> types and user-defined types. Built-in types (like
<firstterm>int4</firstterm>) are those that are compiled
<Sect1> into the system.
<Title>About the <ProductName>Postgres</ProductName> System Catalogs</Title> User-defined types are those created by the user in the
manner to be described below.
<Para> </para>
Having introduced the basic extensibility concepts, we </sect1>
can now take a look at how the catalogs are actually
laid out. You can skip this section for now, but some <sect1>
later sections will be incomprehensible without the <title>About the <productname>Postgres</productname> System Catalogs</title>
information given here, so mark this page for later
reference. <para>
All system catalogs have names that begin with <FirstTerm>pg_</FirstTerm>. Having introduced the basic extensibility concepts, we
The following classes contain information that may be can now take a look at how the catalogs are actually
useful to the end user. (There are many other system laid out. You can skip this section for now, but some
catalogs, but there should rarely be a reason to query later sections will be incomprehensible without the
them directly.) information given here, so mark this page for later
reference.
<TABLE TOCENTRY="1"> All system catalogs have names that begin with
<TITLE>Postgres System Catalogs</TITLE> <firstterm>pg_</firstterm>.
<TITLEABBREV>Catalogs</TITLEABBREV> The following classes contain information that may be
<TGROUP COLS="2"> useful to the end user. (There are many other system
<THEAD> catalogs, but there should rarely be a reason to query
<ROW> them directly.)
<ENTRY>Catalog Name</ENTRY>
<ENTRY>Description</ENTRY> <table tocentry="1">
</ROW> <title>Postgres System Catalogs</title>
</THEAD> <titleabbrev>Catalogs</titleabbrev>
<TBODY> <tgroup cols="2">
<ROW> <thead>
<ENTRY>pg_database</ENTRY> <row>
<ENTRY> databases</ENTRY> <entry>Catalog Name</entry>
</ROW> <entry>Description</entry>
<ROW> </row>
<ENTRY>pg_class</ENTRY> </thead>
<ENTRY> classes</ENTRY> <tbody>
</ROW> <row>
<ROW> <entry>pg_database</entry>
<ENTRY>pg_attribute</ENTRY> <entry> databases</entry>
<ENTRY> class attributes</ENTRY> </row>
</ROW> <row>
<ROW> <entry>pg_class</entry>
<ENTRY>pg_index</ENTRY> <entry> classes</entry>
<ENTRY> secondary indices</ENTRY> </row>
</ROW> <row>
<ROW> <entry>pg_attribute</entry>
<ENTRY>pg_proc</ENTRY> <entry> class attributes</entry>
<ENTRY> procedures (both C and SQL)</ENTRY> </row>
</ROW> <row>
<ROW> <entry>pg_index</entry>
<ENTRY>pg_type</ENTRY> <entry> secondary indices</entry>
<ENTRY> types (both base and complex)</ENTRY> </row>
</ROW> <row>
<ROW> <entry>pg_proc</entry>
<ENTRY>pg_operator</ENTRY> <entry> procedures (both C and SQL)</entry>
<ENTRY> operators</ENTRY> </row>
</ROW> <row>
<ROW> <entry>pg_type</entry>
<ENTRY>pg_aggregate</ENTRY> <entry> types (both base and complex)</entry>
<ENTRY> aggregates and aggregate functions</ENTRY> </row>
</ROW> <row>
<ROW> <entry>pg_operator</entry>
<ENTRY>pg_am</ENTRY> <entry> operators</entry>
<ENTRY> access methods</ENTRY> </row>
</ROW> <row>
<ROW> <entry>pg_aggregate</entry>
<ENTRY>pg_amop</ENTRY> <entry> aggregates and aggregate functions</entry>
<ENTRY> access method operators</ENTRY> </row>
</ROW> <row>
<ROW> <entry>pg_am</entry>
<ENTRY>pg_amproc</ENTRY> <entry> access methods</entry>
<ENTRY> access method support functions</ENTRY> </row>
</ROW> <row>
<ROW> <entry>pg_amop</entry>
<ENTRY>pg_opclass</ENTRY> <entry> access method operators</entry>
<ENTRY> access method operator classes</ENTRY> </row>
</ROW> <row>
</TBODY> <entry>pg_amproc</entry>
</TGROUP> <entry> access method support functions</entry>
</TABLE> </row>
</Para> <row>
<entry>pg_opclass</entry>
<Para> <entry> access method operator classes</entry>
<Figure Id="EXTEND-CATALOGS" Float="1"> </row>
<Title>The major <ProductName>Postgres</ProductName> system catalogs</Title> </tbody>
<Graphic Align="center" FileRef="catalogs.gif" Format="GIF"></Graphic> </tgroup>
</Figure> </table>
</para>
The Reference Manual gives a more detailed explanation
of these catalogs and their attributes. However, <para>
<XRef LinkEnd="EXTEND-CATALOGS" EndTerm="EXTEND-CATALOGS"> <figure float="1" id="EXTEND-CATALOGS">
shows the major entities and their relationships <title>The major <productname>Postgres</productname> system catalogs</title>
in the system catalogs. (Attributes that do not refer <graphic fileref="catalogs.gif" format="GIF" align="center"></graphic>
to other entities are not shown unless they are part of </figure>
a primary key.)
This diagram is more or less incomprehensible until you The Reference Manual gives a more detailed explanation
actually start looking at the contents of the catalogs of these catalogs and their attributes. However,
and see how they relate to each other. For now, the <xref endterm="EXTEND-CATALOGS" linkend="EXTEND-CATALOGS">
main things to take away from this diagram are as follows: shows the major entities and their relationships
in the system catalogs. (Attributes that do not refer
to other entities are not shown unless they are part of
a primary key.)
This diagram is more or less incomprehensible until you
actually start looking at the contents of the catalogs
and see how they relate to each other. For now, the
main things to take away from this diagram are as follows:
<ItemizedList Mark="bullet" Spacing="compact"> <itemizedlist spacing="compact" mark="bullet">
<ListItem> <listitem>
<Para> <para>
In several of the sections that follow, we will In several of the sections that follow, we will
present various join queries on the system present various join queries on the system
catalogs that display information we need to extend catalogs that display information we need to extend
the system. Looking at this diagram should make the system. Looking at this diagram should make
some of these join queries (which are often some of these join queries (which are often
three- or four-way joins) more understandable, three- or four-way joins) more understandable,
because you will be able to see that the because you will be able to see that the
attributes used in the queries form foreign keys attributes used in the queries form foreign keys
in other classes. in other classes.
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> Many different features (classes, attributes, <para>
functions, types, access methods, etc.) are Many different features (classes, attributes,
tightly integrated in this schema. A simple functions, types, access methods, etc.) are
create command may modify many of these catalogs. tightly integrated in this schema. A simple
</Para> create command may modify many of these catalogs.
</ListItem> </para>
<ListItem> </listitem>
<Para> Types and procedures <listitem>
are central to the schema. <para>
Types and procedures
<Note> are central to the schema.
<Para>
We use the words <FirstTerm>procedure</FirstTerm> and <FirstTerm>function</FirstTerm> more or less <note>
interchangably. <para>
</Para> We use the words <firstterm>procedure</firstterm>
</Note> and <firstterm>function</firstterm> more or less interchangably.
</para>
Nearly every catalog contains some reference to </note>
instances in one or both of these classes. For
example, <ProductName>Postgres</ProductName> frequently uses type Nearly every catalog contains some reference to
signatures (e.g., of functions and operators) to instances in one or both of these classes. For
identify unique instances of other catalogs. example, <productname>Postgres</productname> frequently uses type
signatures (e.g., of functions and operators) to
</Para> identify unique instances of other catalogs.
</ListItem> </para>
<ListItem> </listitem>
<Para> There are many attributes and relationships that <listitem>
have obvious meanings, but there are many <para>
(particularly those that have to do with access There are many attributes and relationships that
methods) that do not. The relationships between have obvious meanings, but there are many
pg_am, pg_amop, pg_amproc, pg_operator and (particularly those that have to do with access
pg_opclass are particularly hard to understand methods) that do not. The relationships between
and will be described in depth (in the section pg_am, pg_amop, pg_amproc, pg_operator and
on interfacing types and operators to indices) pg_opclass are particularly hard to understand
after we have discussed basic extensions. and will be described in depth (in the section
</para> on interfacing types and operators to indices)
</ListItem> after we have discussed basic extensions.
</ItemizedList> </para>
</listitem>
</Para> </itemizedlist>
</sect1> </para>
</Chapter> </sect1>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
sgml-local-ecat-files:nil
End:
-->
<chapter id="indices"> <chapter id="indices">
<title>Indices</title> <title id="indices-title">Indices and Keys</title>
<para> <para>
Indexes are primarily used to enhance database
performance. They should be defined on table columns (or class
attributes) which are used as qualifications in repetative queries.
Inappropriate use will result in slower performance, since update
and insertion times are increased in the presence of indices.
</para>
<sect1> <para>
<title>Partial Indices</title> Two forms of indices may be defined:
<para> <itemizedlist>
<note> <listitem>
<title>Author</title> <para>
<para> For a <firstterm>value index</firstterm>,
This is from a reply to a question on the e-mail list the key fields for the
by <ulink url="aoki@CS.Berkeley.EDU">Paul M. Aoki</ulink> index are specified as column names; a column may also have
on 1998-08-11. an associated operator class. An operator class is used
to specify the operators to be used for a particular
index. For example, a btree index on four-byte integers
would use the <literal>int4_ops</literal> class;
this operator class includes
comparison functions for four-byte integers. The default
operator class is the appropriate operator class for that
field type.
</para>
</listitem>
<listitem>
<para>
For a <firstterm>functional index</firstterm>, an index is defined
on the result of a user-defined function applied
to one or more attributes of a single class.
These functional indices
can be used to obtain fast access to data
based on operators that would normally require some
transformation to apply them to the base data.
</para>
</listitem>
</itemizedlist>
</para>
<para>
Postgres provides btree, rtree and hash access methods for
secondary indices. The btree access method is an implementation of
the Lehman-Yao high-concurrency btrees. The rtree access method
implements standard rtrees using Guttman's quadratic split algorithm.
The hash access method is an implementation of Litwin's linear
hashing. We mention the algorithms used solely to indicate that all
of these access methods are fully dynamic and do not have to be
optimized periodically (as is the case with, for example, static hash
access methods).
</para>
<para>
The Postgres query optimizer will consider using btree indices in a scan
whenever an indexed attribute is involved in a comparison using one of:
<simplelist type="inline">
<member>&lt;</member>
<member>&lt;=</member>
<member>=</member>
<member>&gt;=</member>
<member>&gt;</member>
</simplelist>
</para>
<para>
Both box classes support indices on the <literal>box</literal> data
type in <productname>Postgres</productname>.
The difference between them is that <literal>bigbox_ops</literal>
scales box coordinates down, to avoid floating point exceptions from
doing multiplication, addition, and subtraction on very large
floating-point coordinates. If the field on which your rectangles lie
is about 20,000 units square or larger, you should use
<literal>bigbox_ops</literal>.
The <literal>poly_ops</literal> operator class supports rtree
indices on <literal>polygon</literal> data.
</para>
<para>
The <productname>Postgres</productname>
query optimizer will consider using an rtree index whenever
an indexed attribute is involved in a comparison using one of:
<simplelist type="inline">
<member>&lt;&lt;</member>
<member>&amp;&lt;</member>
<member>&amp;&gt;</member>
<member>&gt;&gt;</member>
<member>@</member>
<member>~=</member>
<member>&amp;&amp;</member>
</simplelist>
</para>
<para>
The <productname>Postgres</productname>
query optimizer will consider using a hash index whenever
an indexed attribute is involved in a comparison using
the <literal>=</literal> operator.
</para>
<para>
Currently, only the BTREE access method supports multi-column
indexes. Up to 7 keys may be specified.
</para>
<para>
Use <xref endterm="sql-dropindex-title"
linkend="sql-dropindex-title">
to remove an index.
</para>
<para>
The <literal>int24_ops</literal>
operator class is useful for constructing indices on int2 data, and
doing comparisons against int4 data in query qualifications.
Similarly, <literal>int42_ops</literal>
support indices on int4 data that is to be compared against int2 data
in queries.
</para>
<para>
The following select list returns all ops_names:
<programlisting>
SELECT am.amname AS acc_name,
opc.opcname AS ops_name,
opr.oprname AS ops_comp
FROM pg_am am, pg_amop amop,
pg_opclass opc, pg_operator opr
WHERE amop.amopid = am.oid AND
amop.amopclaid = opc.oid AND
amop.amopopr = opr.oid
ORDER BY acc_name, ops_name, ops_comp
</programlisting>
</para>
<sect1 id="keys">
<title id="keys-title">Keys</title>
<para>
<note>
<title>Author</title>
<para>
Written by
<ulink url="herouth@oumail.openu.ac.il">Herouth Maoz</ulink>
This originally appeared on the User's Mailing List on 1998-03-02
in response to the question:
"What is the difference between PRIMARY KEY and UNIQUE constraints?".
</para>
</note>
</para>
<para>
<programlisting>
Subject: Re: [QUESTIONS] PRIMARY KEY | UNIQUE
What's the difference between:
PRIMARY KEY(fields,...) and
UNIQUE (fields,...)
- Is this an alias?
- If PRIMARY KEY is already unique, then why
is there another kind of key named UNIQUE?
</programlisting>
</para>
<para>
A primary key is the field(s) used to identify a specific row. For example,
Social Security numbers identifying a person.
</para>
<para>
A simply UNIQUE combination of fields has nothing to do with identifying
the row. It's simply an integrity constraint. For example, I have
collections of links. Each collection is identified by a unique number,
which is the primary key. This key is used in relations.
</para>
<para>
However, my application requires that each collection will also have a
unique name. Why? So that a human being who wants to modify a collection
will be able to identify it. It's much harder to know, if you have two
collections named "Life Science", the the one tagged 24433 is the one you
need, and the one tagged 29882 is not.
</para>
<para>
So, the user selects the collection by its name. We therefore make sure,
withing the database, that names are unique. However, no other table in the
database relates to the collections table by the collection Name. That
would be very inefficient.
</para>
<para>
Moreover, despite being unique, the collection name does not actually
define the collection! For example, if somebody decided to change the name
of the collection from "Life Science" to "Biology", it will still be the
same collection, only with a different name. As long as the name is unique,
that's OK.
</para>
<para>
So:
<itemizedlist>
<listitem>
<para>
Primary key:
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<para>
Is used for identifying the row and relating to it.
</para>
</listitem>
<listitem>
<para>
Is impossible (or hard) to update.
</para>
</listitem>
<listitem>
<para>
Should not allow NULLs.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>
Unique field(s):
<itemizedlist spacing="compact" mark="bullet">
<listitem>
<para>
Are used as an alternative access to the row.
</para>
</listitem>
<listitem>
<para>
Are updateable, so long as they are kept unique.
</para>
</listitem>
<listitem>
<para>
NULLs are acceptable.
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
<para>
As for why no non-unique keys are defined explicitly in standard
<acronym>SQL</acronym> syntax? Well, you
must understand that indices are implementation-dependent.
<acronym>SQL</acronym> does not
define the implementation, merely the relations between data in the
database. <productname>Postgres</productname> does allow
non-unique indices, but indices
used to enforce <acronym>SQL</acronym> keys are always unique.
</para>
<para>
Thus, you may query a table by any combination of its columns, despite the
fact that you don't have an index on these columns. The indexes are merely
an implementational aid which each <acronym>RDBMS</acronym> offers
you, in order to cause
commonly used queries to be done more efficiently.
Some <acronym>RDBMS</acronym> may give you
additional measures, such as keeping a key stored in main memory. They will
have a special command, for example
<programlisting>
CREATE MEMSTORE ON &lt;table&gt; COLUMNS &lt;cols&gt;
</programlisting>
(this is not an existing command, just an example).
</para>
<para>
In fact, when you create a primary key or a unique combination of fields,
nowhere in the <acronym>SQL</acronym> specification does it say
that an index is created, nor that
the retrieval of data by the key is going to be more efficient than a
sequential scan!
</para>
<para>
So, if you want to use a combination of fields which is not unique as a
secondary key, you really don't have to specify anything - just start
retrieving by that combination! However, if you want to make the retrieval
efficient, you'll have to resort to the means your
<acronym>RDBMS</acronym> provider gives you
- be it an index, my imaginary MEMSTORE command, or an intelligent
<acronym>RDBMS</acronym>
which creates indices without your knowledge based on the fact that you have
sent it many queries based on a specific combination of keys... (It learns
from experience).
</para>
</sect1>
<sect1 id="partial-index">
<title id="partial-index-title">Partial Indices</title>
<note>
<title>Author</title>
<para>
This is from a reply to a question on the e-mail list
by <ulink url="aoki@CS.Berkeley.EDU">Paul M. Aoki</ulink>
on 1998-08-11.
<!-- <!--
Paul M. Aoki | University of California at Berkeley Paul M. Aoki | University of California at Berkeley
aoki@CS.Berkeley.EDU | Dept. of EECS, Computer Science Division #1776 aoki@CS.Berkeley.EDU | Dept. of EECS, Computer Science Division #1776
| Berkeley, CA 94720-1776 | Berkeley, CA 94720-1776
--> -->
</note> </para>
</note>
A <firstterm>partial index</firstterm>
is an index built over a subset of a table; the subset is defined by <para>
a predicate. <productname>Postgres</productname> A <firstterm>partial index</firstterm>
supported partial indices with arbitrary is an index built over a subset of a table; the subset is defined by
predicates. I believe IBM's db2 for as/400 supports partial indices a predicate. <productname>Postgres</productname>
using single-clause predicates. supported partial indices with arbitrary
predicates. I believe IBM's db2 for as/400 supports partial indices
<para> using single-clause predicates.
The main motivation for partial indices is this: </para>
if all of the queries you ask that can
profitably use an index fall into a certain range, why build an index <para>
over the whole table and suffer the associated space/time costs? The main motivation for partial indices is this:
if all of the queries you ask that can
(There are other reasons too; see profitably use an index fall into a certain range, why build an index
<xref linkend="STON89b-full" endterm="STON89b"> for details.) over the whole table and suffer the associated space/time costs?
<para> (There are other reasons too; see
The machinery to build, update and query partial indices isn't too <xref endterm="STON89b" linkend="STON89b-full"> for details.)
bad. The hairy parts are index selection (which indices do I build?) </para>
and query optimization (which indices do I use?); i.e., the parts
that involve deciding what predicate(s) match the workload/query in <para>
some useful way. For those who are into database theory, the problems The machinery to build, update and query partial indices isn't too
are basically analogous to the corresponding materialized view bad. The hairy parts are index selection (which indices do I build?)
problems, albeit with different cost parameters and formulae. These and query optimization (which indices do I use?); i.e., the parts
are, in the general case, hard problems for the standard ordinal that involve deciding what predicate(s) match the workload/query in
<acronym>SQL</acronym> some useful way. For those who are into database theory, the problems
types; they're super-hard problems with black-box extension types, are basically analogous to the corresponding materialized view
because the selectivity estimation technology is so crude. problems, albeit with different cost parameters and formulae. These
are, in the general case, hard problems for the standard ordinal
<para> <acronym>SQL</acronym>
Check <xref linkend="STON89b-full" endterm="STON89b">, types; they're super-hard problems with black-box extension types,
<xref linkend="OLSON93-full" endterm="OLSON93">, because the selectivity estimation technology is so crude.
and </para>
<xref linkend="SESHADRI95-full" endterm="SESHADRI95">
for more information. <para>
Check <xref endterm="STON89b" linkend="STON89b-full">,
<xref endterm="OLSON93" linkend="OLSON93-full">,
and
<xref endterm="SESHADRI95" linkend="SESHADRI95-full">
for more information.
</para>
</sect1>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/catalog"
sgml-local-ecat-files:nil
End:
-->
<chapter id="lisp">
<title id="lisp-title">Lisp Programming Interface</title>
<abstract>
<para>
<filename>pg.el</filename> is a socket-level interface to
<productname>Postgres</productname> for emacs.
</para>
</abstract>
<note>
<title>Author</title>
<para>
Written by
<ulink url="mailto:emarsden@mail.dotcom.fr">Eric Marsden</ulink>
on 21 Jul 1999.
</para>
</note>
<para>
<filename>pg.el</filename> is a socket-level interface to
<productname>Postgres</productname> for emacs (text
editor extraordinaire). The module is capable of type coercions from a
range of SQL types to the equivalent Emacs Lisp type. It currently
supports neither crypt or Kerberos authentication, nor large objects.
</para>
<para>
The code (version 0.2) is available under GNU GPL from
<ulink url="http://www.chez.com/emarsden/downloads/pg.el">
http://www.chez.com/emarsden/downloads/pg.el</ulink>
</para>
<para>
Changes since last release:
<itemizedlist mark="bullet" spacing="compact">
<listitem>
<para>
now works with XEmacs (tested with Emacs 19.34 & 20.2, and XEmacs
20.4)
</para>
</listitem>
<listitem>
<para>
added functions to provide database metainformation (list of
databases, of tables, of columns)
</para>
</listitem>
<listitem>
<para>
arguments to `pg:result' are now :keywords
</para>
</listitem>
<listitem>
<para>
MULE-resistant
</para>
</listitem>
<listitem>
<para>
more self-testing code
</para>
</listitem>
</itemizedlist>
</para>
<para>
Please note that this is a programmer's API, and doesn't provide any
form of user interface. Example:
<programlisting>
(defun demo ()
(interactive)
(let* ((conn (pg:connect "template1" "postgres" "postgres"))
(res (pg:exec conn "SELECT * from scshdemo WHERE a = 42")))
(message "status is %s" (pg:result res :status))
(message "metadata is %s" (pg:result res :attributes))
(message "data is %s" (pg:result res :tuples))
(pg:disconnect conn)))
</programlisting>
</para>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
sgml-local-ecat-files:nil
End:
-->
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<ProductName>Postgres</ProductName> provides a large number of <ProductName>Postgres</ProductName> provides a large number of
built-in operators on system types. built-in operators on system types.
These operators are declared in the system catalog These operators are declared in the system catalog
pg_operator. Every entry in pg_operator includes <literal>pg_operator</literal>. Every entry in <literal>pg_operator</literal> includes
the name of the procedure that implements the operator and the the name of the procedure that implements the operator and the
class <Acronym>OIDs</Acronym> of the input and output types. class <Acronym>OIDs</Acronym> of the input and output types.
</Para> </Para>
......
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/postgres.sgml,v 1.28 1999/06/23 06:15:12 thomas Exp $
Postgres integrated documentation.
Other subset docs should be copied and shrunk from here.
thomas 1998-02-23
$Log: postgres.sgml,v $
Revision 1.28 1999/06/23 06:15:12 thomas
Add backup/restore info to Admin Guide.
Split management chapter from start-ag.sgml to manage-ag.sgml.
Revision 1.27 1999/06/03 04:21:49 thomas
Markup changes for v6.5 release.
Clean out duplicate stuff in odbc.sgml resulting from a faulty patch.
Revision 1.26 1999/06/01 17:26:18 thomas
Make sure that only one intro is included in the integrated doc.
Multiple intros cause trouble since they have some section elements
(e.g. "y2k.sgml") in common leading to duplicate labels.
Include emacs formatting hints in the intro*.sgml sources.
Revision 1.25 1999/05/27 15:49:08 thomas
Markup fixes.
Update for v6.5 release.
Revision 1.24 1999/05/26 17:30:29 thomas
Add chapters on CVS access, MVCC, SQL theory to the docs.
Add an appendix with more details on date/time attributes and handling.
Update most references to Postgres version numbers to 6.5,
*except* for the porting list which will require a report
from a successful installation to be updated.
Revision 1.23 1999/05/22 02:27:24 thomas
Finish initial markup of cvs.sgml, and include it in the programmer's guide
and the integrated doc. Clean up other markup.
Revision 1.22 1999/05/20 05:39:27 thomas
Rearrange and consolidate the Admin Guide.
Add reference pages for utilities and remove standalone chapters for same.
Add material for an appendix on date/time properties, but not yet
integrated with the User's Guide.
Break up the former chapter on pg_options
into Admin and Programmer's Guides.
Revision 1.21 1999/05/04 02:19:20 thomas
Include chapters on security and an intro to SQL.
Revision 1.20 1999/04/06 15:41:13 thomas
Fix markup to include all closing tags.
Required by newest versions of DocBook and style sheets.
Revision 1.19 1999/03/30 15:23:03 thomas
Include libpq+.sgml in the doc set.
Had been omitted from the integrated doc for no good reason.
Revision 1.18 1999/02/13 03:52:46 thomas
Include chapter on SQL language elements (keywords, etc).
Should merge with or complement Stefan's Master's Thesis intro to SQL.
Revision 1.17 1999/01/19 16:06:25 thomas
Merge current.sgml into release.sgml so all release notes are in the same
file. Per Bruce's preference. Go to it Bruce!
No info yet for v6.4.2 or upcoming releases.
Revision 1.16 1999/01/07 02:59:45 thomas
Include installation instructions for WIN32 client-side libraries.
From Magnus Hagander <mha@sollentuna.net>.
Revision 1.15 1998/12/18 16:23:34 thomas
Fix typos in rules.sgml.
Add Emacs configuration block to postgres.sgml.
Revision 1.14 1998/10/31 09:36:34 thomas
Cleanup for v6.4 release.
Make new file current.sgml to hold release info for the current release.
Should be moved to release.sgml before filling with next release info.
Revision 1.13 1998/10/30 19:37:09 thomas
Minor editing and markup changes as a result of preparing the Postscript
documentation for v6.4.
Bigger updates to the installation instructions (install and config).
Revision 1.12 1998/10/27 06:14:01 thomas
Include configuration chapter with new info on configure and make.
Revision 1.11 1998/10/25 00:24:31 thomas
Add Y2K statement for intros.
Make sure notation section is included in most intros.
Revision 1.7-1.10 1998/10/21 05:31:52 thomas
Include new information from Massimo. Rearrange ODBC docs.
Add information for operator precedence.
Split introduction sections into separate files to allow the legal notice
and notation sections appear in all documents without having the history
show up everplace too.
Add full list of reserved and non-reserved key words in syntax.sgml.
Add a separate chapter to the admin guide on security.
Move SQL reference pages up into the User's Guide.
-->
<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [ <!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
<!entity about SYSTEM "about.sgml"> <!entity about SYSTEM "about.sgml">
...@@ -123,8 +21,8 @@ Move SQL reference pages up into the User's Guide. ...@@ -123,8 +21,8 @@ Move SQL reference pages up into the User's Guide.
<!entity datetime SYSTEM "datetime.sgml"> <!entity datetime SYSTEM "datetime.sgml">
<!entity environ SYSTEM "environ.sgml"> <!entity environ SYSTEM "environ.sgml">
<!entity func SYSTEM "func.sgml"> <!entity func SYSTEM "func.sgml">
<!entity indices SYSTEM "indices.sgml">
<!entity inherit SYSTEM "inherit.sgml"> <!entity inherit SYSTEM "inherit.sgml">
<!entity keys SYSTEM "keys.sgml">
<!entity manage SYSTEM "manage.sgml"> <!entity manage SYSTEM "manage.sgml">
<!entity mvcc SYSTEM "mvcc.sgml"> <!entity mvcc SYSTEM "mvcc.sgml">
<!entity oper SYSTEM "oper.sgml"> <!entity oper SYSTEM "oper.sgml">
...@@ -156,28 +54,29 @@ Move SQL reference pages up into the User's Guide. ...@@ -156,28 +54,29 @@ Move SQL reference pages up into the User's Guide.
<!entity trouble SYSTEM "trouble.sgml"> <!entity trouble SYSTEM "trouble.sgml">
<!-- programmer's guide --> <!-- programmer's guide -->
<!entity intro-pg SYSTEM "intro-pg.sgml">
<!entity arch-pg SYSTEM "arch-pg.sgml"> <!entity arch-pg SYSTEM "arch-pg.sgml">
<!entity extend SYSTEM "extend.sgml">
<!entity rules SYSTEM "rules.sgml">
<!entity xfunc SYSTEM "xfunc.sgml">
<!entity xtypes SYSTEM "xtypes.sgml">
<!entity xoper SYSTEM "xoper.sgml">
<!entity xaggr SYSTEM "xaggr.sgml">
<!entity xindex SYSTEM "xindex.sgml">
<!entity gist SYSTEM "gist.sgml">
<!entity dfunc SYSTEM "dfunc.sgml"> <!entity dfunc SYSTEM "dfunc.sgml">
<!entity lobj SYSTEM "lobj.sgml"> <!entity ecpg SYSTEM "ecpg.sgml">
<!entity trigger SYSTEM "trigger.sgml"> <!entity extend SYSTEM "extend.sgml">
<!entity spi SYSTEM "spi.sgml">
<!entity func-ref SYSTEM "func-ref.sgml"> <!entity func-ref SYSTEM "func-ref.sgml">
<!entity gist SYSTEM "gist.sgml">
<!entity intro-pg SYSTEM "intro-pg.sgml">
<!entity jdbc SYSTEM "jdbc.sgml">
<!entity libpq SYSTEM "libpq.sgml"> <!entity libpq SYSTEM "libpq.sgml">
<!entity libpqpp SYSTEM "libpq++.sgml"> <!entity libpqpp SYSTEM "libpq++.sgml">
<!entity libpgtcl SYSTEM "libpgtcl.sgml"> <!entity libpgtcl SYSTEM "libpgtcl.sgml">
<!entity ecpg SYSTEM "ecpg.sgml"> <!entity lisp SYSTEM "lisp.sgml">
<!entity lobj SYSTEM "lobj.sgml">
<!entity odbc SYSTEM "odbc.sgml"> <!entity odbc SYSTEM "odbc.sgml">
<!entity jdbc SYSTEM "jdbc.sgml"> <!entity rules SYSTEM "rules.sgml">
<!entity spi SYSTEM "spi.sgml">
<!entity trigger SYSTEM "trigger.sgml">
<!entity xaggr SYSTEM "xaggr.sgml">
<!entity xfunc SYSTEM "xfunc.sgml">
<!entity xindex SYSTEM "xindex.sgml">
<!entity xplang SYSTEM "xplang.sgml"> <!entity xplang SYSTEM "xplang.sgml">
<!entity xoper SYSTEM "xoper.sgml">
<!entity xtypes SYSTEM "xtypes.sgml">
<!-- developer's guide --> <!-- developer's guide -->
<!entity arch-dev SYSTEM "arch-dev.sgml"> <!entity arch-dev SYSTEM "arch-dev.sgml">
...@@ -277,7 +176,7 @@ Your name here... ...@@ -277,7 +176,7 @@ Your name here...
&oper; &oper;
&func; &func;
&typeconv; &typeconv;
&keys; &indices;
&array; &array;
&inherit; &inherit;
&mvcc; &mvcc;
...@@ -341,7 +240,6 @@ Your name here... ...@@ -341,7 +240,6 @@ Your name here...
&trigger; &trigger;
&spi; &spi;
&xplang; &xplang;
<!-- &libpq; -->
</Part> </Part>
<part Id="part-interfaces"> <part Id="part-interfaces">
...@@ -359,6 +257,7 @@ Your name here... ...@@ -359,6 +257,7 @@ Your name here...
&libpgtcl; &libpgtcl;
&odbc; &odbc;
&jdbc; &jdbc;
&lisp;
</Part> </Part>
<part Id="part-developer"> <part Id="part-developer">
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/programmer.sgml,v 1.18 1999/06/23 06:21:19 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/programmer.sgml,v 1.19 1999/07/22 15:11:04 thomas Exp $
Postgres Programmer's Guide. Postgres Programmer's Guide.
$Log: programmer.sgml,v $ $Log: programmer.sgml,v $
Revision 1.19 1999/07/22 15:11:04 thomas
Complete merge of all old man page information.
lisp.sgml is a placeholder for Eric Marsden's upcoming contribution.
catalogs.sgml is not yet marked up or integrated.
It should perhaps become an appendix.
Revision 1.18 1999/06/23 06:21:19 thomas Revision 1.18 1999/06/23 06:21:19 thomas
Remove User's Guide entities since they were not being used. Remove User's Guide entities since they were not being used.
...@@ -34,28 +40,29 @@ Make new file current.sgml to hold release info for the current release. ...@@ -34,28 +40,29 @@ Make new file current.sgml to hold release info for the current release.
<!entity notation SYSTEM "notation.sgml"> <!entity notation SYSTEM "notation.sgml">
<!entity y2k SYSTEM "y2k.sgml"> <!entity y2k SYSTEM "y2k.sgml">
<!entity intro-pg SYSTEM "intro-pg.sgml">
<!entity arch-pg SYSTEM "arch-pg.sgml"> <!entity arch-pg SYSTEM "arch-pg.sgml">
<!entity extend SYSTEM "extend.sgml">
<!entity rules SYSTEM "rules.sgml">
<!entity xfunc SYSTEM "xfunc.sgml">
<!entity xtypes SYSTEM "xtypes.sgml">
<!entity xoper SYSTEM "xoper.sgml">
<!entity xaggr SYSTEM "xaggr.sgml">
<!entity xindex SYSTEM "xindex.sgml">
<!entity gist SYSTEM "gist.sgml">
<!entity dfunc SYSTEM "dfunc.sgml"> <!entity dfunc SYSTEM "dfunc.sgml">
<!entity lobj SYSTEM "lobj.sgml"> <!entity ecpg SYSTEM "ecpg.sgml">
<!entity trigger SYSTEM "trigger.sgml"> <!entity extend SYSTEM "extend.sgml">
<!entity spi SYSTEM "spi.sgml">
<!entity func-ref SYSTEM "func-ref.sgml"> <!entity func-ref SYSTEM "func-ref.sgml">
<!entity gist SYSTEM "gist.sgml">
<!entity intro-pg SYSTEM "intro-pg.sgml">
<!entity jdbc SYSTEM "jdbc.sgml">
<!entity libpq SYSTEM "libpq.sgml"> <!entity libpq SYSTEM "libpq.sgml">
<!entity libpqpp SYSTEM "libpq++.sgml"> <!entity libpqpp SYSTEM "libpq++.sgml">
<!entity libpgtcl SYSTEM "libpgtcl.sgml"> <!entity libpgtcl SYSTEM "libpgtcl.sgml">
<!entity ecpg SYSTEM "ecpg.sgml"> <!entity lisp SYSTEM "lisp.sgml">
<!entity lobj SYSTEM "lobj.sgml">
<!entity odbc SYSTEM "odbc.sgml"> <!entity odbc SYSTEM "odbc.sgml">
<!entity jdbc SYSTEM "jdbc.sgml"> <!entity rules SYSTEM "rules.sgml">
<!entity spi SYSTEM "spi.sgml">
<!entity trigger SYSTEM "trigger.sgml">
<!entity xaggr SYSTEM "xaggr.sgml">
<!entity xfunc SYSTEM "xfunc.sgml">
<!entity xindex SYSTEM "xindex.sgml">
<!entity xplang SYSTEM "xplang.sgml"> <!entity xplang SYSTEM "xplang.sgml">
<!entity xoper SYSTEM "xoper.sgml">
<!entity xtypes SYSTEM "xtypes.sgml">
<!-- developer's guide --> <!-- developer's guide -->
<!entity arch-dev SYSTEM "arch-dev.sgml"> <!entity arch-dev SYSTEM "arch-dev.sgml">
...@@ -172,6 +179,7 @@ Disable it until we put in some info. ...@@ -172,6 +179,7 @@ Disable it until we put in some info.
&ecpg; &ecpg;
&odbc; &odbc;
&jdbc; &jdbc;
&lisp;
<!-- development --> <!-- development -->
......
...@@ -102,6 +102,221 @@ ...@@ -102,6 +102,221 @@
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</para> </para>
<Sect2>
<Title>Host-Based Access Control</Title>
<Para>
.SH NAME
$PGDATA/pg_hba.conf
.SH DESCRIPTION
<firstterm>Host-based access control</firstterm>
is the name for the basic controls PostgreSQL
exercises on what clients are allowed to access a database and how
the users on those clients must authenticate themselves.
</para>
<para>
Each database system contains a file named
<filename>pg_hba.conf</filename>, in its <envar>PGDATA</envar>
directory, which controls who can connect to each database.
</para>
<para>
Every client accessing a database
<emphasis>must</emphasis>
be covered by one of
the entries in <filename>pg_hba.conf</filename>.
Otherwise all attempted connections from that
client will be rejected with a "User authentication failed" error
message.
</para>
<para>
The general format of the <filename>pg_hba.conf</filename>
file is of a set of records, one per
line. Blank lines and lines beginning with a hash character
("#") are ignored. A record is
made up of a number of fields which are separated by spaces and/or tabs.
</para>
<para>
Connections from clients can be made using UNIX domain sockets or Internet
domain sockets (ie. TCP/IP). Connections made using UNIX domain sockets
are controlled using records of the following format:
<synopsis>
local <replaceable>database</replaceable> <replaceable>authentication method</replaceable>
</synopsis>
where
<simplelist>
<member>
<replaceable>database</replaceable>
specifies the database that this record applies to. The value
<literal>all</literal>
specifies that it applies to all databases.
</member>
<member>
<replaceable>authentication method</replaceable>
specifies the method a user must use to authenticate themselves when
connecting to that database using UNIX domain sockets. The different methods
are described below.
</member>
</simplelist>
</para>
<para>
Connections made using Internet domain sockets are controlled using records
of the following format.
<synopsis>
host <replaceable>database</replaceable> <replaceable>TCP/IP address</replaceable> <replaceable>TCP/IP mask</replaceable> <replaceable>authentication method</replaceable>
</synopsis>
</para>
<para>
The <replaceable>TCP/IP address</replaceable>
is logically anded to both the specified
<replaceable>TCP/IP mask</replaceable>
and the TCP/IP address
of the connecting client.
If the two resulting values are equal then the
record is used for this connection. If a connection matches more than one
record then the earliest one in the file is used.
Both the
<replaceable>TCP/IP address</replaceable>
and the
<replaceable>TCP/IP mask</replaceable>
are specified in dotted decimal notation.
</para>
<para>
If a connection fails to match any record then the
<firstterm>reject</firstterm>
authentication method is applied (see below).
</para>
<sect3>
<title>Authentication Methods</title>
<para>
The following authentication methods are supported for both UNIX and TCP/IP
domain sockets:
<variablelist>
<varlistentry>
<term>trust</term>
<listitem>
<para>
The connection is allowed unconditionally.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>reject</term>
<listitem>
<para>
The connection is rejected unconditionally.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>crypt</term>
<listitem>
<para>
The client is asked for a password for the user. This is sent encrypted
(using <citetitle>crypt(3)</citetitle>)
and compared against the password held in the
<filename>pg_shadow</filename> table.
If the passwords match, the connection is allowed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>password</term>
<listitem>
<para>
The client is asked for a password for the user. This is sent in clear
and compared against the password held in the
<filename>pg_shadow</filename> table.
If the passwords match, the connection is allowed. An optional password file
may be specified after the
<literal>password</literal>
keyword which is used to match the supplied password rather than the pg_shadow
table. See
<citerefentry><refentrytitle>pg_passwd</refentrytitle></citerefentry>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
The following authentication methods are supported for TCP/IP
domain sockets only:
<variablelist>
<varlistentry>
<term>krb4</term>
<listitem>
<para>
Kerberos V4 is used to authenticate the user.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>krb5</term>
<listitem>
<para>
Kerberos V5 is used to authenticate the user.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>ident</term>
<listitem>
<para>
The ident server on the client is used to authenticate the user (RFC 1413).
An optional map name may be specified after the
<literal>ident</literal>
keyword which allows ident user names to be mapped onto
<productname>Postgres</productname> user names.
Maps are held in the file
<filename>$<envar>PGDATA</envar>/pg_ident.conf</filename>.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect3>
<sect3>
<title>Examples</title>
<para>
<programlisting>
# Trust any connection via UNIX domain sockets.
local trust
# Trust any connection via TCP/IP from this machine.
host all 127.0.0.1 255.255.255.255 trust
# We don't like this machine.
host all 192.168.0.10 255.255.255.0 reject
# This machine can't encrypt so we ask for passwords in clear.
host all 192.168.0.3 255.255.255.0 password
# The rest of this group of machines should provide encrypted passwords.
host all 192.168.0.0 255.255.255.0 crypt
</programlisting>
</para>
</sect3>
</sect2>
</sect1> </sect1>
<sect1> <sect1>
...@@ -138,20 +353,50 @@ ...@@ -138,20 +353,50 @@
have to explicitly insert/update the <literal>pg_group table</literal>. have to explicitly insert/update the <literal>pg_group table</literal>.
For example: For example:
jolly=> insert into pg_group (groname, grosysid, grolist) <programlisting>
jolly=> values ('posthackers', '1234', '{5443, 8261}'); jolly=> insert into pg_group (groname, grosysid, grolist)
INSERT 548224 jolly=> values ('posthackers', '1234', '{5443, 8261}');
jolly=> grant insert on foo to group posthackers; INSERT 548224
CHANGE jolly=> grant insert on foo to group posthackers;
jolly=> CHANGE
jolly=>
The fields in pg_group are: </programlisting>
* groname: the group name. This a name and should be purely </para>
alphanumeric. Do not include underscores or other punctuation.
* grosysid: the group id. This is an int4. This should be unique for <para>
each group. The fields in <filename>pg_group</filename> are:
* grolist: the list of pg_user id's that belong in the group. This
is an int4[]. <variablelist>
<varlistentry>
<term>groname</term>
<listitem>
<para>
The group name. This a name and should be purely
alphanumeric. Do not include underscores or other punctuation.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>grosysid</term>
<listitem>
<para>
The group id. This is an int4. This should be unique for
each group.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>grolist</term>
<listitem>
<para>
The list of pg_user id's that belong in the group. This
is an int4[].
</para>
</listitem>
</varlistentry>
</variablelist>
</para> </para>
</sect2> </sect2>
......
...@@ -3,14 +3,18 @@ ...@@ -3,14 +3,18 @@
<abstract> <abstract>
<para> <para>
<acronym>SQL</acronym> manipulates sets of data. The language is A description of the general syntax of SQL.
composed of various <firstterm>key words</firstterm>. Arithmetic
and procedural expressions are allowed. We will cover these topics
in this chapter; subsequent chapters will include details on data
types, functions, and operators.
</para> </para>
</abstract> </abstract>
<para>
<acronym>SQL</acronym> manipulates sets of data. The language is
composed of various <firstterm>key words</firstterm>. Arithmetic
and procedural expressions are allowed. We will cover these topics
in this chapter; subsequent chapters will include details on data
types, functions, and operators.
</para>
<sect1> <sect1>
<title>Key Words</title> <title>Key Words</title>
...@@ -230,7 +234,7 @@ MAXVALUE MINVALUE MODE ...@@ -230,7 +234,7 @@ MAXVALUE MINVALUE MODE
NOCREATEDB NOCREATEUSER NOTHING NOTNULL NOCREATEDB NOCREATEUSER NOTHING NOTNULL
OIDS OPERATOR OIDS OPERATOR
PASSWORD PROCEDURAL PASSWORD PROCEDURAL
RECIPE RENAME RETURNS ROW RULE RECIPE RENAME RETURNS ROW RULE
SEQUENCE SERIAL SHARE START STATEMENT STDIN STDOUT SEQUENCE SERIAL SHARE START STATEMENT STDIN STDOUT
TRUSTED TRUSTED
VALID VERSION VALID VERSION
...@@ -302,18 +306,455 @@ UNCOMMITTED UNNAMED ...@@ -302,18 +306,455 @@ UNCOMMITTED UNNAMED
</sect2> </sect2>
</sect1> </sect1>
<sect1>
<title>Comments</title>
<para>
A <firstterm>comment</firstterm>
is an arbitrary sequence of characters following double dashes up to the end
of the line. We also support double-slashes as comments, e.g.:
<programlisting>
-- This is a standard SQL comment
// And this is another supported comment style, like C++
</programlisting>
We also support C-style block comments, e.g.:
<programlisting>
/* multi
line
comment */
</programlisting>
</para>
</sect1>
<sect1>
<title>Names</title>
<para>
Names in SQL are sequences of less than NAMEDATALEN alphanumeric characters,
starting with an alphabetic character. By default, NAMEDATALEN is set
to 32, but at the time the system is built, NAMEDATALEN can be changed
by changing the #ifdef in src/backend/include/postgres.h. Underscore
("_") is considered an alphabetic character.
</para>
</sect1>
<sect1>
<title>Constants</title>
<para>
There are six types of
<firstterm>constants</firstterm>
for use in SQL. They are described below.
</para>
<sect2>
<title>String Constants</title>
<para>
<firstterm>Strings</firstterm>
in SQL are arbitrary sequences of ASCII characters bounded by single
quotes ("'", e.g. 'This is a string').
Uppercase alphabetics within strings are accepted
literally. Non-printing characters may be embedded within strings by
prepending them with a backslash
("\"; e.g. "\<replaceable>tab</replaceable>".
SQL92 allows single quotes to be embedded in strings by typing two
adjacent single quotes (e.g. 'Dianne''s horse'), and for
historical reasons <productname>Postgres</productname> also allows
single quotes to be escaped with a backslash
(e.g. 'Dianne\'s horse').
</para>
<para>
Because of the limitations on
instance sizes, string constants are currently limited to a length of
a little less than 8192 bytes. Larger strings may be handled using the
Postgres Large Object interface.
</para>
</sect2>
<sect2>
<title>Integer Constants</title>
<para>
<firstterm>Integer constants</firstterm>
in SQL are collection of ASCII digits with no decimal point. Legal
values range from -2147483648 to +2147483647. This will vary
depending on the operating system and host machine.
</para>
</sect2>
<sect2>
<title>Floating Point Constants</title>
<para>
<firstterm>Floating point constants</firstterm>
consist of an integer part, a decimal point, and a fraction part or
scientific notation of the following format:
<synopsis>
{<replaceable>dig</replaceable>}.{<replaceable>dig</replaceable>} [e [+-] {<replaceable>dig</replaceable>}]
</synopsis>
where <replaceable>dig</replaceable> is one or more digits.
You must include at least one <replaceable>dig</replaceable> after the
period and after the [+-] if you use those options. An exponent with
a missing mantissa has a mantissa of 1 inserted. There may be no
extra characters embedded in the string.
Floating point constaints are of type float8.
</para>
</sect2>
<sect2>
<title>Constants of Postgres User-Defined Types</title>
<para>
A constant of an
<emphasis>arbitrary</emphasis>
type can be entered using the notations:
<synopsis>
<replaceable>type</replaceable> '<replaceable>string</replaceable>'
'<replaceable>string</replaceable>'::<replaceable>type</replaceable>
CAST '<replaceable>string</replaceable>' AS <replaceable>type</replaceable>
</synopsis>
The value inside the string is passed to the input
conversion routine for the type called type-name. The result is a
constant of the indicated type. The explicit typecast may be omitted
if there is no ambiguity as to the type the constant must be, in which
case it is automatically coerced.
</para>
</sect2>
<sect2>
<title>Array constants</title>
<para>
<firstterm>Array constants</firstterm>
are arrays of any Postgres type, including other arrays, string
constants, etc. The general format of an array constant is the
following:
<synopsis>
{<replaceable>val1</replaceable><replaceable>delim</replaceable><replaceable>val2</replaceable><replaceable>delim</replaceable>}
</synopsis>
where <replaceable>delim</replaceable>
is the delimiter for the type stored in the <literal>pg_type</literal> class.
(For built-in types, this is the comma character (","). An
example of an array constant is
<programlisting>
{{1,2,3},{4,5,6},{7,8,9}}
</programlisting>
This constant is a two-dimensional, 3 by 3 array consisting of three
sub-arrays of integers.
</para>
<para>
Individual array elements can and should be placed between quotation
marks whenever possible to avoid ambiguity problems with respect to
leading white space.
</para>
</sect2>
</sect1>
<sect1>
<title>Fields and Columns</title>
<sect2>
<title>Fields</title>
<para>
A <firstterm>field</firstterm>
is either an attribute of a given class or one of the following:
<variablelist>
<varlistentry>
<term>oid</term>
<listitem>
<para>
stands for the unique identifier of an instance which is added by
Postgres to all instances automatically. Oids are not reused and are 32
bit quantities.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>xmin</term>
<listitem>
<para>
The identity of the inserting transaction.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>xmax</term>
<listitem>
<para>
The identity of the deleting transaction.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>cmin</term>
<listitem>
<para>
The command identifier within the transaction.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>cmax</term>
<listitem>
<para>
The identity of the deleting command.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
For further information on these fields consult
<xref linkend="STON87a" endterm="STON87a">.
Times are represented internally as instances of the
<literal>abstime</literal>
data type. Transaction and command identifiers are 32 bit quantities.
Transactions are assigned sequentially starting at 512.
</para>
</sect2>
<sect2>
<title>Columns</title>
<para>
A <firstterm>column</firstterm> is a construct of the form:
<synopsis>
<replaceable>instance</replaceable>{.<replaceable>composite_field</replaceable>}.<replaceable>field</replaceable> `['<replaceable>number</replaceable>`]'
</synopsis>
<replaceable>instance</replaceable>
identifies a particular class and can be thought of as standing for
the instances of that class. An instance variable is either a class
name, a surrogate for a class defined by means of a FROM clause,
or the keyword NEW or CURRENT.
NEW and CURRENT can only appear in the action portion of a rule, while
other instance variables can be used in any SQL statement.
<replaceable>composite_field</replaceable>
is a field of of one of the Postgres composite types,
while successive composite fields address attributes in the
class(s) to which the composite field evaluates. Lastly,
<replaceable>field</replaceable>
is a normal (base type) field in the class(s) last addressed. If
<replaceable>field</replaceable>
is of type <literal>array</literal>,
then the optional <replaceable>number</replaceable>
designator indicates a specific element in the array. If no number is
indicated, then all array elements are returned.
</para>
</sect2>
</sect1>
<sect1>
<title>Operators</title>
<para>
Any built-in system, or user-defined operator may be used in SQL.
For the list of built-in and system operators consult
<xref linkend="operators" endterm="operators">.
For a list of user-defined operators consult your system administrator
or run a query on the <literal>pg_operator</literal> class.
Parentheses may be used for arbitrary grouping of operators in expressions.
</para>
</sect1>
<sect1> <sect1>
<title>Expressions</title> <title>Expressions</title>
<para> <para>
<acronym>SQL92</acronym> allows <firstterm>expressions</firstterm> <acronym>SQL92</acronym> allows <firstterm>expressions</firstterm>
to transform data in expressions. Expressions may contain operators to transform data in tables. Expressions may contain operators
(see <xref linkend="operators-title" endterm="operators-title"> (see <xref linkend="operators-title" endterm="operators-title">
for more details) and functions for more details) and functions
(<xref linkend="functions-title" endterm="functions-title"> has (<xref linkend="functions-title" endterm="functions-title"> has
more information). more information).
</para>
<para>
An expression is one of the following:
<simplelist>
<member>( a_expr )</member>
<member>constant</member>
<member>attribute</member>
<member><replaceable>a_expr</replaceable> <replaceable>binary_operator</replaceable> <replaceable>a_expr</replaceable></member>
<member><replaceable>a_expr</replaceable> <replaceable>right_unary_operator</replaceable></member>
<member><replaceable>left_unary_operator</replaceable> <replaceable>a_expr</replaceable></member>
<member>parameter</member>
<member>functional expressions</member>
<member>aggregate expressions</member>
</simplelist>
</para>
<para>
We have already discussed constants and attributes. The two kinds of
operator expressions indicate respectively binary and left_unary
expressions. The following sections discuss the remaining options.
</para> </para>
<sect2>
<title>Parameters</title>
<para>
A <firstterm>parameter</firstterm>
is used to indicate a parameter in a SQL function. Typically this
is used in SQL function definition statement. The form of a
parameter is:
<synopsis>
$<replaceable class="parameter">number</replaceable>
</synopsis>
</para>
<para>
For example, consider the definition of a function,
<function>dept</function>, as
<programlisting>
CREATE FUNCTION dept (name)
RETURNS dept
AS 'select * from
dept where name=$1'
LANGUAGE 'sql';
</programlisting>
</para>
</sect2>
<sect2>
<title>Functional Expressions</title>
<para>
A <firstterm>functional expression</firstterm>
is the name of a legal SQL function, followed by its argument list
enclosed in parentheses:
<synopsis>
<replaceable>function</replaceable> (<replaceable>a_expr</replaceable> [, <replaceable>a_expr</replaceable> )
</synopsis>
</para>
<para>
For example, the following computes the square root of an employee
salary:
<programlisting>
sqrt(emp.salary)
</programlisting>
</para>
</sect2>
<sect2>
<title>Aggregate Expression</title>
<para>
An <firstterm>aggregate expression</firstterm>
represents a simple aggregate (i.e., one that computes a single value)
or an aggregate function (i.e., one that computes a set of values).
The syntax is the following:
<synopsis>
<replaceable>aggregate_name</replaceable> (<replaceable>attribute</replaceable>)
</synopsis>
where <replaceable>aggregate_name</replaceable>
must be a previously defined aggregate.
</para>
</sect2>
<sect2>
<title>Target List</title>
<para>
A <firstterm>target list</firstterm>
is a parenthesized, comma-separated list of one or more elements, each
of which must be of the form:
<synopsis>
<replaceable>a_expr</replaceable> [ AS <replaceable>result_attname</replaceable> ]
</synopsis>
where <replaceable>result_attname</replaceable>
is the name of the attribute to be created (or an
already existing attribute name in the case of update statements.) If
<replaceable>result_attname</replaceable>
is not present, then
<replaceable>a_expr</replaceable>
must contain only one attribute name which is assumed to be the name
of the result field. In <productname>Postgres</productname>
default naming is only used if
<replaceable>a_expr</replaceable>
is an attribute.
</para>
</sect2>
<sect2>
<title>Qualification</title>
<para>
A <firstterm>qualification</firstterm>
consists of any number of clauses connected by the logical operators:
<simplelist>
<member>NOT</member>
<member>AND</member>
<member>OR</member>
</simplelist>
A clause is an <replaceable>a_expr</replaceable>
that evaluates to a <literal>boolean</literal> over a set of instances.
</para>
</sect2>
<sect2>
<title>From List</title>
<para>
The <firstterm>from list</firstterm>
is a comma-separated list of <firstterm>from expressions</firstterm>.
Each "from expression" is of the form:
<synopsis>
[ <replaceable>class_reference</replaceable> ] <replaceable>instance_variable</replaceable>
{, [ <replaceable>class_ref</replaceable> ] <replaceable>instance_variable</replaceable>... }
</synopsis>
where <replaceable>class_reference</replaceable>
is of the form
<synopsis>
<replaceable>class_name</replaceable> [ * ]
</synopsis>
The "from expression"
defines one or more instance variables to range over the class
indicated in <replaceable>class_reference</replaceable>.
One can also request
the instance variable to range over all classes that are beneath the
indicated class in the inheritance hierarchy by postpending the
designator asterisk ("*").
</para>
</sect2>
</sect1> </sect1>
</chapter> </chapter>
......
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/user.sgml,v 1.12 1999/06/03 04:21:51 thomas Exp $
Postgres User's Manual.
Derived from postgres.sgml.
thomas 1998-02-24
$Log: user.sgml,v $
Revision 1.12 1999/06/03 04:21:51 thomas
Markup changes for v6.5 release.
Clean out duplicate stuff in odbc.sgml resulting from a faulty patch.
Revision 1.11 1999/05/26 17:30:30 thomas
Add chapters on CVS access, MVCC, SQL theory to the docs.
Add an appendix with more details on date/time attributes and handling.
Update most references to Postgres version numbers to 6.5,
*except* for the porting list which will require a report
from a successful installation to be updated.
Revision 1.10 1999/05/22 02:27:25 thomas
Finish initial markup of cvs.sgml, and include it in the programmer's guide
and the integrated doc. Clean up other markup.
Revision 1.9 1999/05/20 05:39:29 thomas
Rearrange and consolidate the Admin Guide.
Add reference pages for utilities and remove standalone chapters for same.
Add material for an appendix on date/time properties, but not yet
integrated with the User's Guide.
Break up the former chapter on pg_options
into Admin and Programmer's Guides.
Revision 1.8 1999/05/04 02:26:06 thomas
Include new introductory chapter on SQL from Stefan S.
Should this be in the tutorial instead?
Revision 1.7 1998/10/30 19:37:16 thomas
Minor editing and markup changes as a result of preparing the Postscript
documentation for v6.4.
Bigger updates to the installation instructions (install and config).
Revision 1.6 1998/09/30 05:41:54 thomas
Clean up pages. Add information for operator precedence.
Split introduction sections into separate files to allow the legal notice
and notation sections appear in all documents without having the history
show up everplace too.
Add full list of reserved and non-reserved key words in syntax.sgml.
Add a separate chapter to the admin guide on security.
Revision 1.5 1998/08/17 16:20:32 thomas
Move SQL reference pages up into the User's Guide.
-->
<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [ <!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [
<!entity about SYSTEM "about.sgml"> <!entity about SYSTEM "about.sgml">
...@@ -67,9 +14,9 @@ Move SQL reference pages up into the User's Guide. ...@@ -67,9 +14,9 @@ Move SQL reference pages up into the User's Guide.
<!entity datetime SYSTEM "datetime.sgml"> <!entity datetime SYSTEM "datetime.sgml">
<!entity environ SYSTEM "environ.sgml"> <!entity environ SYSTEM "environ.sgml">
<!entity func SYSTEM "func.sgml"> <!entity func SYSTEM "func.sgml">
<!entity indices SYSTEM "indices.sgml">
<!entity inherit SYSTEM "inherit.sgml"> <!entity inherit SYSTEM "inherit.sgml">
<!entity intro SYSTEM "intro.sgml"> <!entity intro SYSTEM "intro.sgml">
<!entity keys SYSTEM "keys.sgml">
<!entity manage SYSTEM "manage.sgml"> <!entity manage SYSTEM "manage.sgml">
<!entity mvcc SYSTEM "mvcc.sgml"> <!entity mvcc SYSTEM "mvcc.sgml">
<!entity oper SYSTEM "oper.sgml"> <!entity oper SYSTEM "oper.sgml">
...@@ -157,7 +104,7 @@ Your name here... ...@@ -157,7 +104,7 @@ Your name here...
&oper; &oper;
&func; &func;
&typeconv; &typeconv;
&keys; &indices;
&array; &array;
&inherit; &inherit;
&mvcc; &mvcc;
......
<Chapter Id="xfunc"> <chapter id="xfunc">
<Title>Extending <Acronym>SQL</Acronym>: Functions</Title> <title id="xfunc-title">Extending <acronym>SQL</acronym>: Functions</title>
<Para> <para>
As it turns out, part of defining a new type is the As it turns out, part of defining a new type is the
definition of functions that describe its behavior. definition of functions that describe its behavior.
Consequently, while it is possible to define a new Consequently, while it is possible to define a new
function without defining a new type, the reverse is function without defining a new type, the reverse is
not true. We therefore describe how to add new functions not true. We therefore describe how to add new functions
to <ProductName>Postgres</ProductName> before describing to <productname>Postgres</productname> before describing
how to add new types. how to add new types.
<ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> </para>
provides two types of functions: query language functions
(functions written in <Acronym>SQL</Acronym> and programming <para>
language functions (functions written in a compiled <productname>Postgres</productname> <acronym>SQL</acronym>
programming language such as <Acronym>C</Acronym>.) Either kind provides three types of functions:
of function can take a base type, a composite type or
some combination as arguments (parameters). In addition, <itemizedlist>
both kinds of functions can return a base type or <listitem>
a composite type. It's easier to define <Acronym>SQL</Acronym> <para>
functions, so we'll start with those. Examples in this section query language functions
can also be found in <FileName>funcs.sql</FileName> (functions written in <acronym>SQL</acronym>)
and <FileName>funcs.c</FileName>. </para>
</Para> </listitem>
<listitem>
<Sect1> <para>
<Title>Query Language (<Acronym>SQL</Acronym>) Functions</Title> procedural language
functions (functions written in, for example, PLTCL or PLSQL)
<Sect2> </para>
<Title><Acronym>SQL</Acronym> Functions on Base Types</Title> </listitem>
<listitem>
<Para> <para>
The simplest possible <Acronym>SQL</Acronym> function has no arguments and programming
simply returns a base type, such as <Acronym>int4</Acronym>: language functions (functions written in a compiled
programming language such as <acronym>C</acronym>)
</para>
</listitem>
</itemizedlist>
Every kind
of function can take a base type, a composite type or
some combination as arguments (parameters). In addition,
every kind of function can return a base type or
a composite type. It's easiest to define <acronym>SQL</acronym>
functions, so we'll start with those. Examples in this section
can also be found in <filename>funcs.sql</filename>
and <filename>funcs.c</filename>.
</para>
<sect1>
<title>Query Language (<acronym>SQL</acronym>) Functions</title>
<para>
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
<literal>setof</literal>,
then an arbitrary element of the last query's result will be returned.
</para>
<para>
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.
</para>
<para>
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 <firstterm>dot</firstterm>
notation (e.g. "$1.emp") may be
used to access attributes of the argument or
to invoke functions.
</para>
<sect2>
<title>Examples</title>
<para>
To illustrate a simple SQL function, consider the following,
which might be used to debit a bank account:
<programlisting>
create function TP1 (int4, float8) returns int4
as 'update BANK set balance = BANK.balance - $2
where BANK.acctountno = $1
select(x = 1)'
language 'sql';
</programlisting>
A user could execute this function to debit account 17 by $100.00 as
follows:
<programlisting>
select (x = TP1( 17,100.0));
</programlisting>
</para>
<para>
The following more interesting example takes a single argument of type
EMP, and retrieves multiple results:
<programlisting>
select function hobbies (EMP) returns set of HOBBIES
as 'select (HOBBIES.all) from HOBBIES
where $1.name = HOBBIES.person'
language 'sql';
</programlisting>
</para>
</sect2>
<sect2>
<title><acronym>SQL</acronym> Functions on Base Types</title>
<para>
The simplest possible <acronym>SQL</acronym> function has no arguments and
simply returns a base type, such as <acronym>int4</acronym>:
<ProgramListing> <programlisting>
CREATE FUNCTION one() RETURNS int4 CREATE FUNCTION one() RETURNS int4
AS 'SELECT 1 as RESULT' LANGUAGE 'sql'; AS 'SELECT 1 as RESULT' LANGUAGE 'sql';
...@@ -44,23 +129,22 @@ ...@@ -44,23 +129,22 @@
+-------+ +-------+
|1 | |1 |
+-------+ +-------+
</ProgramListing> </programlisting>
</para>
</Para> <para>
<Para>
Notice that we defined a target list for the function Notice that we defined a target list for the function
(with the name RESULT), but the target list of the (with the name RESULT), but the target list of the
query that invoked the function overrode the function's query that invoked the function overrode the function's
target list. Hence, the result is labelled answer target list. Hence, the result is labelled answer
instead of one. instead of one.
</Para> </para>
<Para> <para>
It's almost as easy to define <Acronym>SQL</Acronym> functions It's almost as easy to define <acronym>SQL</acronym> functions
that take base types as arguments. In the example below, notice that take base types as arguments. In the example below, notice
how we refer to the arguments within the function as $1 how we refer to the arguments within the function as $1
and $2. and $2:
<ProgramListing> <programlisting>
CREATE FUNCTION add_em(int4, int4) RETURNS int4 CREATE FUNCTION add_em(int4, int4) RETURNS int4
AS 'SELECT $1 + $2;' LANGUAGE 'sql'; AS 'SELECT $1 + $2;' LANGUAGE 'sql';
...@@ -71,22 +155,22 @@ ...@@ -71,22 +155,22 @@
+-------+ +-------+
|3 | |3 |
+-------+ +-------+
</ProgramListing> </programlisting>
</Para> </para>
</sect2> </sect2>
<Sect2> <sect2>
<Title><Acronym>SQL</Acronym> Functions on Composite Types</Title> <title><acronym>SQL</acronym> Functions on Composite Types</title>
<Para> <para>
When specifying functions with arguments of composite When specifying functions with arguments of composite
types (such as EMP), we must not only specify which types (such as EMP), we must not only specify which
argument we want (as we did above with $1 and $2) but argument we want (as we did above with $1 and $2) but
also the attributes of that argument. For example, also the attributes of that argument. For example,
take the function double_salary that computes what your take the function double_salary that computes what your
salary would be if it were doubled. salary would be if it were doubled:
<ProgramListing> <programlisting>
CREATE FUNCTION double_salary(EMP) RETURNS int4 CREATE FUNCTION double_salary(EMP) RETURNS int4
AS 'SELECT $1.salary * 2 AS salary;' LANGUAGE 'sql'; AS 'SELECT $1.salary * 2 AS salary;' LANGUAGE 'sql';
...@@ -100,17 +184,17 @@ ...@@ -100,17 +184,17 @@
+-----+-------+ +-----+-------+
|Sam | 2400 | |Sam | 2400 |
+-----+-------+ +-----+-------+
</ProgramListing> </programlisting>
</para> </para>
<Para> <para>
Notice the use of the syntax $1.salary. Notice the use of the syntax $1.salary.
Before launching into the subject of functions that Before launching into the subject of functions that
return composite types, we must first introduce the return composite types, we must first introduce the
function notation for projecting attributes. The simple way function notation for projecting attributes. The simple way
to explain this is that we can usually use the to explain this is that we can usually use the
notation attribute(class) and class.attribute interchangably. notation attribute(class) and class.attribute interchangably:
<ProgramListing> <programlisting>
-- --
-- this is the same as: -- this is the same as:
-- SELECT EMP.name AS youngster FROM EMP WHERE EMP.age &lt; 30 -- SELECT EMP.name AS youngster FROM EMP WHERE EMP.age &lt; 30
...@@ -124,59 +208,60 @@ ...@@ -124,59 +208,60 @@
+----------+ +----------+
|Sam | |Sam |
+----------+ +----------+
</ProgramListing> </programlisting>
</para> </para>
<Para> <para>
As we shall see, however, this is not always the case. As we shall see, however, this is not always the case.
This function notation is important when we want to use This function notation is important when we want to use
a function that returns a single instance. We do this a function that returns a single instance. We do this
by assembling the entire instance within the function, by assembling the entire instance within the function,
attribute by attribute. This is an example of a function attribute by attribute. This is an example of a function
that returns a single EMP instance: that returns a single EMP instance:
<ProgramListing> <programlisting>
CREATE FUNCTION new_emp() RETURNS EMP CREATE FUNCTION new_emp() RETURNS EMP
AS 'SELECT \'None\'::text AS name, AS 'SELECT \'None\'::text AS name,
1000 AS salary, 1000 AS salary,
25 AS age, 25 AS age,
\'(2,2)\'::point AS cubicle' \'(2,2)\'::point AS cubicle'
LANGUAGE 'sql'; LANGUAGE 'sql';
</ProgramListing> </programlisting>
</para>
</Para> <para>
<Para>
In this case we have specified each of the attributes In this case we have specified each of the attributes
with a constant value, but any computation or expression with a constant value, but any computation or expression
could have been substituted for these constants. could have been substituted for these constants.
Defining a function like this can be tricky. Some of Defining a function like this can be tricky. Some of
the more important caveats are as follows: the more important caveats are as follows:
<itemizedlist>
<ItemizedList> <listitem>
<ListItem> <para>
<Para> The target list order must be exactly the same as
The target list order must be exactly the same as that in which the attributes appear in the CREATE
that in which the attributes appear in the CREATE TABLE statement (or when you execute a .* query).
TABLE statement (or when you execute a .* query). </para>
</Para> </listitem>
</ListItem> <listitem>
<ListItem> <para>
<Para> You must typecast the expressions (using ::) very carefully
You must typecast the expressions (using ::) very carefully or you will see the following error:
or you will see the following error:
<programlisting>
<ProgramListing> <computeroutput>
WARN::function declared to return type EMP does not retrieve (EMP.*) WARN::function declared to return type EMP does not retrieve (EMP.*)
</ProgramListing> </computeroutput>
</Para> </programlisting>
</ListItem> </para>
<ListItem> </listitem>
<Para> <listitem>
When calling a function that returns an instance, we <para>
When calling a function that returns an instance, we
cannot retrieve the entire instance. We must either cannot retrieve the entire instance. We must either
project an attribute out of the instance or pass the project an attribute out of the instance or pass the
entire instance into another function. entire instance into another function.
<ProgramListing>
<programlisting>
SELECT name(new_emp()) AS nobody; SELECT name(new_emp()) AS nobody;
+-------+ +-------+
...@@ -184,35 +269,35 @@ When calling a function that returns an instance, we ...@@ -184,35 +269,35 @@ When calling a function that returns an instance, we
+-------+ +-------+
|None | |None |
+-------+ +-------+
</ProgramListing> </programlisting>
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
The reason why, in general, we must use the function The reason why, in general, we must use the function
syntax for projecting attributes of function return syntax for projecting attributes of function return
values is that the parser just doesn't understand values is that the parser just doesn't understand
the other (dot) syntax for projection when combined the other (dot) syntax for projection when combined
with function calls. with function calls.
<ProgramListing> <programlisting>
SELECT new_emp().name AS nobody; SELECT new_emp().name AS nobody;
WARN:parser: syntax error at or near "." WARN:parser: syntax error at or near "."
</ProgramListing> </programlisting>
</Para> </para>
</ListItem> </listitem>
</ItemizedList> </itemizedlist>
</para> </para>
<Para> <para>
Any collection of commands in the <Acronym>SQL</Acronym> query Any collection of commands in the <acronym>SQL</acronym> query
language can be packaged together and defined as a function. language can be packaged together and defined as a function.
The commands can include updates (i.e., <Acronym>insert</Acronym>, The commands can include updates (i.e., <acronym>insert</acronym>,
<Acronym>update</Acronym> and <Acronym>delete</Acronym>) as well <acronym>update</acronym> and <acronym>delete</acronym>) as well
as <Acronym>select</Acronym> queries. However, the final command as <acronym>select</acronym> queries. However, the final command
must be a <Acronym>select</Acronym> that returns whatever is must be a <acronym>select</acronym> that returns whatever is
specified as the function's returntype. specified as the function's returntype.
<ProgramListing> <programlisting>
CREATE FUNCTION clean_EMP () RETURNS int4 CREATE FUNCTION clean_EMP () RETURNS int4
AS 'DELETE FROM EMP WHERE EMP.salary &lt;= 0; AS 'DELETE FROM EMP WHERE EMP.salary &lt;= 0;
SELECT 1 AS ignore_this' SELECT 1 AS ignore_this'
...@@ -226,74 +311,312 @@ The reason why, in general, we must use the function ...@@ -226,74 +311,312 @@ The reason why, in general, we must use the function
|1 | |1 |
+--+ +--+
</ProgramListing> </programlisting>
</Para> </para>
</sect2> </sect2>
</sect1> </sect1>
<sect1>
<title>Procedural Language Functions</title>
<para>
Procedural languages aren't built into Postgres. They are offered
by loadable modules. Please refer to the documentation for the
PL in question for details about the syntax and how the AS
clause is interpreted by the PL handler.
</para>
<Sect1> <para>
<Title>Programming Language Functions</Title> There are two procedural languages available with the standard
<productname>Postgres</productname> distribution (PLTCL and PLSQL), and other
languages can be defined.
Refer to <xref linkend="xplang-title" endterm="xplang-title"> for
more information.
</para>
</sect1>
<Sect2> <sect1>
<Title>Programming Language Functions on Base Types</Title> <title>Internal Functions</title>
<Para> <para>
Internally, <ProductName>Postgres</ProductName> regards a Internal functions are functions written in C which have been statically
linked into the <productname>Postgres</productname> backend
process. The AS
clause gives the C-language name of the function, which need not be the
same as the name being declared for SQL use.
(For reasons of backwards compatibility, an empty AS
string is accepted as meaning that the C-language function name is the
same as the SQL name.) Normally, all internal functions present in the
backend are declared as SQL functions during database initialization,
but a user could use <command>CREATE FUNCTION</command>
to create additional alias names for an internal function.
</para>
</sect1>
<sect1>
<title>Compiled (C) Language Functions</title>
<para>
Functions written in C can be defined to Postgres, which will dynamically
load them into its address space. The AS
clause gives the full path name of the object file that contains the
function. This file is loaded either using
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.
</para>
<para>
The string which specifies the object file (the string in the AS clause)
should be the <emphasis>full path</emphasis>
of the object code file for the function, bracketed by quotation
marks. (<productname>Postgres</productname> will not compile a
function automatically; it must
be compiled before it is used in a CREATE FUNCTION
command. See below for additional information.)
</para>
<sect2>
<title>C Language Functions on Base Types</title>
<para>
The following table gives the C type required for parameters in the C
functions that will be loaded into Postgres. The "Defined In"
column gives the actual header file (in the
<filename>.../src/backend/</filename>
directory) that the equivalent C type is defined. However, if you
include <filename>utils/builtins.h</filename>,
these files will automatically be
included.
<table tocentry="1">
<title>Equivalent C Types
for Built-In <productname>Postgres</productname> Types</title>
<titleabbrev>Equivalent C Types</titleabbrev>
<tgroup cols="3">
<thead>
<row>
<entry>
Built-In Type
</entry>
<entry>
C Type
</entry>
<entry>
Defined In
</entry>
</row>
</thead>
<tbody>
<row>
<entry>abstime</entry>
<entry>AbsoluteTime</entry>
<entry>utils/nabstime.h</entry>
</row>
<row>
<entry>bool</entry>
<entry>bool</entry>
<entry>include/c.h</entry>
</row>
<row>
<entry>box</entry>
<entry>(BOX *)</entry>
<entry>utils/geo-decls.h</entry>
</row>
<row>
<entry>bytea</entry>
<entry>(bytea *)</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>char</entry>
<entry>char</entry>
<entry>N/A</entry>
</row>
<row>
<entry>cid</entry>
<entry>CID</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>datetime</entry>
<entry>(DateTime *)</entry>
<entry>include/c.h or include/postgres.h</entry>
</row>
<row>
<entry>int2</entry>
<entry>int2</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>int28</entry>
<entry>(int28 *)</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>int4</entry>
<entry>int4</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>float4</entry>
<entry>float32 or (float4 *)</entry>
<entry>include/c.h or include/postgres.h</entry>
</row>
<row>
<entry>float8</entry>
<entry>float64 or (float8 *)</entry>
<entry>include/c.h or include/postgres.h</entry>
</row>
<row>
<entry>lseg</entry>
<entry>(LSEG *)</entry>
<entry>include/geo-decls.h</entry>
</row>
<row>
<entry>name</entry>
<entry>(Name)</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>oid</entry>
<entry>oid</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>oid8</entry>
<entry>(oid8 *)</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>path</entry>
<entry>(PATH *)</entry>
<entry>utils/geo-decls.h</entry>
</row>
<row>
<entry>point</entry>
<entry>(POINT *)</entry>
<entry>utils/geo-decls.h</entry>
</row>
<row>
<entry>regproc</entry>
<entry>regproc or REGPROC</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>reltime</entry>
<entry>RelativeTime</entry>
<entry>utils/nabstime.h</entry>
</row>
<row>
<entry>text</entry>
<entry>(text *)</entry>
<entry>include/postgres.h</entry>
</row>
<row>
<entry>tid</entry>
<entry>ItemPointer</entry>
<entry>storage/itemptr.h</entry>
</row>
<row>
<entry>timespan</entry>
<entry>(TimeSpan *)</entry>
<entry>include/c.h or include/postgres.h</entry>
</row>
<row>
<entry>tinterval</entry>
<entry>TimeInterval</entry>
<entry>utils/nabstime.h</entry>
</row>
<row>
<entry>uint2</entry>
<entry>uint16</entry>
<entry>include/c.h</entry>
</row>
<row>
<entry>uint4</entry>
<entry>uint32</entry>
<entry>include/c.h</entry>
</row>
<row>
<entry>xid</entry>
<entry>(XID *)</entry>
<entry>include/postgres.h</entry>
</row>
</tbody>
</tgroup>
</table>
</para>
<para>
Internally, <productname>Postgres</productname> regards a
base type as a "blob of memory." The user-defined base type as a "blob of memory." The user-defined
functions that you define over a type in turn define the functions that you define over a type in turn define the
way that <ProductName>Postgres</ProductName> can operate way that <productname>Postgres</productname> can operate
on it. That is, <ProductName>Postgres</ProductName> will on it. That is, <productname>Postgres</productname> will
only store and retrieve the data from disk and use your only store and retrieve the data from disk and use your
user-defined functions to input, process, and output the data. user-defined functions to input, process, and output the data.
Base types can have one of three internal formats: Base types can have one of three internal formats:
<ItemizedList>
<ListItem><Para>pass by value, fixed-length</Para> <itemizedlist>
</ListItem> <listitem>
<ListItem><Para>pass by reference, fixed-length</Para> <para>
</ListItem> pass by value, fixed-length
<ListItem><Para>pass by reference, variable-length</Para> </para>
</ListItem> </listitem>
</ItemizedList> <listitem>
</Para> <para>
pass by reference, fixed-length
<Para> </para>
</listitem>
<listitem>
<para>
pass by reference, variable-length
</para>
</listitem>
</itemizedlist>
</para>
<para>
By-value types can only be 1, 2 or 4 bytes in length By-value types can only be 1, 2 or 4 bytes in length
(even if your computer supports by-value types of other (even if your computer supports by-value types of other
sizes). <ProductName>Postgres</ProductName> itself sizes). <productname>Postgres</productname> itself
only passes integer types by value. You should be careful only passes integer types by value. You should be careful
to define your types such that they will be the same to define your types such that they will be the same
size (in bytes) on all architectures. For example, the size (in bytes) on all architectures. For example, the
<Acronym>long</Acronym> type is dangerous because it <acronym>long</acronym> type is dangerous because it
is 4 bytes on some machines and 8 bytes on others, whereas is 4 bytes on some machines and 8 bytes on others, whereas
<Acronym>int</Acronym> type is 4 bytes on most <acronym>int</acronym> type is 4 bytes on most
<Acronym>UNIX</Acronym> machines (though not on most <acronym>UNIX</acronym> machines (though not on most
personal computers). A reasonable implementation of personal computers). A reasonable implementation of
the <Acronym>int4</Acronym> type on <Acronym>UNIX</Acronym> the <acronym>int4</acronym> type on <acronym>UNIX</acronym>
machines might be: machines might be:
<ProgramListing> <programlisting>
/* 4-byte integer, passed by value */ /* 4-byte integer, passed by value */
typedef int int4; typedef int int4;
</ProgramListing> </programlisting>
</Para> </para>
<Para> <para>
On the other hand, fixed-length types of any size may On the other hand, fixed-length types of any size may
be passed by-reference. For example, here is a sample be passed by-reference. For example, here is a sample
implementation of a <ProductName>Postgres</ProductName> type: implementation of a <productname>Postgres</productname> type:
<ProgramListing> <programlisting>
/* 16-byte structure, passed by reference */ /* 16-byte structure, passed by reference */
typedef struct typedef struct
{ {
double x, y; double x, y;
} Point; } Point;
</ProgramListing> </programlisting>
</Para> </para>
<Para> <para>
Only pointers to such types can be used when passing Only pointers to such types can be used when passing
them in and out of <ProductName>Postgres</ProductName> functions. them in and out of <productname>Postgres</productname> functions.
Finally, all variable-length types must also be passed Finally, all variable-length types must also be passed
by reference. All variable-length types must begin by reference. All variable-length types must begin
with a length field of exactly 4 bytes, and all data to with a length field of exactly 4 bytes, and all data to
...@@ -302,42 +625,42 @@ The reason why, in general, we must use the function ...@@ -302,42 +625,42 @@ The reason why, in general, we must use the function
length field is the total length of the structure length field is the total length of the structure
(i.e., it includes the size of the length field (i.e., it includes the size of the length field
itself). We can define the text type as follows: itself). We can define the text type as follows:
</Para>
<programlisting>
<Para> typedef struct {
<ProgramListing> int4 length;
typedef struct { char data[1];
int4 length; } text;
char data[1]; </programlisting>
} text; </para>
</ProgramListing>
</Para> <para>
<Para>
Obviously, the data field is not long enough to hold Obviously, the data field is not long enough to hold
all possible strings -- it's impossible to declare such all possible strings; it's impossible to declare such
a structure in <Acronym>C</Acronym>. When manipulating a structure in <acronym>C</acronym>. When manipulating
variable-length types, we must be careful to allocate variable-length types, we must be careful to allocate
the correct amount of memory and initialize the length field. the correct amount of memory and initialize the length field.
For example, if we wanted to store 40 bytes in a text For example, if we wanted to store 40 bytes in a text
structure, we might use a code fragment like this: structure, we might use a code fragment like this:
<ProgramListing>
#include "postgres.h"
...
char buffer[40]; /* our source data */
...
text *destination = (text *) palloc(VARHDRSZ + 40);
destination-&gt;length = VARHDRSZ + 40;
memmove(destination-&gt;data, buffer, 40);
...
</ProgramListing>
</Para>
<Para> <programlisting>
#include "postgres.h"
...
char buffer[40]; /* our source data */
...
text *destination = (text *) palloc(VARHDRSZ + 40);
destination-&gt;length = VARHDRSZ + 40;
memmove(destination-&gt;data, buffer, 40);
...
</programlisting>
</para>
<para>
Now that we've gone over all of the possible structures Now that we've gone over all of the possible structures
for base types, we can show some examples of real functions. for base types, we can show some examples of real functions.
Suppose <FileName>funcs.c</FileName> look like: Suppose <filename>funcs.c</filename> look like:
<ProgramListing>
<programlisting>
#include &lt;string.h&gt; #include &lt;string.h&gt;
#include "postgres.h" #include "postgres.h"
...@@ -394,56 +717,58 @@ The reason why, in general, we must use the function ...@@ -394,56 +717,58 @@ The reason why, in general, we must use the function
strncat(VARDATA(new_text), VARDATA(arg2), VARSIZE(arg2)-VARHDRSZ); strncat(VARDATA(new_text), VARDATA(arg2), VARSIZE(arg2)-VARHDRSZ);
return (new_text); return (new_text);
} }
</ProgramListing> </programlisting>
</Para> </para>
<Para> <para>
On <Acronym>OSF/1</Acronym> we would type: On <acronym>OSF/1</acronym> we would type:
<ProgramListing> <programlisting>
CREATE FUNCTION add_one(int4) RETURNS int4 CREATE FUNCTION add_one(int4) RETURNS int4
AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c'; AS '<replaceable>PGROOT</replaceable>/tutorial/funcs.so' LANGUAGE 'c';
CREATE FUNCTION makepoint(point, point) RETURNS point CREATE FUNCTION makepoint(point, point) RETURNS point
AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c'; AS '<replaceable>PGROOT</replaceable>/tutorial/funcs.so' LANGUAGE 'c';
CREATE FUNCTION concat_text(text, text) RETURNS text CREATE FUNCTION concat_text(text, text) RETURNS text
AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c'; AS '<replaceable>PGROOT</replaceable>/tutorial/funcs.so' LANGUAGE 'c';
CREATE FUNCTION copytext(text) RETURNS text CREATE FUNCTION copytext(text) RETURNS text
AS 'PGROOT/tutorial/funcs.so' LANGUAGE 'c'; AS '<replaceable>PGROOT</replaceable>/tutorial/funcs.so' LANGUAGE 'c';
</ProgramListing> </programlisting>
</Para> </para>
<Para> <para>
On other systems, we might have to make the filename On other systems, we might have to make the filename
end in .sl (to indicate that it's a shared library). end in .sl (to indicate that it's a shared library).
</Para> </para>
</Sect2> </sect2>
<Sect2> <sect2>
<Title>Programming Language Functions on Composite Types</Title> <title>C Language Functions on Composite Types</title>
<Para> <para>
Composite types do not have a fixed layout like C Composite types do not have a fixed layout like C
structures. Instances of a composite type may contain structures. Instances of a composite type may contain
null fields. In addition, composite types that are null fields. In addition, composite types that are
part of an inheritance hierarchy may have different part of an inheritance hierarchy may have different
fields than other members of the same inheritance hierarchy. fields than other members of the same inheritance hierarchy.
Therefore, <ProductName>Postgres</ProductName> provides Therefore, <productname>Postgres</productname> provides
a procedural interface for accessing fields of composite types a procedural interface for accessing fields of composite types
from C. As <ProductName>Postgres</ProductName> processes from C. As <productname>Postgres</productname> processes
a set of instances, each instance will be passed into your a set of instances, each instance will be passed into your
function as an opaque structure of type <Acronym>TUPLE</Acronym>. function as an opaque structure of type <acronym>TUPLE</acronym>.
Suppose we want to write a function to answer the query Suppose we want to write a function to answer the query
<ProgramListing>
<programlisting>
* SELECT name, c_overpaid(EMP, 1500) AS overpaid * SELECT name, c_overpaid(EMP, 1500) AS overpaid
FROM EMP FROM EMP
WHERE name = 'Bill' or name = 'Sam'; WHERE name = 'Bill' or name = 'Sam';
</ProgramListing> </programlisting>
In the query above, we can define c_overpaid as: In the query above, we can define c_overpaid as:
<ProgramListing> <programlisting>
#include "postgres.h" #include "postgres.h"
#include "executor/executor.h" /* for GetAttributeByName() */ #include "executor/executor.h" /* for GetAttributeByName() */
...@@ -458,136 +783,248 @@ The reason why, in general, we must use the function ...@@ -458,136 +783,248 @@ The reason why, in general, we must use the function
return (false); return (false);
return(salary &gt; limit); return(salary &gt; limit);
} }
</ProgramListing> </programlisting>
</Para> </para>
<Para> <para>
<Acronym>GetAttributeByName</Acronym> is the <acronym>GetAttributeByName</acronym> is the
<ProductName>Postgres</ProductName> system function that <productname>Postgres</productname> system function that
returns attributes out of the current instance. It has returns attributes out of the current instance. It has
three arguments: the argument of type TUPLE passed into three arguments: the argument of type TUPLE passed into
the function, the name of the desired attribute, and a the function, the name of the desired attribute, and a
return parameter that describes whether the attribute return parameter that describes whether the attribute
is null. <Acronym>GetAttributeByName</Acronym> will is null. <acronym>GetAttributeByName</acronym> will
align data properly so you can cast its return value to align data properly so you can cast its return value to
the desired type. For example, if you have an attribute the desired type. For example, if you have an attribute
name which is of the type name, the <Acronym>GetAttributeByName</Acronym> name which is of the type name, the <acronym>GetAttributeByName</acronym>
call would look like: call would look like:
<ProgramListing>
<programlisting>
char *str; char *str;
... ...
str = (char *) GetAttributeByName(t, "name", &amp;isnull) str = (char *) GetAttributeByName(t, "name", &amp;isnull)
</ProgramListing> </programlisting>
</Para> </para>
<Para> <para>
The following query lets <ProductName>Postgres</ProductName> The following query lets <productname>Postgres</productname>
know about the c_overpaid function: know about the c_overpaid function:
<ProgramListing>
<programlisting>
* CREATE FUNCTION c_overpaid(EMP, int4) RETURNS bool * CREATE FUNCTION c_overpaid(EMP, int4) RETURNS bool
AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c'; AS '<replaceable>PGROOT</replaceable>/tutorial/obj/funcs.so' LANGUAGE 'c';
</ProgramListing> </programlisting>
</Para> </para>
<Para> <para>
While there are ways to construct new instances or modify While there are ways to construct new instances or modify
existing instances from within a C function, these existing instances from within a C function, these
are far too complex to discuss in this manual. are far too complex to discuss in this manual.
</Para> </para>
</Sect2> </sect2>
<Sect2> <sect2>
<Title>Caveats</Title> <title>Writing Code</title>
<Para> <para>
We now turn to the more difficult task of writing We now turn to the more difficult task of writing
programming language functions. Be warned: this section programming language functions. Be warned: this section
of the manual will not make you a programmer. You must of the manual will not make you a programmer. You must
have a good understanding of <Acronym>C</Acronym> have a good understanding of <acronym>C</acronym>
(including the use of pointers and the malloc memory manager) (including the use of pointers and the malloc memory manager)
before trying to write <Acronym>C</Acronym> functions for before trying to write <acronym>C</acronym> functions for
use with <ProductName>Postgres</ProductName>. While it may use with <productname>Postgres</productname>. While it may
be possible to load functions written in languages other be possible to load functions written in languages other
than <Acronym>C</Acronym> into <ProductName>Postgres</ProductName>, than <acronym>C</acronym> into <productname>Postgres</productname>,
this is often difficult (when it is possible at all) this is often difficult (when it is possible at all)
because other languages, such as <Acronym>FORTRAN</Acronym> because other languages, such as <acronym>FORTRAN</acronym>
and <Acronym>Pascal</Acronym> often do not follow the same and <acronym>Pascal</acronym> often do not follow the same
"calling convention" as <Acronym>C</Acronym>. That is, other <firstterm>calling convention</firstterm>
as <acronym>C</acronym>. That is, other
languages do not pass argument and return values languages do not pass argument and return values
between functions in the same way. For this reason, we between functions in the same way. For this reason, we
will assume that your programming language functions will assume that your programming language functions
are written in <Acronym>C</Acronym>. are written in <acronym>C</acronym>.
The basic rules for building <Acronym>C</Acronym> functions </para>
<para>
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
<filename><replaceable>PGROOT</replaceable>/src/backend/utils/builtins.h</filename>
is included as a header file. This can be achieved by having
<programlisting>
#include &lt;utils/builtins.h&gt;
</programlisting>
at the top of the C source file.
</para>
<para>
The basic rules for building <acronym>C</acronym> functions
are as follows: are as follows:
<ItemizedList> <itemizedlist>
<ListItem> <listitem>
<Para> <para>
Most of the header (include) files for Most of the header (include) files for
<ProductName>Postgres</ProductName> <productname>Postgres</productname>
should already be installed in should already be installed in
<FileName>PGROOT/include</FileName> (see Figure 2). <filename><replaceable>PGROOT</replaceable>/include</filename> (see Figure 2).
You should always include You should always include
<ProgramListing> <programlisting>
-I$PGROOT/include -I$PGROOT/include
</ProgramListing> </programlisting>
on your cc command lines. Sometimes, you may
find that you require header files that are in on your cc command lines. Sometimes, you may
the server source itself (i.e., you need a file find that you require header files that are in
we neglected to install in include). In those the server source itself (i.e., you need a file
cases you may need to add one or more of we neglected to install in include). In those
<ProgramListing> cases you may need to add one or more of
-I$PGROOT/src/backend
-I$PGROOT/src/backend/include <programlisting>
-I$PGROOT/src/backend/port/&lt;PORTNAME&gt; -I$PGROOT/src/backend
-I$PGROOT/src/backend/obj -I$PGROOT/src/backend/include
</ProgramListing> -I$PGROOT/src/backend/port/&lt;PORTNAME&gt;
(where &lt;PORTNAME&gt; is the name of the port, e.g., -I$PGROOT/src/backend/obj
alpha or sparc). </programlisting>
</para>
</ListItem> (where &lt;PORTNAME&gt; is the name of the port, e.g.,
<ListItem> alpha or sparc).
<Para> When allocating memory, use the </para>
<ProductName>Postgres</ProductName> </listitem>
routines palloc and pfree instead of the <listitem>
corresponding <Acronym>C</Acronym> library routines <para>
malloc and free. When allocating memory, use the
The memory allocated by palloc will be freed <productname>Postgres</productname>
automatically at the end of each transaction, routines palloc and pfree instead of the
preventing memory leaks. corresponding <acronym>C</acronym> library routines
</Para> malloc and free.
</ListItem> The memory allocated by palloc will be freed
<ListItem> automatically at the end of each transaction,
<Para> Always zero the bytes of your structures using preventing memory leaks.
memset or bzero. Several routines (such as the </para>
hash access method, hash join and the sort algorithm) </listitem>
compute functions of the raw bits contained in <listitem>
your structure. Even if you initialize all fields <para>
of your structure, there may be Always zero the bytes of your structures using
several bytes of alignment padding (holes in the memset or bzero. Several routines (such as the
structure) that may contain garbage values. hash access method, hash join and the sort algorithm)
</Para> compute functions of the raw bits contained in
</ListItem> your structure. Even if you initialize all fields
<ListItem> of your structure, there may be
<Para> Most of the internal <ProductName>Postgres</ProductName> several bytes of alignment padding (holes in the
types are declared in postgres.h, so it's a good structure) that may contain garbage values.
idea to always include that file as well. Including </para>
postgres.h will also include elog.h and palloc.h for you. </listitem>
</Para> <listitem>
</ListItem> <para>
<ListItem> Most of the internal <productname>Postgres</productname>
<Para> Compiling and loading your object code so that types are declared in <filename>postgres.h</filename>,
it can be dynamically loaded into so it's a good
<ProductName>Postgres</ProductName> idea to always include that file as well. Including
always requires special flags. See Appendix A postgres.h will also include elog.h and palloc.h for you.
for a detailed explanation of how to do it for </para>
your particular operating system. </listitem>
</Para> <listitem>
</ListItem> <para>
</ItemizedList> Compiling and loading your object code so that
</Para> it can be dynamically loaded into
</Sect2> <productname>Postgres</productname>
</sect1> always requires special flags.
</chapter> See <xref linkend="dfunc-title" endterm="dfunc-title">
for a detailed explanation of how to do it for
your particular operating system.
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
</sect1>
<sect1>
<title>Function Overloading</title>
<para>
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 <firstterm>overloaded</firstterm>.
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.
</para>
<sect2>
<title>Name Space Conflicts</title>
<para>
As of <productname>Postgres</productname> v6.5,
<command>CREATE FUNCTION</command> can decouple a C language
function name from the name of the entry point. This is now the
preferred technique to accomplish function overloading.
</para>
<sect3>
<title>Pre-v6.5</title>
<para>
For functions written in C, the SQL name declared in
<command>CREATE FUNCTION</command>
must be exactly the same as the actual name of the function in the
C code (hence it must be a legal C function name).
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
Another solution is not to use dynamic loading, but to link your
functions into the backend statically and declare them as INTERNAL
functions. Then, the functions must all have distinct C names but
they can be declared with the same SQL names (as long as their
argument types differ, of course). This way avoids the overhead of
an SQL wrapper function, at the cost of more effort to prepare a
custom backend executable.
</para>
</sect3>
</sect2>
</sect1>
</chapter>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
sgml-local-ecat-files:nil
End:
-->
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.5 1999/07/22 15:11:05 thomas Exp $
Postgres documentation
-->
<chapter id="xindex"> <chapter id="xindex">
<title>Interfacing Extensions To Indices</title> <title>Interfacing Extensions To Indices</title>
......
<Chapter Id="xplang"> <chapter id="xplang">
<Title>Procedural Languages</Title> <title id="xplang-title">Procedural Languages</title>
<!-- ********** <!-- **********
* General information about procedural language support * General information about procedural language support
********** **********
--> -->
<Para> <para>
Beginning with the release of version 6.3, Beginning with the release of version 6.3,
<ProductName>Postgres</ProductName> supports <productname>Postgres</productname> supports
the definition of procedural languages. the definition of procedural languages.
In the case of a function or trigger In the case of a function or trigger
procedure defined in a procedural language, the database has procedure defined in a procedural language, the database has
...@@ -18,60 +18,60 @@ ...@@ -18,60 +18,60 @@
handler itself is a special programming language function handler itself is a special programming language function
compiled into a shared object compiled into a shared object
and loaded on demand. and loaded on demand.
</Para> </para>
<!-- ********** <!-- **********
* Installation of procedural languages * Installation of procedural languages
********** **********
--> -->
<Sect1> <sect1>
<Title>Installing Procedural Languages</Title> <title>Installing Procedural Languages</title>
<Procedure> <procedure>
<Title> <title>
Procedural Language Installation Procedural Language Installation
</Title> </title>
<para> <para>
A procedural language is installed in the database in three steps. A procedural language is installed in the database in three steps.
</para> </para>
<Step Performance="Required"> <step performance="Required">
<Para> <para>
The shared object for the language handler The shared object for the language handler
must be compiled and installed. By default the must be compiled and installed. By default the
handler for PL/pgSQL is built and installed into the handler for PL/pgSQL is built and installed into the
database library directory. If Tcl/Tk support is database library directory. If Tcl/Tk support is
configured in, the handler for PL/Tcl is also built configured in, the handler for PL/Tcl is also built
and installed in the same location. and installed in the same location.
</Para> </para>
<Para> <para>
Writing a handler for a new procedural language (PL) Writing a handler for a new procedural language (PL)
is outside the scope of this manual. is outside the scope of this manual.
</Para> </para>
</Step> </step>
<Step Performance="Required"> <step performance="Required">
<Para> <para>
The handler must be declared with the command The handler must be declared with the command
<ProgramListing> <programlisting>
CREATE FUNCTION <Replaceable>handler_function_name</Replaceable> () RETURNS OPAQUE AS CREATE FUNCTION <replaceable>handler_function_name</replaceable> () RETURNS OPAQUE AS
'<Filename>path-to-shared-object</Filename>' LANGUAGE 'C'; '<filename>path-to-shared-object</filename>' LANGUAGE 'C';
</ProgramListing> </programlisting>
The special return type of <Acronym>OPAQUE</Acronym> tells The special return type of <acronym>OPAQUE</acronym> tells
the database, that this function does not return one of the database, that this function does not return one of
the defined base- or composite types and is not directly usable the defined base- or composite types and is not directly usable
in <Acronym>SQL</Acronym> statements. in <acronym>SQL</acronym> statements.
</Para> </para>
</Step> </step>
<Step Performance="Required"> <step performance="Required">
<Para> <para>
The PL must be declared with the command The PL must be declared with the command
<ProgramListing> <programlisting>
CREATE [ TRUSTED ] PROCEDURAL LANGUAGE '<Replaceable>language-name</Replaceable>' CREATE [ TRUSTED ] PROCEDURAL LANGUAGE '<replaceable>language-name</replaceable>'
HANDLER <Replaceable>handler_function_name</Replaceable> HANDLER <replaceable>handler_function_name</replaceable>
LANCOMPILER '<Replaceable>description</Replaceable>'; LANCOMPILER '<replaceable>description</replaceable>';
</ProgramListing> </programlisting>
The optional keyword <Acronym>TRUSTED</Acronym> tells The optional keyword <acronym>TRUSTED</acronym> tells
if ordinary database users that have no superuser if ordinary database users that have no superuser
privileges can use this language to create functions privileges can use this language to create functions
and trigger procedures. Since PL functions are and trigger procedures. Since PL functions are
...@@ -79,129 +79,129 @@ ...@@ -79,129 +79,129 @@
languages that don't gain access to database backends languages that don't gain access to database backends
internals or the filesystem. The languages PL/pgSQL and internals or the filesystem. The languages PL/pgSQL and
PL/Tcl are known to be trusted. PL/Tcl are known to be trusted.
</Para> </para>
</Step> </step>
</Procedure> </procedure>
<Procedure> <procedure>
<Title>Example</Title> <title>Example</title>
<Step Performance="Required"> <step performance="Required">
<Para> <para>
The following command tells the database where to find the The following command tells the database where to find the
shared object for the PL/pgSQL languages call handler function. shared object for the PL/pgSQL languages call handler function.
</Para> </para>
<ProgramListing> <programlisting>
CREATE FUNCTION plpgsql_call_handler () RETURNS OPAQUE AS CREATE FUNCTION plpgsql_call_handler () RETURNS OPAQUE AS
'/usr/local/pgsql/lib/plpgsql.so' LANGUAGE 'C'; '/usr/local/pgsql/lib/plpgsql.so' LANGUAGE 'C';
</ProgramListing> </programlisting>
</Step> </step>
<Step Performance="Required"> <step performance="Required">
<Para> <para>
The command The command
</Para> </para>
<ProgramListing> <programlisting>
CREATE TRUSTED PROCEDURAL LANGUAGE 'plpgsql' CREATE TRUSTED PROCEDURAL LANGUAGE 'plpgsql'
HANDLER plpgsql_call_handler HANDLER plpgsql_call_handler
LANCOMPILER 'PL/pgSQL'; LANCOMPILER 'PL/pgSQL';
</ProgramListing> </programlisting>
<Para> <para>
then defines that the previously declared call handler then defines that the previously declared call handler
function should be invoked for functions and trigger procedures function should be invoked for functions and trigger procedures
where the language attribute is 'plpgsql'. where the language attribute is 'plpgsql'.
</Para> </para>
<Para> <para>
PL handler functions have a special call interface that is PL handler functions have a special call interface that is
different from regular C language functions. One of the arguments different from regular C language functions. One of the arguments
given to the handler is the object ID in the <FileName>pg_proc</FileName> given to the handler is the object ID in the <filename>pg_proc</filename>
tables entry for the function that should be executed. tables entry for the function that should be executed.
The handler examines various system catalogs to analyze the The handler examines various system catalogs to analyze the
functions call arguments and it's return data type. The source functions call arguments and it's return data type. The source
text of the functions body is found in the prosrc attribute of text of the functions body is found in the prosrc attribute of
<FileName>pg_proc</FileName>. <filename>pg_proc</filename>.
Due to this, in contrast to C language functions, PL functions Due to this, in contrast to C language functions, PL functions
can be overloaded like SQL language functions. There can be can be overloaded like SQL language functions. There can be
multiple different PL functions having the same function name, multiple different PL functions having the same function name,
as long as the call arguments differ. as long as the call arguments differ.
</Para> </para>
<Para> <para>
Procedural languages defined in the <FileName>template1</FileName> Procedural languages defined in the <filename>template1</filename>
database are automatically defined in all subsequently created database are automatically defined in all subsequently created
databases. So the database administrator can decide which databases. So the database administrator can decide which
languages are available by default. languages are available by default.
</Para> </para>
</Step> </step>
</Procedure> </procedure>
</Sect1> <!-- **** End of PL installation **** --> </sect1> <!-- **** End of PL installation **** -->
<!-- ********** <!-- **********
* The procedural language PL/pgSQL * The procedural language PL/pgSQL
********** **********
--> -->
<Sect1> <sect1>
<Title>PL/pgSQL</Title> <title>PL/pgSQL</title>
<Para> <para>
PL/pgSQL is a loadable procedural language for the PL/pgSQL is a loadable procedural language for the
<ProductName>Postgres</ProductName> database system. <productname>Postgres</productname> database system.
</Para> </para>
<Para> <para>
This package was originally written by Jan Wieck. This package was originally written by Jan Wieck.
</Para> </para>
<!-- **** PL/pgSQL overview **** --> <!-- **** PL/pgSQL overview **** -->
<Sect2> <sect2>
<Title>Overview</Title> <title>Overview</title>
<Para> <para>
The design goals of PL/pgSQL were to create a loadable procedural The design goals of PL/pgSQL were to create a loadable procedural
language that language that
<ItemizedList> <itemizedlist>
<ListItem> <listitem>
<Para> <para>
can be used to create functions and trigger procedures, can be used to create functions and trigger procedures,
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
adds control structures to the <Acronym>SQL</Acronym> language, adds control structures to the <acronym>SQL</acronym> language,
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
can perform complex computations, can perform complex computations,
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
inherits all user defined types, functions and operators, inherits all user defined types, functions and operators,
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
can be defined to be trusted by the server, can be defined to be trusted by the server,
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
is easy to use. is easy to use.
</Para> </para>
</ListItem> </listitem>
</ItemizedList> </itemizedlist>
</Para> </para>
<Para> <para>
The PL/pgSQL call handler parses the functions source text and The PL/pgSQL call handler parses the functions source text and
produces an internal binary instruction tree on the first time, the produces an internal binary instruction tree on the first time, the
function is called by a backend. The produced bytecode is identified function is called by a backend. The produced bytecode is identified
in the call handler by the object ID of the function. This ensures, in the call handler by the object ID of the function. This ensures,
that changing a function by a DROP/CREATE sequence will take effect that changing a function by a DROP/CREATE sequence will take effect
without establishing a new database connection. without establishing a new database connection.
</Para> </para>
<Para> <para>
For all expressions and <Acronym>SQL</Acronym> statements used in For all expressions and <acronym>SQL</acronym> statements used in
the function, the PL/pgSQL bytecode interpreter creates a the function, the PL/pgSQL bytecode interpreter creates a
prepared execution plan using the SPI managers SPI_prepare() and prepared execution plan using the SPI managers SPI_prepare() and
SPI_saveplan() functions. This is done the first time, the individual SPI_saveplan() functions. This is done the first time, the individual
...@@ -210,41 +210,41 @@ ...@@ -210,41 +210,41 @@
plans would be required, will only prepare and save those plans plans would be required, will only prepare and save those plans
that are really used during the entire lifetime of the database that are really used during the entire lifetime of the database
connection. connection.
</Para> </para>
<Para> <para>
Except for input-/output-conversion and calculation functions Except for input-/output-conversion and calculation functions
for user defined types, anything that can be defined in C language for user defined types, anything that can be defined in C language
functions can also be done with PL/pgSQL. It is possible to functions can also be done with PL/pgSQL. It is possible to
create complex conditional computation functions and later use create complex conditional computation functions and later use
them to define operators or use them in functional indices. them to define operators or use them in functional indices.
</Para> </para>
</Sect2> </sect2>
<!-- **** PL/pgSQL Description **** --> <!-- **** PL/pgSQL Description **** -->
<Sect2> <sect2>
<Title>Description</Title> <title>Description</title>
<!-- **** PL/pgSQL structure **** --> <!-- **** PL/pgSQL structure **** -->
<Sect3> <sect3>
<Title>Structure of PL/pgSQL</Title> <title>Structure of PL/pgSQL</title>
<Para> <para>
The PL/pgSQL language is case insensitive. All keywords and The PL/pgSQL language is case insensitive. All keywords and
identifiers can be used in mixed upper- and lowercase. identifiers can be used in mixed upper- and lowercase.
</Para> </para>
<Para> <para>
PL/pgSQL is a block oriented language. A block is defined as PL/pgSQL is a block oriented language. A block is defined as
<ProgramListing> <programlisting>
[&lt;&lt;label&gt;&gt;] [&lt;&lt;label&gt;&gt;]
[DECLARE [DECLARE
<replaceable>declarations</replaceable>] <replaceable>declarations</replaceable>]
BEGIN BEGIN
<replaceable>statements</replaceable> <replaceable>statements</replaceable>
END; END;
</ProgramListing> </programlisting>
There can be any number of subblocks in the statement section There can be any number of subblocks in the statement section
of a block. Subblocks can be used to hide variables from outside a of a block. Subblocks can be used to hide variables from outside a
...@@ -252,76 +252,78 @@ ...@@ -252,76 +252,78 @@
declared in the declarations section preceding a block are declared in the declarations section preceding a block are
initialized to their default values every time the block is entered, initialized to their default values every time the block is entered,
not only once per function call. not only once per function call.
</Para> </para>
<Para> <para>
It is important not to misunderstand the meaning of BEGIN/END for It is important not to misunderstand the meaning of BEGIN/END for
grouping statements in PL/pgSQL and the database commands for grouping statements in PL/pgSQL and the database commands for
transaction control. Functions and trigger procedures cannot transaction control. Functions and trigger procedures cannot
start or commit transactions and <ProductName>Postgres</ProductName> start or commit transactions and <productname>Postgres</productname>
does not have nested transactions. does not have nested transactions.
</Para> </para>
</Sect3> </sect3>
<!-- **** PL/pgSQL comments **** --> <!-- **** PL/pgSQL comments **** -->
<Sect3> <sect3>
<Title>Comments</Title> <title>Comments</title>
<Para> <para>
There are two types of comments in PL/pgSQL. A double dash '--' There are two types of comments in PL/pgSQL. A double dash '--'
starts a comment that extends to the end of the line. A '/*' starts a comment that extends to the end of the line. A '/*'
starts a block comment that extends to the next occurence of '*/'. starts a block comment that extends to the next occurence of '*/'.
Block comments cannot be nested, but double dash comments can be Block comments cannot be nested, but double dash comments can be
enclosed into a block comment and a double dash can hide enclosed into a block comment and a double dash can hide
the block comment delimiters '/*' and '*/'. the block comment delimiters '/*' and '*/'.
</Para> </para>
</Sect3> </sect3>
<!-- **** PL/pgSQL declarations **** --> <!-- **** PL/pgSQL declarations **** -->
<Sect3> <sect3>
<Title>Declarations</Title> <title>Declarations</title>
<Para> <para>
All variables, rows and records used in a block or it's All variables, rows and records used in a block or it's
subblocks must be declared in the declarations section of a block subblocks must be declared in the declarations section of a block
except for the loop variable of a FOR loop iterating over a range except for the loop variable of a FOR loop iterating over a range
of integer values. Parameters given to a PL/pgSQL function are of integer values. Parameters given to a PL/pgSQL function are
automatically declared with the usual identifiers $n. automatically declared with the usual identifiers $n.
The declarations have the following syntax: The declarations have the following syntax:
</Para> </para>
<VariableList> <variablelist>
<VarListEntry> <varlistentry>
<Term> <term>
<Replaceable>name</Replaceable> [ CONSTANT ] <Replaceable>type</Replaceable> [ NOT NULL ] [ DEFAULT | := <Replaceable>value</Replaceable> ]; <replaceable>name</replaceable> [ CONSTANT ]
</Term> <replaceable>>typ</replaceable>> [ NOT NULL ] [ DEFAULT | :=
<ListItem> <replaceable>value</replaceable> ];
<Para> </term>
<listitem>
<para>
Declares a variable of the specified base type. If the variable Declares a variable of the specified base type. If the variable
is declared as CONSTANT, the value cannot be changed. If NOT NULL is declared as CONSTANT, the value cannot be changed. If NOT NULL
is specified, an assignment of a NULL value results in a runtime is specified, an assignment of a NULL value results in a runtime
error. Since the default value of all variables is the error. Since the default value of all variables is the
<Acronym>SQL</Acronym> NULL value, all variables declared as NOT NULL <acronym>SQL</acronym> NULL value, all variables declared as NOT NULL
must also have a default value specified. must also have a default value specified.
</Para> </para>
<Para> <para>
The default value is evaluated ever time the function is called. So The default value is evaluated ever time the function is called. So
assigning '<Replaceable>now</Replaceable>' to a variable of type assigning '<replaceable>now</replaceable>' to a variable of type
<Replaceable>datetime</Replaceable> causes the variable to have the <replaceable>datetime</replaceable> causes the variable to have the
time of the actual function call, not when the function was time of the actual function call, not when the function was
precompiled into it's bytecode. precompiled into it's bytecode.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
<Replaceable>name</Replaceable> <Replaceable>class</Replaceable>%ROWTYPE; <replaceable>name</replaceable> <replaceable>class</replaceable>%ROWTYPE;
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Declares a row with the structure of the given class. Class must be Declares a row with the structure of the given class. Class must be
an existing table- or viewname of the database. The fields of the row an existing table- or viewname of the database. The fields of the row
are accessed in the dot notation. Parameters to a function can are accessed in the dot notation. Parameters to a function can
...@@ -331,110 +333,110 @@ ...@@ -331,110 +333,110 @@
attributes of a table row are accessible in the row, no Oid or other attributes of a table row are accessible in the row, no Oid or other
system attributes (hence the row could be from a view and view rows system attributes (hence the row could be from a view and view rows
don't have useful system attributes). don't have useful system attributes).
</Para> </para>
<Para> <para>
The fields of the rowtype inherit the tables fieldsizes The fields of the rowtype inherit the tables fieldsizes
or precision for char() etc. data types. or precision for char() etc. data types.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
<Replaceable>name</Replaceable> RECORD; <replaceable>name</replaceable> RECORD;
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Records are similar to rowtypes, but they have no predefined structure. Records are similar to rowtypes, but they have no predefined structure.
They are used in selections and FOR loops to hold one actual They are used in selections and FOR loops to hold one actual
database row from a SELECT operation. One and the same record can be database row from a SELECT operation. One and the same record can be
used in different selections. Accessing a record or an attempt to assign used in different selections. Accessing a record or an attempt to assign
a value to a record field when there is no actual row in it results a value to a record field when there is no actual row in it results
in a runtime error. in a runtime error.
</Para> </para>
<Para> <para>
The NEW and OLD rows in a trigger are given to the procedure as The NEW and OLD rows in a trigger are given to the procedure as
records. This is necessary because in <ProductName>Postgres</ProductName> records. This is necessary because in <productname>Postgres</productname>
one and the same trigger procedure can handle trigger events for one and the same trigger procedure can handle trigger events for
different tables. different tables.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
<Replaceable>name</Replaceable> ALIAS FOR $n; <replaceable>name</replaceable> ALIAS FOR $n;
</Term> </term>
<ListItem> <listitem>
<Para> <para>
For better readability of the code it is possible to define an alias For better readability of the code it is possible to define an alias
for a positional parameter to a function. for a positional parameter to a function.
</Para> </para>
<Para> <para>
This aliasing is required for composite types given as arguments to This aliasing is required for composite types given as arguments to
a function. The dot notation $1.salary as in SQL functions is not a function. The dot notation $1.salary as in SQL functions is not
allowed in PL/pgSQL. allowed in PL/pgSQL.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
RENAME <Replaceable>oldname</Replaceable> TO <Replaceable>newname</Replaceable>; RENAME <replaceable>oldname</replaceable> TO <replaceable>newname</replaceable>;
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Change the name of a variable, record or row. This is useful Change the name of a variable, record or row. This is useful
if NEW or OLD should be referenced by another name inside a if NEW or OLD should be referenced by another name inside a
trigger procedure. trigger procedure.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
</VariableList> </variablelist>
</Sect3> </sect3>
<!-- **** PL/pgSQL data types **** --> <!-- **** PL/pgSQL data types **** -->
<Sect3> <sect3>
<Title>Data Types</Title> <title>Data Types</title>
<Para> <para>
The type of a varible can be any of the existing basetypes of The type of a varible can be any of the existing basetypes of
the database. <Replaceable>type</Replaceable> in the declarations the database. <replaceable>type</replaceable> in the declarations
section above is defined as: section above is defined as:
</Para> </para>
<Para> <para>
<ItemizedList> <itemizedlist>
<ListItem> <listitem>
<Para> <para>
<ProductName>Postgres</ProductName>-basetype <productname>Postgres</productname>-basetype
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
<Replaceable>variable</Replaceable>%TYPE <replaceable>variable</replaceable>%TYPE
</Para> </para>
</ListItem> </listitem>
<ListItem> <listitem>
<Para> <para>
<Replaceable>class.field</Replaceable>%TYPE <replaceable>class.field</replaceable>%TYPE
</Para> </para>
</ListItem> </listitem>
</ItemizedList> </itemizedlist>
</Para> </para>
<Para> <para>
<Replaceable>variable</Replaceable> is the name of a variable, <replaceable>variable</replaceable> is the name of a variable,
previously declared in the previously declared in the
same function, that is visible at this point. same function, that is visible at this point.
</Para> </para>
<Para> <para>
<Replaceable>class</Replaceable> is the name of an existing table <replaceable>class</replaceable> is the name of an existing table
or view where <Replaceable>field</Replaceable> is the name of or view where <replaceable>field</replaceable> is the name of
an attribute. an attribute.
</Para> </para>
<Para> <para>
Using the <Replaceable>class.field</Replaceable>%TYPE Using the <replaceable>class.field</replaceable>%TYPE
causes PL/pgSQL to lookup the attributes definitions at the causes PL/pgSQL to lookup the attributes definitions at the
first call to the funciton during the lifetime of a backend. first call to the funciton during the lifetime of a backend.
Have a table with a char(20) attribute and some PL/pgSQL functions Have a table with a char(20) attribute and some PL/pgSQL functions
...@@ -444,18 +446,18 @@ previously declared in the ...@@ -444,18 +446,18 @@ previously declared in the
char(40) and restores the data. Ha - he forgot about the char(40) and restores the data. Ha - he forgot about the
funcitons. The computations inside them will truncate the values funcitons. The computations inside them will truncate the values
to 20 characters. But if they are defined using the to 20 characters. But if they are defined using the
<Replaceable>class.field</Replaceable>%TYPE <replaceable>class.field</replaceable>%TYPE
declarations, they will automagically handle the size change or declarations, they will automagically handle the size change or
if the new table schema defines the attribute as text type. if the new table schema defines the attribute as text type.
</Para> </para>
</Sect3> </sect3>
<!-- **** PL/pgSQL expressions **** --> <!-- **** PL/pgSQL expressions **** -->
<Sect3> <sect3>
<Title>Expressions</Title> <title>Expressions</title>
<Para> <para>
All expressions used in PL/pgSQL statements are processed using All expressions used in PL/pgSQL statements are processed using
the backends executor. Expressions which appear to contain the backends executor. Expressions which appear to contain
constants may in fact require run-time evaluation (e.g. 'now' for the constants may in fact require run-time evaluation (e.g. 'now' for the
...@@ -463,22 +465,22 @@ datetime type) so ...@@ -463,22 +465,22 @@ datetime type) so
it is impossible for the PL/pgSQL parser it is impossible for the PL/pgSQL parser
to identify real constant values other than the NULL keyword. All to identify real constant values other than the NULL keyword. All
expressions are evaluated internally by executing a query expressions are evaluated internally by executing a query
<ProgramListing> <programlisting>
SELECT <Replaceable>expression</Replaceable> SELECT <replaceable>expression</replaceable>
</ProgramListing> </programlisting>
using the SPI manager. In the expression, occurences of variable using the SPI manager. In the expression, occurences of variable
identifiers are substituted by parameters and the actual values from identifiers are substituted by parameters and the actual values from
the variables are passed to the executor in the parameter array. All the variables are passed to the executor in the parameter array. All
expressions used in a PL/pgSQL function are only prepared and expressions used in a PL/pgSQL function are only prepared and
saved once. saved once.
</Para> </para>
<Para> <para>
The type checking done by the <productname>Postgres</productname> The type checking done by the <productname>Postgres</productname>
main parser has some side main parser has some side
effects to the interpretation of constant values. In detail there effects to the interpretation of constant values. In detail there
is a difference between what the two functions is a difference between what the two functions
<ProgramListing> <programlisting>
CREATE FUNCTION logfunc1 (text) RETURNS datetime AS ' CREATE FUNCTION logfunc1 (text) RETURNS datetime AS '
DECLARE DECLARE
logtxt ALIAS FOR $1; logtxt ALIAS FOR $1;
...@@ -487,11 +489,11 @@ it is impossible for the PL/pgSQL parser ...@@ -487,11 +489,11 @@ it is impossible for the PL/pgSQL parser
RETURN ''now''; RETURN ''now'';
END; END;
' LANGUAGE 'plpgsql'; ' LANGUAGE 'plpgsql';
</ProgramListing> </programlisting>
and and
<ProgramListing> <programlisting>
CREATE FUNCTION logfunc2 (text) RETURNS datetime AS ' CREATE FUNCTION logfunc2 (text) RETURNS datetime AS '
DECLARE DECLARE
logtxt ALIAS FOR $1; logtxt ALIAS FOR $1;
...@@ -502,9 +504,9 @@ it is impossible for the PL/pgSQL parser ...@@ -502,9 +504,9 @@ it is impossible for the PL/pgSQL parser
RETURN curtime; RETURN curtime;
END; END;
' LANGUAGE 'plpgsql'; ' LANGUAGE 'plpgsql';
</ProgramListing> </programlisting>
do. In the case of logfunc1(), the <ProductName>Postgres</ProductName> do. In the case of logfunc1(), the <productname>Postgres</productname>
main parser main parser
knows when preparing the plan for the INSERT, that the string 'now' knows when preparing the plan for the INSERT, that the string 'now'
should be interpreted as datetime because the target field of logtable should be interpreted as datetime because the target field of logtable
...@@ -512,389 +514,392 @@ it is impossible for the PL/pgSQL parser ...@@ -512,389 +514,392 @@ it is impossible for the PL/pgSQL parser
and this constant value is then used in all invocations of logfunc1() and this constant value is then used in all invocations of logfunc1()
during the lifetime of the backend. Needless to say that this isn't what the during the lifetime of the backend. Needless to say that this isn't what the
programmer wanted. programmer wanted.
</Para> </para>
<Para> <para>
In the case of logfunc2(), the <ProductName>Postgres</ProductName> In the case of logfunc2(), the <productname>Postgres</productname>
main parser does not know main parser does not know
what type 'now' should become and therefor it returns a datatype of what type 'now' should become and therefor it returns a datatype of
text containing the string 'now'. During the assignment text containing the string 'now'. During the assignment
to the local variable curtime, the PL/pgSQL interpreter casts this to the local variable curtime, the PL/pgSQL interpreter casts this
string to the datetime type by calling the text_out() and datetime_in() string to the datetime type by calling the text_out() and datetime_in()
functions for the conversion. functions for the conversion.
</Para> </para>
<Para> <para>
This type checking done by the <ProductName>Postgres</ProductName> main This type checking done by the <productname>Postgres</productname> main
parser got implemented after PL/pgSQL was nearly done. parser got implemented after PL/pgSQL was nearly done.
It is a difference between 6.3 and 6.4 and affects all functions It is a difference between 6.3 and 6.4 and affects all functions
using the prepared plan feature of the SPI manager. using the prepared plan feature of the SPI manager.
Using a local Using a local
variable in the above manner is currently the only way in PL/pgSQL to get variable in the above manner is currently the only way in PL/pgSQL to get
those values interpreted correctly. those values interpreted correctly.
</Para> </para>
<Para> <para>
If record fields are used in expressions or statements, the data types of If record fields are used in expressions or statements, the data types of
fields should not change between calls of one and the same expression. fields should not change between calls of one and the same expression.
Keep this in mind when writing trigger procedures that handle events Keep this in mind when writing trigger procedures that handle events
for more than one table. for more than one table.
</Para> </para>
</Sect3> </sect3>
<!-- **** PL/pgSQL statements **** --> <!-- **** PL/pgSQL statements **** -->
<Sect3> <sect3>
<Title>Statements</Title> <title>Statements</title>
<Para> <para>
Anything not understood by the PL/pgSQL parser as specified below Anything not understood by the PL/pgSQL parser as specified below
will be put into a query and sent down to the database engine will be put into a query and sent down to the database engine
to execute. The resulting query should not return any data. to execute. The resulting query should not return any data.
</Para> </para>
<VariableList> <variablelist>
<VarListEntry> <varlistentry>
<Term> <term>
Assignment Assignment
</Term> </term>
<ListItem> <listitem>
<Para> <para>
An assignment of a value to a variable or row/record field is An assignment of a value to a variable or row/record field is
written as written as
<ProgramListing> <programlisting>
<Replaceable>identifier</Replaceable> := <Replaceable>expression</Replaceable>; <replaceable>identifier</replaceable> := <replaceable>expression</replaceable>;
</ProgramListing> </programlisting>
If the expressions result data type doesn't match the variables If the expressions result data type doesn't match the variables
data type, or the variable has a size/precision that is known data type, or the variable has a size/precision that is known
(as for char(20)), the result value will be implicitly casted by (as for char(20)), the result value will be implicitly casted by
the PL/pgSQL bytecode interpreter using the result types output- and the PL/pgSQL bytecode interpreter using the result types output- and
the variables type input-functions. Note that this could potentially the variables type input-functions. Note that this could potentially
result in runtime errors generated by the types input functions. result in runtime errors generated by the types input functions.
</Para> </para>
<Para> <para>
An assignment of a complete selection into a record or row can An assignment of a complete selection into a record or row can
be done by be done by
<ProgramListing> <programlisting>
SELECT <Replaceable>expressions</Replaceable> INTO <Replaceable>target</Replaceable> FROM ...; SELECT <replaceable>expressions</replaceable> INTO <replaceable>target</replaceable> FROM ...;
</ProgramListing> </programlisting>
<Replaceable>target</Replaceable> can be a record, a row variable or a <replaceable>target</replaceable> can be a record, a row variable or a
comma separated list of variables and record-/row-fields. comma separated list of variables and record-/row-fields.
</Para> </para>
<Para> <para>
if a row or a variable list is used as target, the selected values if a row or a variable list is used as target, the selected values
must exactly match the structure of the target(s) or a runtime error must exactly match the structure of the target(s) or a runtime error
occurs. The FROM keyword can be followed by any valid qualification, occurs. The FROM keyword can be followed by any valid qualification,
grouping, sorting etc. that can be given for a SELECT statement. grouping, sorting etc. that can be given for a SELECT statement.
</Para> </para>
<Para> <para>
There is a special variable named FOUND of type bool that can be used There is a special variable named FOUND of type bool that can be used
immediately after a SELECT INTO to check if an assignment had success. immediately after a SELECT INTO to check if an assignment had success.
<ProgramListing> <programlisting>
SELECT * INTO myrec FROM EMP WHERE empname = myname; SELECT * INTO myrec FROM EMP WHERE empname = myname;
IF NOT FOUND THEN IF NOT FOUND THEN
RAISE EXCEPTION ''employee % not found'', myname; RAISE EXCEPTION ''employee % not found'', myname;
END IF; END IF;
</ProgramListing> </programlisting>
If the selection returns multiple rows, only the first is moved If the selection returns multiple rows, only the first is moved
into the target fields. All others are silently discarded. into the target fields. All others are silently discarded.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
Calling another function Calling another function
</Term> </term>
<ListItem> <listitem>
<Para> <para>
All functions defined in a <ProductName>Prostgres</ProductName> All functions defined in a <productname>Prostgres</productname>
database return a value. Thus, the normal way to call a function database return a value. Thus, the normal way to call a function
is to execute a SELECT query or doing an assignment (resulting is to execute a SELECT query or doing an assignment (resulting
in a PL/pgSQL internal SELECT). But there are cases where someone in a PL/pgSQL internal SELECT). But there are cases where someone
isn't interested int the functions result. isn't interested int the functions result.
<ProgramListing> <programlisting>
PERFORM <Replaceable>query</Replaceable> PERFORM <replaceable>query</replaceable>
</ProgramListing> </programlisting>
executes a 'SELECT <Replaceable>query</Replaceable>' over the executes a 'SELECT <replaceable>query</replaceable>' over the
SPI manager and discards the result. Identifiers like local SPI manager and discards the result. Identifiers like local
variables are still substituted into parameters. variables are still substituted into parameters.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
Returning from the function Returning from the function
</Term> </term>
<ListItem> <listitem>
<Para> <para>
<ProgramListing> <programlisting>
RETURN <Replaceable>expression</Replaceable> RETURN <replaceable>expression</replaceable>
</ProgramListing> </programlisting>
The function terminates and the value of <Replaceable>expression</Replaceable> The function terminates and the value of <replaceable>expression</replaceable>
will be returned to the upper executor. The return value of a function will be returned to the upper executor. The return value of a function
cannot be undefined. If control reaches the end of the toplevel block cannot be undefined. If control reaches the end of the toplevel block
of the function without hitting a RETURN statement, a runtime error of the function without hitting a RETURN statement, a runtime error
will occur. will occur.
</Para> </para>
<Para> <para>
The expressions result will be automatically casted into the The expressions result will be automatically casted into the
functions return type as described for assignments. functions return type as described for assignments.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
Aborting and messages Aborting and messages
</Term> </term>
<ListItem> <listitem>
<Para> <para>
As indicated in the above examples there is a RAISE statement that As indicated in the above examples there is a RAISE statement that
can throw messages into the <ProductName>Postgres</ProductName> can throw messages into the <productname>Postgres</productname>
elog mechanism. elog mechanism.
<ProgramListing> <programlisting>
RAISE <replaceable class="parameter">level</replaceable> ''<replaceable class="parameter">format</replaceable>'' [, <replaceable class="parameter">identifier</replaceable> [...]]; RAISE <replaceable class="parameter">level</replaceable>
</ProgramListing> <replaceable class="parameter">r">for</replaceable>le>'' [,
<replaceable class="parameter">identifier</replaceable> [...]];
</programlisting>
Inside the format, <quote>%</quote> is used as a placeholder for the Inside the format, <quote>%</quote> is used as a placeholder for the
subsequent comma-separated identifiers. Possible levels are subsequent comma-separated identifiers. Possible levels are
DEBUG (silently suppressed in production running databases), NOTICE DEBUG (silently suppressed in production running databases), NOTICE
(written into the database log and forwarded to the client application) (written into the database log and forwarded to the client application)
and EXCEPTION (written into the database log and aborting the transaction). and EXCEPTION (written into the database log and aborting the transaction).
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
Conditionals Conditionals
</Term> </term>
<ListItem> <listitem>
<Para> <para>
<ProgramListing> <programlisting>
IF <Replaceable>expression</Replaceable> THEN IF <replaceable>expression</replaceable> THEN
<replaceable>statements</replaceable> <replaceable>statements</replaceable>
[ELSE [ELSE
<replaceable>statements</replaceable>] <replaceable>statements</replaceable>]
END IF; END IF;
</ProgramListing> </programlisting>
The <Replaceable>expression</Replaceable> must return a value that The <replaceable>expression</replaceable> must return a value that
at least can be casted into a boolean type. at least can be casted into a boolean type.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
Loops Loops
</Term> </term>
<ListItem> <listitem>
<Para> <para>
There are multiple types of loops. There are multiple types of loops.
<ProgramListing> <programlisting>
[&lt;&lt;label&gt;&gt;] [&lt;&lt;label&gt;&gt;]
LOOP LOOP
<replaceable>statements</replaceable> <replaceable>statements</replaceable>
END LOOP; END LOOP;
</ProgramListing> </programlisting>
An unconditional loop that must be terminated explicitly An unconditional loop that must be terminated explicitly
by an EXIT statement. The optional label can be used by by an EXIT statement. The optional label can be used by
EXIT statements of nested loops to specify which level of EXIT statements of nested loops to specify which level of
nesting should be terminated. nesting should be terminated.
<ProgramListing> <programlisting>
[&lt;&lt;label&gt;&gt;] [&lt;&lt;label&gt;&gt;]
WHILE <Replaceable>expression</Replaceable> LOOP WHILE <replaceable>expression</replaceable> LOOP
<replaceable>statements</replaceable> <replaceable>statements</replaceable>
END LOOP; END LOOP;
</ProgramListing> </programlisting>
A conditional loop that is executed as long as the evaluation A conditional loop that is executed as long as the evaluation
of <Replaceable>expression</Replaceable> is true. of <replaceable>expression</replaceable> is true.
<ProgramListing> <programlisting>
[&lt;&lt;label&gt;&gt;] [&lt;&lt;label&gt;&gt;]
FOR <Replaceable>name</Replaceable> IN [ REVERSE ] <Replaceable>expression</Replaceable> .. <Replaceable>expression</Replaceable> LOOP FOR <replaceable>name</replaceable> IN [ REVERSE ]
<replaceable>le>express</replaceable>le> .. <replaceable>expression</replaceable> LOOP
<replaceable>statements</replaceable> <replaceable>statements</replaceable>
END LOOP; END LOOP;
</ProgramListing> </programlisting>
A loop that iterates over a range of integer values. The variable A loop that iterates over a range of integer values. The variable
<Replaceable>name</Replaceable> is automatically created as type <replaceable>name</replaceable> is automatically created as type
integer and exists only inside the loop. The two expressions giving integer and exists only inside the loop. The two expressions giving
the lower and upper bound of the range are evaluated only when entering the lower and upper bound of the range are evaluated only when entering
the loop. The iteration step is always 1. the loop. The iteration step is always 1.
<ProgramListing> <programlisting>
[&lt;&lt;label&gt;&gt;] [&lt;&lt;label&gt;&gt;]
FOR <Replaceable>record | row</Replaceable> IN <Replaceable>select_clause</Replaceable> LOOP FOR <replaceable>record | row</replaceable> IN <replaceable>select_clause</replaceable> LOOP
<replaceable>statements</replaceable> <replaceable>statements</replaceable>
END LOOP; END LOOP;
</ProgramListing> </programlisting>
The record or row is assigned all the rows resulting from the select The record or row is assigned all the rows resulting from the select
clause and the statements executed for each. If the loop is terminated clause and the statements executed for each. If the loop is terminated
with an EXIT statement, the last assigned row is still accessible with an EXIT statement, the last assigned row is still accessible
after the loop. after the loop.
<ProgramListing> <programlisting>
EXIT [ <Replaceable>label</Replaceable> ] [ WHEN <Replaceable>expression</Replaceable> ]; EXIT [ <replaceable>label</replaceable> ] [ WHEN <replaceable>expression</replaceable> ];
</ProgramListing> </programlisting>
If no <Replaceable>label</Replaceable> given, If no <replaceable>label</replaceable> given,
the innermost loop is terminated and the the innermost loop is terminated and the
statement following END LOOP is executed next. statement following END LOOP is executed next.
If <Replaceable>label</Replaceable> is given, it If <replaceable>label</replaceable> is given, it
must be the label of the current or an upper level of nested loop must be the label of the current or an upper level of nested loop
blocks. Then the named loop or block is terminated and control blocks. Then the named loop or block is terminated and control
continues with the statement after the loops/blocks corresponding continues with the statement after the loops/blocks corresponding
END. END.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
</VariableList> </variablelist>
</Sect3> </sect3>
<!-- **** PL/pgSQL trigger procedures **** --> <!-- **** PL/pgSQL trigger procedures **** -->
<Sect3> <sect3>
<Title>Trigger Procedures</Title> <title>Trigger Procedures</title>
<Para> <para>
PL/pgSQL can be used to define trigger procedures. They are created PL/pgSQL can be used to define trigger procedures. They are created
with the usual CREATE FUNCTION command as a function with no with the usual CREATE FUNCTION command as a function with no
arguments and a return type of OPAQUE. arguments and a return type of OPAQUE.
</Para> </para>
<Para> <para>
There are some <ProductName>Postgres</ProductName> specific details There are some <productname>Postgres</productname> specific details
in functions used as trigger procedures. in functions used as trigger procedures.
</Para> </para>
<Para> <para>
First they have some special variables created automatically in the First they have some special variables created automatically in the
toplevel blocks declaration section. They are toplevel blocks declaration section. They are
</Para> </para>
<VariableList> <variablelist>
<VarListEntry> <varlistentry>
<Term> <term>
NEW NEW
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype RECORD; variable holding the new database row on INSERT/UPDATE Datatype RECORD; variable holding the new database row on INSERT/UPDATE
operations on ROW level triggers. operations on ROW level triggers.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
OLD OLD
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype RECORD; variable holding the old database row on UPDATE/DELETE Datatype RECORD; variable holding the old database row on UPDATE/DELETE
operations on ROW level triggers. operations on ROW level triggers.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
TG_NAME TG_NAME
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype name; variable that contains the name of the trigger actually Datatype name; variable that contains the name of the trigger actually
fired. fired.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
TG_WHEN TG_WHEN
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype text; a string of either 'BEFORE' or 'AFTER' depending on the Datatype text; a string of either 'BEFORE' or 'AFTER' depending on the
triggers definition. triggers definition.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
TG_LEVEL TG_LEVEL
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype text; a string of either 'ROW' or 'STATEMENT' depending on the Datatype text; a string of either 'ROW' or 'STATEMENT' depending on the
triggers definition. triggers definition.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
TG_OP TG_OP
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype text; a string of 'INSERT', 'UPDATE' or 'DELETE' telling Datatype text; a string of 'INSERT', 'UPDATE' or 'DELETE' telling
for which operation the trigger is actually fired. for which operation the trigger is actually fired.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
TG_RELID TG_RELID
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype oid; the object ID of the table that caused the Datatype oid; the object ID of the table that caused the
trigger invocation. trigger invocation.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
TG_RELNAME TG_RELNAME
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype name; the name of the table that caused the trigger Datatype name; the name of the table that caused the trigger
invocation. invocation.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
TG_NARGS TG_NARGS
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype integer; the number of arguments given to the trigger Datatype integer; the number of arguments given to the trigger
procedure in the CREATE TRIGGER statement. procedure in the CREATE TRIGGER statement.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
TG_ARGV[] TG_ARGV[]
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Datatype array of text; the arguments from the CREATE TRIGGER statement. Datatype array of text; the arguments from the CREATE TRIGGER statement.
The index counts from 0 and can be given as an expression. Invalid The index counts from 0 and can be given as an expression. Invalid
indices (&lt; 0 or &gt;= tg_nargs) result in a NULL value. indices (&lt; 0 or &gt;= tg_nargs) result in a NULL value.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
</VariableList> </variablelist>
<Para> <para>
Second they must return either NULL or a record/row containing Second they must return either NULL or a record/row containing
exactly the structure of the table the trigger was fired for. exactly the structure of the table the trigger was fired for.
Triggers fired AFTER might always return a NULL value with no Triggers fired AFTER might always return a NULL value with no
...@@ -904,22 +909,22 @@ Loops ...@@ -904,22 +909,22 @@ Loops
row in the operation. It is possible to replace single values directly row in the operation. It is possible to replace single values directly
in NEW and return that or to build a complete new record/row to in NEW and return that or to build a complete new record/row to
return. return.
</Para> </para>
</Sect3> </sect3>
<!-- **** PL/pgSQL exceptions **** --> <!-- **** PL/pgSQL exceptions **** -->
<Sect3> <sect3>
<Title>Exceptions</Title> <title>Exceptions</title>
<Para> <para>
<ProductName>Postgres</ProductName> does not have a very smart <productname>Postgres</productname> does not have a very smart
exception handling model. Whenever the parser, planner/optimizer exception handling model. Whenever the parser, planner/optimizer
or executor decide that a statement cannot be processed any longer, or executor decide that a statement cannot be processed any longer,
the whole transaction gets aborted and the system jumps back the whole transaction gets aborted and the system jumps back
into the mainloop to get the next query from the client application. into the mainloop to get the next query from the client application.
</Para> </para>
<Para> <para>
It is possible to hook into the error mechanism to notice that this It is possible to hook into the error mechanism to notice that this
happens. But currently it's impossible to tell what really happens. But currently it's impossible to tell what really
caused the abort (input/output conversion error, floating point caused the abort (input/output conversion error, floating point
...@@ -929,73 +934,73 @@ Loops ...@@ -929,73 +934,73 @@ Loops
And even if, at this point the information, that the transaction And even if, at this point the information, that the transaction
is aborted, is already sent to the client application, so resuming is aborted, is already sent to the client application, so resuming
operation does not make any sense. operation does not make any sense.
</Para> </para>
<Para> <para>
Thus, the only thing PL/pgSQL currently does when it encounters Thus, the only thing PL/pgSQL currently does when it encounters
an abort during execution of a function or trigger an abort during execution of a function or trigger
procedure is to write some additional DEBUG level log messages procedure is to write some additional DEBUG level log messages
telling in which function and where (line number and type of telling in which function and where (line number and type of
statement) this happened. statement) this happened.
</Para> </para>
</Sect3> </sect3>
</Sect2> </sect2>
<!-- **** PL/pgSQL Examples **** --> <!-- **** PL/pgSQL Examples **** -->
<Sect2> <sect2>
<Title>Examples</Title> <title>Examples</title>
<Para> <para>
Here are only a few functions to demonstrate how easy PL/pgSQL Here are only a few functions to demonstrate how easy PL/pgSQL
functions can be written. For more complex examples the programmer functions can be written. For more complex examples the programmer
might look at the regression test for PL/pgSQL. might look at the regression test for PL/pgSQL.
</Para> </para>
<Para> <para>
One painful detail of writing functions in PL/pgSQL is the handling One painful detail of writing functions in PL/pgSQL is the handling
of single quotes. The functions source text on CREATE FUNCTION must of single quotes. The functions source text on CREATE FUNCTION must
be a literal string. Single quotes inside of literal strings must be be a literal string. Single quotes inside of literal strings must be
either doubled or quoted with a backslash. We are still looking for either doubled or quoted with a backslash. We are still looking for
an elegant alternative. In the meantime, doubling the single qoutes an elegant alternative. In the meantime, doubling the single qoutes
as in the examples below should be used. Any solution for this as in the examples below should be used. Any solution for this
in future versions of <ProductName>Postgres</ProductName> will be in future versions of <productname>Postgres</productname> will be
upward compatible. upward compatible.
</Para> </para>
<Sect3> <sect3>
<Title>Some Simple PL/pgSQL Functions</Title> <title>Some Simple PL/pgSQL Functions</title>
<Para> <para>
The following two PL/pgSQL functions are identical to their The following two PL/pgSQL functions are identical to their
counterparts from the C language function discussion. counterparts from the C language function discussion.
<ProgramListing> <programlisting>
CREATE FUNCTION add_one (int4) RETURNS int4 AS ' CREATE FUNCTION add_one (int4) RETURNS int4 AS '
BEGIN BEGIN
RETURN $1 + 1; RETURN $1 + 1;
END; END;
' LANGUAGE 'plpgsql'; ' LANGUAGE 'plpgsql';
</ProgramListing> </programlisting>
<ProgramListing> <programlisting>
CREATE FUNCTION concat_text (text, text) RETURNS text AS ' CREATE FUNCTION concat_text (text, text) RETURNS text AS '
BEGIN BEGIN
RETURN $1 || $2; RETURN $1 || $2;
END; END;
' LANGUAGE 'plpgsql'; ' LANGUAGE 'plpgsql';
</ProgramListing> </programlisting>
</Para> </para>
</Sect3> </sect3>
<Sect3> <sect3>
<Title>PL/pgSQL Function on Composite Type</Title> <title>PL/pgSQL Function on Composite Type</title>
<Para> <para>
Again it is the PL/pgSQL equivalent to the example from Again it is the PL/pgSQL equivalent to the example from
The C functions. The C functions.
<ProgramListing> <programlisting>
CREATE FUNCTION c_overpaid (EMP, int4) RETURNS bool AS ' CREATE FUNCTION c_overpaid (EMP, int4) RETURNS bool AS '
DECLARE DECLARE
emprec ALIAS FOR $1; emprec ALIAS FOR $1;
...@@ -1007,21 +1012,21 @@ upward compatible. ...@@ -1007,21 +1012,21 @@ upward compatible.
RETURN emprec.salary > sallim; RETURN emprec.salary > sallim;
END; END;
' LANGUAGE 'plpgsql'; ' LANGUAGE 'plpgsql';
</ProgramListing> </programlisting>
</Para> </para>
</Sect3> </sect3>
<Sect3> <sect3>
<Title>PL/pgSQL Trigger Procedure</Title> <title>PL/pgSQL Trigger Procedure</title>
<Para> <para>
This trigger ensures, that any time a row is inserted or updated This trigger ensures, that any time a row is inserted or updated
in the table, the current username and time are stamped into the in the table, the current username and time are stamped into the
row. And it ensures that an employees name is given and that the row. And it ensures that an employees name is given and that the
salary is a positive value. salary is a positive value.
<ProgramListing> <programlisting>
CREATE TABLE emp ( CREATE TABLE emp (
empname text, empname text,
salary int4, salary int4,
...@@ -1052,108 +1057,110 @@ upward compatible. ...@@ -1052,108 +1057,110 @@ upward compatible.
CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
FOR EACH ROW EXECUTE PROCEDURE emp_stamp(); FOR EACH ROW EXECUTE PROCEDURE emp_stamp();
</ProgramListing> </programlisting>
</Para> </para>
</Sect3> </sect3>
</Sect2> </sect2>
</Sect1> </sect1>
<!-- ********** <!-- **********
* The procedural language PL/Tcl * The procedural language PL/Tcl
********** **********
--> -->
<Sect1> <sect1>
<Title>PL/Tcl</Title> <title>PL/Tcl</title>
<Para> <para>
PL/Tcl is a loadable procedural language for the PL/Tcl is a loadable procedural language for the
<ProductName>Postgres</ProductName> database system <productname>Postgres</productname> database system
that enables the Tcl language to be used to create functions and that enables the Tcl language to be used to create functions and
trigger-procedures. trigger-procedures.
</Para> </para>
<Para> <para>
This package was originally written by Jan Wieck. This package was originally written by Jan Wieck.
</Para> </para>
<!-- **** PL/Tcl overview **** --> <!-- **** PL/Tcl overview **** -->
<Sect2> <sect2>
<Title>Overview</Title> <title>Overview</title>
<Para> <para>
PL/Tcl offers most of the capabilities a function PL/Tcl offers most of the capabilities a function
writer has in the C language, except for some restrictions. writer has in the C language, except for some restrictions.
</Para> </para>
<Para> <para>
The good restriction is, that everything is executed in a safe The good restriction is, that everything is executed in a safe
Tcl-interpreter. In addition to the limited command set of safe Tcl, only Tcl-interpreter. In addition to the limited command set of safe Tcl, only
a few commands are available to access the database over SPI and to raise a few commands are available to access the database over SPI and to raise
messages via elog(). There is no way to access internals of the messages via elog(). There is no way to access internals of the
database backend or gaining OS-level access under the permissions of the database backend or gaining OS-level access under the permissions of the
<ProductName>Postgres</ProductName> user ID like in C. <productname>Postgres</productname> user ID like in C.
Thus, any unprivileged database user may be Thus, any unprivileged database user may be
permitted to use this language. permitted to use this language.
</Para> </para>
<Para> <para>
The other, internal given, restriction is, that Tcl procedures cannot The other, internal given, restriction is, that Tcl procedures cannot
be used to create input-/output-functions for new data types. be used to create input-/output-functions for new data types.
</Para> </para>
<Para> <para>
The shared object for the PL/Tcl call handler is automatically built The shared object for the PL/Tcl call handler is automatically built
and installed in the <ProductName>Postgres</ProductName> and installed in the <productname>Postgres</productname>
library directory if the Tcl/Tk support is specified library directory if the Tcl/Tk support is specified
in the configuration step of the installation procedure. in the configuration step of the installation procedure.
</Para> </para>
</Sect2> </sect2>
<!-- **** PL/Tcl description **** --> <!-- **** PL/Tcl description **** -->
<Sect2> <sect2>
<Title>Description</Title> <title>Description</title>
<Sect3> <sect3>
<Title><ProductName>Postgres</ProductName> Functions and Tcl Procedure Names</Title> <title><productname>Postgres</productname> Functions and Tcl Procedure Names</title>
<Para> <para>
In <ProductName>Postgres</ProductName>, one and the In <productname>Postgres</productname>, one and the
same function name can be used for same function name can be used for
different functions as long as the number of arguments or their types different functions as long as the number of arguments or their types
differ. This would collide with Tcl procedure names. To offer the same differ. This would collide with Tcl procedure names. To offer the same
flexibility in PL/Tcl, the internal Tcl procedure names contain the object flexibility in PL/Tcl, the internal Tcl procedure names contain the object
ID of the procedures pg_proc row as part of their name. Thus, different ID of the procedures pg_proc row as part of their name. Thus, different
argtype versions of the same <ProductName>Postgres</ProductName> argtype versions of the same <productname>Postgres</productname>
function are different for Tcl too. function are different for Tcl too.
</Para> </para>
</Sect3> </sect3>
<Sect3> <sect3>
<Title>Defining Functions in PL/Tcl</Title> <title>Defining Functions in PL/Tcl</title>
<Para> <para>
To create a function in the PL/Tcl language, use the known syntax To create a function in the PL/Tcl language, use the known syntax
<ProgramListing> <programlisting>
CREATE FUNCTION <Replaceable>funcname</Replaceable> (<Replaceable>argument-types</Replaceable>) RETURNS <Replaceable>returntype</Replaceable> AS ' CREATE FUNCTION <replaceable>funcname</replaceable>
<replaceable>ceable>argumen</replaceable>ceable>) RETURNS
<replaceable>returntype</replaceable> AS '
# PL/Tcl function body # PL/Tcl function body
' LANGUAGE 'pltcl'; ' LANGUAGE 'pltcl';
</ProgramListing> </programlisting>
When calling this function in a query, the arguments are given as When calling this function in a query, the arguments are given as
variables $1 ... $n to the Tcl procedure body. So a little max function variables $1 ... $n to the Tcl procedure body. So a little max function
returning the higher of two int4 values would be created as: returning the higher of two int4 values would be created as:
<ProgramListing> <programlisting>
CREATE FUNCTION tcl_max (int4, int4) RETURNS int4 AS ' CREATE FUNCTION tcl_max (int4, int4) RETURNS int4 AS '
if {$1 > $2} {return $1} if {$1 > $2} {return $1}
return $2 return $2
' LANGUAGE 'pltcl'; ' LANGUAGE 'pltcl';
</ProgramListing> </programlisting>
Composite type arguments are given to the procedure as Tcl arrays. Composite type arguments are given to the procedure as Tcl arrays.
The element names The element names
...@@ -1161,9 +1168,9 @@ upward compatible. ...@@ -1161,9 +1168,9 @@ upward compatible.
type. If an attribute in the actual row type. If an attribute in the actual row
has the NULL value, it will not appear in the array! Here is has the NULL value, it will not appear in the array! Here is
an example that defines the overpaid_2 function (as found in the an example that defines the overpaid_2 function (as found in the
older <ProductName>Postgres</ProductName> documentation) in PL/Tcl older <productname>Postgres</productname> documentation) in PL/Tcl
<ProgramListing> <programlisting>
CREATE FUNCTION overpaid_2 (EMP) RETURNS bool AS ' CREATE FUNCTION overpaid_2 (EMP) RETURNS bool AS '
if {200000.0 < $1(salary)} { if {200000.0 < $1(salary)} {
return "t" return "t"
...@@ -1173,15 +1180,15 @@ upward compatible. ...@@ -1173,15 +1180,15 @@ upward compatible.
} }
return "f" return "f"
' LANGUAGE 'pltcl'; ' LANGUAGE 'pltcl';
</ProgramListing> </programlisting>
</Para> </para>
</Sect3> </sect3>
<Sect3> <sect3>
<Title>Global Data in PL/Tcl</Title> <title>Global Data in PL/Tcl</title>
<Para> <para>
Sometimes (especially when using the SPI functions described later) it Sometimes (especially when using the SPI functions described later) it
is useful to have some global status data that is held between two is useful to have some global status data that is held between two
calls to a procedure. calls to a procedure.
...@@ -1191,146 +1198,146 @@ upward compatible. ...@@ -1191,146 +1198,146 @@ upward compatible.
an array is made available to each procedure via the upvar an array is made available to each procedure via the upvar
command. The global name of this variable is the procedures internal command. The global name of this variable is the procedures internal
name and the local name is GD. name and the local name is GD.
</Para> </para>
</Sect3> </sect3>
<Sect3> <sect3>
<Title>Trigger Procedures in PL/Tcl</Title> <title>Trigger Procedures in PL/Tcl</title>
<Para> <para>
Trigger procedures are defined in <ProductName>Postgres</ProductName> Trigger procedures are defined in <productname>Postgres</productname>
as functions without as functions without
arguments and a return type of opaque. And so are they in the PL/Tcl arguments and a return type of opaque. And so are they in the PL/Tcl
language. language.
</Para> </para>
<Para> <para>
The informations from the trigger manager are given to the procedure body The informations from the trigger manager are given to the procedure body
in the following variables: in the following variables:
</Para> </para>
<VariableList> <variablelist>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$TG_name $TG_name
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
The name of the trigger from the CREATE TRIGGER statement. The name of the trigger from the CREATE TRIGGER statement.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$TG_relid $TG_relid
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
The object ID of the table that caused the trigger procedure The object ID of the table that caused the trigger procedure
to be invoked. to be invoked.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$TG_relatts $TG_relatts
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
A Tcl list of the tables field names prefixed with an empty list element. A Tcl list of the tables field names prefixed with an empty list element.
So looking up an element name in the list with the lsearch Tcl command So looking up an element name in the list with the lsearch Tcl command
returns the same positive number starting from 1 as the fields are numbered returns the same positive number starting from 1 as the fields are numbered
in the pg_attribute system catalog. in the pg_attribute system catalog.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$TG_when $TG_when
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
The string BEFORE or AFTER depending on the event of the trigger call. The string BEFORE or AFTER depending on the event of the trigger call.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$TG_level $TG_level
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
The string ROW or STATEMENT depending on the event of the trigger call. The string ROW or STATEMENT depending on the event of the trigger call.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$TG_op $TG_op
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
The string INSERT, UPDATE or DELETE depending on the event of the The string INSERT, UPDATE or DELETE depending on the event of the
trigger call. trigger call.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$NEW $NEW
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
An array containing the values of the new table row on INSERT/UPDATE An array containing the values of the new table row on INSERT/UPDATE
actions, or empty on DELETE. actions, or empty on DELETE.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$OLD $OLD
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
An array containing the values of the old table row on UPDATE/DELETE An array containing the values of the old table row on UPDATE/DELETE
actions, or empty on INSERT. actions, or empty on INSERT.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$GD $GD
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
The global status data array as described above. The global status data array as described above.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term><Replaceable class="Parameter"> <term><replaceable class="Parameter">
$args $args
</Replaceable></Term> </replaceable></term>
<ListItem> <listitem>
<Para> <para>
A Tcl list of the arguments to the procedure as given in the A Tcl list of the arguments to the procedure as given in the
CREATE TRIGGER statement. The arguments are also accessible as $1 ... $n CREATE TRIGGER statement. The arguments are also accessible as $1 ... $n
in the procedure body. in the procedure body.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
</VariableList> </variablelist>
<Para> <para>
The return value from a trigger procedure is one of the strings OK or SKIP, The return value from a trigger procedure is one of the strings OK or SKIP,
or a list as returned by the 'array get' Tcl command. If the return value or a list as returned by the 'array get' Tcl command. If the return value
is OK, the normal operation (INSERT/UPDATE/DELETE) that fired this trigger is OK, the normal operation (INSERT/UPDATE/DELETE) that fired this trigger
...@@ -1339,14 +1346,14 @@ $args ...@@ -1339,14 +1346,14 @@ $args
to return a modified row to the trigger manager that will be inserted instead to return a modified row to the trigger manager that will be inserted instead
of the one given in $NEW (INSERT/UPDATE only). Needless to say that all of the one given in $NEW (INSERT/UPDATE only). Needless to say that all
this is only meaningful when the trigger is BEFORE and FOR EACH ROW. this is only meaningful when the trigger is BEFORE and FOR EACH ROW.
</Para> </para>
<Para> <para>
Here's a little example trigger procedure that forces an integer value Here's a little example trigger procedure that forces an integer value
in a table to keep track of the # of updates that are performed on the in a table to keep track of the # of updates that are performed on the
row. For new row's inserted, the value is initialized to 0 and then row. For new row's inserted, the value is initialized to 0 and then
incremented on every update operation: incremented on every update operation:
<ProgramListing> <programlisting>
CREATE FUNCTION trigfunc_modcount() RETURNS OPAQUE AS ' CREATE FUNCTION trigfunc_modcount() RETURNS OPAQUE AS '
switch $TG_op { switch $TG_op {
INSERT { INSERT {
...@@ -1367,161 +1374,163 @@ $args ...@@ -1367,161 +1374,163 @@ $args
CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt'); FOR EACH ROW EXECUTE PROCEDURE trigfunc_modcount('modcnt');
</ProgramListing> </programlisting>
</Para> </para>
</Sect3> </sect3>
<Sect3> <sect3>
<Title>Database Access from PL/Tcl</Title> <title>Database Access from PL/Tcl</title>
<Para> <para>
The following commands are available to access the database from The following commands are available to access the database from
the body of a PL/Tcl procedure: the body of a PL/Tcl procedure:
</Para> </para>
<VariableList> <variablelist>
<VarListEntry> <varlistentry>
<Term> <term>
elog <Replaceable>level</Replaceable> <Replaceable>msg</Replaceable> elog <replaceable>level</replaceable> <replaceable>msg</replaceable>
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Fire a log message. Possible levels are NOTICE, WARN, ERROR, Fire a log message. Possible levels are NOTICE, WARN, ERROR,
FATAL, DEBUG and NOIND FATAL, DEBUG and NOIND
like for the elog() C function. like for the elog() C function.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
quote <Replaceable>string</Replaceable> quote <replaceable>string</replaceable>
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Duplicates all occurences of single quote and backslash characters. Duplicates all occurences of single quote and backslash characters.
It should be used when variables are used in the query string given It should be used when variables are used in the query string given
to spi_exec or spi_prepare (not for the value list on spi_execp). to spi_exec or spi_prepare (not for the value list on spi_execp).
Think about a query string like Think about a query string like
<ProgramListing> <programlisting>
"SELECT '$val' AS ret" "SELECT '$val' AS ret"
</ProgramListing> </programlisting>
where the Tcl variable val actually contains "doesn't". This would result where the Tcl variable val actually contains "doesn't". This would result
in the final query string in the final query string
<ProgramListing> <programlisting>
"SELECT 'doesn't' AS ret" "SELECT 'doesn't' AS ret"
</ProgramListing> </programlisting>
what would cause a parse error during spi_exec or spi_prepare. what would cause a parse error during spi_exec or spi_prepare.
It should contain It should contain
<ProgramListing> <programlisting>
"SELECT 'doesn''t' AS ret" "SELECT 'doesn''t' AS ret"
</ProgramListing> </programlisting>
and has to be written as and has to be written as
<ProgramListing> <programlisting>
"SELECT '[ quote $val ]' AS ret" "SELECT '[ quote $val ]' AS ret"
</ProgramListing> </programlisting>
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replaceable>? <Replaceable>query</Replaceable> ?<Replaceable>loop-body</Replaceable>? spi_exec ?-count <replaceable>n</replaceable>? ?-array
</Term> <replaceable>>nam</replaceable>>?<replaceable>e>que</replaceable>e> ?<replaceable>loop-body</replaceable>?
<ListItem> </term>
<Para> <listitem>
<para>
Call parser/planner/optimizer/executor for query. Call parser/planner/optimizer/executor for query.
The optional -count value tells spi_exec the maximum number of rows The optional -count value tells spi_exec the maximum number of rows
to be processed by the query. to be processed by the query.
</Para> </para>
<Para> <para>
If the query is If the query is
a SELECT statement and the optional loop-body (a body of Tcl commands a SELECT statement and the optional loop-body (a body of Tcl commands
like in a foreach statement) is given, it is evaluated for each like in a foreach statement) is given, it is evaluated for each
row selected and behaves like expected on continue/break. The values row selected and behaves like expected on continue/break. The values
of selected fields are put into variables named as the column names. So a of selected fields are put into variables named as the column names. So a
<ProgramListing> <programlisting>
spi_exec "SELECT count(*) AS cnt FROM pg_proc" spi_exec "SELECT count(*) AS cnt FROM pg_proc"
</ProgramListing> </programlisting>
will set the variable $cnt to the number of rows in the pg_proc system will set the variable $cnt to the number of rows in the pg_proc system
catalog. If the option -array is given, the column values are stored catalog. If the option -array is given, the column values are stored
in the associative array named 'name' indexed by the column name in the associative array named 'name' indexed by the column name
instead of individual variables. instead of individual variables.
<ProgramListing> <programlisting>
spi_exec -array C "SELECT * FROM pg_class" { spi_exec -array C "SELECT * FROM pg_class" {
elog DEBUG "have table $C(relname)" elog DEBUG "have table $C(relname)"
} }
</ProgramListing> </programlisting>
will print a DEBUG log message for every row of pg_class. The return value will print a DEBUG log message for every row of pg_class. The return value
of spi_exec is the number of rows affected by query as found in of spi_exec is the number of rows affected by query as found in
the global variable SPI_processed. the global variable SPI_processed.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
spi_prepare <Replaceable>query</Replaceable> <Replaceable>typelist</Replaceable> spi_prepare <replaceable>query</replaceable> <replaceable>typelist</replaceable>
</Term> </term>
<ListItem> <listitem>
<Para> <para>
Prepares AND SAVES a query plan for later execution. It is a bit different Prepares AND SAVES a query plan for later execution. It is a bit different
from the C level SPI_prepare in that the plan is automatically copied to the from the C level SPI_prepare in that the plan is automatically copied to the
toplevel memory context. Thus, there is currently no way of preparing a toplevel memory context. Thus, there is currently no way of preparing a
plan without saving it. plan without saving it.
</Para> </para>
<Para> <para>
If the query references arguments, the type names must be given as a Tcl If the query references arguments, the type names must be given as a Tcl
list. The return value from spi_prepare is a query ID to be used in list. The return value from spi_prepare is a query ID to be used in
subsequent calls to spi_execp. See spi_execp for a sample. subsequent calls to spi_execp. See spi_execp for a sample.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replaceable>? ?-nulls <Replaceable>str</Replaceable>? <Replaceable>query</Replaceable> ?<Replaceable>valuelist</Replaceable>? ?<Replaceable>loop-body</Replaceable>? spi_exec ?-count <replaceable>n</replaceable>? ?-array
</Term> <replaceable>>nam</replaceable>>? ?-nulls<replaceable>e>s</replaceable>e><replaceable>le>qu</replaceable>le<replaceable>ble>value</replaceable>ble>? ?<replaceable>loop-body</replaceable>?
<ListItem> </term>
<Para> <listitem>
<para>
Execute a prepared plan from spi_prepare with variable substitution. Execute a prepared plan from spi_prepare with variable substitution.
The optional -count value tells spi_execp the maximum number of rows The optional -count value tells spi_execp the maximum number of rows
to be processed by the query. to be processed by the query.
</Para> </para>
<Para> <para>
The optional value for -nulls is a string of spaces and 'n' characters The optional value for -nulls is a string of spaces and 'n' characters
telling spi_execp which of the values are NULL's. If given, it must telling spi_execp which of the values are NULL's. If given, it must
have exactly the length of the number of values. have exactly the length of the number of values.
</Para> </para>
<Para> <para>
The queryid is the ID returned by the spi_prepare call. The queryid is the ID returned by the spi_prepare call.
</Para> </para>
<Para> <para>
If there was a typelist given to spi_prepare, a Tcl list of values of If there was a typelist given to spi_prepare, a Tcl list of values of
exactly the same length must be given to spi_execp after the query. If exactly the same length must be given to spi_execp after the query. If
the type list on spi_prepare was empty, this argument must be omitted. the type list on spi_prepare was empty, this argument must be omitted.
</Para> </para>
<Para> <para>
If the query is a SELECT statement, the same as described for spi_exec If the query is a SELECT statement, the same as described for spi_exec
happens for the loop-body and the variables for the fields selected. happens for the loop-body and the variables for the fields selected.
</Para> </para>
<Para> <para>
Here's an example for a PL/Tcl function using a prepared plan: Here's an example for a PL/Tcl function using a prepared plan:
<ProgramListing> <programlisting>
CREATE FUNCTION t1_count(int4, int4) RETURNS int4 AS ' CREATE FUNCTION t1_count(int4, int4) RETURNS int4 AS '
if {![ info exists GD(plan) ]} { if {![ info exists GD(plan) ]} {
# prepare the saved plan on the first call # prepare the saved plan on the first call
...@@ -1532,7 +1541,7 @@ spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replac ...@@ -1532,7 +1541,7 @@ spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replac
spi_execp -count 1 $GD(plan) [ list $1 $2 ] spi_execp -count 1 $GD(plan) [ list $1 $2 ]
return $cnt return $cnt
' LANGUAGE 'pltcl'; ' LANGUAGE 'pltcl';
</ProgramListing> </programlisting>
Note that each backslash that Tcl should see must be doubled in Note that each backslash that Tcl should see must be doubled in
the query creating the function, since the main parser processes the query creating the function, since the main parser processes
...@@ -1540,16 +1549,16 @@ spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replac ...@@ -1540,16 +1549,16 @@ spi_exec ?-count <Replaceable>n</Replaceable>? ?-array <Replaceable>name</Replac
Inside the query string given to spi_prepare should Inside the query string given to spi_prepare should
really be dollar signs to mark the parameter positions and to not let really be dollar signs to mark the parameter positions and to not let
$1 be substituted by the value given in the first function call. $1 be substituted by the value given in the first function call.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
<VarListEntry> <varlistentry>
<Term> <term>
Modules and the unknown command Modules and the unknown command
</Term> </term>
<ListItem> <listitem>
<Para> <para>
PL/Tcl has a special support for things often used. It recognizes two PL/Tcl has a special support for things often used. It recognizes two
magic tables, pltcl_modules and pltcl_modfuncs. magic tables, pltcl_modules and pltcl_modfuncs.
If these exist, the module 'unknown' is loaded into the interpreter If these exist, the module 'unknown' is loaded into the interpreter
...@@ -1558,21 +1567,36 @@ Modules and the unknown command ...@@ -1558,21 +1567,36 @@ Modules and the unknown command
of the modules. If this is true, the module is loaded on demand. of the modules. If this is true, the module is loaded on demand.
To enable this behavior, the PL/Tcl call handler must be compiled To enable this behavior, the PL/Tcl call handler must be compiled
with -DPLTCL_UNKNOWN_SUPPORT set. with -DPLTCL_UNKNOWN_SUPPORT set.
</Para> </para>
<Para> <para>
There are support scripts to maintain these tables in the modules There are support scripts to maintain these tables in the modules
subdirectory of the PL/Tcl source including the source for the subdirectory of the PL/Tcl source including the source for the
unknown module that must get installed initially. unknown module that must get installed initially.
</Para> </para>
</ListItem> </listitem>
</VarListEntry> </varlistentry>
</VariableList> </variablelist>
</Sect3> </sect3>
</Sect2> </sect2>
</Sect1> </sect1>
</chapter>
</Chapter> <!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:nil
sgml-default-dtd-file:"./reference.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:"/usr/lib/sgml/CATALOG"
sgml-local-ecat-files:nil
End:
-->
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment