.\".he '\*(dA'DRAFT'\*(tI'		\" comment out in production version
.\"========================================================
.\"------------------------------------
.\" /home1/frew/s2k/postgres/manual/RCS/manual.me,v 1.10 1992/07/07 17:44:44 frew Exp
.\"------------------------------------
.\" XXX standard disclaimer belongs here....
.\"---------------------------------------------------------------------------
.de cW					\" arg3arg1arg2, constant-width arg1
\&\\$3\\fC\\$1\\fP\\$2
.\"\&\\$3\\fC\\s-1\\$1\\s0\\fP\\$2
..
.\"------------------------------------
.de xP					\" ip for references
.ip \\$1 \\w'[STON90B]'u+2n
..
.\"------------------------------------
.de (P					\" prologue for constant-width block
.ft C
.ps -1
.vs -1
..
.\"-----------------
.de )P					\" epilogue for constant-width block
.vs +1
.ps +1
.ft P
..
.\"------------------------------------
.de (T					\" prologue for constant-width table
.(P
.in +\\n(biu
..
.\"-----------------
.de )T					\" epilogue for constant-width table
.in -\\n(biu
.)P
..
.\"------------------------------------
.de (C					\" begin constant-width list
.(l
.(P
..
.\"-----------------
.de )C					\" end constant-width list
.)P
.)l
..
.\"---------------------------------------------------------------------------
.    ds II \s-1INGRES\s0
.    ds PP \s-1POSTGRES\s0
.    ds UU \s-1UNIX\s0
.    ds PQ \s-1POSTQUEL\s0
.    ds LP \s-1LIBPQ\s0
.    ds PV \s-14.0\s0
.    ds OF \s-1PICASSO\s0
.\"------------------------------------
.ps 11
.vs 13
.\"-----------------
.nr pp \n(.s
.nr sp \n(.s+1				\" +1-pt section headers
.\"-----------------
.nr bs 1v
.nr ps 0.3v
.nr ss 1v
.\"-----------------
.fo ''\\s+2%\\s0''			\" +2-pt page numbers in center footers
.\"-----------------
.nr $i .5i				\" main text indented
.nr so -\n($i				\" section headers un-indented
.\"------------------------------------
.rm xX					\" scratch register
.\"------------------------------------
.\"!Gexpand
.\"---------------------------------------------------------------------------
.(l C
.b
\s+3The \*(PP User Manual\s0
.sp 2
.i
Edited by Jon Rhein, Greg Kemnitz and The \*(PP Group
EECS Dept.
University of California, Berkeley
.r
.)l
.sp 3
.\"---------------------------------------------------------------------------
.sh 1 "OVERVIEW"
.lp
This document is the user manual for the \*(PP database
system under development at the University of California,
Berkeley.
This project, led by Professor Michael Stonebraker, is
sponsored by the Defense Advanced Research Projects Agency
(DARPA), the Army Research Office (ARO), the National Science
Foundation (NSF), and ESL, Inc.
.\"------------------------------------
.sh 2 "DISTRIBUTION"
.lp
This manual describes Version \*(PV of \*(PP.
The \*(PP Group has compiled and tested Version \*(PV on the following
platforms:
.TS
center tab(|);
c | c
l | l .
architecture|operating system
=
DECstation (MIPS)|ULTRIX V4.2
SPARC|SunOS 4.1.2
Sequent Symmetry (386)|DYNIX V3.0
.TE
.\"------------------------------------
.sh 2 "PERFORMANCE"
.lp
Version \*(PV has been tuned modestly.
On the
Wisconsin benchmark, one should expect performance about twice
that of the public domain, University of California version of
\*(II, a relational prototype from the late 1970's.
.\"------------------------------------
.sh 2 "ACKNOWLEDGEMENTS"
.lp
\*(PP has been constructed by a team of undergraduate,
graduate, and staff programmers.
The contributors (in
alphabetical order) consisted of James Bell, Jennifer Caetta, Jolly Chen,
Ron Choi, Jeffrey Goh, Joey Hellerstein, Wei Hong,
Anant Jhingran, Greg Kemnitz, Case Larsen, Jeff Meredith, Michael Olson,
Lay-Peng Ong, Spyros Potamianos, Sunita Sarawagi and Cimarron Taylor.
.lp
For version \*(PV Jeff Meredith served as chief programmer and was
responsible for overall coordination of the project and for individually
implementing the
.q "everything else"
portion of the system.
.lp
The above implementation team contributed significantly to
this manual, as did Claire Mosher, Chandra Ghosh, and Jim Frew.
.\"---------------------------------------------------------------------------
.sh 1 "INTRODUCTION"
.lp
Traditional relational DBMSs support a data model consisting
of a collection of named relations, each attribute of which has a
specific type.
In current commercial systems, possible types are
floating point numbers, integers, character strings, money, and
dates.
It is commonly recognized that this model is inadequate
for future data processing applications.
.lp
The relational model succeeded in
replacing previous models in part because of its simplicity.
The \*(PP data model offers substantial
additional power by incorporating the following four additional basic
constructs:
.(l
classes
inheritance
types
functions
.)l
The \*(PP DBMS has been under construction since 1986.
The initial concepts for the system were presented in [STON86]
and the initial data model appeared in [ROWE87].
The first rule
system that was implemented is discussed in [STON88] and the
storage manager concepts are detailed in [STON87].
The first
.q demo-ware
was operational in 1987, and we released Version 1 of
\*(PP to a few external users in June 1989.
A critique of
version 1 of \*(PP appears in [STON90].
Version 2 followed in
June 1990, and it included a new rule system documented in
[STON90B].
Version \*(PV, the current version of \*(PP,
is about 200,000 lines of code in the C programming language.
\*(PP is available free of charge, and is being used by approximately
200 sites around the world at this writing.
.\"---------------------------------------------------------------------------
.sh 1 "ORGANIZATION"
.lp
This manual discusses the \*(PQ query language, including extensions such
as user-defined types, operators, and both query language and programming
language functions.
Arrays of types and functions of an instance are
discussed, as well as the \*(PP rule system.
This manual concludes with
a discussion on adding an operator class to \*(PP for use in access methods.
.lp
This manual describes the major
concepts of the system
and attempts to provide an accessible path into using the system.
As such, it tries to give examples of the use of the major
constructs, so a beginning user does not need to delve
immediately into the Reference Manual.
.\"---------------------------------------------------------------------------
.sh 1 "WHAT YOU SHOULD READ"
.lp
This manual is primarily intended to provide a broad overview of the system,
as well as to illustrate how programmers would use functions to interact with
the \*(PP
.q backend.
The \*(PP Reference Manual discusses additional aspects
of
the system, and provides full syntactic descriptions of every \*(PP and \*(PQ
command in a format similar to that used in \*(UU
.q "man pages."
.lp
If you are new to \*(PP, you should probably read this manual first, followed
by the parts of the \*(PP Reference Manual necessary to build your application.
In particular, you should read the section on \*(LP if you intend to build
a client application around \*(PP, as this is not discussed at all in this
manual.
.\"---------------------------------------------------------------------------
.sh 1 "The \*(PQ Query Language"
.lp
\*(PQ is the query language used for interacting with \*(PP.
Here, we
give an overview of how to use \*(PQ to access data.
In other sections,
user extensions to \*(PQ will be discussed.
.\"------------------------------------
.sh 2 "Creating a database"
.lp
Once \*(PP has been installed at your site by following
the directions in the release notes, you can create a database named
.cW foo
using the following command:
.(C
% createdb foo
.)C
\*(PP allows you to create any number of databases at a
given site and you automatically become the database
administrator of the database just created.
Database names must
have an alphabetic first character and are limited to 16
characters in length.
.lp
Once you have constructed a database, there are four ways to
interact with it:
.ip \(bu
You can run the \*(PP terminal
monitor which allows you to interactively enter, edit, and
execute commands in the query language \*(PQ.
.ip \(bu
You can
interact with \*(PP from a C program by using the \*(LP
library of subroutine and call facilities.
This allows you to submit
\*(PQ commands from C and get answers and status messages back
to your program.
This interface is discussed further in the
\*(LP section of the Reference Manual.
.ip \(bu
You can
use the
.b "fast path"
facility,
which
allows you to directly execute functions stored in the database.
This facility is described in the Reference Manual under
.q "Fast Path."
.ip \(bu
\*(PP is accessible from the \*(OF programming
environment.
\*(OF is a graphical user interface (GUI) toolkit
that allows a user to build sophisticated DBMS-oriented
applications.
\*(OF is a separate research project described
in a collection of reports
[WANG88, SCHA90] and is not treated further in this manual.
.lp
The terminal monitor can be activated for
the
.cW foo
database by
typing the command\**:
.(f
\**You may first need to set the
.cW POSTGRESHOME
environment variable to the name of the \*(PP root directory at your site,
if it is not the default
.cW /usr/postgres .
If the \*(PP you wish to access is on a remote host, then you will also need to
set the
.cW PGHOST
environment variable to the name of the remote host.
.)f
.(C
% monitor foo
.)C
(the
.cW % '' ``
is your \*(UU shell prompt.)
You will be greeted by the following message:
.(C
Welcome to the C POSTGRES terminal monitor

Go
*
.)C
The
.cW Go
indicates the terminal monitor is listening to you and
that you can type \*(PQ commands into a workspace maintained
by the monitor.
The monitor indicates it is listening by typing
.cW *
as a prompt.
Printing the workspace can be performed by
typing:
.(C
* \\p
.)C
and it can be passed to \*(PP for execution by typing:
.(C
* \\g
.)C
If you make a typing mistake, you can invoke the
.cW vi
text editor
by typing:
.(C
* \\e
.)C
The workspace will be passed to the editor, and you have the full
power of
.cW vi
to make any necessary changes.
For more info on using
.cW vi ,
type
.(C
% man vi
.)C
Once you exit
.cW vi ,
your edited query will be in the monitor's query
buffer and you can submit it to \*(PP by using the
.cW \eg
command
described above.
.lp
To get out of the monitor and return to \*(UU, type
.(C
* \\q
.)C
and the monitor will respond:
.(C
I live to serve you.
%
.)C
For a complete collection of monitor commands, see the manual page
on
.cW monitor
in the \*(UU section of the Reference Manual.
.lp
If you are the database administrator for the database
.cW foo ,
you
can destroy it using the following \*(UU command:
.(C
% destroydb foo
.)C
Other DBA commands include
.cW createuser
and
.cW destroyuser ,
which are discussed further in the \*(UU section of the Reference Manual.
.\"------------------------------------
.sh 2 "Classes and the Query Language \*(PQ"
.\"-----------------
.sh 3 "Basic Capabilities"
.lp
The fundamental notion in \*(PP is that of a
.b class,
which is a named collection of instances of objects.
Each
instance has the same collection of named attributes, and each
attribute is of a specific type.
Furthermore, each instance has
an installation-wide unique (never-changing)
.b "object identifier"
or
.b oid .
.\"-----------------
.sh 3 "Creating a New Class"
.lp
(In order to try out the following \*(PQ examples, create the
.cW foo
database
as described in the previous section, and start the terminal
monitor.)
.lp
A user can create a new class by specifying the class name,
along with all attribute names and their types:
.(C
* create EMP (name = text, salary = int4,
              age = int4, dept = char16) \\g

* create DEPT (dname = char16, floor = int4,
               manager = text) \\g
.)C
The \*(PQ base types used above are
a variable-length array of printable characters
.cW text ), (
a 4-byte signed integer
.cW int4 ), (
and a fixed-length array of 16 characters
.cW char16 .)\** (
.(f
\**See
.q "Built-In Types"
in the Reference Manual.
.)f
Spaces, tabs and newlines may be used freely in \*(PQ queries.
.lp
So far, the
.cW create
command looks exactly like the create
statement in a traditional relational system.
However, we will presently see
that classes have properties that are extensions of the
relational model, so we use a different word to describe them.
.\"-----------------
.sh 3 "Populating a Class with Instances"
.ds xX \n($1.\n($2.\n($3
.lp
To populate a class with instances, one can use the
.cW append
command:
.(C
* append EMP (name = "Joe", salary = 1400,
              age = 40, dept = "shoe") \\g

* append EMP (name = "Sam", salary = 1200,
              age = 29, dept = "toy") \\g

* append EMP (name = "Bill", salary = 1600,
              age = 36, dept = "candy") \\g
.)C
This will add 3 instances to
.cW EMP ,
one for each
.cW append
command.
.\"-----------------
.sh 3 "Querying a Class"
.lp
The
.cW EMP
class can be queried with normal selection and
projection queries.
For example, to find the employees under 35 years of age,
one would type:
.(C
* retrieve (EMP.name) where EMP.age < 35 \\g
.)C
and the output would be:
.(T
.TS
allbox;
l.
name
Sam
.TE
.)T
Notice that parentheses are required around
the
.b "target list"
of returned attributes
(e.g.,
.cW EMP.name .)
.lp
\*(PQ allows you to return
computations in the target list as long as they are given a name
(e.g.,
.cW result ):
.(C
* retrieve (result = EMP.salary / EMP.age)
      where EMP.name = "Bill" \\g
.)C
.\"-----------------
.sh 3 "Redirecting retrieve queries"
.lp
Any retrieve query can be redirected to a
new class in the database, and arbitrary boolean operators
.cW and , (
.cW or ,
.cW not )
are allowed in the qualification of any query:
.(C
* retrieve into temp (EMP.name)
      where EMP.age < 35 and EMP.salary > 1000 \\g
.)C
.\"-----------------
.sh 3 "Joins"
.lp
To find the names of employees which are the same age, one
could write:
.(C
* retrieve (E1.name, E2.name)
      from E1 in EMP, E2 in EMP
      where E1.age = E2.age and E1.name != E2.name \\g
.)C
In this case both E1 and E2 are
.b surrogates
for an instance of the
class
.cW EMP ,
and both range over all instances of the class.
A \*(PQ
query can contain an arbitrary number of class names and
surrogates.\**
.(f
\**The semantics of such a join are that
the qualification is a truth expression defined
for the Cartesian product of the classes indicated in the query.
For those instances in the Cartesian product for which the
qualification is true, \*(PP must compute and return the
target list.
.)f
.\"-----------------
.sh 3 "Updates"
.lp
Updates are accomplished in \*(PQ using the
.cW replace
command:
.(C
* replace EMP (salary = E.salary)
      from E in EMP
      where EMP.name = "Joe" and E.name = "Sam" \\g
.)C
This command replaces the salary of Joe by that of Sam.
.\"-----------------
.sh 3 "Deletions"
.lp
Deletions are done using the
.cW delete
command:
.(C
* delete EMP where EMP.salary > 0 \\g
.)C
Since all employees have positive salaries, this command will
leave the
.cW EMP
class empty.
.\"-----------------
.sh 3 "Arrays"
.lp
\*(PP supports both fixed-length and variable-length
one-dimensional arrays.
To illustrate their use, we first create a class with an array type.
.(C
* create SAL_EMP (name = char[],
                  pay_by_quarter = int4[4]) \\g
.)C
The above query will create a class named
.cW SAL_EMP
with a variable-length array of
.cW text
strings
.cW name ), (
and an array of 4
.cW int4
integers
.cW pay_by_quarter ), (
which represents the employee's salary by quarter.
Now we do some
.cW append s;
note that when appending to a non-character array, we enclose the values
within braces and separate them by commas.
.(C
* append SAL_EMP (name = "bill",
      pay_by_quarter = "{10000, 10000, 10000, 10000}") \\g

* append SAL_EMP (name = "jack",
      pay_by_quarter = "{10000, 15000, 15000, 15000}") \\g

* append SAL_EMP (name = "joe",
      pay_by_quarter = "{20000, 25000, 25000, 25000}") \\g
.)C
\*(PP uses the FORTRAN numbering convention for arrays\(emthat is, \*(PP
arrays start with array[1] and end with array[n].
.lp
Now, we can run some
queries on
.cW SAL_EMP .
This query retrieves the names of the employees whose pay changed in the
second quarter:
.(C
* retrieve (SAL_EMP.name)
      where SAL_EMP.pay_by_quarter[1] !=
            SAL_EMP.pay_by_quarter[2] \\g
.)C
This query retrieves the third quarter pay of all employees:
.(C
* retrieve (SAL_EMP.pay_by_quarter[3]) \\g
.)C
This query deletes everyone from
.cW SAL_EMP
whose name begins with the letter
.q j.
.cW SAL_EMP
should now contain only the employee named
.q bill :
.(C
* delete SAL_EMP where SAL_EMP.name[1] = 'j' \\g
.)C
Let's make sure (note that the attribute
.cW all
may be used as a shorthand for all attributes of a class):
.(C
* retrieve (SAL_EMP.all) \\g
.TS
allbox tab(|);
l l.
name|pay_by_quarter
bill|{10000,10000,10000,10000}
.TE
.)C
\*(PP supports arrays of base and user-defined types, as well as
.q "arrays of arrays,"
as in the following example:
.(C
* create manager (name = char16, employees = text[]) \\g

* append manager (name = "mike",
                  employees = "{"wei", "greg", "jeff"}") \\g

* append manager (name = "alice",
                  employees = "{"bill", "joe"}") \\g

* append manager (name = "marge",
                  employees = "{"mike", "alice"}") \\g
.)C
This creates a class
.cW manager ,
and provides a list of employees.
.\"------------------------------------
.sh 2 "Advanced \*(PQ"
.lp
Now we have covered the basics of using \*(PQ to access your data.
In this section we will discuss those features of \*(PP which
distinguish it from other data managers, such as
inheritance
and
time travel.
In the next section we will cover how the user can extend
the query language via
query language functions
and
composite objects,
as well
as additional extensions to \*(PP using
user defined types,
operators,
and
programming language functions.
.\"-----------------
.sh 3 "Inheritance"
.lp
First, re-populate the
.cW EMP
class by repeating the
.cW append
commands in section \*(xX.
Then, create a second class
.cW STUD_EMP ,
and populate it as follows:
.(C
* create STUD_EMP (location = point) inherits (EMP) \\g

* append STUD_EMP (name = "Sunita", salary = 1300,
                   age = 41, dept = "electronics",
                   location = "(3, 5)") \\g
.)C
In this case, an instance of
.cW STUD_EMP
.b inherits
all data fields
.cW name , (
.cW salary ,
.cW age ,
and
.cW dept )
from its parent,
.cW EMP .
Furthermore, student employees have an extra field,
.cW location ,
that shows their address as a coordinate pair.
In
\*(PP, a class can inherit from zero or more other classes,\**
.(f
\**i.e.,
the inheritance hierarchy is a directed acyclic graph.
.)f
and a query can reference either all
instances of a class or all instances of a class plus all of its
descendants.
For example, the following query finds the
employees over 39:
.(C
* retrieve (E.name) from E in EMP where E.age > 39 \\g
.)C
On the other hand, to find the names of all
employees, including student employees, over age 40, the query is:
.(C
* retrieve (E.name) from E in EMP* where E.age > 39 \\g
.)C
which returns:
.(T
.TS
allbox;
l.
name
Joe
Sunita
.TE
.)T
Here the
.cW *
after
.cW EMP
indicates that the query should be run over
.cW EMP
and all classes below
.cW EMP
in the inheritance hierarchy.
.lp
Note that
.cW location
in
.cW STUD_EMP
is not a traditional
relational data type.
As we will see later, \*(PP can be
customized with an arbitrary number of user-defined data types.
.\"-----------------
.sh 3 "Time Travel"
.lp
\*(PP supports the notion of
.b "time travel" .
This
feature allows a user to run historical queries.
For example, to
find Sam's current salary, one would query:
.(C
* retrieve (E.salary) from E in EMP["now"]
      where E.name = "Sam" \\g
.)C
\*(PP will automatically find the version of Sam's record
valid at the correct time and get the appropriate salary.
.lp
One can also
give a time
.b range .
For example to see all the salaries that Sam has
ever earned, one would query:
.(C
* retrieve (E.salary)
      from E in EMP["Jan 1 00:00:00 1970 GMT", "now"]
      where E.name = "Sam" \\g
.)C
If you have executed all of the examples so far, then the above query returns:
.(T
.TS
allbox;
l.
salary
1200
1200
.TE
.)T
There are two salaries for Sam, since he was deleted from and then
re-appended to the
.cW EMP
class.
.lp
The default beginning of a time range is the origin of the system clock
(which just happens to be
.cW "Jan 1 00:00:00 1970 GMT" '' ``
on \*(UU systems),
and the default end is the current time;
thus, the above time range can be abbreviated as
.cW [,] .'' ``
.\"---------------------------------------------------------------------------
.sh 1 "User Extensions to \*(PQ"
.lp
Here, we will discuss user extensions to the \*(PQ query language,
query language functions, composite types, and user defined types, functions
and operators.
.\"------------------------------------
.sh 2 "User Defined \*(PQ Functions"
.lp
\*(PQ provides two types of functions:
.b "query language functions"
(functions written in \*(PQ)
and
.b "programming language functions"
(functions written in a separately-compiled programming language such as C.)
In this section we will cover \*(PQ functions; programming language
functions will be covered below with the discussion on user-defined types.
.lp
Any collection of commands in the \*(PQ
query language can be packaged together and defined as a
function, usually returning either a set of instances or a set of base types.
For example, the following function
.cW high_pay
returns all employees in class
.cW EMP
whose salaries exceed 50,000:
.(C
* define function high_pay
      (language = "postquel", returntype = setof EMP)
      as retrieve (EMP.all) where EMP.salary > 50000 \\g
.)C
\*(PQ functions can also have parameters.
The following function
.cW large_pay
allows the threshold salary to be specified as an argument:
.(C
* define function large_pay
      (language = "postquel", returntype = setof EMP)
      arg is (int4)
      as retrieve (EMP.all) where EMP.salary > $1 \\g
.)C
In addition to their obvious utility as
.q aliases
for commonly-used queries,
\*(PQ functions are useful for creating composite types, as described
below.
.\"------------------------------------
.sh 2 "Composite Types"
.lp
Since \*(PQ functions return instances or sets of instances,
they are the mechanism used to assign values to composite
types.
For example, consider extending the
.cW EMP
class with a
.cW manager
field.
That is, for each instance of
.cW EMP ,
we want to associate another
instance of
.cW EMP 
corresponding to the manager of the first instance.
Specifically, we will
define a \*(PQ function
.cW manager :
.(C
* define function manager
      (language = "postquel", returntype = EMP)
      arg is (EMP)
      as "retrieve (E.all) from E in EMP
              where E.name = DEPT.manager
              and DEPT.name = $1.dept" \\g
.)C
The function
.cW manager
takes an instance as its only argument, so \*(PQ allows referencing
into it with the use of the nested dot notation.
Whenever such a
function is defined over a class, a user can utilize the cascaded dot
notation to reference into (i.e. access the fields of) the objects
returned by the function.
.lp
The following query finds all the employees who work for
Joe:
.(C
* retrieve (EMP.name) where EMP.manager.name = "Joe" \\g
.)C
This is exactly equivalent to:
.(C
* retrieve (EMP.name)
      where name(manager(EMP)) = "Joe" \\g
.)C
Here, we have essentially added an attribute to the
.cW EMP
class which is of
type
.cW EMP ,
i.e. it has a value which is an instance of
the class
.cW EMP .
Since the value of
.cW manager
has a record-oriented structure, we call it a
.b "composite object" .
Consequently, the user can think of the function
.cW manager
as an attribute of
.cW EMP
and can reference it just like any other
attribute, with the following two exceptions.
First, one cannot do
direct
.cW append s\(emthat
is,
.(C
* append emp (emp.manager.name = "Smith") \\g
.)C
.b won't
work.
Non-projected
retrieves will also be rejected,
i.e.:
.(C
* retrieve (emp.manager) \\g
.)C
will result
in a warning from the \*(PQ language parser.
.lp
Note that 
.cW manager
is defined as returning a single instance of
.cW EMP.
We can also write a \*(PQ function that returns sets of
instances.
For example, consider the function
.(C
* define function children
      (language = "postquel", returntype = setof KIDS)
      arg is (EMP)
      as "retrieve (KIDS.all)
              where $1.name = KIDS.dad
              or $1.name = KIDS.mom"\\g
.)C
The
.cW children
function is defined as returning a set of instances, rather than a
single instance.
Given the query
.(C
* retrieve(emp.name, emp.children.name)
.)C
if the query in the body of the
.cW children
function returns many instances, the retrieve query will return all of
them, in a
.q flattened
form.
If the query in the body of
.cW manager
returns more than one instance,
the
.cW manager
function will return only one instance, arbitrarily chosen from the
set returned by the query in the function's body.
See the \*(PP
Reference Manual's entry on the 
.cW "define function"
command for further details and examples.

.\"---------------------------------------------------------------------------
.sh 1 "User Defined Types, Operators, and Programming Language Functions"
.lp
The central concept of extending \*(PP lies in \*(PP's ability to
.b "dynamically load"
a binary object file created by the user.
This allows \*(PP to call
arbitrary user functions which can be written in a standard programming
language.
These functions can then be used:
.ip \(bu
to convert between
.b internal
(binary) and
.b external
(character string) representations of
user-defined
types;
.ip \(bu
as operators; and
.ip \(bu
to
define ordering for indices on user-defined types.
.lp
\*(PP's concept of types includes
.b built-in
types and
.b user-defined
types.
Built-in types are those required by the system to bootstrap itself.
User-defined types are those created by the user in the manner described
below.
There is no intrinsic performance difference between using a system
type or user-defined type, other than the overhead due to the complexity of
the type itself.
.\"------------------------------------
.sh 2 "Internal storage of types"
.lp
Internally,
\*(PP regards a user-defined type as a
.q "blob of memory"
upon which
user-defined functions impose structure and meaning.
\*(PP will store and retrieve the data from disk and use user-defined
functions to input, process, and output the data.
.\"------------------------------------
.sh 2 "Functions needed for a user-defined type"
.lp
A completely defined user type requires the following user-defined functions:
.ip \(bu
.b input
and
.b output
functions for the type:
These functions determine how the type appears in strings
(for input by the user and output to the user) and how the type is organized
in memory.
These at least are necessary to define the type.
.ip \(bu
.b operator
functions for the type:
These functions define the meanings of
.q equal,
.q "less than,"
.q "greater than,"
etc., for your type.
.\"------------------------------------
.sh 2 "An Example User Defined Type"
.lp
In this discussion, we will be defining a
.cW circle
type, using functions written in the C programming language.
.\"-----------------
.sh 3 "Data structures for our type"
.lp
Before we do anything, we have to decide on what a circle looks
like, both in string format and internally in memory.
Circles
have a center and a radius, so a reasonable string representation of a circle
would be an ordered triple:
.(l
(center_x, center_y, radius)
.)l
where each element is a real number with arbitrary units,
e.g.:
.(C
(5.0, 10.3, 3)
.)C
This is what
the input to the circle input function looks like,
and what the output from the circle output function looks
like.
.lp
Now we have to come up with an internal representation for
a circle in memory.
The following
declarations are legal
and reasonable given the format we chose above:
.(C
typedef struct {
    double x, y;
} POINT;

typedef struct {
    POINT center;
    double r;
} CIRCLE;
.)C
Memory containing values of type
.cW CIRCLE
will be written to
disk and read from disk, so
.cW CIRCLE
must be both
.b complete
and
.b contiguous ;
that is, it cannot contain any pointers.
The alternate declaration
.(C
typedef struct {
    POINT *center
    double r;
} CIRCLE;
.)C
will
.b NOT
work,
because only the address stored in
.cW center
would be written to disk, not the
.cW POINT
structure that
.cW center
presumably points to.
\*(PP cannot detect this kind of coding error;
you must guard against it yourself.
.\"-----------------
.sh 3 "Defining the input and output functions for our type"
.lp
Suppose in defining our type
.q circle,
we have a C source file called
.cW circle.c ,
and a corresponding object code file
.cW /usr/postgres/tutorial/circle.o .
(All functions related to our
.cW circle
type have to be in the same
object file.)
For the sake of argument, suppose we our platform is a DECstation,
where sizeof(double) is 8 bytes (this will be important later).
.lp
We will create source file
.cW circle.c ,
containing C source code for the functions that support our
.cW CIRCLE
type.
.cW circle.c
contains
three functions:
.ip \(bu
.cW circle_in ,
which is the input function for circles.
It
takes a string as an argument and returns a pointer to a
.cW CIRCLE .
.ip \(bu
.cW circle_out ,
which is the output function for circles.
It is
takes a pointer to s
.cW CIRCLE
as input and returns a string.
.ip
The return value of
.cW circle_in
must be a legal argument to
.cW circle_out ,
and vice versa.
.ip \(bu
.cW eq_area_circle ,
which is the equality function for
circles.
For the purposes of this discussion, circles are equal
if their areas are equal.
.lp
The contents of
.cW circle.c
are:
.(C
#include <math.h>
#include <stdio.h>
#include <string.h>

#include "tmp/c.h"           /* (always)                 */
#include "utils/geo-decls.h" /* for POINT declaration    */
#include "utils/palloc.h"    /* for palloc() declaration */

typedef struct {
    POINT  center;
    double radius;
} CIRCLE;

#define LDELIM '('
#define RDELIM ')'
#define NARGS  3

CIRCLE *
circle_in(str)
    char   *str;
{
    char   *p, *coord[NARGS];
    int    i;
    CIRCLE *result;

    if (str == NULL) return(NULL);

    for (i = 0, p = str;
         *p && i < NARGS && *p != RDELIM;
         p++)
    {
        if (*p == ',' || (*p == LDELIM && !i))
            coord[i++] = p + 1;
    }

    if (i < NARGS - 1) return(NULL);

    result = (CIRCLE *) palloc(sizeof(CIRCLE));

    result->center.x = atof(coord[0]);
    result->center.y = atof(coord[1]);
    result->radius = atof(coord[2]);

    return(result);
}

char *
circle_out(circle)
    CIRCLE *circle;
{
    char   *result;

    if (circle == NULL) return(NULL);

    result = (char *) palloc(60);

    sprintf(result, "(%g, %g, %g)",
            circle->center.x, circle->center.y,
            circle->radius);

    return(result);
}

int
eq_area_circle(circle1, circle2)
    CIRCLE *circle1, *circle2;
{
    return(circle1->radius == circle2->radius);
}
.)C
.lp
Now that we have written these functions and compiled the source file,\**
.(f
\**You will need to supply an option like
.cW -I$POSTGRESHOME/src/lib/H
to your C compiler so it can find the \*(PP
.cW .h '' ``
files.
Also, various platform-specific compiler options may be required to support
\*(PP dynamic linking (for example, the DECstation ULTRIX compiler requires
the
.cW "-G0" '' ``
option.)
See
.q "define function"
in the Reference Manual for details.
.)f
we have to let \*(PP know that they exist.
First, we
run the following queries to define the input and
output functions.
These functions must be defined
.b before
we define the
type.
\*(PP will
notify you that return type circle is not defined yet, but this
is OK\**:
.(f
\**By default,
user-defined C functions use addresses instead of values for all but
.q small
(<= 4-byte) argument and return types,
so we can use the \*(PQ type
.cW char16
as a placeholder for the C type
.cW "char *" .
.)f
.(C
* define function circle_in
      (language = "c", returntype = circle)
      arg is (char16)
      as "/usr/postgres/tutorial/circle.o" \\g

* define function circle_out
      (language = "c", returntype = char16)
      arg is (circle)
      as "/usr/postgres/tutorial/circle.o" \\g
.)C
Note that the full pathname of the object code file must be specified,
so you would change
.cW /usr/postgres/tutorial
to whatever is appropriate for your installation.
.lp
Now we can define the
.cW circle
type:
.(C
* define type circle
      (internallength = 24,
       input = circle_in, output = circle_out) \\g
.)C
where
.cW internallength
is the size of the
.cW CIRCLE
structure
in bytes.
For circles, the type members are three
.cW double s,
which on most platforms are 8 bytes each, with no additional alignment
constraints.
However,
when defining your own types, you should
.b not
make assumptions about structure sizes,
but instead
write a test program
that does a
.(C
printf("size is %d\en", sizeof (MYTYPE));
.)C
on your type.
.lp
If
.cW internallength
is defined incorrectly, you will encounter strange errors which may crash
the data manager itself.
If this were to happen with our
.cW CIRCLE
type,
we would have to do a
.(C
* remove type circle \\g
.)C
and then redefine the
.cW circle
type correctly.
Note that we would
.b not
have to redefine our functions,
since their behavior would not have changed.
.\"-----------------
.sh 3 "Defining an operator for our type"
.lp
Now that we have finished defining the
.cW circle
type, we can
.cW create
classes with circles in them,
.cW append
records to them
with circles defined, and
.cW retrieve
the values of the entire list
of records.
But we can do nothing else until we have some circle
operators.
To do this, we make use of the concept of
.b "operator overloading" ,
and in this case we will set the \*(PP equality
operator
.cW = '' ``
to work for circles.
First we have to tell \*(PP
that our circle equality function exists:
.(C
* define function eq_area_circle
      (language = "c", returntype = bool)
      arg is (circle, circle)
      as "/usr/postgres/tutorial/circle.o" \\g
.)C
We will now bind this function to the
equality symbol with the following query:
.(C
* define operator =
      (arg1 = circle, arg2 = circle,
       procedure = eq_area_circle) \\g
.)C
.\"-----------------
.sh 3 "Using our type"
.lp
Let's create a class
.cW tutorial
that contains a
.cW circle
attribute,
and run some queries against it:
.(C
* create tutorial(a = circle) \\g

* append tutorial (a = "(1.0, 1.0, 10.0)"::circle) \\g

* append tutorial (a = "(2.0, 2.0, 5.0)"::circle) \\g

* append tutorial (a = "(0.0, 1.8, 10.0)"::circle) \\g

* retrieve (tutorial.all)
      where tutorial.a = "(0.0, 0.0, 10.0)"::circle \\g
.)C
which returns:
.(T
.TS
allbox;
l.
a
(1.0, 1.0, 10.0)
(0.0, 1.8, 10.0)
.TE
.)T
Recall that we defined circles as being equal if their areas were
equal.
.lp
Other operators (less than, greater than, etc.) can be defined in
a similar way.
Note that the
.cW = '' ``
symbol will still work for
other types\(emit has merely had a new type added to the list of
types it works on.
Any string of
.q "punctuation characters"
other than
brackets,
braces, or parentheses can be used in defining an operator.
.\"------------------------------------
.sh 2 "Additional info on creating a user-defined function"
.\"-----------------
.sh 3 "Use palloc and not malloc"
.lp
In order for \*(PP to correctly manage memory associated with processing your
type, you
must use the memory allocator
.cW palloc
and avoid standard \*(UU memory managers
such as
.cW malloc .
If you do not, \*(PP will chew up ever increasing amounts of
memory.
.cW palloc
has the same arguments as
.cW malloc ,
that is
.(C
char *palloc(size)
unsigned long size;
.)C
To free memory allocated with
.cW palloc ,
use
.cW pfree ,
which is analogous to
the \*(UU library function
.cW free :
.(C
void pfree(ptr)
char *ptr;
.)C
.\"-----------------
.sh 3 "Re-loading user functions"
.lp
In the process of creating a user-defined type, you may find it necessary to
re-load a function in the course of debugging.
This is
.b not
done automatically when you edit or re-compile the file, but
.b is
done if you quit and restart the data manager.
.lp
We would re-load our example functions by using the following command:
.(C
* load "/usr/postgres/tutorial/circle.o" \\g
.)C
.\"-----------------
.sh 3 "Writing a Function of an Instance"
.lp
We've already discussed user functions which take \*(PP base or user defined
types as arguments; in this section, we will discuss inheritable C functions
or methods.
.lp
C language methods are useful particularly when we want to make a function
.b inheritable ;
that is, to have the function process every instance in an inheritance
hierarchy of classes.
.lp
In using a function of an instance in qualifying an instance,
\*(PP defines the
.q "current instance"
to be the instance being qualified at the moment your function is
called.
The instance itself will be passed in your function's
parameter list as an opaque structure of type TUPLE, and you will use
\*(PP library routines to access the data in the object as described
below.\**
.(f
\**In \*(PP \*(PV,
.cW TUPLE
is defined as
.cW "void *" .
.)f
.cW 
.lp
Suppose we want to write a function to answer the query
.(C
* retrieve (EMP.all) where overpaid(EMP) \\g
.)C
In the query above, a reasonable
.cW overpaid
function might be:
.(C
bool
overpaid(t) 
TUPLE t;   /* the current instance */
{
    extern char *GetAttributeByName();
    short salary, seniority, performance;

    salary = (short) GetAttributeByName(t, "salary");
    seniority = (short) GetAttributeByName(t, "seniority");
    performance = (short) GetAttributeByName(t, "performance");

    return (salary > (seniority * performance));
}
.)C
.cW GetAttributeByName
is the \*(PP system function that returns
attributes out of the current instance.
It has two arguments: the argument of type TUPLE passed into the function,
and the name of the desired attribute.
.cW GetAttributeByName
will align data properly so you can cast its return value to
the desired type.
For example, if you have an attribute
.cW name
which is of the \*(PQ type
.cW char16 ,
the
.cW GetAttributeByName
call would look like:
.(C
char *str;
\&...
str = (char *) GetAttributeByName(t, "name")
.)C
.lp
To let \*(PP know about the
.cW overpaid
function,
do:
.(C
* define function overpaid
      (language = "c", returntype = bool)
      arg is (EMP)
      as "/usr/postgres/tutorial/overpaid.o" \\g
.)C
.lp
You can have additional complex, base or user-defined types as
arguments to the inheritable function.
Thus,
.(C
* retrieve (EMP.all)
      where overpaid2(EMP, DEPT, "bill", 8) \\g
.)C
could be written, and
.cW overpaid2
would be declared:
.(C
bool
overpaid2(emp, dept, name, number)
    TUPLE emp, dept;
    char *name;
    long number;
.)C
.\"------------------------------------
.sh 2 "Arrays of types"
.lp
As discussed above, \*(PP fully supports arrays of base types.
Additionally,
\*(PP supports arrays of user-defined types as well.
When you define a type,
\*(PP
.b automatically
provides support for arrays of that type.
.\"-----------------
.sh 3 "Arrays of user-defined types"
.lp
Using the
.q circle
example discussed above, we will create a class containing
an array of
circles:
.(C
* create circles (list = circle[]) \\g
.)C
and do some appends
.(C
* append circles (list = "{"(1.0, 1.0, 5.0)",
                         "(2.0, 2.0, 10.0)"}") \\g

* append circles (list = "{"(2.0, 3.0, 15.0)",
                         "(2.0, 2.0, 10.0)"}") \\g

* append circles (list = "{"(2.0, 3.0, 4.0)"}") \\g
.)C
We can now run queries like:
.(C
* retrieve (circles.list[1]) \\g
.)C
which returns the first element of each
.cW list :
.(T
.TS
allbox;
l.
list
(1, 1, 5)
(2, 3, 4)
.TE
.)T
and
.(C
* retrieve (circles.all)
      where circles.list[1] = "(0.0, 0.0, 4.0)" \\g
.)C
which returns:
.(T
.TS
allbox;
l.
list
{"(2, 3, 4)"}
.TE
.)T
Note the
.cW {} s,
indicating that an array has been retrieved, as opposed to a single element.
.\"-----------------
.sh 3 "Defining a new array type"
.lp
An array may be defined as an element of a class, as shown above, or it may
be defined as a type in and of itself.
This is useful for defining
.b "arrays of arrays" .
.lp
The special built-in functions
.cW array_in
and
.cW array_out
are used by \*(PP to input and output arrays of any existing type.
Here,
we define an array of integers:
.(C
* define type int_array
      (element = int4, internallength = variable,
       input = array_in, output = array_out) \\g
.)C
The
.cW element
parameter indicates that this is an array, and setting
.cW internallength
to
.cW variable
indicates that the array is a variable-length attribute.\**
.(f
\**Note
that any type using
.cW array_in
and
.cW array_out
.b must
be variable-length.
.)f
.lp
We can use our type defined above to create an array of integer arrays:
.(C
* define type int_arrays
      (element = int_array, internallength = variable,
       input = array_in, output = array_out) \\g

* create stuff (a = int_arrays) \\g

* append stuff (a = "{{1, 2, 3} , {4, 5}, {6, 7, 8}}") \\g

* append stuff (a = "{{88, 99, 3}}") \\g

* append stuff (a = "{{5, 4, 3} , {2, 2}}") \\g

* retrieve (stuff.a[1])
      where stuff.a[1][1] < stuff.a[1][2] \\g

* retrieve (stuff.a)
      where stuff.a[3][1] < stuff.a[1][2] \\g

* retrieve (s.all) from s in stuff
      where s.a[2][2] = stuff.a[1][1] \\g
.)C
We can also define operators for equality, less than, greater than, etc. which
operate on our new array type as necessary.
.\"-----------------
.sh 3 "Creating an array type from scratch"
.lp
There are many situations in which the above scheme for creating an array
type is inappropriate, particularly when it is necessary to define a
fixed-length array.
In this section, we will create an array of four longs called
.cW quarterly ,
and a variable-length array of longs called
.cW  stats .\**
.(f
We assume
.cW sizeof(long)
== 4.
.)f
.lp
The only special things we need to know when writing the input and output
functions for
.cW quarterly
is that \*(PP will pass a
.q simple
(i.e. fixed-length) array of
.cW long s
to the
output function and expect a simple array of
.cW long s
in return from the input
function.
A simple array suitable for
.cW quarterly
can be declared:
.(C
long quarterly[4];
.)C
For the variable-length array
.cW stats ,
the situation is a little more
complicated.
Because \*(PP will not know in advance how big the array is,
\*(PP will expect the length of the array (in bytes) to be encoded in the
first four bytes of the memory which contains the array.
The expected
structure is:
.(C
typedef struct {
    long length;
    unsigned char bytes[1]; /* Force contiguity */
} VAR_LEN_ATTR;
.)C
The input function for the
.cW stats
array will look something like:
.(C
VAR_LEN_ATTR *
stats_in(s)
    char s;
{
    VAR_LEN_ATTR *stats;
    long array_size, *arrayp, nbytes;

    /*
     * nbytes is the total number of bytes in stats,
     * INCLUDING the byte count at the beginning
     */
    nbytes = array_size * sizeof(long)  +  sizeof(long);

    stats = (VAR_LEN_ATTR *) palloc(nbytes);

    stats->length = nbytes;

    arrayp = &(stats->bytes[0]);

    /*
     * put code here that loads interesting stuff into
     * arrayp[0] .. arrayp[array_size]
     */

    return(stats);
}
.)C
The output function for
.cW stats
will get the same
.cW VAR_LEN_ATTR
structure.
.lp
Now,
assuming the functions are in
.cW /usr/postgres/tutorial/stats.c
and
.cW /usr/postgres/tutorial/quarterly.c ,
we
can define our two arrays.
First we will define the fixed-size array
.cW quarterly .\**
.(f
.cW internallength
== 16 follows from our assumption about
.cW sizeof(long) .
.)f
.(C
* define function quarterly_in
      (language = "c", returntype = quarterly)
      arg is (char16)
      as "/usr/postgres/tutorial/quarterly.o" \\g

* define function quarterly_out
      (language = "c", returntype = char16)
      arg is (quarterly)
      as "/usr/postgres/tutorial/quarterly.o" \\g

* define type quarterly
      (element = int4, internallength = 16,
       input = quarterly_in, output = quarterly_out) \\g
.)C
Now we define the
.cW stats
array:
.(C
* define function stats_in
      (language = "c", returntype = stats)
      arg is (char16)
      as "/usr/postgres/tutorial/stats.o" \\g

* define function stats_out
      (language = "c", returntype = char16)
      arg is (stats)
      as "/usr/postgres/tutorial/stats.o" \\g

* define type stats
      (element = int4, internallength = variable,
       input = stats_in, output = stats_out) \\g
.)C
Now we can run some queries:
.(C
* create test (a = quarterly, b = stats) \\g

* append test (a = "1 2 3 4"::quarterly,
               b = "5 6 7"::stats) \\g

* append test (a = "1 3 2 4"::quarterly,
               b = "6 4"::stats) \\g

* append test (a = "7 11 6 9"::quarterly,
               b = "1 2"::stats) \\g

* retrieve (test.all) where test.a[4] = test.b[2] \\g
.)C
which returns:
.(T
.TS
tab(|) allbox;
l l.
a|b
1324|64
.TE
.)T
.b NOTE
that when you use your own functions to input and output array types,
.b "your function"
will define how to parse the external (string) representation.
The braces
notation is only a
convention used by
.cW array_in
and
.cW array_out
and is
.b not
part of the formal \*(PQ definition.
.\"------------------------------------
.sh 2 "Large Object types"
.lp
The types discussed to this point are all
.b small
objects\(emthat is, they are
smaller than 8 Kbytes\**
.(f
\**8 * 1,024 == 8,192 bytes
.)f
in size.
If you require a larger type for something like
a document retrieval system or for storing bitmaps, you will need to use
the \*(PP
.b "large object"
interface.
The interface to large objects is quite similar to the
\*(UU file system interface.
The particulars are detailed in
Section 7 of the \*(PP Reference Manual, which you should have available to
consult as you read the following.
.\"-----------------
.sh 3 "Defining a large object"
.lp
Just like any other type, a large object type requires input and output
functions.
For the purposes of this discussion, we assume that two functions,
.cW large_in
and
.cW large_out
have been written using the large object interface, and that the compiled
functions
are in
.cW /usr/postgres/tutorial/large.o .
We also presume that we are using
the
.q "file as an ADT"
interface for large objects discussed in the Reference
Manual.
.lp
We define a large object which could be used for storing map data:
.(C
* define function large_in
      (language = "c", returntype = map)
      arg is (char16)
      as "/usr/postgres/tutorial/large.o" \\g

* define function large_out
      (language = "c", returntype = char16)
      arg is (map)
      as "/usr/postgres/tutorial/large.o" \\g

* define type map
      (internallength = variable,
       input = large_in, output = large_out) \\g
.)C
Note that
large objects are
.b always
variable-length.
.lp
Now we can use our
.cW map
object:
.(C
* create maps (name = text, a = map) \\g

* append maps (name = "earth",
               a = "/usr/postgres/maps/earth") \\g

* append maps (name = "moon",
               a = "/usr/postgres/maps/moon") \\g
.)C
Notice that the above queries are identical in syntax to those we have been
using
all along to define types and such; the fact that this type is a large object
is completely hidden in the large object interface and \*(PP storage manager.
.\"-----------------
.sh 3 "Writing functions and operators for large object types"
.lp
Like any other \*(PP type, you can define functions and operators for large
object types.
The only caveat is that, like any other functions which process
a large object, they
.b must
use the large object interface described in Section 7 of the \*(PP Reference
Manual.
Possible queries which involve functions on large objects could include
.(C
* retrieve (emp.name) where beard(emp.picture) = "red" \\g

* retrieve (mountain.name)
      where height(mountain.topomap) > 10000 \\g
.)C
Because all functionality is available
to large objects,
.b any
aspect of \*(PP is available for use with them, including index access
methods, if the appropriate operator classes have been defined.
Operator
classes for index access methods will be discussed later in this manual.
.\"---------------------------------------------------------------------------
.sh 1 "The \*(PP Rule System"
.lp
The discussion in this section is intended to provide an overview of the
\*(PP rule system and point the user at helpful references and examples.
\*(PP actually has two rule systems, the
.b instance-level
rule system and the
.b "query rewrite"
rule system.
.\"------------------------------------
.sh 2 "The Instance-level Rule System"
.lp
The instance-level rule system uses markers placed in each instance in a
class to
.q trigger
rules.
Examples of the instance-level rule system are
explained and illustrated in
.cW $POSTGRESHOME/demo ,
which is included with the
\*(PP distribution.
Additional discussion of the instance-level rule system
can be found in the Reference Manual under
.cW "define rule" .
The theoretical
foundations
of the \*(PP rule system can be found in [STON90].
.\"------------------------------------
.sh 2 "The Query Rewrite Rule System"
.lp
The query rewrite rule system modifies queries to take rules into
consideration, and then passes the modified query to the query optimizer for
execution.
It is very powerful, and can be used for many things such as
query language procedures, views, and versions.
Examples and discussion can
be found in the demo in
.cW $POSTGRESHOME/video ,
and further discussion is in the
Reference Manual under
.cW "define rule" .
The power of this rule system is
discussed in
[ONG90] and [STON90].
.\"------------------------------------
.sh 2 "When to use either?"
.lp
Since each rule system is architected quite differently, they work best in
different situations.
The query rewrite system is best when rules affect
most of the instances in a class, while the instance-level system is best when
a rule affects only a few instances.
.\"---------------------------------------------------------------------------
.sh 1 "Administering \*(PP"
.lp
In this section, we will discuss aspects of \*(PP of interest to those
making extensive use of \*(PP, or who are the database administrator for
a group of \*(PP users.
.\"------------------------------------
.sh 2 "User administration"
.lp
The
.cW createuser
and
.cW destroyuser
enable and disable access to \*(PP by specific users on the host system.
Please read the descriptions of these
commands in the Reference Manual for specifics on their use.
.\"------------------------------------
.sh 2 "Moving database directories out of $POSTGRESHOME/data/base"
.lp
By default,
all \*(PP databases are stored in separate subdirectories under
.cW $POSTGRESHOME/data/base/ .\**
.(f
\**Data for certain classes may stored elsewhere if
a non-standard storage manager was specified
when they were created.
.)f
To move a particular data base to an alternate directory (e.g., on a
filesystem with more free space),
do the following:
.ip \(bu
Create the database
(if it doesn't already exist)
using the
.b createdb
command.
In the following steps
we will assume the database is named
.cW foo .
.ip \(bu
Copy
the directory
.cW $POSTGRESHOME/data/base/foo
and it contents
to its ultimate destination.
It should still be owned by the
.cW postgres
user.
.ip \(bu
Remove the directory
.cW $POSTGRESHOME/data/base/foo .
.ip \(bu
Make a symbolic link in
.cW $POSTGRESHOME/data/base
to the new directory.
.\"------------------------------------
.sh 2 "Troubleshooting \*(PP"
.lp
Occasionally, \*(PP will fail with cryptic error messages that are due to
relatively simple problems.
The following are a list of \*(PP error
messages and the likely fix.
These messages are ones you would likely see
in the
monitor
program.
.(C
Message: semget: No space left on device

Explanation and Likely Fix:
.)C
Either the kernel has not been configured for System V shared memory, or some
other program is using it up.
On most machines, the \*(UU command
.cW ipcs
will
show shared memory and semaphore usage.
.lp
To delete all shared memory and
semaphores (may be necessary if a backend fails), run the
.cW ipcclean
command.
Note, however, that
.cW ipcclean
deletes
.b all
semaphores belonging
to the user running it, so the user should be certain that none of his/her
non-\*(PP
processes are using semaphores before running this command.
.(C
Message: Unable to get shared buffers

Explanation and Likely Fix:
.)C
This message means that a \*(PP backend was expecting shared memory to be
available and it was not.
Usually this is due to
.cW ipcclean
being run while a
.cW postmaster
was also running.
.(C
Message: Can't connect to the backend (...)

Explanation and Likely Fix:
.)C
This message means that you are running a \*(LP application but it could
not link up with a
.cW postmaster .
If you see this error message, you should
see if a
.cW postmaster
is truly running.
If one is running, the problem is
likely related to your network.
.\"---------------------------------------------------------------------------
.sh 1 "REFERENCES"
.\"------------------------------------
.xP [ONG90]
Ong, L. and Goh, J.,
``A Unified Framework for Version Modeling Using Production Rules in a Database
System,"
Electronics Research Laboratory,
University of California, Berkeley,
ERL Memo M90/33,
April 1990.
.\"------------------------------------
.xP [ROWE87]
Rowe, L. and Stonebraker, M.,
``The POSTGRES Data Model,''
Proc. 1987 VLDB Conference,
Brighton, England,
Sept. 1987.
.\"------------------------------------
.xP [SCHA90]
Shapiro, L.,
``Join Processing in Database Systems with Large Main Memories,''
ACM-TODS,
Sept. 1986.
.\"------------------------------------
.xP [STON86]
(missing)
.\"------------------------------------
.xP [STON87]
Stonebraker, M.,
``The POSTGRES Storage System,''
Proc. 1987 VLDB Conference,
Brighton, England,
Sept. 1987.
.\"------------------------------------
.xP [STON88]
(missing)
.\"------------------------------------
.xP [STON90]
Stonebraker, M. et. al.,
``On Rules, Procedures, Caching and Views in Database Systems,''
Proc. 1990 ACM-SIGMOD Conference on Management of Data,
Atlantic City, N.J.,
June 1990.
.\"------------------------------------
.xP [STON90B]
(missing)
.\"------------------------------------
.xP [WANG88]
(missing)
.\"---------------------------------------------------------------------------
.uh "APPENDIX: User defined types and indices"
.lp
In this section, we will discuss how to extend \*(PP to use a user-defined
type and associated functions with existing access methods.
This way, you
can define a BTREE or RTREE index on your own type.
To do this, we will
discuss how to define a new operator class in \*(PP
for use with an existing access method.
.lp
Our example will be to add a new operator class to the BTREE access method.
The new operator class will sort integers in ascending absolute value
order.
This tutorial will describe how to define the operator class.
If you work the example,
you will be able to define and use indices that sort integer
keys by absolute value.
.lp
There are several \*(PP system classes that are important in understanding how
the
access methods work.
These will be discussed, and then a sample procedure
for adding a new set of operators to an existing access method will be shown
as an example.
.lp
The
.cW pg_am
class contains one instance for every user defined access method.
Support for the HEAP access method is built into \*(PP,
but every other access method is described here.
The schema is
.TS
center tab(|);
lf(C)|l.
amname|name of the access method
_
amowner|object id of the owner's instance in pg_user
_
amkind|not used at present, but set to 'o' as a place holder
_
amstrategies|number of strategies for this access method (see below)
_
amsupport|number of support routines for this access method (see below)
_
am*|T{
procedure identifiers for interface
routines to the access method.
For
example,
.cW regproc
ids for opening, closing,
and getting instances from the access
method appear here.
T}
.TE
The object ID of the instance in
.cW pg_am
is used as a foreign key in lots of
other classes.
For BTREES, this object ID is 403.
You don't need to add
a new instance to this class; all you're interested in is the object ID of
the access method instance you want to extend:
.(C
* retrieve (pg_am.oid) where pg_am.amname = "btree" \\g
.TS
allbox;
l.
oid
403
.TE
.)C
The
.cW amstrategies
attribute exists to standardize comparisons across data
types.
For example, BTREES impose a strict ordering on keys, less to
greater.
Since \*(PP allows the user to define operators, \*(PP cannot
in general look at the name of an operator (eg,
.cW > ,
.cW < )
and tell what kind
of comparison it is.
In fact, some access methods (like rtrees) don't impose
a less-to-greater ordering, but some other ordering, like containment.
\*(PP needs some consistent way of taking a scan qualification, looking at
the operator, deciding if a usable index exists, and rewriting the query
qualification in order to improve access speeds.
This implies
that \*(PP needs to know, for example, that
.cW <=
and
.cW >
partition
a BTREE.
Strategies is the way that we do this.
.lp
Defining a new set of strategies is beyond the scope of this discussion, but
how the BTREE strategies work will be explained, since you'll need to know that
to add a new operator class.
In the
.cW pg_am
class, the
.cW amstrategies
attribute is the number of strategies defined for this access method.
For BTREES, this
number is 5.
These strategies correspond to
.TS
center tab(|);
l|l.
less than|1
_
less than or equal|2
_
equal|3
_
greater than or equal|4
_
greater than|5
.TE
The idea is that you'll add procedures corresponding to the comparisons
above to the
.cW pg_amop
relation (see below).
The access method code can use
these numbers, regardless of data type, to figure out how to partition the
BTREE, compute selectivity, and so on.
Don't worry about the details of adding
procedures yet; just understand that there's a set of these for
.cW int2 ,
.cW int4 ,
.cW oid ,
and every other data type on which a BTREE can operate.
.lp
Strategies are used by all of the \*(PP access methods.
Some access methods require other support routines in order to work.
For example,
the BTREE access method must be able to compare two keys and determine
whether one is greater than, equal to, or less than the other.
Similarly,
the RTREE access method must be able to compute intersections,
unions,
and sizes of rectangles.
These operations do not correspond to user qualifications in
\*(PQ queries;
they are administrative routines used by the access methods,
internally.
.lp
In order to manage diverse support routines consistently across
all \*(PP access methods,
.cW pg_am
includes a field called
.cW amsupport .
This field records the number of support routines used by
an access method.
For BTREES, this number is one\(emthe routine to take two keys and return
\(mi\^1,
0,
or
\(pl\^1,
depending on whether the first key is less than,
equal to,
or greater than the second.
.lp
The
.cW amstrategies
entry in
.cW pg_am
is just the number of strategies defined
for the access method in question.
The procedures for less than, less equal, and so on don't appear in
.cW pg_am .
Similarly,
.cW amsupport
is just the number of support routines required by the access method.
The actual routines are listed elsewhere.
.lp
The next class of interest is
.cW pg_opclass.
This class exists only to associate a name with an
.cW oid .
In
.cW pg_amop ,
every BTREE operator class has a set of procedures,
one through five, above.
Some existing opclasses are
.cW int2_ops ,
.cW int4_ops , and
.cW oid_ops .
You need to add an instance with your opclass name (for example,
.cW int4_abs_ops )
to
.cW pg_opclass .
The
.cW oid
of this instance is a foreign key in other classes.
.(C
* append pg_opclass (opcname = "int4_abs_ops") \\g

* retrieve (cl.oid, cl.opcname) from cl in pg_opclass
      where cl.opcname = "int4_abs_ops" \\g
.TS
tab(|) allbox;
l l.
oid|opcname
17314|int4_abs_ops
.TE
.)C
.b NOTE:
The
.cW oid
for your
.cW pg_opclass
instance
.b "may be different" !
You should
substitute your value for 17314
wherever it appears in this discussion.
.lp
So now we have an access method and an operator class.
We still need a set of operators;
the procedure for defining operators was discussed earlier in this manual.
For the
.cW int4_abs_ops
operator class on BTREES,
the operators we require are:
.(l
absolute value less-than
absolute value less-than-or-equal
absolute value equal
absolute value greater-than-or-equal
absolute value greater-than
.)l
Suppose the code that implements the functions defined is stored in the file
.cW /usr/postgres/tutorial/int4_abs.c .
The code is
.(C
/*
 * int4_abs.c -- absolute value comparison functions
 *               for int4 data
 */

#include "tmp/c.h"

#define ABS(a) a = ((a < 0) ? -a : a)

bool int4_abs_lt(a, b) int32 a, b;
     { ABS(a); ABS(b); return (a < b); }

bool int4_abs_le(a, b) int32 a, b;
     { ABS(a); ABS(b); return (a <= b); }

bool int4_abs_eq(a, b) int32 a, b;
     { ABS(a); ABS(b); return (a == b); }

bool int4_abs_ge(a, b) int32 a, b;
     { ABS(a); ABS(b); return (a >= b); }

bool int4_abs_gt(a, b) int32 a, b;
     { ABS(a); ABS(b); return (a > b); }
.)C
There are a couple of important things that are happening below.
First, note that operators for less, less equal, equal, greater equal,
and greater for
.cW int4
are being defined.
All of these operators are already defined
for
.cW int4
under the names
.cW < ,
.cW <= ,
.cW = ,
.cW >= ,
and
.cW > .
The new operators behave differently, of course.
In order to guarantee that \*(PP uses
these new operators rather than the old ones,
they need to be named differently from the old ones.
This is a key point:  you can overload operators in
\*(PP, but only if the operator isn't already defined for the argument
types.
.lp
That is, if you have
.cW <
defined for
.cW int4 , (
.cW int4 ),
you can't define it again.
\*(PP
.b doesn't
check this when you define your operator,
so be careful.
To avoid this problem,
odd names will be used for the operators.
If you get this wrong,
the access methods are likely to crash when you try to do scans.
.lp
The other important point is that all the functions return
.b boolean
values;
the access methods rely on this fact.
.(C
* define function int4_abs_lt
      (language = "c", returntype = bool)
      arg is (int4, int4)
      as "/usr/postgres/tutorial/int4_abs.o" \\g

* define function int4_abs_le
      (language = "c", returntype = bool)
      arg is (int4, int4)
      as "/usr/postgres/tutorial/int4_abs.o" \\g

* define function int4_abs_eq
      (language = "c", returntype = bool)
      arg is (int4, int4)
      as "/usr/postgres/tutorial/int4_abs.o" \\g

* define function int4_abs_ge
      (language = "c", returntype = bool)
      arg is (int4, int4)
      as "/usr/postgres/tutorial/int4_abs.o" \\g

* define function int4_abs_gt
      (language = "c", returntype = bool)
      arg is (int4, int4)
      as "/usr/postgres/tutorial/int4_abs.o" \\g
.)C
Now define the operators that use them.
As noted,
the operator names must be unique for two
.cW int4
operands.
You can do a query on
.cW pg_operator :
.(C
* retrieve (pg_operator.all) \\g
.)C
to see if your name is taken for the types you want.
The important things here are the procedure
(which are the C functions defined above)
and the restriction and join selectivity functions.
You should just use the ones used below\(emnote that there are different such
functions for the less-than,
equal,
and greater-than cases.
These
.b must
be supplied,
or the access method will die when it tries to use the operator.
You should copy the names for
.cW restrict
and
.cW join ,
but use the procedure names you defined in the last step.
.(C
* define operator <<&
      (arg1 = int4, arg2 = int4, procedure=int4_abs_lt,
       associativity = left, restrict = intltsel,
       join = intltjoinsel) \\g

* define operator <=&
      (arg1 = int4, arg2 = int4, procedure = int4_abs_le,
       associativity = left, restrict = intltsel,
       join = intltjoinsel) \\g

* define operator ==&
      (arg1 = int4, arg2 = int4, procedure = int4_abs_eq,
       associativity = left, restrict = eqsel,
       join = eqjoinsel) \\g

* define operator >=&
      (arg1 = int4, arg2 = int4, procedure = int4_abs_ge,
       associativity = left, restrict = intgtsel,
       join = intgtjoinsel) \\g

* define operator >>&
      (arg1 = int4, arg2 = int4, procedure = int4_abs_gt,
       associativity = left, restrict = intgtsel,
       join = intgtjoinsel) \\g
.)C
Notice that five operators corresponding to less, less equal, equal, greater,
and greater equal are defined.
.lp
We're just about finished. the last thing we
need to do is to update the
.cW pg_amop
relation.
To do this, we need the
following attributes:
.TS
center tab(|);
lf(C)|l.
amopid|T{
the
.cW oid
of the
.cW pg_am
instance for BTREE (== 400, see above)
T}
_
amopclaid|T{
the
.cW oid
of the
.cW pg_opclass
instance for
.cW int4_abs_ops
(== whatever you got instead
of 17314,
see above)
T}
_
amopopr|T{
the
.cW oid s
of the operators for the
opclass (which we'll get in just a
minute)
T}
_
T{
amopselect,
.br
amopnpages
T}|cost functions.
.TE
The cost functions are used by the query optimizer to decide whether
or not to use a given index in a scan.
Fortunately, these already
exist.
The two functions we'll use are
.cW btreesel,
which estimates the
selectivity of the btree, and
.cW btreenpage,
which estimates the number of
pages a search will touch in the tree.
.lp
So we need the
.cW oid s
of the operators we just defined.
We'll look up the
names of all the operators that take two
.cW int4 s,
and pick ours out:
.(C
* retrieve (o.oid, o.oprname)
      from o in pg_operator, t in pg_type
      where o.oprleft = t.oid and o.oprright = t.oid
          and t.typname = "int4" \\g
.)C
which returns:
.(T
.TS
tab(|) allbox;
l l.
oid|oprname
96|\\=
97|<
514|*
518|!=
521|>
523|<=
525|>=
528|/
530|%
551|+
555|-
17321|<<&
17322|<=&
17323|==*
17324|>=&
17325|>>&
.TE
.)T
(Note
that your
.cW oid
numbers may be different.)
The operators we are interested in are those with
.cW oid s
17321 through 17325.
The values you get will probably be different, and you should substitute
them for the values below.
We can look at the operator names and pick out the ones we just added.
(Of course, there are lots of other queries we could used to get the oids
we wanted.)
.lp
Now we're ready to update
.cW pg_amop
with our new operator class.
The most
important thing in this entire discussion is that the operators are
ordered, from less equal through greater equal, in
.cW pg_amop .
Recall that
the BTREE instance's
.cW oid
is 400
and
.cW int4_abs_ops
is
.cW oid
17314.
Then we
add the instances we need:
.(C
* append pg_amop
      (amopid = "400"::oid,          /* btree oid        */
       amopclaid = "17314"::oid,     /* pg_opclass tuple */
       amopopr = "17321"::oid,       /* <<& tup oid      */
       amopstrategy = "1"::int2,     /* 1 is <<&         */
       amopselect = "btreesel"::regproc,
       amopnpages = "btreenpage"::regproc) \\g

* append pg_amop (amopid = "400"::oid,
                  amopclaid = "17314"::oid,
                  amopopr = "17322"::oid,
                  amopstrategy = "2"::int2,
                  amopselect = "btreesel"::regproc,
                  amopnpages = "btreenpage"::regproc) \\g

* append pg_amop (amopid = "400"::oid,
                  amopclaid = "17314"::oid,
                  amopopr = "17323"::oid,
                  amopstrategy = "3"::int2,
                  amopselect = "btreesel"::regproc,
                  amopnpages = "btreenpage"::regproc) \\g

* append pg_amop (amopid = "400"::oid,
                  amopclaid = "17314"::oid,
                  amopopr = "17324"::oid,
                  amopstrategy = "4"::int2,
                  amopselect = "btreesel"::regproc,
                  amopnpages = "btreenpage"::regproc) \\g

* append pg_amop (amopid = "400"::oid,
                  amopclaid = "17314"::oid,
                  amopopr = "17325"::oid,
                  amopstrategy = "5"::int2,
                  amopselect = "btreesel"::regproc,
                  amopnpages = "btreenpage"::regproc) \\g
.)C
NOTE the order:
.q less
is 1,
.q "less equal"
is 2,
.q equal
is 3,
.q "greater equal"
is 4,
and
.q greater
is 5.
.lp
Okay, now it's time to test the new opclass.
First we'll create and
populate a class:
.(C
* create pairs (name = char16, number = int4) \\g

* append pairs (name = "mike", number = -10000) \\g

* append pairs (name = "greg", number = 3000) \\g

* append pairs (name = "lay peng", number = 5000) \\g

* append pairs (name = "jeff", number = -2000) \\g

* append pairs (name = "mao", number = 7000) \\g

* append pairs (name = "cimarron", number = -3000) \\g

* retrieve (pairs.all) \\g
.TS
tab(|) allbox;
l l.
name|number
mike|-10000
greg|3000
lay peng|5000
jeff|-2000
mao|7000
cimarron|-3000
.TE
.)C
Okay, looks pretty random.
Define an index using the new opclass:
.(C
* define index pairsind on pairs
      using btree (number int4_abs_ops) \\g
.)C
Now run a query that doesn't use one of our new operators.
What we're
trying to do here is to run a query that
.b won't
use our index, so that
we can tell the difference when we see a query that
.b does
use the index.
This query won't use the index because the operator we use in the qualification
isn't one that appears in the list of strategies for our index.
.(C
* retrieve (pairs.all) where pairs.number < 9000 \\g
.TS
tab(|) allbox;
l l.
name|number
mike|-10000
greg|3000
lay peng|5000
jeff|-2000
mao|7000
cimarron|-3000
.TE
.)C
Yup, just as random; that didn't use the index.
Okay, let's run a query
that
.b does
use the index:
.(C
* retrieve (pairs.all) where pairs.number <<& 9000 \\g
.TS
tab(|) allbox;
l l.
name|number
jeff|-2000
cimarron|-3000
greg|3000
lay peng|5000
mao|7000
.TE
.)C
Note that the
.cW number
values are in order of increasing absolute value
(as they should be, since the index was used for this scan) and that
we got the right answer\(emthe instance for
.cW mike
doesn't appear, because \(mi10000 >=& 9000.
