mirror of https://github.com/postgres/postgres
parent
878531f1ac
commit
c8cfb0cea8
@ -0,0 +1,120 @@ |
||||
# Postgres documentation makefile
|
||||
# Thomas Lockhart
|
||||
|
||||
PGDOCS= ..
|
||||
SRCDIR= ../../src
|
||||
|
||||
HPATH=$(PGDOCS)/doc
|
||||
PPATH=$(PGDOCS)/doc
|
||||
|
||||
#HSTYLE=/usr/lib/sgml/stylesheets/jade/docbook/html
|
||||
#PSTYLE=/usr/lib/sgml/stylesheets/jade/docbook/print
|
||||
|
||||
HSTYLE=/home/tgl/SGML/db107.d/docbook/html
|
||||
PSTYLE=/home/tgl/SGML/db107.d/docbook/print
|
||||
|
||||
HDSL=$(HSTYLE)/docbook.dsl
|
||||
PDSL=$(PSTYLE)/docbook.dsl
|
||||
|
||||
#DBOPTS=-V %no-split-output% -V %no-make-index%
|
||||
|
||||
TAR= tar
|
||||
TAREXCLUDE= --exclude=Makefile --exclude='*.sgml'
|
||||
|
||||
# Pick up Makefile.custom from the source area
|
||||
# This is the only resource from the code source area and is optional
|
||||
|
||||
ifneq ($(wildcard $(SRCDIR)/Makefile.custom), ) |
||||
include $(SRCDIR)/Makefile.custom |
||||
endif |
||||
|
||||
TARGETS= postgres tutorial user admin programmer
|
||||
|
||||
HTARGETS=#make this a mapping from targets
|
||||
PTARGETS=#make this a mapping from targets
|
||||
|
||||
.PRECIOUS: postgres.html postgres.tex postgres.dvi |
||||
.PHONY: sources clean |
||||
|
||||
install:: |
||||
$(MAKE) all
|
||||
(mv -rf *.gz ..)
|
||||
|
||||
all:: $(SGO) $(SGP) |
||||
|
||||
sources:: |
||||
($(TAR) zcf sources.tar.gz --exclude='*.htm*' --exclude='*.gz' .)
|
||||
|
||||
user.tar.gz: |
||||
$(MAKE) -C sgml clean
|
||||
$(MAKE) -C sgml user.html
|
||||
($(TAR) zcf $@ $(TAREXCLUDE) -C sgml .)
|
||||
|
||||
tutorial.tar.gz: |
||||
$(MAKE) -C sgml clean
|
||||
$(MAKE) -C sgml tutorial.html
|
||||
($(TAR) zcf $@ $(TAREXCLUDE) -C sgml . -C .. -C graphics clientserver.gif)
|
||||
|
||||
clean:: |
||||
(rm -rf *.html *.htm)
|
||||
|
||||
distclean:: |
||||
$(MAKE) -C sgml clean
|
||||
|
||||
# Generic production rules
|
||||
|
||||
# Compressed file
|
||||
|
||||
%.gz: % |
||||
(gzip -f $<)
|
||||
|
||||
# TAR file for HTML package
|
||||
|
||||
%.tar: %.html # %.ps
|
||||
(tar cf $@ $*.html index.html *.htm *.gif) # $*.ps
|
||||
(rm -rf index.html *.htm)
|
||||
|
||||
# (mkdir $*)
|
||||
# (rm -rf $*/*)
|
||||
# (mv *.htm $*/)
|
||||
# (cd $*/; ln -sf book01.htm index.html)
|
||||
# (tar cf $@ $*)
|
||||
|
||||
# HTML
|
||||
# Include some softlinks to the generic default file names
|
||||
|
||||
%.html: %.sgml $(HDSL) |
||||
(rm -rf *.htm)
|
||||
jade $(DBOPTS) -D sgml -d $(HDSL) -t sgml $<
|
||||
(ln -sf book01.htm index.html)
|
||||
(ln -sf book01.htm $*.html)
|
||||
|
||||
# (mkdir $(HPATH)/$*) # be sure there is somewhere to put them
|
||||
# (rm -rf $(HPATH)/$*/*) # remove existing files since some names may be obsolete
|
||||
# (mv *.htm $(HPATH)/$*/) # and copy 'em over
|
||||
# (cd $(HPATH)/$*/; ln -sf book01.htm index.html)
|
||||
|
||||
# RTF to allow minor editing for hardcopy
|
||||
# This is used for v6.3 docs
|
||||
|
||||
%.rtf: %.sgml $(PDSL) |
||||
jade $(DBOPTS) -d $(PDSL) -t rtf $<
|
||||
|
||||
# TeX and DVI
|
||||
|
||||
%.tex: %.sgml $(PDSL) |
||||
jade $(DBOPTS) -d $(PDSL) -t tex $<
|
||||
|
||||
%.dvi: %.tex |
||||
jadetex $<
|
||||
jadetex $<
|
||||
|
||||
# Postscript from TeX
|
||||
|
||||
%.ps: %.dvi |
||||
dvips -o $@ $<
|
||||
|
||||
# Graphics
|
||||
|
||||
%.gif: |
||||
cp -p graphics/%.gif .
|
||||
@ -0,0 +1,103 @@ |
||||
<!-- admin.sgml |
||||
- |
||||
- Postgres administrator's guide. |
||||
- Derived from postgres.sgml. |
||||
- thomas 1998-02-27 |
||||
- |
||||
- --> |
||||
<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [ |
||||
<!entity intro SYSTEM "intro.sgml"> |
||||
|
||||
<!entity install SYSTEM "install.sgml"> |
||||
<!entity ports SYSTEM "ports.sgml"> |
||||
<!entity recovery SYSTEM "recovery.sgml"> |
||||
<!entity regress SYSTEM "regress.sgml"> |
||||
<!entity release SYSTEM "release.sgml"> |
||||
<!entity start-ag SYSTEM "start-ag.sgml"> |
||||
|
||||
<!entity biblio SYSTEM "biblio.sgml"> |
||||
]> |
||||
<!-- entity manpages SYSTEM "man/manpages.sgml" subdoc --> |
||||
<Book> |
||||
|
||||
<!-- Title information --> |
||||
|
||||
<Title>PostgreSQL Administrator's Guide</Title> |
||||
<BookInfo> |
||||
<ReleaseInfo>Covering v6.3 for general release</ReleaseInfo> |
||||
<BookBiblio> |
||||
<AuthorGroup> |
||||
<CorpAuthor>The PostgreSQL Development Team</CorpAuthor> |
||||
</AuthorGroup> |
||||
<!-- editor in authorgroup is not supported |
||||
<AuthorGroup> |
||||
--> |
||||
<Editor> |
||||
<FirstName>Thomas</FirstName> |
||||
<SurName>Lockhart</SurName> |
||||
<Affiliation> |
||||
<OrgName>Caltech/JPL</OrgName> |
||||
</Affiliation> |
||||
</Editor> |
||||
<!-- |
||||
</AuthorGroup> |
||||
--> |
||||
|
||||
<!-- |
||||
<AuthorInitials>TGL</AuthorInitials> |
||||
--> |
||||
|
||||
<Date>(last updated 1998-02-23)</Date> |
||||
</BookBiblio> |
||||
|
||||
<LegalNotice> |
||||
<Para> |
||||
<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group. |
||||
</Para> |
||||
</LegalNotice> |
||||
|
||||
</BookInfo> |
||||
|
||||
<!-- |
||||
<TOC> </TOC> |
||||
<LOT> </LOT> |
||||
--> |
||||
|
||||
<!-- |
||||
<Dedication> |
||||
<Para> |
||||
Your name here... |
||||
</Para> |
||||
</Dedication> |
||||
--> |
||||
|
||||
<Preface> |
||||
<Title>Summary</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName>, |
||||
developed originally in the UC Berkeley Computer Science Department, |
||||
pioneered many of the object-relational concepts |
||||
now becoming available in some commercial databases. |
||||
It provides SQL92/SQL3 language support, |
||||
transaction integrity, and type extensibility. |
||||
<ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant |
||||
of this original Berkeley code. |
||||
</Para> |
||||
</Preface> |
||||
|
||||
&intro; |
||||
|
||||
&ports; |
||||
&install; |
||||
&start-ag; |
||||
&recovery; |
||||
®ress; |
||||
&release; |
||||
|
||||
&biblio; |
||||
|
||||
<INDEX> </INDEX> |
||||
|
||||
</Book> |
||||
|
||||
@ -0,0 +1,304 @@ |
||||
<Chapter> |
||||
<Title>Advanced <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> Features</Title> |
||||
|
||||
<Para> |
||||
Having covered the basics of using <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> to |
||||
access your data, we will now discuss those features of |
||||
<ProductName>Postgres</ProductName> that distinguish it from conventional data |
||||
managers. These features include inheritance, time |
||||
travel and non-atomic data values (array- and |
||||
set-valued attributes). |
||||
Examples in this section can also be found in |
||||
<FileName>advance.sql</FileName> in the tutorial directory. |
||||
(Refer to <XRef LinkEnd="QUERY"> for how to use it.) |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Inheritance</Title> |
||||
|
||||
<Para> |
||||
Let's create two classes. The capitals class contains |
||||
state capitals which are also cities. Naturally, the |
||||
capitals class should inherit from cities. |
||||
|
||||
<ProgramListing> |
||||
CREATE TABLE cities ( |
||||
name text, |
||||
population float, |
||||
altitude int -- (in ft) |
||||
); |
||||
|
||||
CREATE TABLE capitals ( |
||||
state char2 |
||||
) INHERITS (cities); |
||||
</ProgramListing> |
||||
|
||||
In this case, an instance of capitals <FirstTerm>inherits</FirstTerm> all |
||||
attributes (name, population, and altitude) from its |
||||
parent, cities. The type of the attribute name is |
||||
<Type>text</Type>, a native <ProductName>Postgres</ProductName> type for variable length |
||||
ASCII strings. The type of the attribute population is |
||||
<Type>float</Type>, a native <ProductName>Postgres</ProductName> type for double precision |
||||
floating point numbers. State capitals have an extra |
||||
attribute, state, that shows their state. In <ProductName>Postgres</ProductName>, |
||||
a class can inherit from zero or more other classes, |
||||
and a query can reference either all instances of a |
||||
class or all instances of a class plus all of its |
||||
descendants. |
||||
<Note> |
||||
<Para> |
||||
The inheritance hierarchy is a directed acyclic graph. |
||||
</Para> |
||||
</Note> |
||||
For example, the following query finds |
||||
all the cities that are situated at an attitude of 500ft or higher: |
||||
|
||||
<ProgramListing> |
||||
SELECT name, altitude |
||||
FROM cities |
||||
WHERE altitude > 500; |
||||
|
||||
+----------+----------+ |
||||
|name | altitude | |
||||
+----------+----------+ |
||||
|Las Vegas | 2174 | |
||||
+----------+----------+ |
||||
|Mariposa | 1953 | |
||||
+----------+----------+ |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
On the other hand, to find the names of all cities, |
||||
including state capitals, that are located at an altitude |
||||
over 500ft, the query is: |
||||
|
||||
<ProgramListing> |
||||
SELECT c.name, c.altitude |
||||
FROM cities* c |
||||
WHERE c.altitude > 500; |
||||
</ProgramListing> |
||||
|
||||
which returns: |
||||
|
||||
<ProgramListing> |
||||
+----------+----------+ |
||||
|name | altitude | |
||||
+----------+----------+ |
||||
|Las Vegas | 2174 | |
||||
+----------+----------+ |
||||
|Mariposa | 1953 | |
||||
+----------+----------+ |
||||
|Madison | 845 | |
||||
+----------+----------+ |
||||
</ProgramListing> |
||||
|
||||
Here the <Quote>*</Quote> after cities indicates that the query should |
||||
be run over cities and all classes below cities in the |
||||
inheritance hierarchy. Many of the commands that we |
||||
have already discussed (<Command>select</Command>, <Command>update</Command> and <Command>delete</Command>) |
||||
support this <Quote>*</Quote> notation, as do others, like <Command>alter</Command>. |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Non-Atomic Values</Title> |
||||
|
||||
<Para> |
||||
One of the tenets of the relational model is that the |
||||
attributes of a relation are atomic. <ProductName>Postgres</ProductName> does not |
||||
have this restriction; attributes can themselves contain |
||||
sub-values that can be accessed from the query |
||||
language. For example, you can create attributes that |
||||
are arrays of base types. |
||||
|
||||
<Sect2> |
||||
<Title>Arrays</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> allows attributes of an instance to be defined |
||||
as fixed-length or variable-length multi-dimensional |
||||
arrays. Arrays of any base type or user-defined type |
||||
can be created. To illustrate their use, we first create a |
||||
class with arrays of base types. |
||||
|
||||
<ProgramListing> |
||||
CREATE TABLE SAL_EMP ( |
||||
name text, |
||||
pay_by_quarter int4[], |
||||
schedule char16[][] |
||||
); |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The above query will create a class named SAL_EMP with |
||||
a <FirstTerm>text</FirstTerm> string (name), a one-dimensional array of <FirstTerm>int4</FirstTerm> |
||||
(pay_by_quarter), which represents the employee's |
||||
salary by quarter and a two-dimensional array of <FirstTerm>char16</FirstTerm> |
||||
(schedule), which represents the employee's weekly |
||||
schedule. Now we do some <FirstTerm>INSERTS</FirstTerm>s; note that when |
||||
appending to an array, we enclose the values within |
||||
braces and separate them by commas. If you know <FirstTerm>C</FirstTerm>, |
||||
this is not unlike the syntax for initializing structures. |
||||
|
||||
<ProgramListing> |
||||
INSERT INTO SAL_EMP |
||||
VALUES ('Bill', |
||||
'{10000, 10000, 10000, 10000}', |
||||
'{{"meeting", "lunch"}, {}}'); |
||||
|
||||
INSERT INTO SAL_EMP |
||||
VALUES ('Carol', |
||||
'{20000, 25000, 25000, 25000}', |
||||
'{{"talk", "consult"}, {"meeting"}}'); |
||||
</ProgramListing> |
||||
|
||||
By default, <ProductName>Postgres</ProductName> uses the "one-based" numbering |
||||
convention for arrays -- that is, an array of n elements starts with array[1] and ends with array[n]. |
||||
Now, we can run some queries on SAL_EMP. First, we |
||||
show how to access a single element of an array at a |
||||
time. This query retrieves the names of the employees |
||||
whose pay changed in the second quarter: |
||||
|
||||
<ProgramListing> |
||||
SELECT name |
||||
FROM SAL_EMP |
||||
WHERE SAL_EMP.pay_by_quarter[1] <> |
||||
SAL_EMP.pay_by_quarter[2]; |
||||
|
||||
+------+ |
||||
|name | |
||||
+------+ |
||||
|Carol | |
||||
+------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
This query retrieves the third quarter pay of all |
||||
employees: |
||||
|
||||
<ProgramListing> |
||||
SELECT SAL_EMP.pay_by_quarter[3] FROM SAL_EMP; |
||||
|
||||
|
||||
+---------------+ |
||||
|pay_by_quarter | |
||||
+---------------+ |
||||
|10000 | |
||||
+---------------+ |
||||
|25000 | |
||||
+---------------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
We can also access arbitrary slices of an array, or |
||||
subarrays. This query retrieves the first item on |
||||
Bill's schedule for the first two days of the week. |
||||
|
||||
<ProgramListing> |
||||
SELECT SAL_EMP.schedule[1:2][1:1] |
||||
FROM SAL_EMP |
||||
WHERE SAL_EMP.name = 'Bill'; |
||||
|
||||
+-------------------+ |
||||
|schedule | |
||||
+-------------------+ |
||||
|{{"meeting"},{""}} | |
||||
+-------------------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Time Travel</Title> |
||||
|
||||
<Para> |
||||
As of <ProductName>Postgres</ProductName> v6.2, <Emphasis>time travel is no longer supported</Emphasis>. There are |
||||
several reasons for this: performance impact, storage size, and a pg_time file which grows |
||||
toward infinite size in a short period of time. |
||||
</Para> |
||||
|
||||
<Para> |
||||
New features such as triggers allow one to mimic the behavior of time travel when desired, without |
||||
incurring the overhead when it is not needed (for most users, this is most of the time). |
||||
See examples in the <FileName>contrib</FileName> directory for more information. |
||||
</Para> |
||||
|
||||
<Note> |
||||
<Title>Time travel is deprecated</Title> |
||||
<Para> |
||||
The remaining text in this section is retained only until it can be rewritten in the context |
||||
of new techniques to accomplish the same purpose. Volunteers? - thomas 1998-01-12 |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> supports the notion of time travel. This feature |
||||
allows a user to run historical queries. For |
||||
example, to find the current population of Mariposa |
||||
city, one would query: |
||||
|
||||
<ProgramListing> |
||||
SELECT * FROM cities WHERE name = 'Mariposa'; |
||||
|
||||
+---------+------------+----------+ |
||||
|name | population | altitude | |
||||
+---------+------------+----------+ |
||||
|Mariposa | 1320 | 1953 | |
||||
+---------+------------+----------+ |
||||
</ProgramListing> |
||||
|
||||
<ProductName>Postgres</ProductName> will automatically find the version of Mariposa's |
||||
record valid at the current time. |
||||
One can also give a time range. For example to see the |
||||
past and present populations of Mariposa, one would |
||||
query: |
||||
|
||||
<ProgramListing> |
||||
SELECT name, population |
||||
FROM cities['epoch', 'now'] |
||||
WHERE name = 'Mariposa'; |
||||
</ProgramListing> |
||||
|
||||
where "epoch" indicates the beginning of the system |
||||
clock. |
||||
<Note> |
||||
<Para> |
||||
On UNIX systems, this is always midnight, January 1, 1970 GMT. |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
|
||||
If you have executed all of the examples so |
||||
far, then the above query returns: |
||||
|
||||
<ProgramListing> |
||||
+---------+------------+ |
||||
|name | population | |
||||
+---------+------------+ |
||||
|Mariposa | 1200 | |
||||
+---------+------------+ |
||||
|Mariposa | 1320 | |
||||
+---------+------------+ |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
The default beginning of a time range is the earliest |
||||
time representable by the system and the default end is |
||||
the current time; thus, the above time range can be |
||||
abbreviated as ``[,].'' |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>More Advanced Features</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> has many features not touched upon in this |
||||
tutorial introduction, which has been oriented toward newer users of <Acronym>SQL</Acronym>. |
||||
These are discussed in more detail in both the User's and Programmer's Guides. |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,80 @@ |
||||
<Chapter> |
||||
<TITLE>Architecture</TITLE> |
||||
|
||||
<Sect1> |
||||
<Title><ProductName>Postgres</ProductName> Architectural Concepts</Title> |
||||
|
||||
<Para> |
||||
Before we continue, you should understand the basic |
||||
<ProductName>Postgres</ProductName> system architecture. Understanding how the |
||||
parts of <ProductName>Postgres</ProductName> interact will make the next chapter |
||||
somewhat clearer. |
||||
In database jargon, <ProductName>Postgres</ProductName> uses a simple "process |
||||
per-user" client/server model. A <ProductName>Postgres</ProductName> session |
||||
consists of the following cooperating UNIX processes (programs): |
||||
|
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
A supervisory daemon process (<Application>postmaster</Application>), |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
the user's frontend application (e.g., the <Application>psql</Application> program), and |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
the one or more backend database servers (the <Application>postgres</Application> process itself). |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
<Para> |
||||
A single <Application>postmaster</Application> manages a given collection of |
||||
databases on a single host. Such a collection of |
||||
databases is called an installation or site. Frontend |
||||
applications that wish to access a given database |
||||
within an installation make calls to the library. |
||||
The library sends user requests over the network to the |
||||
<Application>postmaster</Application> (<XRef LinkEnd="ARCHDEV-CONNECTIONS" EndTerm="ARCHDEV-CONNECTIONS">(a)), which in turn starts a new |
||||
backend server process (<XRef LinkEnd="ARCHDEV-CONNECTIONS" EndTerm="ARCHDEV-CONNECTIONS">(b)) |
||||
|
||||
<Figure id="ARCHDEV-CONNECTIONS"> |
||||
<Title>How a connection is established</Title> |
||||
<Graphic Align="center" FileRef="connections.gif" Format="GIF"></Graphic> |
||||
</Figure> |
||||
|
||||
and connects the |
||||
frontend process to the new server (<XRef LinkEnd="ARCHDEV-CONNECTIONS" EndTerm="ARCHDEV-CONNECTIONS">(c)). From |
||||
that point on, the frontend process and the backend |
||||
server communicate without intervention by the |
||||
<Application>postmaster</Application>. Hence, the <Application>postmaster</Application> is always running, waiting |
||||
for requests, whereas frontend and backend processes |
||||
come and go. The <FileName>libpq</FileName> library allows a single |
||||
frontend to make multiple connections to backend processes. |
||||
However, the frontend application is still a |
||||
single-threaded process. Multithreaded frontend/backend |
||||
connections are not currently supported in <FileName>libpq</FileName>. |
||||
One implication of this architecture is that the |
||||
<Application>postmaster</Application> and the backend always run on the same |
||||
machine (the database server), while the frontend |
||||
application may run anywhere. You should keep this |
||||
in mind, |
||||
because the files that can be accessed on a client |
||||
machine may not be accessible (or may only be accessed |
||||
using a different filename) on the database server |
||||
machine. |
||||
You should also be aware that the <Application>postmaster</Application> and |
||||
postgres servers run with the user-id of the <ProductName>Postgres</ProductName> |
||||
"superuser." Note that the <ProductName>Postgres</ProductName> superuser does not |
||||
have to be a special user (e.g., a user named |
||||
"postgres"). Furthermore, the <ProductName>Postgres</ProductName> superuser |
||||
should |
||||
definitely not be the UNIX superuser, "root"! In any |
||||
case, all files relating to a database should belong to |
||||
this <ProductName>Postgres</ProductName> superuser. |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,83 @@ |
||||
<Chapter> |
||||
<TITLE>Architecture</TITLE> |
||||
|
||||
<Sect1> |
||||
<Title><ProductName>Postgres</ProductName> Architectural Concepts</Title> |
||||
|
||||
<Para> |
||||
Before we continue, you should understand the basic |
||||
<ProductName>Postgres</ProductName> system architecture. Understanding how the |
||||
parts of <ProductName>Postgres</ProductName> interact will make the next chapter |
||||
somewhat clearer. |
||||
In database jargon, <ProductName>Postgres</ProductName> uses a simple "process |
||||
per-user" client/server model. A <ProductName>Postgres</ProductName> session |
||||
consists of the following cooperating UNIX processes (programs): |
||||
|
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
A supervisory daemon process (<Application>postmaster</Application>), |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
the user's frontend application (e.g., the <Application>psql</Application> program), and |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
the one or more backend database servers (the <Application>postgres</Application> process itself). |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
<Para> |
||||
A single <Application>postmaster</Application> manages a given collection of |
||||
databases on a single host. Such a collection of |
||||
databases is called an installation or site. Frontend |
||||
applications that wish to access a given database |
||||
within an installation make calls to the library. |
||||
The library sends user requests over the network to the |
||||
<Application>postmaster</Application> |
||||
(<XRef LinkEnd="PGARCH-CONNECTIONS" EndTerm="PGARCH-CONNECTIONS">(a)), |
||||
which in turn starts a new backend server process |
||||
(<XRef LinkEnd="PGARCH-CONNECTIONS" EndTerm="PGARCH-CONNECTIONS">(b)) |
||||
|
||||
<Figure Id="PGARCH-CONNECTIONS"> |
||||
<Title>How a connection is established</Title> |
||||
<Graphic Align="center" FileRef="connections.gif" Format="GIF"></Graphic> |
||||
</Figure> |
||||
|
||||
and connects the frontend process to the new server |
||||
(<XRef LinkEnd="PGARCH-CONNECTIONS" EndTerm="PGARCH-CONNECTIONS">(c)). |
||||
From that point on, the frontend process and the backend |
||||
server communicate without intervention by the |
||||
<Application>postmaster</Application>. Hence, the <Application>postmaster</Application> is always running, waiting |
||||
for requests, whereas frontend and backend processes |
||||
come and go. The <FileName>libpq</FileName> library allows a single |
||||
frontend to make multiple connections to backend processes. |
||||
However, the frontend application is still a |
||||
single-threaded process. Multithreaded frontend/backend |
||||
connections are not currently supported in <FileName>libpq</FileName>. |
||||
One implication of this architecture is that the |
||||
<Application>postmaster</Application> and the backend always run on the same |
||||
machine (the database server), while the frontend |
||||
application may run anywhere. You should keep this |
||||
in mind, |
||||
because the files that can be accessed on a client |
||||
machine may not be accessible (or may only be accessed |
||||
using a different filename) on the database server |
||||
machine. |
||||
You should also be aware that the <Application>postmaster</Application> and |
||||
postgres servers run with the user-id of the <ProductName>Postgres</ProductName> |
||||
"superuser." |
||||
Note that the <ProductName>Postgres</ProductName> superuser does not |
||||
have to be a special user (e.g., a user named |
||||
"postgres"), although many systems are installed that way. |
||||
Furthermore, the <ProductName>Postgres</ProductName> superuser should |
||||
definitely not be the UNIX superuser, "root"! In any |
||||
case, all files relating to a database should belong to |
||||
this <ProductName>Postgres</ProductName> superuser. |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,85 @@ |
||||
<Chapter> |
||||
<TITLE>Architecture</TITLE> |
||||
|
||||
<Sect1> |
||||
<Title><ProductName>Postgres</ProductName> Architectural Concepts</Title> |
||||
|
||||
<Para> |
||||
Before we begin, you should understand the basic |
||||
<ProductName>Postgres</ProductName> system architecture. Understanding how the |
||||
parts of <ProductName>Postgres</ProductName> interact will make the next chapter |
||||
somewhat clearer. |
||||
In database jargon, <ProductName>Postgres</ProductName> uses a simple "process |
||||
per-user" client/server model. A <ProductName>Postgres</ProductName> session |
||||
consists of the following cooperating UNIX processes (programs): |
||||
|
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
A supervisory daemon process (<Application>postmaster</Application>), |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
the user's frontend application (e.g., the <Application>psql</Application> program), and |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
the one or more backend database servers (the <Application>postgres</Application> process itself). |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
<Para> |
||||
A single <Application>postmaster</Application> manages a given collection of |
||||
databases on a single host. Such a collection of |
||||
databases is called an installation or site. Frontend |
||||
applications that wish to access a given database |
||||
within an installation make calls to the library. |
||||
The library sends user requests over the network to the |
||||
<Application>postmaster</Application> (<XRef LinkEnd="ARCH-CLIENTSERVER" EndTerm="ARCH-CLIENTSERVER">), |
||||
which in turn starts a new backend server process |
||||
|
||||
<Figure Id="ARCH-CLIENTSERVER"> |
||||
<Title>How a connection is established</Title> |
||||
<Graphic Align="center" FileRef="clientserver.gif" Format="GIF"></Graphic> |
||||
</Figure> |
||||
|
||||
and connects the |
||||
frontend process to the new server. From |
||||
that point on, the frontend process and the backend |
||||
server communicate without intervention by the |
||||
<Application>postmaster</Application>. Hence, the <Application>postmaster</Application> is always running, waiting |
||||
for requests, whereas frontend and backend processes |
||||
come and go. |
||||
|
||||
<Para> |
||||
The <FileName>libpq</FileName> library allows a single |
||||
frontend to make multiple connections to backend processes. |
||||
However, the frontend application is still a |
||||
single-threaded process. Multithreaded frontend/backend |
||||
connections are not currently supported in <FileName>libpq</FileName>. |
||||
One implication of this architecture is that the |
||||
<Application>postmaster</Application> and the backend always run on the same |
||||
machine (the database server), while the frontend |
||||
application may run anywhere. You should keep this |
||||
in mind, |
||||
because the files that can be accessed on a client |
||||
machine may not be accessible (or may only be accessed |
||||
using a different filename) on the database server |
||||
machine. |
||||
|
||||
<Para> |
||||
You should also be aware that the <Application>postmaster</Application> and |
||||
postgres servers run with the user-id of the <ProductName>Postgres</ProductName> |
||||
"superuser." Note that the <ProductName>Postgres</ProductName> superuser does not |
||||
have to be a special user (e.g., a user named |
||||
"postgres"). Furthermore, the <ProductName>Postgres</ProductName> superuser |
||||
should |
||||
definitely not be the UNIX superuser ("root")! In any |
||||
case, all files relating to a database should belong to |
||||
this <ProductName>Postgres</ProductName> superuser. |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,108 @@ |
||||
<Chapter> |
||||
<Title>Arrays</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
This must become a chapter on array behavior. Volunteers? - thomas 1998-01-12 |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> allows attributes of an instance to be defined |
||||
as fixed-length or variable-length multi-dimensional |
||||
arrays. Arrays of any base type or user-defined type |
||||
can be created. To illustrate their use, we first create a |
||||
class with arrays of base types. |
||||
|
||||
<ProgramListing> |
||||
CREATE TABLE SAL_EMP ( |
||||
name text, |
||||
pay_by_quarter int4[], |
||||
schedule char16[][] |
||||
); |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The above query will create a class named SAL_EMP with |
||||
a <FirstTerm>text</FirstTerm> string (name), a one-dimensional array of <FirstTerm>int4</FirstTerm> |
||||
(pay_by_quarter), which represents the employee's |
||||
salary by quarter and a two-dimensional array of <FirstTerm>char16</FirstTerm> |
||||
(schedule), which represents the employee's weekly |
||||
schedule. Now we do some <FirstTerm>INSERTS</FirstTerm>s; note that when |
||||
appending to an array, we enclose the values within |
||||
braces and separate them by commas. If you know <FirstTerm>C</FirstTerm>, |
||||
this is not unlike the syntax for initializing structures. |
||||
|
||||
<ProgramListing> |
||||
INSERT INTO SAL_EMP |
||||
VALUES ('Bill', |
||||
'{10000, 10000, 10000, 10000}', |
||||
'{{"meeting", "lunch"}, {}}'); |
||||
|
||||
INSERT INTO SAL_EMP |
||||
VALUES ('Carol', |
||||
'{20000, 25000, 25000, 25000}', |
||||
'{{"talk", "consult"}, {"meeting"}}'); |
||||
</ProgramListing> |
||||
|
||||
By default, <ProductName>Postgres</ProductName> uses the "one-based" numbering |
||||
convention for arrays -- that is, an array of n elements starts with array[1] and ends with array[n]. |
||||
Now, we can run some queries on SAL_EMP. First, we |
||||
show how to access a single element of an array at a |
||||
time. This query retrieves the names of the employees |
||||
whose pay changed in the second quarter: |
||||
|
||||
<ProgramListing> |
||||
SELECT name |
||||
FROM SAL_EMP |
||||
WHERE SAL_EMP.pay_by_quarter[1] <> |
||||
SAL_EMP.pay_by_quarter[2]; |
||||
|
||||
+------+ |
||||
|name | |
||||
+------+ |
||||
|Carol | |
||||
+------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
This query retrieves the third quarter pay of all |
||||
employees: |
||||
|
||||
<ProgramListing> |
||||
SELECT SAL_EMP.pay_by_quarter[3] FROM SAL_EMP; |
||||
|
||||
|
||||
+---------------+ |
||||
|pay_by_quarter | |
||||
+---------------+ |
||||
|10000 | |
||||
+---------------+ |
||||
|25000 | |
||||
+---------------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
We can also access arbitrary slices of an array, or |
||||
subarrays. This query retrieves the first item on |
||||
Bill's schedule for the first two days of the week. |
||||
|
||||
<ProgramListing> |
||||
SELECT SAL_EMP.schedule[1:2][1:1] |
||||
FROM SAL_EMP |
||||
WHERE SAL_EMP.name = 'Bill'; |
||||
|
||||
+-------------------+ |
||||
|schedule | |
||||
+-------------------+ |
||||
|{{"meeting"},{""}} | |
||||
+-------------------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,504 @@ |
||||
<BIBLIOGRAPHY> |
||||
<Title><Acronym>SQL</Acronym> References</Title> |
||||
|
||||
<Para> |
||||
Selected references and readings for <Acronym>SQL</Acronym> and <ProductName>Postgres</ProductName>. |
||||
</Para> |
||||
|
||||
<BIBLIODIV> |
||||
<TITLE><Acronym>SQL</Acronym> Reference Books</TITLE> |
||||
<PARA>Reference texts for <Acronym>SQL</Acronym> features.</PARA> |
||||
|
||||
<BIBLIOENTRY ID="BOWMAN93"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="BOWMAN93"> |
||||
--> |
||||
<TITLE>The Practical <Acronym>SQL</Acronym> Handbook</TITLE> |
||||
<SUBTITLE>Using Structured Query Language</SUBTITLE> |
||||
<EDITION>3</EDITION> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>Judity</FIRSTNAME> |
||||
<SURNAME>Bowman</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>Sandra</FIRSTNAME> |
||||
<SURNAME>Emerson</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>Marcy</FIRSTNAME> |
||||
<SURNAME>Damovsky</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<ISBN>0-201-44787-8</ISBN> |
||||
<PUBDATE>1996</PUBDATE> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>Addison-Wesley</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<COPYRIGHT> |
||||
<YEAR>1997</YEAR> |
||||
<HOLDER>Addison-Wesley Longman, Inc.</HOLDER> |
||||
</COPYRIGHT> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="DATE97"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="DATE97"> |
||||
--> |
||||
<TITLE>A Guide to The <Acronym>SQL</Acronym> Standard</TITLE> |
||||
<TITLEABBREV>The <Acronym>SQL</Acronym> Standard</TITLEABBREV> |
||||
<SUBTITLE>A user's guide to the standard database language <Acronym>SQL</Acronym></SUBTITLE> |
||||
<EDITION>4</EDITION> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>C. J.</FIRSTNAME> |
||||
<SURNAME>Date</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>Hugh</FIRSTNAME> |
||||
<SURNAME>Darwen</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<ISBN>0-201-96426-0</ISBN> |
||||
<PUBDATE>1997</PUBDATE> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>Addison-Wesley</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<COPYRIGHT> |
||||
<YEAR>1997</YEAR> |
||||
<HOLDER>Addison-Wesley Longman, Inc.</HOLDER> |
||||
</COPYRIGHT> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="MELT93"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="MELT93"> |
||||
--> |
||||
<TITLE>Understanding the New <Acronym>SQL</Acronym></TITLE> |
||||
<SUBTITLE>A complete guide</SUBTITLE> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>Jim</FIRSTNAME> |
||||
<SURNAME>Melton</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>Alan R.</FIRSTNAME> |
||||
<SURNAME>Simon</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<ISBN>1-55860-245-3</ISBN> |
||||
<PUBDATE>1993</PUBDATE> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>Morgan Kaufmann</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<COPYRIGHT> |
||||
<YEAR>1993</YEAR> |
||||
<HOLDER>Morgan Kaufmann Publishers, Inc.</HOLDER> |
||||
</COPYRIGHT> |
||||
<ABSTRACT> |
||||
<TITLE>Abstract</TITLE> |
||||
<PARA>Accessible reference for <Acronym>SQL</Acronym> features.</PARA> |
||||
</ABSTRACT> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
</BIBLIODIV> |
||||
<BIBLIODIV> |
||||
<TITLE>PostgreSQL-Specific Documentation</TITLE> |
||||
<PARA>This section is for related documentation.</PARA> |
||||
|
||||
<BIBLIOENTRY ID="ADMIN-GUIDE"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="ADMIN-GUIDE"> |
||||
--> |
||||
<TITLE>The <ProductName>PostgreSQL</ProductName> Administrator's Guide</TITLE> |
||||
<Editor> |
||||
<FIRSTNAME>Thomas</FIRSTNAME> |
||||
<SURNAME>Lockhart</SURNAME> |
||||
</Editor> |
||||
|
||||
<PUBDATE>1998-03-01</PUBDATE> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="PROGRAMMERS-GUIDE"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="PROGRAMMERS-GUIDE"> |
||||
--> |
||||
<TITLE>The <ProductName>PostgreSQL</ProductName> Programmer's Guide</TITLE> |
||||
<Editor> |
||||
<FIRSTNAME>Thomas</FIRSTNAME> |
||||
<SURNAME>Lockhart</SURNAME> |
||||
</Editor> |
||||
|
||||
<PUBDATE>1998-03-01</PUBDATE> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="TUTORIAL"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="REFERENCE"> |
||||
--> |
||||
<TITLE>The <ProductName>PostgreSQL</ProductName> Reference Manual</TITLE> |
||||
<Editor> |
||||
<FIRSTNAME>Thomas</FIRSTNAME> |
||||
<SURNAME>Lockhart</SURNAME> |
||||
</Editor> |
||||
|
||||
<PUBDATE>1998-03-01</PUBDATE> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="USERS-GUIDE"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="TUTORIAL"> |
||||
--> |
||||
<TITLE>The <ProductName>PostgreSQL</ProductName> Tutorial Introduction</TITLE> |
||||
<Editor> |
||||
<FIRSTNAME>Thomas</FIRSTNAME> |
||||
<SURNAME>Lockhart</SURNAME> |
||||
</Editor> |
||||
|
||||
<PUBDATE>1998-03-01</PUBDATE> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="REFERENCE"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="USERS-GUIDE"> |
||||
--> |
||||
<TITLE>The <ProductName>PostgreSQL</ProductName> User's Guide</TITLE> |
||||
<Editor> |
||||
<FIRSTNAME>Thomas</FIRSTNAME> |
||||
<SURNAME>Lockhart</SURNAME> |
||||
</Editor> |
||||
|
||||
<PUBDATE>1998-03-01</PUBDATE> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>The PostgreSQL Global Development Group</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="YU95"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="YU95"> |
||||
--> |
||||
<TITLE>The <ProductName>Postgres95</ProductName> User Manual</TITLE> |
||||
<TITLEABBREV>YU95</TITLEABBREV> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>A.</FIRSTNAME> |
||||
<SURNAME>Yu</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>J.</FIRSTNAME> |
||||
<SURNAME>Chen</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<AUTHORGROUP> |
||||
<COLLAB> |
||||
<COLLABNAME> |
||||
The POSTGRES Group |
||||
</COLLABNAME> |
||||
</COLLAB> |
||||
</AUTHORGROUP> |
||||
|
||||
<PUBDATE>Sept. 5, 1995</PUBDATE> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>University of California, Berkeley CA</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
</BIBLIODIV> |
||||
<BIBLIODIV> |
||||
<TITLE>Proceedings and Articles</TITLE> |
||||
<PARA>This section is for articles and newsletters.</PARA> |
||||
|
||||
<BIBLIOENTRY ID="ONG90"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="ONG90"> |
||||
--> |
||||
<TITLE>A Unified Framework for Version Modeling Using Production Rules in a Database System</TITLE> |
||||
<TITLEABBREV>ONG90</TITLEABBREV> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>L.</FIRSTNAME> |
||||
<SURNAME>Ong</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>J.</FIRSTNAME> |
||||
<SURNAME>Goh</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<PUBDATE>April, 1990</PUBDATE> |
||||
<ISSN>ERL Technical Memorandum M90/33</ISSN> |
||||
<PUBLISHER> |
||||
<PUBLISHERNAME>University of California, Berkeley CA</PUBLISHERNAME> |
||||
</PUBLISHER> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="ROWE87"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="ROWE87"> |
||||
--> |
||||
<TITLE>The <ProductName>Postgres</ProductName> Data Model</TITLE> |
||||
<TITLEABBREV>ROWE87</TITLEABBREV> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>L.</FIRSTNAME> |
||||
<SURNAME>Rowe</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>M.</FIRSTNAME> |
||||
<SURNAME>Stonebraker</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<CONFGROUP> |
||||
<CONFDATES>Sept. 1987</CONFDATES> |
||||
<CONFTITLE>VLDB Conference, Brighton, England</CONFTITLE> |
||||
<CONFNUM>1987</CONFNUM> |
||||
</CONFGROUP> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="STON86"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="STON86"> |
||||
--> |
||||
<TITLE>The Design of <ProductName>Postgres</ProductName></TITLE> |
||||
<TITLEABBREV>STON86</TITLEABBREV> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>M.</FIRSTNAME> |
||||
<SURNAME>Stonebraker</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>L.</FIRSTNAME> |
||||
<SURNAME>Rowe</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<CONFGROUP> |
||||
<CONFDATES>May 1986</CONFDATES> |
||||
<CONFTITLE>Conference on Management of Data, Washington DC</CONFTITLE> |
||||
<CONFSPONSOR>ACM-SIGMOD</CONFSPONSOR> |
||||
<CONFNUM>1986</CONFNUM> |
||||
</CONFGROUP> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="STON87a"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="STON87a"> |
||||
--> |
||||
<TITLE>The Design of the <ProductName>Postgres</ProductName> Rules System</TITLE> |
||||
<TITLEABBREV>STON87a</TITLEABBREV> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>M.</FIRSTNAME> |
||||
<SURNAME>Stonebraker</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>E.</FIRSTNAME> |
||||
<SURNAME>Hanson</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>C. H.</FIRSTNAME> |
||||
<SURNAME>Hong</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<CONFGROUP> |
||||
<CONFDATES>Feb. 1987</CONFDATES> |
||||
<CONFTITLE>Conference on Data Engineering, Los Angeles, CA</CONFTITLE> |
||||
<CONFSPONSOR>IEEE</CONFSPONSOR> |
||||
<CONFNUM>1987</CONFNUM> |
||||
</CONFGROUP> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="STON87b"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="STON87b"> |
||||
--> |
||||
<TITLE>The <ProductName>Postgres</ProductName> Storage System</TITLE> |
||||
<TITLEABBREV>STON87b</TITLEABBREV> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>M.</FIRSTNAME> |
||||
<SURNAME>Stonebraker</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<CONFGROUP> |
||||
<CONFDATES>Sept. 1987</CONFDATES> |
||||
<CONFTITLE>VLDB Conference, Brighton, England</CONFTITLE> |
||||
<CONFNUM>1987</CONFNUM> |
||||
</CONFGROUP> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="STON89"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="STON89"> |
||||
--> |
||||
<TITLE>A Commentary on the <ProductName>Postgres</ProductName> Rules System</TITLE> |
||||
<TITLEABBREV>STON89</TITLEABBREV> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>M.</FIRSTNAME> |
||||
<SURNAME>Stonebraker</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>M.</FIRSTNAME> |
||||
<SURNAME>Hearst</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>S.</FIRSTNAME> |
||||
<SURNAME>Potamianos</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<CONFGROUP> |
||||
<CONFDATES>Sept. 1989</CONFDATES> |
||||
<CONFTITLE>Record 18(3)</CONFTITLE> |
||||
<CONFSPONSOR>SIGMOD</CONFSPONSOR> |
||||
<CONFNUM>1987</CONFNUM> |
||||
</CONFGROUP> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="STON90a"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="STON90a"> |
||||
--> |
||||
<TITLE>The Implementation of <ProductName>Postgres</ProductName></TITLE> |
||||
<TITLEABBREV>STON90a</TITLEABBREV> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>M.</FIRSTNAME> |
||||
<SURNAME>Stonebraker</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>L. A.</FIRSTNAME> |
||||
<SURNAME>Rowe</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<FIRSTNAME>M.</FIRSTNAME> |
||||
<SURNAME>Hirohama</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<CONFGROUP> |
||||
<CONFDATES>March 1990</CONFDATES> |
||||
<CONFTITLE>Transactions on Knowledge and Data Engineering 2(1)</CONFTITLE> |
||||
<CONFSPONSOR>IEEE</CONFSPONSOR> |
||||
</CONFGROUP> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
<BIBLIOENTRY ID="STON90b"> |
||||
<!-- |
||||
<BIBLIOMISC>‐</BIBLIOMISC> |
||||
|
||||
<BOOKBIBLIO ID="STON90b"> |
||||
--> |
||||
<TITLE>On Rules, Procedures, Caching and Views in Database Systems</TITLE> |
||||
<TITLEABBREV>STON90b</TITLEABBREV> |
||||
<AUTHORGROUP> |
||||
<AUTHOR> |
||||
<FIRSTNAME>M.</FIRSTNAME> |
||||
<SURNAME>Stonebraker</SURNAME> |
||||
</AUTHOR> |
||||
<AUTHOR> |
||||
<SURNAME>et. al.</SURNAME> |
||||
</AUTHOR> |
||||
</AUTHORGROUP> |
||||
<CONFGROUP> |
||||
<CONFDATES>June 1990</CONFDATES> |
||||
<CONFTITLE>Conference on Management of Data</CONFTITLE> |
||||
<CONFSPONSOR>ACM-SIGMOD</CONFSPONSOR> |
||||
</CONFGROUP> |
||||
<!-- |
||||
</BOOKBIBLIO> |
||||
--> |
||||
</BIBLIOENTRY> |
||||
|
||||
</BIBLIODIV> |
||||
</BIBLIOGRAPHY> |
||||
@ -0,0 +1,73 @@ |
||||
<Chapter> |
||||
<DocInfo> |
||||
<AuthorGroup> |
||||
<Author> |
||||
<FirstName>Brian</FirstName> |
||||
<Surname>Gallew</Surname> |
||||
</Author> |
||||
</AuthorGroup> |
||||
<Date>Transcribed 1998-02-12</Date> |
||||
</DocInfo> |
||||
|
||||
<Title>GCC Default Optimizations</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
Contributed by <ULink url="mailto:geek+@cmu.edu">Brian Gallew</ULink> |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
Configuring gcc to use certain flags by default is a simple matter of |
||||
editing the |
||||
<FileName>/usr/local/lib/gcc-lib/<Replaceable>platform</Replaceable>/<Replaceable>version</Replaceable>/specs</FileName> |
||||
file. |
||||
The format of this file pretty simple. The file is broken into |
||||
sections, each of which is three lines long. The first line is |
||||
"*<Replaceable>section_name</Replaceable>:" (e.g. "*asm:"). |
||||
The second line is a list of flags, |
||||
and the third line is blank. |
||||
|
||||
<Para> |
||||
The easiest change to make is to append |
||||
the desired default flags to the list in the appropriate section. As |
||||
an example, let's suppose that I have linux running on a '486 with gcc |
||||
2.7.2 installed in the default location. In the file |
||||
/usr/local/lib/gcc-lib/i486-linux/2.7.2/specs, 13 lines down I find |
||||
the following section: |
||||
<ProgramListing> |
||||
- ----------SECTION---------- |
||||
*cc1: |
||||
|
||||
|
||||
- ----------SECTION---------- |
||||
</ProgramListing> |
||||
As you can see, there aren't any default flags. If I always wanted |
||||
compiles of C code to use "-m486 -fomit-frame-pointer", I would |
||||
change it to look like: |
||||
<ProgramListing> |
||||
- ----------SECTION---------- |
||||
*cc1: |
||||
- -m486 -fomit-frame-pointer |
||||
|
||||
- ----------SECTION---------- |
||||
</ProgramListing> |
||||
If I wanted to be able to generate 386 code for another, older linux |
||||
box lying around, I'd have to make it look like this: |
||||
<ProgramListing> |
||||
- ----------SECTION---------- |
||||
*cc1: |
||||
%{!m386:-m486} -fomit-frame-pointer |
||||
|
||||
- ----------SECTION---------- |
||||
</ProgramListing> |
||||
This will always omit frame pointers, any will build 486-optimized |
||||
code unless -m386 is specified on the command line. |
||||
|
||||
<Para> |
||||
You can actually do quite a lot of customization with the specs file. |
||||
Always remember, however, that these changes are global, and affect |
||||
all users of the system. |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,23 @@ |
||||
<Appendix label="B"> |
||||
<Title>Contacts</Title> |
||||
|
||||
<Sect1> |
||||
<Title>Introduction</Title> |
||||
<Para> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>People</Title> |
||||
|
||||
<Para> |
||||
<ItemizedList Mark="bullet" Spacing="compact"> |
||||
<ListItem> |
||||
<Para> |
||||
<ULink url="http://alumni.caltech.edu/~lockhart">Thomas Lockhart</ULink> |
||||
works on SQL standards compliance and documentation. |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
</Para> |
||||
|
||||
</Appendix> |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,242 @@ |
||||
<Chapter> |
||||
<Title>Linking Dynamically-Loaded Functions</Title> |
||||
|
||||
<Para> |
||||
After you have created and registered a user-defined |
||||
function, your work is essentially done. <ProductName>Postgres</ProductName>, |
||||
however, must load the object code (e.g., a <FileName>.o</FileName> file, or |
||||
a shared library) that implements your function. As |
||||
previously mentioned, <ProductName>Postgres</ProductName> loads your code at |
||||
runtime, as required. In order to allow your code to be |
||||
dynamically loaded, you may have to compile and |
||||
linkedit it in a special way. This section briefly |
||||
describes how to perform the compilation and |
||||
linkediting required before you can load your user-defined |
||||
functions into a running <ProductName>Postgres</ProductName> server. Note that |
||||
this process has changed as of Version 4.2. |
||||
<Tip> |
||||
<Para> |
||||
The old <ProductName>Postgres</ProductName> dynamic |
||||
loading mechanism required |
||||
in-depth knowledge in terms of executable format, placement |
||||
and alignment of executable instructions within memory, etc. |
||||
on the part of the person writing the dynamic loader. Such |
||||
loaders tended to be slow and buggy. As of Version 4.2, the |
||||
<ProductName>Postgres</ProductName> dynamic loading mechanism has been rewritten to use |
||||
the dynamic loading mechanism provided by the operating |
||||
system. This approach is generally faster, more reliable and |
||||
more portable than our previous dynamic loading mechanism. |
||||
The reason for this is that nearly all modern versions of |
||||
UNIX use a dynamic loading mechanism to implement shared |
||||
libraries and must therefore provide a fast and reliable |
||||
mechanism. On the other hand, the object file must be |
||||
postprocessed a bit before it can be loaded into <ProductName>Postgres</ProductName>. We |
||||
hope that the large increase in speed and reliability will |
||||
make up for the slight decrease in convenience. |
||||
<Para> |
||||
</Tip> |
||||
You should expect to read (and reread, and re-reread) the |
||||
manual pages for the C compiler, cc(1), and the link |
||||
editor, ld(1), if you have specific questions. In |
||||
addition, the regression test suites in the directory |
||||
<FileName>PGROOT/src/regress</FileName> contain several |
||||
working examples of this process. If you copy what these |
||||
tests do, you should not have any problems. |
||||
The following terminology will be used below: |
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
<FirstTerm>Dynamic loading</FirstTerm> |
||||
is what <ProductName>Postgres</ProductName> does to an object file. The |
||||
object file is copied into the running <ProductName>Postgres</ProductName> |
||||
server and the functions and variables within the |
||||
file are made available to the functions within |
||||
the <ProductName>Postgres</ProductName> process. <ProductName>Postgres</ProductName> does this using |
||||
the dynamic loading mechanism provided by the |
||||
operating system. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
<FirstTerm>Loading and link editing</FirstTerm> |
||||
is what you do to an object file in order to produce |
||||
another kind of object file (e.g., an executable |
||||
program or a shared library). You perform |
||||
this using the link editing program, ld(1). |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The following general restrictions and notes also apply |
||||
to the discussion below: |
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
Paths given to the create function command must be |
||||
absolute paths (i.e., start with "/") that refer to |
||||
directories visible on the machine on which the |
||||
<ProductName>Postgres</ProductName> server is running. |
||||
<Tip> |
||||
<Para> |
||||
Relative paths do in fact work, |
||||
but are relative to |
||||
the directory where the database resides (which is generally |
||||
invisible to the frontend application). Obviously, it makes |
||||
no sense to make the path relative to the directory in which |
||||
the user started the frontend application, since the server |
||||
could be running on a completely different machine! |
||||
</Para> |
||||
</Tip> |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
The <ProductName>Postgres</ProductName> user must be able to traverse the path |
||||
given to the create function command and be able to |
||||
read the object file. This is because the <ProductName>Postgres</ProductName> |
||||
server runs as the <ProductName>Postgres</ProductName> user, not as the user |
||||
who starts up the frontend process. (Making the |
||||
file or a higher-level directory unreadable and/or |
||||
unexecutable by the "postgres" user is an extremely |
||||
common mistake.) |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
Symbol names defined within object files must not |
||||
conflict with each other or with symbols defined in |
||||
<ProductName>Postgres</ProductName>. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
The GNU C compiler usually does not provide the special |
||||
options that are required to use the operating |
||||
system's dynamic loader interface. In such cases, |
||||
the C compiler that comes with the operating system |
||||
must be used. |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
<Sect1> |
||||
<Title><Acronym>ULTRIX</Acronym></Title> |
||||
|
||||
<Para> |
||||
It is very easy to build dynamically-loaded object |
||||
files under ULTRIX. ULTRIX does not have any sharedlibrary |
||||
mechanism and hence does not place any restrictions on |
||||
the dynamic loader interface. On the other |
||||
hand, we had to (re)write a non-portable dynamic loader |
||||
ourselves and could not use true shared libraries. |
||||
Under ULTRIX, the only restriction is that you must |
||||
produce each object file with the option -G 0. (Notice |
||||
that that's the numeral ``0'' and not the letter |
||||
``O''). For example, |
||||
<ProgramListing> |
||||
# simple ULTRIX example |
||||
% cc -G 0 -c foo.c |
||||
</ProgramListing> |
||||
produces an object file called foo.o that can then be |
||||
dynamically loaded into <ProductName>Postgres</ProductName>. No additional loading or link-editing must be performed. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title><Acronym>DEC OSF/1</Acronym></Title> |
||||
|
||||
<Para> |
||||
Under DEC OSF/1, you can take any simple object file |
||||
and produce a shared object file by running the ld command over it with the correct options. The commands to |
||||
do this look like: |
||||
<ProgramListing> |
||||
# simple DEC OSF/1 example |
||||
% cc -c foo.c |
||||
% ld -shared -expect_unresolved '*' -o foo.so foo.o |
||||
</ProgramListing> |
||||
|
||||
The resulting shared object file can then be loaded |
||||
into <ProductName>Postgres</ProductName>. When specifying the object file name to |
||||
the create function command, one must give it the name |
||||
of the shared object file (ending in .so) rather than |
||||
the simple object file. |
||||
<Tip> |
||||
<Para> |
||||
Actually, <ProductName>Postgres</ProductName> does not care |
||||
what you name the |
||||
file as long as it is a shared object file. If you prefer |
||||
to name your shared object files with the extension .o, this |
||||
is fine with <ProductName>Postgres</ProductName> so long as you make sure that the correct |
||||
file name is given to the create function command. In |
||||
other words, you must simply be consistent. However, from a |
||||
pragmatic point of view, we discourage this practice because |
||||
you will undoubtedly confuse yourself with regards to which |
||||
files have been made into shared object files and which have |
||||
not. For example, it's very hard to write Makefiles to do |
||||
the link-editing automatically if both the object file and |
||||
the shared object file end in .o! |
||||
</Para> |
||||
</Tip> |
||||
|
||||
If the file you specify is |
||||
not a shared object, the backend will hang! |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title> |
||||
<Acronym>SunOS 4.x</Acronym>, <Acronym>Solaris 2.x</Acronym> and <Acronym>HP-UX</Acronym></Title> |
||||
|
||||
<Para> |
||||
Under SunOS 4.x, Solaris 2.x and HP-UX, the simple |
||||
object file must be created by compiling the source |
||||
file with special compiler flags and a shared library |
||||
must be produced. |
||||
The necessary steps with HP-UX are as follows. The +z |
||||
flag to the HP-UX C compiler produces so-called |
||||
"Position Independent Code" (PIC) and the +u flag |
||||
removes |
||||
some alignment restrictions that the PA-RISC architecture |
||||
normally enforces. The object file must be turned |
||||
into a shared library using the HP-UX link editor with |
||||
the -b option. This sounds complicated but is actually |
||||
very simple, since the commands to do it are just: |
||||
<ProgramListing> |
||||
# simple HP-UX example |
||||
% cc +z +u -c foo.c |
||||
% ld -b -o foo.sl foo.o |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
As with the .so files mentioned in the last subsection, |
||||
the create function command must be told which file is |
||||
the correct file to load (i.e., you must give it the |
||||
location of the shared library, or .sl file). |
||||
Under SunOS 4.x, the commands look like: |
||||
<ProgramListing> |
||||
# simple SunOS 4.x example |
||||
% cc -PIC -c foo.c |
||||
% ld -dc -dp -Bdynamic -o foo.so foo.o |
||||
</ProgramListing> |
||||
|
||||
and the equivalent lines under Solaris 2.x are: |
||||
<ProgramListing> |
||||
# simple Solaris 2.x example |
||||
% cc -K PIC -c foo.c |
||||
or |
||||
% gcc -fPIC -c foo.c |
||||
% ld -G -Bdynamic -o foo.so foo.o |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
When linking shared libraries, you may have to specify |
||||
some additional shared libraries (typically system |
||||
libraries, such as the C and math libraries) on your ld |
||||
command line. |
||||
</Para> |
||||
</Sect1> |
||||
</Chapter> |
||||
@ -0,0 +1,347 @@ |
||||
<Appendix label="A"> |
||||
<DocInfo> |
||||
<AuthorGroup> |
||||
<Author> |
||||
<FirstName>Thomas</FirstName> |
||||
<Surname>Lockhart</Surname> |
||||
</Author> |
||||
</AuthorGroup> |
||||
<Date>1998-02-26</Date> |
||||
</DocInfo> |
||||
|
||||
<Title>Documentation</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> documentation is written using |
||||
the <FirstTerm>Standard Generalized Markup Language</FirstTerm> |
||||
(<Acronym>SGML</Acronym>) |
||||
<ULink url="http://www.ora.com/davenport/"><ProductName>DocBook</ProductName></ULink> |
||||
<FirstTerm>Document Type Definition</FirstTerm> (<Acronym>DTD</Acronym>). |
||||
|
||||
<Para> |
||||
Packaged documentation is available in both <FirstTerm>HTML</FirstTerm> and <FirstTerm>Postscript</FirstTerm> |
||||
formats. These are available as part of the standard <ProductName>Postgres</ProductName> installation. |
||||
We discuss here working with the documentation sources and generating documentation packages. |
||||
|
||||
<Note> |
||||
<Para> |
||||
This is the first release of new <ProductName>Postgres</ProductName> documentation in three years. |
||||
The content and environment are in flux and still evolving. |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Sect1> |
||||
<Title>Introduction</Title> |
||||
|
||||
<Para> |
||||
The purpose of <Acronym>SGML</Acronym> is to allow an author to specify the structure and content of |
||||
a document (e.g. using the <ProductName>DocBook</ProductName> <Acronym>DTD</Acronym>), |
||||
and to have the document style define |
||||
how that content is rendered into a final form |
||||
(e.g. using Norm Walsh's stylesheets). |
||||
|
||||
<Para> |
||||
See |
||||
<ULink url="http://nis-www.lanl.gov/~rosalia/mydocs/docbook-intro.html">Introduction to DocBook</ULink> |
||||
for a nice "quickstart" summary of DocBook features. |
||||
<ULink url="http://www.ora.com/homepages/dtdparse/docbook/3.0/">DocBook Elements</ULink> |
||||
provides a powerful cross-reference for features of <ProductName>DocBook</ProductName>. |
||||
|
||||
<Para> |
||||
This documentation set is constructed using several tools, |
||||
including James Clark's |
||||
<ULink url="http://www.jclark.com/jade/"><ProductName>jade</ProductName></ULink> |
||||
and Norm Walsh's |
||||
<ULink url="http://www.berkshire.net/~norm/docbook/dsssl">Modular DocBook Stylesheets</ULink>. |
||||
|
||||
<Para> |
||||
Currently, hardcopy is produced by importing <FirstTerm>Rich Text Format</FirstTerm> (<Acronym>RTF</Acronym>) |
||||
output from <Application>jade</Application> to <ProductName>ApplixWare</ProductName> |
||||
for minor formatting fixups then exporting as a Postscript file. |
||||
|
||||
<Para> |
||||
<ULink url="http://sunsite.unc.edu/pub/packages/TeX/systems/unix/"><ProductName>TeX</ProductName></ULink> |
||||
is a supported format for <Application>jade</Application> output, but was not used at this time for |
||||
several reasons, including the inability to make minor format fixes before committing to hardcopy and |
||||
generally inadequate table support in the <ProductName>TeX</ProductName> stylesheets. |
||||
|
||||
<Sect1> |
||||
<Title>Styles and Conventions</Title> |
||||
|
||||
<Para> |
||||
<ProductName>DocBook</ProductName> has a rich set of tags and constructs, and a suprisingly large |
||||
percentage are directly and obviously useful for well-formed documentation. |
||||
The <ProductName>Postgres</ProductName> documentation set has only recently |
||||
been adapted to <Acronym>SGML</Acronym>, and in the near future several sections of the set |
||||
will be selected and maintained as prototypical examples of <ProductName>DocBook</ProductName> |
||||
usage. Also, a short summary of <ProductName>DocBook</ProductName> tags will be included below. |
||||
|
||||
<!-- |
||||
<Para> |
||||
<TABLE TOCENTRY="1"> |
||||
<TITLE>SGML Constructs</TITLE> |
||||
<TITLEABBREV>SGML Constructs</TITLEABBREV> |
||||
<TGROUP COLS="2"> |
||||
<THEAD> |
||||
<ROW> |
||||
<ENTRY>SGML Tag</ENTRY> |
||||
<ENTRY>Usage</ENTRY> |
||||
</ROW> |
||||
</THEAD> |
||||
<TBODY> |
||||
<ROW> |
||||
</ROW> |
||||
</TBODY> |
||||
</TGROUP> |
||||
</TABLE> |
||||
</Para> |
||||
|
||||
--> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Building Documentation</Title> |
||||
|
||||
<Para> |
||||
HTML documentation packages can be generated from the SGML source by typing |
||||
|
||||
<ProgramListing> |
||||
% cd doc/src |
||||
% make tutorial.tar.gz |
||||
% make user.tar.gz |
||||
% make admin.tar.gz |
||||
% make programmer.tar.gz |
||||
% make postgres.tar.gz |
||||
% make install |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
These packages can be installed from the main documentation directory by typing |
||||
<ProgramListing> |
||||
% cd doc |
||||
% make install |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Toolsets</Title> |
||||
|
||||
<Sect2> |
||||
<Title><ProductName>jade</ProductName></Title> |
||||
|
||||
<Para> |
||||
The current stable release of <ProductName>jade</ProductName> is version 1.0.1. |
||||
</Para> |
||||
|
||||
<Sect3> |
||||
<Title>Installation for Linux</Title> |
||||
|
||||
<Para> |
||||
Install <ULink url="ftp://ftp.cygnus.com/pub/home/rosalia/"><Acronym>RPMs</Acronym></ULink> |
||||
for <ProductName>jade</ProductName> and related packages. |
||||
</Para> |
||||
</Sect3> |
||||
|
||||
<Sect3> |
||||
<Title>Installation for non-Linux Platforms</Title> |
||||
|
||||
<Para> |
||||
There are some other packaged distributions for jade. <ProductName>FreeBSD</ProductName> seems |
||||
to have one available. Please report package status to the docs mailing list and we will |
||||
include that information here. |
||||
|
||||
<Para> |
||||
For other platforms, install <ULink url="ftp://ftp.cygnus.com/pub/eichin/docware/SOURCES/">sources</ULink> |
||||
for <ProductName>jade</ProductName> and related packages and build from scratch. |
||||
</Para> |
||||
</Sect3> |
||||
|
||||
<Sect2> |
||||
<Title><ProductName>Modular Style Sheets</ProductName></Title> |
||||
|
||||
<Para> |
||||
The current stable release of the <ProductName>Modular Style Sheets</ProductName> is version 1.0.7. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Hardcopy Generation for v6.3</Title> |
||||
|
||||
<Para> |
||||
The hardcopy Postscript documentation is generated by converting the <Acronym>SGML</Acronym> |
||||
source code to <Acronym>RTF</Acronym>, then importing into Applixware. After a little cleanup |
||||
(see the following section) the output is "printed" to a postscript file. |
||||
|
||||
<Para> |
||||
Some figures were redrawn to avoid having bitmap <Acronym>GIF</Acronym> files in the hardcopy |
||||
documentation. One figure, of the system catalogs, was sufficiently complex that there was |
||||
not time to redraw it. It was converted to fit using the following commands: |
||||
|
||||
<ProgramListing> |
||||
% convert -v -geometry 400x400'>' figure03.gif con.gif |
||||
% convert -v -crop 400x380 con.gif connections.gif |
||||
</ProgramListing> |
||||
|
||||
<Sect2> |
||||
<Title>RTF Cleanup Procedure</Title> |
||||
|
||||
<Para> |
||||
Several items must be addressed in generating Postscript hardcopy: |
||||
|
||||
<Procedure> |
||||
<Title>Applixware RTF Cleanup</Title> |
||||
|
||||
<Para> |
||||
Applixware does not seem to do a complete job of importing RTF generated by jade/MSS. In particular, |
||||
all text is given the <Quote>Header1</Quote> style attribute label, although the text formatting itself |
||||
is acceptable. Also, the Table of Contents page numbers do not refer to the section listed in the |
||||
table, but rather refer to the page of the ToC itself. |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Generate the <Acronym>RTF</Acronym> input by typing |
||||
<ProgramListing> |
||||
% cd doc/src/sgml |
||||
% make tutorial.rtf |
||||
</ProgramListing> |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Open a new document in <ProductName>Applix Words</ProductName> and then import the RTF file. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Print out the existing Table of Contents, to mark up in the following few steps. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Insert figures into the document. Center each figure on the page using the centering margins button. |
||||
|
||||
<Para> |
||||
Not all documents have figures. You can grep the SGML source files for the string <Quote>Graphic</Quote> |
||||
to identify those parts of the documentation which may have figures. A few figures are replicated in |
||||
various parts of the documentation. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Work through the document, adjusting page breaks and table column widths. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
If a bibliography is present, Applix Words seems to mark all remaining text after the first title |
||||
as having an underlined attribute. Select all remaining text, turn off underlining using the underlining button, |
||||
then explicitly underline each document and book title. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Work through the document, marking up the ToC hardcopy with the actual page number of each ToC entry. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Replace the right-justified incorrect page numbers in the ToC with correct values. This only takes a few |
||||
minutes per document. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Save the document as native Applix Words format to allow easier last minute editing later. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Export the document to a file in Postscript format. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Compress the Postscript file using <Application>gzip</Application>. Place the compressed file into the |
||||
<FileName>doc</FileName> directory. |
||||
</Para> |
||||
</Step> |
||||
</Procedure> |
||||
|
||||
</Sect2> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Alternate Toolsets</Title> |
||||
|
||||
<Para> |
||||
The current stable release of <ProductName>sgml-tools</ProductName> is version 1.0.4. |
||||
The v1.0 release includes some restructuring of the directory tree |
||||
to more easily support additional document styles, possibly including <ProductName>DocBook</ProductName>. |
||||
The only version of <ProductName>sgml-tools</ProductName> evaluated for <ProductName>Postgres</ProductName> was v0.99.0. |
||||
</Para> |
||||
|
||||
<Sect2> |
||||
<Title><ProductName>sgml-tools</ProductName></Title> |
||||
|
||||
<Para> |
||||
Install |
||||
<ProductName>sgml-tools-0.99.0</ProductName> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Apply |
||||
<ULink url="http://alumni.caltech.edu/~lockhart/postgres/linuxdoc/sgml-tools-patches-0.99.0.tar.gz"> |
||||
<ProductName>sgml-tools-patches</ProductName> |
||||
</ULink> |
||||
to the linuxdoc styles. These patches fix small problems with |
||||
table formatting and with figure file names on conversion to postscript or html. |
||||
</Para> |
||||
|
||||
<Sect2> |
||||
<Title><ProductName>sgml2latex</ProductName></Title> |
||||
|
||||
<Para> |
||||
The current stable release of <ProductName>sgml2latex</ProductName> is version 1.4. |
||||
I have misplaced the original reference |
||||
for this package, so will temporarily post it with this example. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Install <ULink url="http://alumni.caltech.edu/~lockhart/postgres/linuxdoc/sgml2latex-format.1.4.tar.gz"> |
||||
<ProductName>sgml2latex</ProductName> |
||||
</ULink>. |
||||
</Para> |
||||
|
||||
<Sect2> |
||||
<Title><ProductName>latex</ProductName></Title> |
||||
|
||||
<Para> |
||||
Get and install <ProductName>texmf</ProductName>, <ProductName>teTeX</ProductName>, |
||||
or another package providing full tex/latex functionality. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Add the |
||||
<ULink url="http://alumni.caltech.edu/~lockhart/postgres/linuxdoc/latex-styles-0.99.0.tar.gz">required styles</ULink> |
||||
linuxdoc-sgml.sty, linuxdoc-sgml-a4.sty isolatin.sty, qwertz.sty, and null.sty |
||||
to texmf/tex/latex/tools/ or the appropriate area. |
||||
<ProgramListing> |
||||
% cat latex-styles-0.99.0.tar.gz | (cd texmf/tex/latex/tools/; tar zxvf -) |
||||
</ProgramListing> |
||||
|
||||
Run <ProductName>texhash</ProductName> to update the tex database. |
||||
</Para> |
||||
|
||||
|
||||
</Appendix> |
||||
@ -0,0 +1,836 @@ |
||||
<Chapter> |
||||
<DocInfo> |
||||
<AuthorGroup> |
||||
<Author> |
||||
<FirstName>Linux</FirstName> |
||||
<Surname>Tolke</Surname> |
||||
</Author> |
||||
<Author> |
||||
<FirstName>Michael</FirstName> |
||||
<Surname>Meskes</Surname> |
||||
</Author> |
||||
</AuthorGroup> |
||||
<Copyright> |
||||
<Year>1996-1997</Year> |
||||
<Holder>Linus Tolke</Holder> |
||||
</Copyright> |
||||
<Copyright> |
||||
<Year>1998</Year> |
||||
<Holder>Michael Meskes</Holder> |
||||
</Copyright> |
||||
<Date>Transcribed 1998-02-12</Date> |
||||
</DocInfo> |
||||
|
||||
<Title><Application>ecpg</Application> - Embedded <Acronym>SQL</Acronym> in <Acronym>C</Acronym></Title> |
||||
|
||||
<Para> |
||||
This describes an embedded <Acronym>SQL</Acronym> in <Acronym>C</Acronym> package for <ProductName>Postgres</ProductName>. |
||||
|
||||
It is written by <ULink url="mailto:linus@epact.se">Linus Tolke</ULink> |
||||
and <ULink url="mailto:meskes@debian.org">Michael Meskes</ULink>. |
||||
|
||||
<Note> |
||||
<Para> |
||||
Permission is granted to copy and use in the same way as you are allowed |
||||
to copy and use the rest of the <ProductName>PostgreSQL</ProductName>. |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Sect1> |
||||
<Title>Why Embedded <Acronym>SQL</Acronym>?</Title> |
||||
|
||||
<Para> |
||||
Embedded <Acronym>SQL</Acronym> has some small advantages over other ways to handle <Acronym>SQL</Acronym> |
||||
queries. It takes care of all the tedious moving of information to and |
||||
from variables in your <Acronym>C</Acronym> program. Many <Acronym>RDBMS</Acronym> packages |
||||
support this embedded language. |
||||
|
||||
<Para> |
||||
There is an ANSI-standard describing how the embedded language should |
||||
work. Most embedded <Acronym>SQL</Acronym> preprocessors I have seen and heard of make |
||||
extensions so it is difficult to obtain portability between them |
||||
anyway. I have not read the standard but I hope that my implementation |
||||
does not deviate too much and that it would be possible to port programs |
||||
with embedded <Acronym>SQL</Acronym> written for other <Acronym>RDBMS</Acronym> packages |
||||
to <ProductName>Postgres</ProductName> and thus |
||||
promoting the spirit of free software. |
||||
|
||||
<Sect1> |
||||
<Title>The Concept</Title> |
||||
|
||||
<Para> |
||||
You write your program in <Acronym>C</Acronym> with some special <Acronym>SQL</Acronym> things. |
||||
For declaring variables that can be used in <Acronym>SQL</Acronym> statements you need to |
||||
put them in a special declare section. |
||||
You use a special syntax for the <Acronym>SQL</Acronym> queries. |
||||
|
||||
<Para> |
||||
Before compiling you run the file through the embedded <Acronym>SQL</Acronym> <Acronym>C</Acronym> |
||||
preprocessor and it converts the <Acronym>SQL</Acronym> statements you used to function |
||||
calls with the variables used as arguments. Both variables that are used |
||||
as input to the <Acronym>SQL</Acronym> statements and variables that will contain the |
||||
result are passed. |
||||
|
||||
<Para> |
||||
Then you compile and at link time you link with a special library that |
||||
contains the functions used. These functions (actually it is mostly one |
||||
single function) fetches the information from the arguments, performs |
||||
the <Acronym>SQL</Acronym> query using the ordinary interface (<FileName>libpq</FileName>) and puts back |
||||
the result in the arguments dedicated for output. |
||||
|
||||
<Para> |
||||
Then you run your program and when the control arrives to the <Acronym>SQL</Acronym> |
||||
statement the <Acronym>SQL</Acronym> statement is performed against the database and you |
||||
can continue with the result. |
||||
|
||||
|
||||
<Sect1> |
||||
<Title>How To Use <Application>egpc</Application></Title> |
||||
|
||||
<Para> |
||||
This section describes how to use the <Application>egpc</Application> tool. |
||||
|
||||
<Sect2> |
||||
<Title>Preprocessor |
||||
|
||||
<Para> |
||||
The preprocessor is called <Application>ecpg</Application>. After installation it resides in |
||||
the <ProductName>Postgres</ProductName> <FileName>bin/</FileName> directory. |
||||
|
||||
<Sect2> |
||||
<Title>Library |
||||
|
||||
<Para> |
||||
The <Application>ecpg</Application> library is called <FileName>libecpg.a</FileName> or |
||||
<FileName>libecpg.so</FileName>. Additionally, the library |
||||
uses the <FileName>libpq</FileName> library for communication to the |
||||
<ProductName>Postgres</ProductName> server so you will |
||||
have to link your program with <Parameter>-lecpg -lpq</Parameter>. |
||||
|
||||
<Para> |
||||
The library has some methods that are "hidden" but that could prove very |
||||
useful sometime. |
||||
|
||||
<VariableList> |
||||
<VarListEntry> |
||||
<Term>ECPGdebug(int, FILE *stream)</Term> |
||||
<ListItem> |
||||
<Para> |
||||
If this is called, with the first argument non-zero, then debuglogging is turned |
||||
on. Debuglogging is done on <Function>stream</Function>. Most <Acronym>SQL</Acronym> statement logs its |
||||
arguments and result. |
||||
|
||||
<Para> |
||||
The most important one (<Function>ECPGdo</Function>) that is called on all <Acronym>SQL</Acronym> |
||||
statements except <Command>EXEC SQL COMMIT</Command>, <Command>EXEC SQL ROLLBACK</Command>, |
||||
<Command>EXEC SQL CONNECT</Command> logs both its expanded string, i.e. the string |
||||
with all the input variables inserted, and the result from the |
||||
<ProductName>Postgres</ProductName> server. This can be very useful when searching for errors |
||||
in your <Acronym>SQL</Acronym> statements. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>ECPGstatus()</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This method returns TRUE if we are connected to a database and FALSE if not. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
</VariableList> |
||||
|
||||
<Sect2> |
||||
<Title>Error handling |
||||
|
||||
<Para> |
||||
To be able to detect errors from the <ProductName>Postgres</ProductName> server you include a line |
||||
like |
||||
<ProgramListing> |
||||
exec sql include sqlca; |
||||
</ProgramListing> |
||||
in the include section of your file. This will define a struct and a |
||||
variable with the name <Parameter>sqlca</Parameter> as following: |
||||
<ProgramListing> |
||||
struct sqlca { |
||||
int sqlcode; |
||||
struct { |
||||
int sqlerrml; |
||||
char sqlerrmc[1000]; |
||||
} sqlerrm; |
||||
} sqlca; |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
If an error occured in the last <Acronym>SQL</Acronym> statement then <Parameter>sqlca.sqlcode</Parameter> |
||||
will be non-zero. If <Parameter>sqlca.sqlcode</Parameter> is less that 0 then this is |
||||
some kind of serious error, like the database definition does not match |
||||
the query given. If it is bigger than 0 then this is a normal error like |
||||
the table did not contain the requested row. |
||||
|
||||
<Para> |
||||
sqlca.sqlerrm.sqlerrmc will contain a string that describes the error. |
||||
The string ends with <Quote>line 23.</Quote> where the line is the line number |
||||
in the source file (actually the file generated by the preprocessor but |
||||
I hope I can fix this to be the line number in the input file.) |
||||
|
||||
<Para> |
||||
List of errors that can occur: |
||||
|
||||
<VariableList> |
||||
<VarListEntry> |
||||
<Term>-1, Unsupported type %s on line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Does not normally occur. This is a sign that the preprocessor has |
||||
generated something that the library does not know about. Perhaps you |
||||
are running incompatible versions of the preprocessor and the library. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Too many arguments line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
The preprocessor has goofed up and generated some incorrect code. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Too few arguments line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
The preprocessor has goofed up and generated some incorrect code. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Error starting transaction line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
<ProductName>Postgres</ProductName> signalled to us that we cannot open the connection. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Postgres error: %s line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Some <ProductName>Postgres</ProductName> error. The message contains the error message from the |
||||
<ProductName>Postgres</ProductName> backend. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>1, Data not found line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This is a "normal" error that tells you that what you are quering cannot |
||||
be found or we have gone through the cursor. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, To many matches line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This means that the query has returned several lines. The <Command>SELECT</Command> |
||||
you made probably was not unique. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Not correctly formatted int type: %s line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This means that the host variable is of an <Type>int</Type> type and the field |
||||
in the <ProductName>Postgres</ProductName> database is of another type and contains a value that |
||||
cannot be interpreted as an <Type>int</Type>. The library uses <Function>strtol</Function> |
||||
for this conversion. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Not correctly formatted unsigned type: %s line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This means that the host variable is of an <Type>unsigned int</Type> type and |
||||
the field in the <ProductName>Postgres</ProductName> database is of another type and contains a |
||||
value that cannot be interpreted as an <Type>unsigned int</Type>. The library |
||||
uses <Function>strtoul</Function> for this conversion. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Not correctly formatted floating point type: %s line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This means that the host variable is of an <Type>float</Type> type and |
||||
the field in the <ProductName>Postgres</ProductName> database is of another type and contains a |
||||
value that cannot be interpreted as an <Type>float</Type>. The library |
||||
uses <Function>strtod</Function> for this conversion. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Too few arguments line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This means that <ProductName>Postgres</ProductName> has returned more records than we have |
||||
matching variables. Perhaps you have forgotten a couple of the host |
||||
variables in the <Command>INTO :var1,:var2</Command>-list. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Too many arguments line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This means that <ProductName>Postgres</ProductName> has returned fewer records than we have |
||||
host variables. Perhaps you have to many host variables in the |
||||
<Command>INTO :var1,:var2</Command>-list. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Empty query line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
<ProductName>Postgres</ProductName> returned PGRES_EMPTY_QUERY. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Error: %s line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This means that <ProductName>Postgres</ProductName> returned on of the errors |
||||
PGRES_NONFATAL_ERROR, PGRES_FATAL_ERROR or PGRES_BAD_RESPONSE. Which one |
||||
and why is explained in the message. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Postgres error line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
<ProductName>Postgres</ProductName> returns something that the library does not know how to |
||||
handle. This is probably because the version of <ProductName>Postgres</ProductName> does not |
||||
match the version of the <Application>ecpg</Application> library. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Error committing line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Error during <Command>COMMIT</Command>. <Command>EXEC SQL COMMIT</Command> is translated to an |
||||
<Command>end</Command> operation in <ProductName>Postgres</ProductName> and that is the operation that could |
||||
not be performed. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, Error rolling back line %d.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Error during <Command>ROLLBACK</Command>. <Command>EXEC SQL ROLLBACK</Command> is translated to |
||||
an <Command>abort</Command> operation in <ProductName>Postgres</ProductName> and that is the operation that |
||||
could not be performed. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>-1, ECPGconnect: could not open database %s.</Term> |
||||
<ListItem> |
||||
<Para> |
||||
The connect to the database did not work. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
</VariableList> |
||||
|
||||
</Sect2> |
||||
|
||||
<Sect1> |
||||
<Title>Limitations</Title> |
||||
|
||||
<Para> |
||||
What will never be included and why or what cannot be done with this |
||||
concept. |
||||
|
||||
<VariableList> |
||||
<VarListEntry> |
||||
<Term>oracles single tasking possibility</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Oracle version 7.0 on AIX 3 uses the OS-supported locks on the shared |
||||
memory segments and allows the application designer to link an |
||||
application in a so called single tasking way. Instead of starting one |
||||
client process per application process both the database part and the |
||||
application part is run in the same process. In later versions of oracle |
||||
this is no longer supported. |
||||
|
||||
<Para> |
||||
This would require a total redesign of the <ProductName>Postgres</ProductName> access model and |
||||
that effort can not justify the performance gained. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
</VariableList> |
||||
|
||||
<Sect1> |
||||
<Title>Porting From Other <Acronym>RDBMS</Acronym> Packages</Title> |
||||
|
||||
<Para> |
||||
To be written by persons that knows the different <Acronym>RDBMS</Acronym> packages and that |
||||
actually does port something... |
||||
|
||||
<Sect1> |
||||
<Title>Installation</Title> |
||||
|
||||
<Para> |
||||
Since version 0.5 <Application>ecpg</Application> is distributed together with <ProductName>Postgres</ProductName>. So you |
||||
should get your precompiler, libraries and header files compiled and |
||||
installed on the fly. |
||||
|
||||
<Sect1> |
||||
<Title>For the Developer</Title> |
||||
|
||||
<Para> |
||||
This section is for those that wants to develop the <Application>ecpg</Application> interface. It |
||||
describes how the things work. The ambition is to make this section |
||||
contain things for those that want to have a look inside and the section |
||||
on How to use it should be enough for all normal questions. |
||||
|
||||
So, read this before looking at the internals of the <Application>ecpg</Application>. If |
||||
you are not interested in how it really works, skip this section. |
||||
|
||||
<Sect2> |
||||
<Title>ToDo List</Title> |
||||
|
||||
<Para> |
||||
This version the preprocessor has some flaws: |
||||
|
||||
<VariableList> |
||||
<VarListEntry> |
||||
<Term>Preprocessor output</Term> |
||||
<ListItem> |
||||
<Para> |
||||
The variables should be static. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Preprocessor cannot do syntax checking on your <Acronym>SQL</Acronym> statements</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Whatever you write is copied more or less exactly to the <ProductName>Postgres</ProductName> and |
||||
you will not be able to locate your errors until run-time. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>no restriction to strings only</Term> |
||||
<ListItem> |
||||
<Para> |
||||
The PQ interface, and most of all the PQexec function, that is used by |
||||
the <Application>ecpg</Application> relies on that the request is built up as a string. In some |
||||
cases, like when the data contains the null character, this will be a |
||||
serious problem. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>error codes</Term> |
||||
<ListItem> |
||||
<Para> |
||||
There should be different error numbers for the different errors instead |
||||
of just -1 for them all. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>library functions</Term> |
||||
<ListItem> |
||||
<Para> |
||||
to_date et al. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>records</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Possibility to define records or structures in the declare section |
||||
in a way that the record can be filled from one row in the database. |
||||
|
||||
<Para> |
||||
This is a simpler way to handle an entire row at a time. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>array operations</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Oracle has array operations that enhances speed. When implementing it in |
||||
<Application>ecpg</Application> it is done for compatibility reasons only. For them to |
||||
improve speed would require a lot more insight in the <ProductName>Postgres</ProductName> internal |
||||
mechanisms than I possess. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>indicator variables</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Oracle has indicator variables that tell if a value is <Type>null</Type> or if |
||||
it is empty. This largely simplifies array operations and provides for a |
||||
way to hack around some design flaws in the handling of <Type>VARCHAR2</Type> |
||||
(like that an empty string isn't distinguishable from a |
||||
<Type>null</Type> value). I am not sure if this is an Oracle extension or part |
||||
of the ANSI standard. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>typedefs</Term> |
||||
<ListItem> |
||||
<Para> |
||||
As well as complex types like records and arrays, typedefs would be |
||||
a good thing to take care of. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>conversion of scripts</Term> |
||||
<ListItem> |
||||
<Para> |
||||
To set up a database you need a few scripts with table definitions and |
||||
other configuration parameters. If you have these scripts for an old |
||||
database you would like to just apply them to get a <ProductName>Postgres</ProductName> database |
||||
that works in the same way. |
||||
|
||||
<Para> |
||||
To set up a database you need a few scripts with table definitions and |
||||
The functionality could be accomplished with some conversion scripts. |
||||
Speed will never be accomplished in this way. To do this you need a |
||||
bigger insight in the database construction and the use of the database |
||||
than could be realised in a script. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
</VariableList> |
||||
|
||||
<Sect2> |
||||
<Title>The Preprocessor</Title> |
||||
|
||||
<Para> |
||||
First four lines are written to the output. Two comments and two include |
||||
lines necessary for the interface to the library. |
||||
|
||||
<Para> |
||||
Then the preprocessor works in one pass only reading the input file and |
||||
writing to the output as it goes along. Normally it just echoes |
||||
everything to the output without looking at it further. |
||||
|
||||
<Para> |
||||
When it comes to an <Command>EXEC SQL</Command> statements it interviens and |
||||
changes them depending on what iit is. The <Command>EXEC SQL</Command> statement can |
||||
be one of these: |
||||
|
||||
<VariableList> |
||||
<VarListEntry> |
||||
<Term>Declare sections</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Declare sections begins with |
||||
<ProgramListing> |
||||
exec sql begin declare section; |
||||
</ProgramListing> |
||||
and ends with |
||||
<ProgramListing> |
||||
exec sql end declare section; |
||||
</ProgramListing> |
||||
In the section only variable declarations are allowed. Every variable |
||||
declare within this section is also entered in a list of variables |
||||
indexed on their name together with the corresponding type. |
||||
|
||||
<Para> |
||||
The declaration is echoed to the file to make the variable a normal |
||||
C-variable also. |
||||
|
||||
<Para> |
||||
The special types VARCHAR and VARCHAR2 are converted into a named struct |
||||
for every variable. A declaration like: |
||||
<ProgramListing> |
||||
VARCHAR var[180]; |
||||
</ProgramListing> |
||||
is converted into |
||||
<ProgramListing> |
||||
struct varchar_var { int len; char arr[180]; } var; |
||||
</ProgramListing> |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Include statements</Term> |
||||
<ListItem> |
||||
<Para> |
||||
An include statement looks like: |
||||
<ProgramListing> |
||||
exec sql include filename; |
||||
</ProgramListing> |
||||
It is converted into |
||||
<ProgramListing> |
||||
#include <filename.h> |
||||
</ProgramListing> |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Connect statement</Term> |
||||
<ListItem> |
||||
<Para> |
||||
A connect statement looks like: |
||||
<ProgramListing> |
||||
exec sql connect '<Replaceable>database</Replaceable>'; |
||||
</ProgramListing> |
||||
That statement is converted into |
||||
<ProgramListing> |
||||
ECPGconnect("<Replaceable>database</Replaceable>"); |
||||
</ProgramListing> |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Open cursor statement</Term> |
||||
<ListItem> |
||||
<Para> |
||||
An open cursor statement looks like: |
||||
<ProgramListing> |
||||
exec sql open <Replaceable>cursor</Replaceable>; |
||||
</ProgramListing> |
||||
and is ignore and not copied from the output. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Commit statement</Term> |
||||
<ListItem> |
||||
<Para> |
||||
A commit statement looks like |
||||
<ProgramListing> |
||||
exec sql commit; |
||||
</ProgramListing> |
||||
and is translated on the output to |
||||
<ProgramListing> |
||||
ECPGcommit(__LINE__); |
||||
</ProgramListing> |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Rollback statement</Term> |
||||
<ListItem> |
||||
<Para> |
||||
A rollback statement looks like |
||||
<ProgramListing> |
||||
exec sql rollback; |
||||
</ProgramListing> |
||||
and is translated on the output to |
||||
<ProgramListing> |
||||
ECPGrollback(__LINE__); |
||||
</ProgramListing> |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Other statements</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Other <Acronym>SQL</Acronym> statements are other statements that start with |
||||
<Command>exec sql</Command> and ends with <Command>;</Command>. Everything inbetween is treated |
||||
as an <Acronym>SQL</Acronym> statement and parsed for variable substitution. |
||||
|
||||
<Para> |
||||
Variable substitution occur when a symbol starts with a colon |
||||
(<Command>:</Command>). Then a variable with that name is found among the variables |
||||
that were previously declared within a declare section and depending on |
||||
whether or not the <Acronym>SQL</Acronym> statements knows it to be a variable for input or |
||||
output the pointers to the variables are written to the output to allow |
||||
for access by the function. |
||||
|
||||
<Para> |
||||
For every variable that is part of the <Acronym>SQL</Acronym> request the function gets |
||||
another five arguments. |
||||
|
||||
<SimpleList> |
||||
<Member>The type as a special symbol</Member> |
||||
<Member>A pointer to the value</Member> |
||||
<Member>The size of the variable if it is a varchar</Member> |
||||
<Member>Number of elements in the array (for array fetches)</Member> |
||||
<Member>The offset to the next element in the array (for array fetches)</Member> |
||||
</SimpleList> |
||||
|
||||
<Para> |
||||
Since the array fetches are not implemented yet the two last arguments |
||||
are not really important. They could perhaps have been left out. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
</VariableList> |
||||
|
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>A Complete Example</Title> |
||||
|
||||
<Para> |
||||
Here is a complete example describing the output of the preprocessor: |
||||
<ProgramListing> |
||||
exec sql begin declare section; |
||||
int index; |
||||
int result; |
||||
exec sql end declare section; |
||||
... |
||||
exec sql select res into :result from mytable where index = :index; |
||||
</ProgramListing> |
||||
is translated into: |
||||
<ProgramListing> |
||||
/* These two include files are added by the preprocessor */ |
||||
#include <ecpgtype.h> |
||||
#include <ecpglib.h> |
||||
/* exec sql begin declare section */ |
||||
|
||||
int index; |
||||
int result; |
||||
/* exec sql end declare section */ |
||||
|
||||
... |
||||
ECPGdo(__LINE__, "select res from mytable where index = ;;", |
||||
ECPGt_int,&index,0,0,sizeof(int), |
||||
ECPGt_EOIT, |
||||
ECPGt_int,&result,0,0,sizeof(int), |
||||
ECPGt_EORT ); |
||||
</ProgramListing> |
||||
(the indentation in this manual is added for readability and not |
||||
something that the preprocessor can do.) |
||||
|
||||
<Sect2> |
||||
<Title>The Library</Title> |
||||
|
||||
<Para> |
||||
The most important function in the library is the <Function>ECPGdo</Function> |
||||
function. It takes a variable amount of arguments. Hopefully we wont run |
||||
into machines with limits on the amount of variables that can be |
||||
accepted by a varchar function. This could easily add up to 50 or so |
||||
arguments. |
||||
|
||||
<Para> |
||||
The arguments are: |
||||
|
||||
<VariableList> |
||||
<VarListEntry> |
||||
<Term>A line number</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This is a line number for the original line used in error messages only. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>A string</Term> |
||||
<ListItem> |
||||
<Para> |
||||
This is the <Acronym>SQL</Acronym> request that is to be issued. This request is modified |
||||
by the input variables, i.e. the variables that where not known at |
||||
compile time but are to be entered in the request. Where the variables |
||||
should go the string contains <Quote>;</Quote>. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Input variables</Term> |
||||
<ListItem> |
||||
<Para> |
||||
As described in the section about the preprocessor every input variable |
||||
gets five arguments. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>ECPGt_EOIT</Term> |
||||
<ListItem> |
||||
<Para> |
||||
An enum telling that there are no more input variables. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Output variables</Term> |
||||
<ListItem> |
||||
<Para> |
||||
As described in the section about the preprocessor every input variable |
||||
gets five arguments. These variables are filled by the function. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>ECPGt_EORT</Term> |
||||
<ListItem> |
||||
<Para> |
||||
An enum telling that there are no more variables. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
</VariableList> |
||||
|
||||
<Para> |
||||
All the <Acronym>SQL</Acronym> statements are performed in one transaction unless you issue |
||||
a commit transaction. This works so that the first transaction or the |
||||
first after a commit or rollback always begins a transaction. |
||||
|
||||
<Para> |
||||
To be completed: entries describing the other entries. |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,62 @@ |
||||
<Chapter> |
||||
<Title>Setting Up Your Environment</Title> |
||||
|
||||
<Para> |
||||
This section discusses how to set up |
||||
your own environment so that you can use frontend |
||||
applications. We assume <ProductName>Postgres</ProductName> has already been |
||||
successfully installed and started; refer to the Administrator's Guide |
||||
and the installation notes |
||||
for how to install Postgres. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> is a client/server application. As a user, |
||||
you only need access to the client portions of the installation (an example |
||||
of a client application is the interactive monitor <Application>psql</Application>). |
||||
For simplicity, |
||||
we will assume that <ProductName>Postgres</ProductName> has been installed in the |
||||
directory <FileName>/usr/local/pgsql</FileName>. Therefore, wherever |
||||
you see the directory <FileName>/usr/local/pgsql</FileName> you should |
||||
substitute the name of the directory where <ProductName>Postgres</ProductName> is |
||||
actually installed. |
||||
All <ProductName>Postgres</ProductName> commands are installed in the directory |
||||
<FileName>/usr/local/pgsql/bin</FileName>. Therefore, you should add |
||||
this directory to your shell command path. If you use |
||||
a variant of the Berkeley C shell, such as <Application>csh</Application> or <Application>tcsh</Application>, |
||||
you would add |
||||
<ProgramListing> |
||||
set path = ( /usr/local/pgsql/bin path ) |
||||
</ProgramListing> |
||||
in the <FileName>.login</FileName> file in your home directory. If you use |
||||
a variant of the Bourne shell, such as <Application>sh</Application>, <Application>ksh</Application>, or |
||||
<Application>bash</Application>, then you would add |
||||
<ProgramListing> |
||||
PATH=/usr/local/pgsql/bin PATH |
||||
export PATH |
||||
</ProgramListing> |
||||
to the <FileName>.profile</FileName> file in your home directory. |
||||
From now on, we will assume that you have added the |
||||
<ProductName>Postgres</ProductName> bin directory to your path. In addition, we |
||||
will make frequent reference to <Quote>setting a shell |
||||
variable</Quote> or <Quote>setting an environment variable</Quote> throughout |
||||
this document. If you did not fully understand the |
||||
last paragraph on modifying your search path, you |
||||
should consult the UNIX manual pages that describe your |
||||
shell before going any further. |
||||
</Para> |
||||
|
||||
<Para> |
||||
If your site administrator has not set things up in the |
||||
default way, you may have some more work to do. For example, if the database |
||||
server machine is a remote machine, you |
||||
will need to set the <Acronym>PGHOST</Acronym> environment variable to the name |
||||
of the database server machine. The environment variable |
||||
<Acronym>PGPORT</Acronym> may also have to be set. The bottom line is this: if |
||||
you try to start an application program and it complains |
||||
that it cannot connect to the <Application>postmaster</Application>, |
||||
you should immediately consult your site administrator to make sure that your |
||||
environment is properly set up. |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,250 @@ |
||||
<Chapter> |
||||
<Title>Extending <Acronym>SQL</Acronym>: An Overview</Title> |
||||
|
||||
<Para> |
||||
In the sections that follow, we will discuss how you |
||||
can extend the <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> query language by adding: |
||||
<ItemizedList Mark="bullet" Spacing="compact"> |
||||
<ListItem> |
||||
<Para> |
||||
functions |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
types |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
operators |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
aggregates |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>How Extensibility Works</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> is extensible because its operation is |
||||
catalog-driven. If you are familiar with standard |
||||
relational systems, you know that they store information |
||||
about databases, tables, columns, etc., in what are |
||||
commonly known as system catalogs. (Some systems call |
||||
this the data dictionary). The catalogs appear to the |
||||
user as classes, like any other, but the <Acronym>DBMS</Acronym> stores |
||||
its internal bookkeeping in them. One key difference |
||||
between <ProductName>Postgres</ProductName> and standard relational systems is |
||||
that <ProductName>Postgres</ProductName> stores much more information in its |
||||
catalogs -- not only information about tables and columns, |
||||
but also information about its types, functions, access |
||||
methods, and so on. These classes can be modified by |
||||
the user, and since <ProductName>Postgres</ProductName> bases its internal operation |
||||
on these classes, this means that <ProductName>Postgres</ProductName> can be |
||||
extended by users. By comparison, conventional |
||||
database systems can only be extended by changing hardcoded |
||||
procedures within the <Acronym>DBMS</Acronym> or by loading modules |
||||
specially-written by the <Acronym>DBMS</Acronym> vendor. |
||||
</Para> |
||||
<Para> |
||||
<ProductName>Postgres</ProductName> is also unlike most other data managers in |
||||
that the server can incorporate user-written code into |
||||
itself through dynamic loading. That is, the user can |
||||
specify an object code file (e.g., a compiled .o file |
||||
or shared library) that implements a new type or function |
||||
and <ProductName>Postgres</ProductName> will load it as required. Code written |
||||
in <Acronym>SQL</Acronym> are even more trivial to add to the server. |
||||
This ability to modify its operation "on the fly" makes |
||||
<ProductName>Postgres</ProductName> uniquely suited for rapid prototyping of new |
||||
applications and storage structures. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>The <ProductName>Postgres</ProductName> Type System</Title> |
||||
|
||||
<Para> |
||||
The <ProductName>Postgres</ProductName> type system can be broken down in several ways. |
||||
Types are divided into base types and composite types. |
||||
Base types are those, like <FirstTerm>int4</FirstTerm>, that are implemented |
||||
in a language such as <ProductName>C</ProductName>. They generally correspond to |
||||
what are often known as "abstract data types"; <ProductName>Postgres</ProductName> |
||||
can only operate on such types through methods provided |
||||
by the user and only understands the behavior of such |
||||
types to the extent that the user describes them. |
||||
Composite types are created whenever the user creates a |
||||
class. EMP is an example of a composite type. |
||||
</Para> |
||||
<Para> |
||||
<ProductName>Postgres</ProductName> stores these types in only one way (within the |
||||
file that stores all instances of the class) but the |
||||
user can "look inside" at the attributes of these types |
||||
from the query language and optimize their retrieval by |
||||
(for example) defining indices on the attributes. |
||||
<ProductName>Postgres</ProductName> base types are further divided into built-in |
||||
types and user-defined types. Built-in types (like |
||||
<FirstTerm>int4</FirstTerm>) are those that are compiled into the system. |
||||
User-defined types are those created by the user in the |
||||
manner to be described below. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>About the <ProductName>Postgres</ProductName> System Catalogs</Title> |
||||
|
||||
<Para> |
||||
Having introduced the basic extensibility concepts, we |
||||
can now take a look at how the catalogs are actually |
||||
laid out. You can skip this section for now, but some |
||||
later sections will be incomprehensible without the |
||||
information given here, so mark this page for later |
||||
reference. |
||||
All system catalogs have names that begin with <FirstTerm>pg_</FirstTerm>. |
||||
The following classes contain information that may be |
||||
useful to the end user. (There are many other system |
||||
catalogs, but there should rarely be a reason to query |
||||
them directly.) |
||||
|
||||
<TABLE TOCENTRY="1"> |
||||
<TITLE>Postgres System Catalogs</TITLE> |
||||
<TITLEABBREV>Catalogs</TITLEABBREV> |
||||
<TGROUP COLS="2"> |
||||
<THEAD> |
||||
<ROW> |
||||
<ENTRY>Catalog Name</ENTRY> |
||||
<ENTRY>Description</ENTRY> |
||||
</ROW> |
||||
</THEAD> |
||||
<TBODY> |
||||
<ROW> |
||||
<ENTRY>pg_database</ENTRY> |
||||
<ENTRY> databases</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_class</ENTRY> |
||||
<ENTRY> classes</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_attribute</ENTRY> |
||||
<ENTRY> class attributes</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_index</ENTRY> |
||||
<ENTRY> secondary indices</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_proc</ENTRY> |
||||
<ENTRY> procedures (both C and SQL)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_type</ENTRY> |
||||
<ENTRY> types (both base and complex)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_operator</ENTRY> |
||||
<ENTRY> operators</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_aggregate</ENTRY> |
||||
<ENTRY> aggregates and aggregate functions</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_am</ENTRY> |
||||
<ENTRY> access methods</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_amop</ENTRY> |
||||
<ENTRY> access method operators</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_amproc</ENTRY> |
||||
<ENTRY> access method support functions</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>pg_opclass</ENTRY> |
||||
<ENTRY> access method operator classes</ENTRY> |
||||
</ROW> |
||||
</TBODY> |
||||
</TGROUP> |
||||
</TABLE> |
||||
</Para> |
||||
|
||||
<Para> |
||||
<Figure Id="EXTEND-CATALOGS" Float="1"> |
||||
<Title>The major <ProductName>Postgres</ProductName> system catalogs</Title> |
||||
<Graphic Align="center" FileRef="catalogs.gif" Format="GIF"></Graphic> |
||||
</Figure> |
||||
|
||||
The Reference Manual gives a more detailed explanation |
||||
of these catalogs and their attributes. However, |
||||
<XRef LinkEnd="EXTEND-CATALOGS" EndTerm="EXTEND-CATALOGS"> |
||||
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"> |
||||
<ListItem> |
||||
<Para> |
||||
In several of the sections that follow, we will |
||||
present various join queries on the system |
||||
catalogs that display information we need to extend |
||||
the system. Looking at this diagram should make |
||||
some of these join queries (which are often |
||||
three- or four-way joins) more understandable, |
||||
because you will be able to see that the |
||||
attributes used in the queries form foreign keys |
||||
in other classes. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> Many different features (classes, attributes, |
||||
functions, types, access methods, etc.) are |
||||
tightly integrated in this schema. A simple |
||||
create command may modify many of these catalogs. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> Types and procedures |
||||
are central to the schema. |
||||
|
||||
<Note> |
||||
<Para> |
||||
We use the words <FirstTerm>procedure</FirstTerm> and <FirstTerm>function</FirstTerm> more or less |
||||
interchangably. |
||||
</Para> |
||||
</Note> |
||||
|
||||
Nearly every catalog contains some reference to |
||||
instances in one or both of these classes. For |
||||
example, <ProductName>Postgres</ProductName> frequently uses type |
||||
signatures (e.g., of functions and operators) to |
||||
identify unique instances of other catalogs. |
||||
|
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> There are many attributes and relationships that |
||||
have obvious meanings, but there are many |
||||
(particularly those that have to do with access |
||||
methods) that do not. The relationships between |
||||
pg_am, pg_amop, pg_amproc, pg_operator and |
||||
pg_opclass are particularly hard to understand |
||||
and will be described in depth (in the section |
||||
on interfacing types and operators to indices) |
||||
after we have discussed basic extensions. |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
</Para> |
||||
</Chapter> |
||||
@ -0,0 +1,19 @@ |
||||
<Chapter> |
||||
<Title>Functions</Title> |
||||
|
||||
<Abstract> |
||||
<Para> |
||||
Reference information for user-callable functions. |
||||
</Para> |
||||
</Abstract> |
||||
|
||||
<Note> |
||||
<Para> |
||||
This section needs to be written. Volunteers? |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,228 @@ |
||||
<Chapter> |
||||
<DocInfo> |
||||
<Author> |
||||
<FirstName>Martin</FirstName> |
||||
<SurName>Utesch</SurName> |
||||
</Author> |
||||
</DocInfo> |
||||
|
||||
<Title>Genetic Query Optimization in Database Systems</Title> |
||||
|
||||
<Para> |
||||
<ProgramListing> |
||||
<ULink url="utesch@aut.tu-freiberg.de">Martin Utesch</ULink> |
||||
|
||||
Institute of Automatic Control |
||||
University of Mining and Technology |
||||
Freiberg, Germany |
||||
|
||||
02/10/1997 |
||||
|
||||
|
||||
1.) Query Handling as a Complex Optimization Problem |
||||
==================================================== |
||||
|
||||
Among all relational operators the most difficult one to process and |
||||
optimize is the JOIN. The number of alternative plans to answer a query |
||||
grows exponentially with the number of JOINs included in it. Further |
||||
optimization effort is caused by the support of a variety of *JOIN |
||||
methods* (e.g., nested loop, index scan, merge join in Postgres) to |
||||
process individual JOINs and a diversity of *indices* (e.g., r-tree, |
||||
b-tree, hash in Postgres) as access paths for relations. |
||||
|
||||
The current Postgres optimizer implementation performs a *near- |
||||
exhaustive search* over the space of alternative strategies. This query |
||||
optimization technique is inadequate to support database application |
||||
domains that involve the need for extensive queries, such as artificial |
||||
intelligence. |
||||
|
||||
The Institute of Automatic Control at the University of Mining and |
||||
Technology, in Freiberg, Germany, encountered the described problems as its |
||||
folks wanted to take the Postgres DBMS as the backend for a decision |
||||
support knowledge based system for the maintenance of an electrical |
||||
power grid. The DBMS needed to handle large JOIN queries for the |
||||
inference machine of the knowledge based system. |
||||
|
||||
Performance difficulties within exploring the space of possible query |
||||
plans arose the demand for a new optimization technique being developed. |
||||
|
||||
In the following we propose the implementation of a *Genetic |
||||
Algorithm* as an option for the database query optimization problem. |
||||
|
||||
|
||||
2.) Genetic Algorithms (GA) |
||||
=========================== |
||||
|
||||
The GA is a heuristic optimization method which operates through |
||||
determined, randomized search. The set of possible solutions for the |
||||
optimization problem is considered as a *population* of *individuals*. |
||||
The degree of adaption of an individual to its environment is specified |
||||
by its *fitness*. |
||||
|
||||
The coordinates of an individual in the search space are represented |
||||
by *chromosomes*, in essence a set of character strings. A *gene* is a |
||||
subsection of a chromosome which encodes the value of a single parameter |
||||
being optimized. Typical encodings for a gene could be *binary* or |
||||
*integer*. |
||||
|
||||
Through simulation of the evolutionary operations *recombination*, |
||||
*mutation*, and *selection* new generations of search points are found |
||||
that show a higher average fitness than their ancestors. |
||||
|
||||
According to the "comp.ai.genetic" FAQ it cannot be stressed too |
||||
strongly that a GA is not a pure random search for a solution to a |
||||
problem. A GA uses stochastic processes, but the result is distinctly |
||||
non-random (better than random). |
||||
|
||||
Structured Diagram of a GA: |
||||
--------------------------- |
||||
|
||||
P(t) generation of ancestors at a time t |
||||
P''(t) generation of descendants at a time t |
||||
|
||||
+=========================================+ |
||||
|>>>>>>>>>>> Algorithm GA <<<<<<<<<<<<<<| |
||||
+=========================================+ |
||||
| INITIALIZE t := 0 | |
||||
+=========================================+ |
||||
| INITIALIZE P(t) | |
||||
+=========================================+ |
||||
| evalute FITNESS of P(t) | |
||||
+=========================================+ |
||||
| while not STOPPING CRITERION do | |
||||
| +-------------------------------------+ |
||||
| | P'(t) := RECOMBINATION{P(t)} | |
||||
| +-------------------------------------+ |
||||
| | P''(t) := MUTATION{P'(t)} | |
||||
| +-------------------------------------+ |
||||
| | P(t+1) := SELECTION{P''(t) + P(t)} | |
||||
| +-------------------------------------+ |
||||
| | evalute FITNESS of P''(t) | |
||||
| +-------------------------------------+ |
||||
| | t := t + 1 | |
||||
+===+=====================================+ |
||||
|
||||
|
||||
3.) Genetic Query Optimization (GEQO) in PostgreSQL |
||||
=================================================== |
||||
|
||||
The GEQO module is intended for the solution of the query |
||||
optimization problem similar to a traveling salesman problem (TSP). |
||||
Possible query plans are encoded as integer strings. Each string |
||||
represents the JOIN order from one relation of the query to the next. |
||||
E. g., the query tree /\ |
||||
/\ 2 |
||||
/\ 3 |
||||
4 1 is encoded by the integer string '4-1-3-2', |
||||
which means, first join relation '4' and '1', then '3', and |
||||
then '2', where 1, 2, 3, 4 are relids in PostgreSQL. |
||||
|
||||
Parts of the GEQO module are adapted from D. Whitley's Genitor |
||||
algorithm. |
||||
|
||||
Specific characteristics of the GEQO implementation in PostgreSQL |
||||
are: |
||||
|
||||
o usage of a *steady state* GA (replacement of the least fit |
||||
individuals in a population, not whole-generational replacement) |
||||
allows fast convergence towards improved query plans. This is |
||||
essential for query handling with reasonable time; |
||||
|
||||
o usage of *edge recombination crossover* which is especially suited |
||||
to keep edge losses low for the solution of the TSP by means of a GA; |
||||
|
||||
o mutation as genetic operator is deprecated so that no repair |
||||
mechanisms are needed to generate legal TSP tours. |
||||
|
||||
The GEQO module gives the following benefits to the PostgreSQL DBMS |
||||
compared to the Postgres query optimizer implementation: |
||||
|
||||
o handling of large JOIN queries through non-exhaustive search; |
||||
|
||||
o improved cost size approximation of query plans since no longer |
||||
plan merging is needed (the GEQO module evaluates the cost for a |
||||
query plan as an individual). |
||||
|
||||
|
||||
References |
||||
========== |
||||
|
||||
J. Heitk"otter, D. Beasley: |
||||
--------------------------- |
||||
"The Hitch-Hicker's Guide to Evolutionary Computation", |
||||
FAQ in 'comp.ai.genetic', |
||||
'ftp://ftp.Germany.EU.net/pub/research/softcomp/EC/Welcome.html' |
||||
|
||||
Z. Fong: |
||||
-------- |
||||
"The Design and Implementation of the Postgres Query Optimizer", |
||||
file 'planner/Report.ps' in the 'postgres-papers' distribution |
||||
|
||||
R. Elmasri, S. Navathe: |
||||
----------------------- |
||||
"Fundamentals of Database Systems", |
||||
The Benjamin/Cummings Pub., Inc. |
||||
|
||||
|
||||
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= |
||||
* Things left to done for the PostgreSQL * |
||||
= Genetic Query Optimization (GEQO) = |
||||
* module implementation * |
||||
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= |
||||
* Martin Utesch * Institute of Automatic Control * |
||||
= = University of Mining and Technology = |
||||
* utesch@aut.tu-freiberg.de * Freiberg, Germany * |
||||
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= |
||||
|
||||
|
||||
1.) Basic Improvements |
||||
=============================================================== |
||||
|
||||
a) improve freeing of memory when query is already processed: |
||||
------------------------------------------------------------- |
||||
with large JOIN queries the computing time spent for the genetic query |
||||
optimization seems to be a mere *fraction* of the time Postgres |
||||
needs for freeing memory via routine 'MemoryContextFree', |
||||
file 'backend/utils/mmgr/mcxt.c'; |
||||
debugging showed that it get stucked in a loop of routine |
||||
'OrderedElemPop', file 'backend/utils/mmgr/oset.c'; |
||||
the same problems arise with long queries when using the normal |
||||
Postgres query optimization algorithm; |
||||
|
||||
b) improve genetic algorithm parameter settings: |
||||
------------------------------------------------ |
||||
file 'backend/optimizer/geqo/geqo_params.c', routines |
||||
'gimme_pool_size' and 'gimme_number_generations'; |
||||
we have to find a compromise for the parameter settings |
||||
to satisfy two competing demands: |
||||
1. optimality of the query plan |
||||
2. computing time |
||||
|
||||
c) find better solution for integer overflow: |
||||
--------------------------------------------- |
||||
file 'backend/optimizer/geqo/geqo_eval.c', routine |
||||
'geqo_joinrel_size'; |
||||
the present hack for MAXINT overflow is to set the Postgres integer |
||||
value of 'rel->size' to its logarithm; |
||||
modifications of 'struct Rel' in 'backend/nodes/relation.h' will |
||||
surely have severe impacts on the whole PostgreSQL implementation. |
||||
|
||||
d) find solution for exhausted memory: |
||||
-------------------------------------- |
||||
that may occur with more than 10 relations involved in a query, |
||||
file 'backend/optimizer/geqo/geqo_eval.c', routine |
||||
'gimme_tree' which is recursively called; |
||||
maybe I forgot something to be freed correctly, but I dunno what; |
||||
of course the 'rel' data structure of the JOIN keeps growing and |
||||
growing the more relations are packed into it; |
||||
suggestions are welcome :-( |
||||
|
||||
|
||||
2.) Further Improvements |
||||
=============================================================== |
||||
Enable bushy query tree processing within PostgreSQL; |
||||
that may improve the quality of query plans. |
||||
|
||||
</ProgramListing> |
||||
</Para> |
||||
</Chapter> |
||||
@ -0,0 +1,98 @@ |
||||
<Chapter> |
||||
<DocInfo> |
||||
<AuthorGroup> |
||||
<Author> |
||||
<FirstName>Gene</FirstName> |
||||
<Surname>Selkov</Surname> |
||||
</Author> |
||||
</AuthorGroup> |
||||
<Date>Transcribed 1998-02-19</Date> |
||||
</DocInfo> |
||||
<Title>GiST Indices</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Title>Caveat</Title> |
||||
<Para> |
||||
This extraction from an e-mail sent by |
||||
<ULink url="mailto:selkovjr@mcs.anl.gov">Eugene Selkov Jr.</ULink> |
||||
contains good information |
||||
on GiST. Hopefully we will learn more in the future and update this information. |
||||
- thomas |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
Well, I can't say I quite understand what's going on, but at least |
||||
I (almost) succeeded in porting GiST examples to linux. The GiST access |
||||
method is already in the postgres tree (<FileName>src/backend/access/gist</FileName>). |
||||
|
||||
<Para> |
||||
<ULink url="ftp://s2k-ftp.cs.berkeley.edu/pub/gist/pggist/pggist.tgz">Examples at Berkeley</ULink> |
||||
come with an overview of the methods and demonstrate spatial index |
||||
mechanisms for 2D boxes, polygons, integer intervals and text |
||||
(see also <ULink url="http://gist.cs.berkeley.edu:8000/gist/">GiST at Berkeley</ULink>). |
||||
In the box example, we |
||||
are supposed to see a performance gain when using the GiST index; it did |
||||
work for me but I do not have a reasonably large collection of boxes |
||||
to check that. Other examples also worked, except polygons: I got an |
||||
error doing |
||||
|
||||
<ProgramListing> |
||||
test=> create index pix on polytmp using gist (p:box gist_poly_ops) with |
||||
(islossy); |
||||
ERROR: cannot open pix |
||||
|
||||
(PostgreSQL 6.3 Sun Feb 1 14:57:30 EST 1998) |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
I could not get sense of this error message; it appears to be something |
||||
we'd rather ask the developers about (see also Note 4 below). What I |
||||
would suggest here is that someone of you linux guys (linux==gcc?) fetch the |
||||
original sources quoted above and apply my patch (see attachment) and |
||||
tell us what you feel about it. Looks cool to me, but I would not like |
||||
to hold it up while there are so many competent people around. |
||||
|
||||
<Para> |
||||
A few notes on the sources: |
||||
|
||||
<Para> |
||||
1. I failed to make use of the original (HPUX) Makefile and rearranged |
||||
the Makefile from the ancient postgres95 tutorial to do the job. I |
||||
tried |
||||
to keep it generic, but I am a very poor makefile writer -- just did |
||||
some monkey work. Sorry about that, but I guess it is now a little |
||||
more portable that the original makefile. |
||||
|
||||
<Para> |
||||
2. I built the example sources right under pgsql/src (just extracted the |
||||
tar file there). The aforementioned Makefile assumes it is one level |
||||
below pgsql/src (in our case, in pgsql/src/pggist). |
||||
|
||||
<Para> |
||||
3. The changes I made to the *.c files were all about #include's, |
||||
function prototypes and typecasting. Other than that, I just threw |
||||
away a bunch of unused vars and added a couple parentheses to please |
||||
gcc. I hope I did not screw up too much :) |
||||
|
||||
<Para> |
||||
4. There is a comment in polyproc.sql: |
||||
|
||||
<ProgramListing> |
||||
-- -- there's a memory leak in rtree poly_ops!! |
||||
-- -- create index pix2 on polytmp using rtree (p poly_ops); |
||||
</ProgramListing> |
||||
|
||||
Roger that!! I thought it could be related to a number of |
||||
<ProductName>Postgres</ProductName> versions |
||||
back and tried the query. My system went nuts and I had to shoot down |
||||
the postmaster in about ten minutes. |
||||
|
||||
|
||||
<Para> |
||||
I will continue to look into GiST for a while, but I would also |
||||
appreciate |
||||
more examples of R-tree usage. |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,87 @@ |
||||
<Chapter> |
||||
<Title>Inheritance</Title> |
||||
|
||||
<Para> |
||||
Let's create two classes. The capitals class contains |
||||
state capitals which are also cities. Naturally, the |
||||
capitals class should inherit from cities. |
||||
|
||||
<ProgramListing> |
||||
CREATE TABLE cities ( |
||||
name text, |
||||
population float, |
||||
altitude int -- (in ft) |
||||
); |
||||
|
||||
CREATE TABLE capitals ( |
||||
state char2 |
||||
) INHERITS (cities); |
||||
</ProgramListing> |
||||
|
||||
In this case, an instance of capitals <FirstTerm>inherits</FirstTerm> all |
||||
attributes (name, population, and altitude) from its |
||||
parent, cities. The type of the attribute name is |
||||
<Type>text</Type>, a native <ProductName>Postgres</ProductName> type for variable length |
||||
ASCII strings. The type of the attribute population is |
||||
<Type>float</Type>, a native <ProductName>Postgres</ProductName> type for double precision |
||||
floating point numbers. State capitals have an extra |
||||
attribute, state, that shows their state. In <ProductName>Postgres</ProductName>, |
||||
a class can inherit from zero or more other classes, |
||||
and a query can reference either all instances of a |
||||
class or all instances of a class plus all of its |
||||
descendants. |
||||
<Note> |
||||
<Para> |
||||
The inheritance hierarchy is a actually a directed acyclic graph. |
||||
</Para> |
||||
</Note> |
||||
For example, the following query finds |
||||
all the cities that are situated at an attitude of 500ft or higher: |
||||
|
||||
<ProgramListing> |
||||
SELECT name, altitude |
||||
FROM cities |
||||
WHERE altitude > 500; |
||||
|
||||
+----------+----------+ |
||||
|name | altitude | |
||||
+----------+----------+ |
||||
|Las Vegas | 2174 | |
||||
+----------+----------+ |
||||
|Mariposa | 1953 | |
||||
+----------+----------+ |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
On the other hand, to find the names of all cities, |
||||
including state capitals, that are located at an altitude |
||||
over 500ft, the query is: |
||||
|
||||
<ProgramListing> |
||||
SELECT c.name, c.altitude |
||||
FROM cities* c |
||||
WHERE c.altitude > 500; |
||||
</ProgramListing> |
||||
|
||||
which returns: |
||||
|
||||
<ProgramListing> |
||||
+----------+----------+ |
||||
|name | altitude | |
||||
+----------+----------+ |
||||
|Las Vegas | 2174 | |
||||
+----------+----------+ |
||||
|Mariposa | 1953 | |
||||
+----------+----------+ |
||||
|Madison | 845 | |
||||
+----------+----------+ |
||||
</ProgramListing> |
||||
|
||||
Here the <Quote>*</Quote> after cities indicates that the query should |
||||
be run over cities and all classes below cities in the |
||||
inheritance hierarchy. Many of the commands that we |
||||
have already discussed -- <Command>select</Command>, <Command>update</Command> and <Command>delete</Command> -- |
||||
support this <Quote>*</Quote> notation, as do others, like <Command>alter</Command>. |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,74 @@ |
||||
<Chapter> |
||||
<TITLE>Introduction</TITLE> |
||||
|
||||
<Para> |
||||
This document is the programmer's manual for the |
||||
<Ulink url="http://postgresql.org/"><ProductName>PostgreSQL</ProductName></Ulink> |
||||
database management system, originally developed at the University |
||||
of California at Berkeley. <ProductName>PostgreSQL</ProductName> is based on |
||||
<Ulink url="http://s2k-ftp.CS.Berkeley.EDU:8000/postgres/postgres.html"> |
||||
<ProductName>Postgres release 4.2</ProductName></Ulink>. |
||||
The <ProductName>Postgres</ProductName> project, |
||||
led by Professor Michael Stonebraker, has been sponsored by the |
||||
Defense Advanced Research Projects Agency (<Acronym>DARPA</Acronym>), the |
||||
Army Research Office (<Acronym>ARO</Acronym>), the National Science |
||||
Foundation (<Acronym>NSF</Acronym>), and ESL, Inc. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The first part of this manual |
||||
explains the |
||||
<ProductName>Postgres</ProductName> approach to extensibility and describe how |
||||
users can extend <ProductName>Postgres</ProductName> by adding user-defined types, |
||||
operators, aggregates, and both query language and programming language functions. |
||||
After an extremely brief |
||||
overview of the <ProductName>Postgres</ProductName> rule system, we discuss |
||||
the trigger and SPI interfaces. |
||||
The manual concludes with a detailed description of the programming interfaces and |
||||
support libraries for various languages. |
||||
</Para> |
||||
|
||||
<Para> |
||||
We assume proficiency with UNIX and C programming. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Copyrights and Trademarks</Title> |
||||
|
||||
<Para> |
||||
<ProductName>PostgreSQL</ProductName> is copyright (C) 1996-8 by the PostgreSQL Global Development Group, |
||||
and is distributed under the terms of the Berkeley license. |
||||
|
||||
<Para> |
||||
<ProductName>Postgres95</ProductName> is copyright (C) 1994-5 by the Regents of the University of California. |
||||
Permission to use, copy, modify, and distribute this software and its documentation |
||||
for any purpose, without fee, and without a written agreement is hereby granted, |
||||
provided that the above copyright notice and this paragraph and the following two |
||||
paragraphs appear in all copies. |
||||
</Para> |
||||
<Para> |
||||
In no event shall the University of California be liable to |
||||
any party for direct, indirect, special, incidental, or consequential |
||||
damages, including lost profits, arising out of the use of this |
||||
software and its documentation, even if the University of California |
||||
has been advised of the possibility of such damage. |
||||
</Para> |
||||
<Para> |
||||
The University of California specifically disclaims any |
||||
warranties, including, but not limited to, the implied warranties |
||||
of merchantability and fitness for a particular purpose. |
||||
The software provided hereunder is on an "as-is" basis, and |
||||
the University of California has no obligations to provide |
||||
maintainance, support, updates, enhancements, or modifications. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<Acronym>UNIX</Acronym> is a trademark of X/Open, Ltd. Sun4, SPARC, SunOS |
||||
and Solaris are trademarks of Sun Microsystems, Inc. DEC, |
||||
DECstation, Alpha AXP and ULTRIX are trademarks of Digital |
||||
Equipment Corp. PA-RISC and HP-UX are trademarks of |
||||
Hewlett-Packard Co. OSF/1 is a trademark of the Open |
||||
Software Foundation. |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,482 @@ |
||||
<Chapter> |
||||
<TITLE>Introduction</TITLE> |
||||
|
||||
<Para> |
||||
This document is the user manual for the |
||||
<Ulink url="http://postgresql.org/"><ProductName>PostgreSQL</ProductName></Ulink> |
||||
database management system, originally developed at the University |
||||
of California at Berkeley. <ProductName>PostgreSQL</ProductName> is based on |
||||
<Ulink url="http://s2k-ftp.CS.Berkeley.EDU:8000/postgres/postgres.html"> |
||||
<ProductName>Postgres release 4.2</ProductName></Ulink>. |
||||
The <ProductName>Postgres</ProductName> project, |
||||
led by Professor Michael Stonebraker, has been sponsored by the |
||||
Defense Advanced Research Projects Agency (<Acronym>DARPA</Acronym>), the |
||||
Army Research Office (<Acronym>ARO</Acronym>), the National Science |
||||
Foundation (<Acronym>NSF</Acronym>), and ESL, Inc. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title> What is <ProductName>Postgres</ProductName>?</Title> |
||||
|
||||
<Para> |
||||
Traditional relational database management systems |
||||
(DBMSs) support a data model consisting of a collection |
||||
of named relations, containing attributes of a specific |
||||
type. In current commercial systems, possible types |
||||
include floating point numbers, integers, character |
||||
strings, money, and dates. It is commonly recognized |
||||
that this model is inadequate for future data |
||||
processing applications. |
||||
The relational model successfully replaced previous |
||||
models in part because of its "Spartan simplicity". |
||||
However, as mentioned, this simplicity often makes the |
||||
implementation of certain applications very difficult. |
||||
<ProductName>Postgres</ProductName> offers substantial additional |
||||
power by incorporating the following four additional |
||||
basic concepts in such a way that users can easily |
||||
extend the system: |
||||
|
||||
<SimpleList> |
||||
<Member>classes</Member> |
||||
<Member>inheritance</Member> |
||||
<Member>types</Member> |
||||
<Member>functions</Member> |
||||
</SimpleList> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Other features provide additional power and flexibility: |
||||
|
||||
<SimpleList> |
||||
<Member>constraints</Member> |
||||
<Member>triggers</Member> |
||||
<Member>rules</Member> |
||||
<Member>transaction integrity</Member> |
||||
</SimpleList> |
||||
</Para> |
||||
|
||||
<Para> |
||||
These features put <ProductName>Postgres</ProductName> into the category of databases |
||||
referred to as <FirstTerm>object-relational</FirstTerm>. Note that this is distinct |
||||
from those referred to as <FirstTerm>object-oriented</FirstTerm>, which in general |
||||
are not as well suited to supporting the traditional relational database languages. |
||||
So, although <ProductName>Postgres</ProductName> has some object-oriented features, |
||||
it is firmly in the relational database world. In fact, some commercial databases |
||||
have recently incorporated features pioneered by <ProductName>Postgres</ProductName>. |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>A Short History of <ProductName>Postgres</ProductName></Title> |
||||
|
||||
<Sect2> |
||||
<Title>The Berkeley <ProductName>Postgres</ProductName> Project</Title> |
||||
|
||||
<Para> |
||||
Implementation of the <ProductName>Postgres</ProductName> <Acronym>DBMS</Acronym> began in 1986. The |
||||
initial concepts for the system were presented in |
||||
<!-- |
||||
<XRef LinkEnd="STON86"> |
||||
--> |
||||
<Citation>[STON86]</Citation> |
||||
and the definition of the initial data model |
||||
appeared in |
||||
<!-- |
||||
<XRef LinkEnd="ROWE87">. |
||||
--> |
||||
<Citation>[ROWE87]</Citation>. |
||||
The design of the rule system at |
||||
that time was described in |
||||
<!-- |
||||
<XRef LinkEnd="STON87a">. |
||||
--> |
||||
<Citation>[STON87a]</Citation>. |
||||
The rationale |
||||
and architecture of the storage manager were detailed in |
||||
<!-- |
||||
<XRef LinkEnd="STON87b">. |
||||
--> |
||||
<Citation>[STON87b]</Citation>. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> has undergone several major releases since |
||||
then. The first "demoware" system became operational |
||||
in 1987 and was shown at the 1988 <Acronym>ACM-SIGMOD</Acronym> |
||||
Conference. We released Version 1, described in |
||||
<!-- |
||||
<XRef LinkEnd="STON90a">, |
||||
--> |
||||
<Citation>[STON90a]</Citation>, |
||||
to a few external users in June 1989. In response to a |
||||
critique of the first rule system |
||||
<!-- |
||||
(<XRef LinkEnd="STON89">), |
||||
--> |
||||
(<Citation>[STON89]</Citation>), |
||||
the rule |
||||
system was redesigned |
||||
<!-- |
||||
(<XRef LinkEnd="STON90b">) |
||||
--> |
||||
(<Citation>[STON90b]</Citation>) |
||||
and Version 2 was |
||||
released in June 1990 with the new rule system. |
||||
Version 3 appeared in 1991 and added support for multiple |
||||
storage managers, an improved query executor, and a |
||||
rewritten rewrite rule system. For the most part, |
||||
releases since then have focused on portability and |
||||
reliability. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> has been used to implement many different |
||||
research and production applications. These include: a |
||||
financial data analysis system, a jet engine |
||||
performance monitoring package, an asteroid tracking |
||||
database, a medical information database, and several |
||||
geographic information systems. <ProductName>Postgres</ProductName> has also been |
||||
used as an educational tool at several universities. |
||||
Finally, <Ulink url="http://www.illustra.com/">Illustra Information Technologies</Ulink> picked up |
||||
the code and commercialized it. |
||||
<ProductName>Postgres</ProductName> became the primary data manager for the |
||||
<Ulink url="http://www.sdsc.edu/0/Parts_Collabs/S2K/s2k_home.html">Sequoia 2000</Ulink> |
||||
scientific computing project in late 1992. |
||||
Furthermore, the size of the external user community |
||||
nearly doubled during 1993. It became increasingly |
||||
obvious that maintenance of the prototype code and |
||||
support was taking up large amounts of time that should |
||||
have been devoted to database research. In an effort |
||||
to reduce this support burden, the project officially |
||||
ended with Version 4.2. |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title><ProductName>Postgres95</ProductName></Title> |
||||
|
||||
<Para> |
||||
In 1994, |
||||
<ULink url="mailto:ayu@informix.com">Andrew Yu</ULink> |
||||
and |
||||
<ULink url="http://http.cs.berkeley.edu/~jolly/">Jolly Chen</ULink> |
||||
added a SQL language interpreter to <ProductName>Postgres</ProductName>, and the code was subsequently released to |
||||
the Web to find its own way in the world. <ProductName>Postgres95</ProductName> was a public-domain, open source descendant |
||||
of this original Berkeley code. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres95</ProductName> is a derivative of the last official release |
||||
of <ProductName>Postgres</ProductName> (version 4.2). The code is now completely |
||||
ANSI C and the code size has been trimmed by 25%. There |
||||
are a lot of internal changes that improve performance |
||||
and code maintainability. <ProductName>Postgres95</ProductName> v1.0.x runs about 30-50% |
||||
faster on the Wisconsin Benchmark compared to v4.2. |
||||
Apart from bug fixes, these are the major enhancements: |
||||
|
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
The query language <ProductName>Postquel</ProductName> has been replaced with |
||||
<Acronym>SQL</Acronym> (implemented in the server). We do not yet support |
||||
subqueries (which can be imitated with user defined |
||||
<Acronym>SQL</Acronym> functions). Aggregates have been |
||||
re-implemented. We also added support for ``GROUP BY''. |
||||
The <FileName>libpq</FileName> interface is still available for <Acronym>C</Acronym> |
||||
programs. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
In addition to the monitor program, we provide a new |
||||
program (<Application>psql</Application>) which supports <Acronym>GNU</Acronym> <FileName>readline</FileName>. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
We added a new front-end library, <FileName>libpgtcl</FileName>, that |
||||
supports <Acronym>Tcl</Acronym>-based clients. A sample shell, |
||||
pgtclsh, provides new Tcl commands to interface <Application>tcl</Application> |
||||
programs with the <ProductName>Postgres95</ProductName> backend. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
The large object interface has been overhauled. We |
||||
kept Inversion large objects as the only mechanism |
||||
for storing large objects. (This is not to be |
||||
confused with the Inversion file system which has been |
||||
removed.) |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
The instance-level rule system has been removed. |
||||
Rules are still available as rewrite rules. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
A short tutorial introducing regular <Acronym>SQL</Acronym> features as |
||||
well as those of ours is distributed with the source |
||||
code. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
<Acronym>GNU</Acronym> make (instead of <Acronym>BSD</Acronym> make) is used for the |
||||
build. Also, <ProductName>Postgres95</ProductName> can be compiled with an |
||||
unpatched <ProductName>gcc</ProductName> (data alignment of doubles has been |
||||
fixed). |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title><ProductName>PostgreSQL</ProductName></Title> |
||||
|
||||
<Para> |
||||
By 1996, it became clear that the name <Quote>Postgres95</Quote> would not stand |
||||
the test of time. A new name, <ProductName>PostgreSQL</ProductName>, was chosen to reflect the |
||||
relationship between original <ProductName>Postgres</ProductName> and the more recent |
||||
versions with <Acronym>SQL</Acronym> capability. At the same time, the version numbering |
||||
was reset to start at 6.0, putting the numbers back into the sequence originally begun by |
||||
the <ProductName>Postgres</ProductName> Project. |
||||
|
||||
<Para> |
||||
The emphasis on development for the v1.0.x releases of <ProductName>Postgres95</ProductName> |
||||
was on stabilizing the backend code. |
||||
With the v6.x series of <ProductName>PostgreSQL</ProductName>, the emphasis has shifted from |
||||
identifying and understanding existing problems in the backend to augmenting features and capabilities, although |
||||
work continues in all areas. |
||||
|
||||
<Para> |
||||
Major enhancements include: |
||||
|
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
Important backend features, including subselects, defaults, constraints, and triggers, have been implemented. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
Additional <Acronym>SQL92</Acronym>-compliant language features have been added, |
||||
including primary keys, quoted identifiers, literal string type coersion, type casting, |
||||
and binary and hexadecimal integer input. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
Built-in types have been improved, including new wide-range date/time types and additional geometric type support. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
Overall backend code speed has been increased by approximately 20%, and backend startup speed has decreased 80%. |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect1> |
||||
<Title>About This Release</Title> |
||||
|
||||
<Para> |
||||
From now on, We will use <ProductName>Postgres</ProductName> to mean <ProductName>PostgreSQL</ProductName>. |
||||
|
||||
<Para> |
||||
<ProductName>PostgreSQL</ProductName> is available without cost. This manual |
||||
describes version 6.3 of <ProductName>PostgreSQL</ProductName>. |
||||
|
||||
<Para> |
||||
Check the Administrator's Guide for a list of currently supported machines. In general, |
||||
<ProductName>PostgreSQL</ProductName> is portable to any Unix/Posix-compatible system |
||||
with full libc library support. |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Resources</Title> |
||||
|
||||
<Para> |
||||
This manual set is organized into several parts: |
||||
|
||||
<VariableList> |
||||
<VarListEntry> |
||||
<Term>Tutorial</Term> |
||||
<ListItem> |
||||
<Para> |
||||
An introduction for new users. Does not cover advanced features. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>User's Guide</Term> |
||||
<ListItem> |
||||
<Para> |
||||
General information for users, including available commands and data types. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Programmer's Guide</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Advanced information for application programmers. Topics include |
||||
type and function extensibility, library interfaces, and application design issues. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Administrator's Guide</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Installation and management information. List of supported machines. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Developer's Guide</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Information for <ProductName>Postgres</ProductName> developers. This is intended |
||||
for those who are contributing to the <ProductName>Postgres</ProductName> |
||||
project; application development information should appear in the Programmer's Guide. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Reference Manual</Term> |
||||
<ListItem> |
||||
<Para> |
||||
Detailed reference information on command syntax. |
||||
At the moment, this manual is very sparse, but eventually should contain |
||||
information similar to that in the man pages. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
</VariableList> |
||||
|
||||
<Para> |
||||
In addition to this manual set, there are other resources to help you with |
||||
<ProductName>Postgres</ProductName> installation and use: |
||||
|
||||
<VariableList> |
||||
<VarListEntry> |
||||
<Term>man pages</Term> |
||||
<ListItem> |
||||
<Para> |
||||
The man pages have general information on command syntax. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>FAQs</Term> |
||||
<ListItem> |
||||
<Para> |
||||
The Frequently Asked Questions (FAQ) documents address both general issues |
||||
and some platform-specific issues. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>READMEs</Term> |
||||
<ListItem> |
||||
<Para> |
||||
README files are available for some contributed packages. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Web Site</Term> |
||||
<ListItem> |
||||
<Para> |
||||
The <ULink url="postgresql.org"><ProductName>Postgres</ProductName></ULink> web site has some information |
||||
not appearing in the distribution. There is a <ProductName>mhonarc</ProductName> catalog of mailing list traffic |
||||
which is a rich resource for many topics. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Mailing Lists</Term> |
||||
<ListItem> |
||||
<Para> |
||||
The <ULink url="mailto:questions@postgresql.org"><ProductName>Postgres</ProductName> Questions</ULink> |
||||
mailing list is a good place to have user questions answered. Other mailing lists are available; consult |
||||
the web page for details. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
|
||||
<VarListEntry> |
||||
<Term>Yourself!</Term> |
||||
<ListItem> |
||||
<Para> |
||||
<ProductName>Postgres</ProductName> is an open source product. As such, it depends on the user community for |
||||
ongoing support. As you begin to use <ProductName>Postgres</ProductName>, you will rely on others |
||||
for help, either through the documentation or through the mailing lists. Consider contributing your |
||||
knowledge back. If you learn something which is not in the documentation, write it up and contribute it. |
||||
If you add features to the code, contribute it. Even those without a lot of experience can provide |
||||
corrections and minor changes in the documentation, and that is a good way to start. |
||||
The <ULink url="mailto:docs@postgresql.org"><ProductName>Postgres</ProductName> Documentation</ULink> |
||||
mailing list is the place to get going. |
||||
</Para> |
||||
</ListItem> |
||||
</VarListEntry> |
||||
</VariableList> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Copyrights and Trademarks</Title> |
||||
|
||||
<Para> |
||||
<ProductName>PostgreSQL</ProductName> is copyright (C) 1996-8 by the PostgreSQL Global Development Group, |
||||
and is distributed under the terms of the Berkeley license. |
||||
|
||||
<Para> |
||||
<ProductName>Postgres95</ProductName> is copyright (C) 1994-5 by the Regents of the University of California. |
||||
Permission to use, copy, modify, and distribute this software and its documentation |
||||
for any purpose, without fee, and without a written agreement is hereby granted, |
||||
provided that the above copyright notice and this paragraph and the following two |
||||
paragraphs appear in all copies. |
||||
</Para> |
||||
<Para> |
||||
In no event shall the University of California be liable to |
||||
any party for direct, indirect, special, incidental, or consequential |
||||
damages, including lost profits, arising out of the use of this |
||||
software and its documentation, even if the University of California |
||||
has been advised of the possibility of such damage. |
||||
</Para> |
||||
<Para> |
||||
The University of California specifically disclaims any |
||||
warranties, including, but not limited to, the implied warranties |
||||
of merchantability and fitness for a particular purpose. |
||||
The software provided hereunder is on an "as-is" basis, and |
||||
the University of California has no obligations to provide |
||||
maintainance, support, updates, enhancements, or modifications. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<Acronym>UNIX</Acronym> is a trademark of X/Open, Ltd. Sun4, SPARC, SunOS |
||||
and Solaris are trademarks of Sun Microsystems, Inc. DEC, |
||||
DECstation, Alpha AXP and ULTRIX are trademarks of Digital |
||||
Equipment Corp. PA-RISC and HP-UX are trademarks of |
||||
Hewlett-Packard Co. OSF/1 is a trademark of the Open |
||||
Software Foundation. |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,8 @@ |
||||
<Chapter> |
||||
<Title>JDBC Interface</Title> |
||||
|
||||
<Para> |
||||
There is a JDBC interface available for Postgres. It is documented elsewhere using |
||||
the accepted tool for Java-language code. |
||||
|
||||
</Chapter> |
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,485 @@ |
||||
<Chapter> |
||||
<Title>Large Objects</Title> |
||||
|
||||
<Para> |
||||
In <ProductName>Postgres</ProductName>, data values are stored in tuples and |
||||
individual tuples cannot span data pages. Since the size of |
||||
a data page is 8192 bytes, the upper limit on the size |
||||
of a data value is relatively low. To support the storage |
||||
of larger atomic values, <ProductName>Postgres</ProductName> provides a large |
||||
object interface. This interface provides file |
||||
oriented access to user data that has been declared to |
||||
be a large type. |
||||
This section describes the implementation and the |
||||
programmatic and query language interfaces to <ProductName>Postgres</ProductName> |
||||
large object data. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Historical Note</Title> |
||||
|
||||
<Para> |
||||
Originally, <ProductName>Postgres 4.2</ProductName> supported three standard |
||||
implementations of large objects: as files external |
||||
to <ProductName>Postgres</ProductName>, as <Acronym>UNIX</Acronym> files managed by <ProductName>Postgres</ProductName>, and as data |
||||
stored within the <ProductName>Postgres</ProductName> database. It causes |
||||
considerable confusion among users. As a result, we only |
||||
support large objects as data stored within the <ProductName>Postgres</ProductName> |
||||
database in <ProductName>PostgreSQL</ProductName>. Even though is is slower to |
||||
access, it provides stricter data integrity. |
||||
For historical reasons, this storage scheme is referred to as |
||||
Inversion large objects. (We will use Inversion and large |
||||
objects interchangeably to mean the same thing in this |
||||
section.) |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Inversion Large Objects</Title> |
||||
|
||||
<Para> |
||||
The Inversion large object implementation breaks large |
||||
objects up into "chunks" and stores the chunks in |
||||
tuples in the database. A B-tree index guarantees fast |
||||
searches for the correct chunk number when doing random |
||||
access reads and writes. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Large Object Interfaces</Title> |
||||
|
||||
<Para> |
||||
The facilities <ProductName>Postgres</ProductName> provides to access large |
||||
objects, both in the backend as part of user-defined |
||||
functions or the front end as part of an application |
||||
using the interface, are described below. (For users |
||||
familiar with <ProductName>Postgres 4.2</ProductName>, <ProductName>PostgreSQL</ProductName> has a new set of |
||||
functions providing a more coherent interface. The |
||||
interface is the same for dynamically-loaded C |
||||
functions as well as for XXX LOST TEXT? WHAT SHOULD GO HERE??. |
||||
|
||||
The <ProductName>Postgres</ProductName> large object interface is modeled after |
||||
the <Acronym>UNIX</Acronym> file system interface, with analogues of |
||||
<Function>open(2)</Function>, <Function>read(2)</Function>, <Function>write(2)</Function>, |
||||
<Function>lseek(2)</Function>, etc. User |
||||
functions call these routines to retrieve only the data of |
||||
interest from a large object. For example, if a large |
||||
object type called mugshot existed that stored |
||||
photographs of faces, then a function called beard could |
||||
be declared on mugshot data. Beard could look at the |
||||
lower third of a photograph, and determine the color of |
||||
the beard that appeared there, if any. The entire |
||||
large object value need not be buffered, or even |
||||
examined, by the beard function. |
||||
Large objects may be accessed from dynamically-loaded <Acronym>C</Acronym> |
||||
functions or database client programs that link the |
||||
library. <ProductName>Postgres</ProductName> provides a set of routines that |
||||
support opening, reading, writing, closing, and seeking on |
||||
large objects. |
||||
</Para> |
||||
|
||||
<Sect2> |
||||
<Title>Creating a Large Object</Title> |
||||
|
||||
<Para> |
||||
The routine |
||||
<ProgramListing> |
||||
Oid lo_creat(PGconn *conn, int mode) |
||||
</ProgramListing> |
||||
creates a new large object. The mode is a bitmask |
||||
describing several different attributes of the new |
||||
object. The symbolic constants listed here are defined |
||||
in |
||||
<FileName> |
||||
PGROOT/src/backend/libpq/libpq-fs.h |
||||
</FileName> |
||||
The access type (read, write, or both) is controlled by |
||||
OR ing together the bits <Acronym>INV_READ</Acronym> and <Acronym>INV_WRITE</Acronym>. If |
||||
the large object should be archived -- that is, if |
||||
historical versions of it should be moved periodically to |
||||
a special archive relation -- then the <Acronym>INV_ARCHIVE</Acronym> bit |
||||
should be set. The low-order sixteen bits of mask are |
||||
the storage manager number on which the large object |
||||
should reside. For sites other than Berkeley, these |
||||
bits should always be zero. |
||||
The commands below create an (Inversion) large object: |
||||
<ProgramListing> |
||||
inv_oid = lo_creat(INV_READ|INV_WRITE|INV_ARCHIVE); |
||||
</ProgramListing> |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Importing a Large Object</Title> |
||||
|
||||
<Para> |
||||
To import a <Acronym>UNIX</Acronym> file as |
||||
a large object, call |
||||
<ProgramListing> |
||||
Oid lo_import(PGconn *conn, text *filename) |
||||
</ProgramListing> |
||||
The filename argument specifies the <Acronym>UNIX</Acronym> pathname of |
||||
the file to be imported as a large object. |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Exporting a Large Object</Title> |
||||
|
||||
<Para> |
||||
To export a large object |
||||
into <Acronym>UNIX</Acronym> file, call |
||||
<ProgramListing> |
||||
int lo_export(PGconn *conn, Oid lobjId, text *filename) |
||||
</ProgramListing> |
||||
The lobjId argument specifies the Oid of the large |
||||
object to export and the filename argument specifies |
||||
the <Acronym>UNIX</Acronym> pathname of the file. |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Opening an Existing Large Object</Title> |
||||
|
||||
<Para> |
||||
To open an existing large object, call |
||||
<ProgramListing> |
||||
int lo_open(PGconn *conn, Oid lobjId, int mode, ...) |
||||
</ProgramListing> |
||||
The lobjId argument specifies the Oid of the large |
||||
object to open. The mode bits control whether the |
||||
object is opened for reading INV_READ), writing or |
||||
both. |
||||
A large object cannot be opened before it is created. |
||||
lo_open returns a large object descriptor for later use |
||||
in lo_read, lo_write, lo_lseek, lo_tell, and lo_close. |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Writing Data to a Large Object</Title> |
||||
|
||||
<Para> |
||||
The routine |
||||
<ProgramListing> |
||||
int lo_write(PGconn *conn, int fd, char *buf, int len) |
||||
</ProgramListing> |
||||
writes len bytes from buf to large object fd. The fd |
||||
argument must have been returned by a previous lo_open. |
||||
The number of bytes actually written is returned. In |
||||
the event of an error, the return value is negative. |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Seeking on a Large Object</Title> |
||||
|
||||
<Para> |
||||
To change the current read or write location on a large |
||||
object, call |
||||
<ProgramListing> |
||||
int lo_lseek(PGconn *conn, int fd, int offset, int whence) |
||||
</ProgramListing> |
||||
This routine moves the current location pointer for the |
||||
large object described by fd to the new location specified |
||||
by offset. The valid values for .i whence are |
||||
SEEK_SET SEEK_CUR and SEEK_END. |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Closing a Large Object Descriptor</Title> |
||||
|
||||
<Para> |
||||
A large object may be closed by calling |
||||
<ProgramListing> |
||||
int lo_close(PGconn *conn, int fd) |
||||
</ProgramListing> |
||||
where fd is a large object descriptor returned by |
||||
lo_open. On success, <Acronym>lo_close</Acronym> returns zero. On error, |
||||
the return value is negative. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Built in registered functions</Title> |
||||
|
||||
<Para> |
||||
There are two built-in registered functions, <Acronym>lo_import</Acronym> |
||||
and <Acronym>lo_export</Acronym> which are convenient for use in <Acronym>SQL</Acronym> |
||||
queries. |
||||
Here is an example of their use |
||||
<ProgramListing> |
||||
CREATE TABLE image ( |
||||
name text, |
||||
raster oid |
||||
); |
||||
|
||||
INSERT INTO image (name, raster) |
||||
VALUES ('beautiful image', lo_import('/etc/motd')); |
||||
|
||||
SELECT lo_export(image.raster, "/tmp/motd") from image |
||||
WHERE name = 'beautiful image'; |
||||
</ProgramListing> |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Accessing Large Objects from LIBPQ</Title> |
||||
|
||||
<Para> |
||||
Below is a sample program which shows how the large object |
||||
interface |
||||
in LIBPQ can be used. Parts of the program are |
||||
commented out but are left in the source for the readers |
||||
benefit. This program can be found in |
||||
<FileName> |
||||
../src/test/examples |
||||
</FileName> |
||||
Frontend applications which use the large object interface |
||||
in LIBPQ should include the header file |
||||
libpq/libpq-fs.h and link with the libpq library. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Sample Program</Title> |
||||
|
||||
<Para> |
||||
<ProgramListing> |
||||
/*-------------------------------------------------------------- |
||||
* |
||||
* testlo.c-- |
||||
* test using large objects with libpq |
||||
* |
||||
* Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* |
||||
* IDENTIFICATION |
||||
* /usr/local/devel/pglite/cvs/src/doc/manual.me,v 1.16 1995/09/01 23:55:00 jolly Exp |
||||
* |
||||
*-------------------------------------------------------------- |
||||
*/ |
||||
#include <stdio.h> |
||||
#include "libpq-fe.h" |
||||
#include "libpq/libpq-fs.h" |
||||
|
||||
#define BUFSIZE 1024 |
||||
|
||||
/* |
||||
* importFile * import file "in_filename" into database as large object "lobjOid" |
||||
* |
||||
*/ |
||||
Oid importFile(PGconn *conn, char *filename) |
||||
{ |
||||
Oid lobjId; |
||||
int lobj_fd; |
||||
char buf[BUFSIZE]; |
||||
int nbytes, tmp; |
||||
int fd; |
||||
|
||||
/* |
||||
* open the file to be read in |
||||
*/ |
||||
fd = open(filename, O_RDONLY, 0666); |
||||
if (fd < 0) { /* error */ |
||||
fprintf(stderr, "can't open unix file |
||||
} |
||||
|
||||
/* |
||||
* create the large object |
||||
*/ |
||||
lobjId = lo_creat(conn, INV_READ|INV_WRITE); |
||||
if (lobjId == 0) { |
||||
fprintf(stderr, "can't create large object"); |
||||
} |
||||
|
||||
lobj_fd = lo_open(conn, lobjId, INV_WRITE); |
||||
/* |
||||
* read in from the Unix file and write to the inversion file |
||||
*/ |
||||
while ((nbytes = read(fd, buf, BUFSIZE)) > 0) { |
||||
tmp = lo_write(conn, lobj_fd, buf, nbytes); |
||||
if (tmp < nbytes) { |
||||
fprintf(stderr, "error while reading |
||||
} |
||||
} |
||||
|
||||
(void) close(fd); |
||||
(void) lo_close(conn, lobj_fd); |
||||
|
||||
return lobjId; |
||||
} |
||||
|
||||
void pickout(PGconn *conn, Oid lobjId, int start, int len) |
||||
{ |
||||
int lobj_fd; |
||||
char* buf; |
||||
int nbytes; |
||||
int nread; |
||||
|
||||
lobj_fd = lo_open(conn, lobjId, INV_READ); |
||||
if (lobj_fd < 0) { |
||||
fprintf(stderr,"can't open large object %d", |
||||
lobjId); |
||||
} |
||||
|
||||
lo_lseek(conn, lobj_fd, start, SEEK_SET); |
||||
buf = malloc(len+1); |
||||
|
||||
nread = 0; |
||||
while (len - nread > 0) { |
||||
nbytes = lo_read(conn, lobj_fd, buf, len - nread); |
||||
buf[nbytes] = ' '; |
||||
fprintf(stderr,">>> %s", buf); |
||||
nread += nbytes; |
||||
} |
||||
fprintf(stderr,"0); |
||||
lo_close(conn, lobj_fd); |
||||
} |
||||
|
||||
void overwrite(PGconn *conn, Oid lobjId, int start, int len) |
||||
{ |
||||
int lobj_fd; |
||||
char* buf; |
||||
int nbytes; |
||||
int nwritten; |
||||
int i; |
||||
|
||||
lobj_fd = lo_open(conn, lobjId, INV_READ); |
||||
if (lobj_fd < 0) { |
||||
fprintf(stderr,"can't open large object %d", |
||||
lobjId); |
||||
} |
||||
|
||||
lo_lseek(conn, lobj_fd, start, SEEK_SET); |
||||
buf = malloc(len+1); |
||||
|
||||
for (i=0;i<len;i++) |
||||
buf[i] = 'X'; |
||||
buf[i] = ' '; |
||||
|
||||
nwritten = 0; |
||||
while (len - nwritten > 0) { |
||||
nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten); |
||||
nwritten += nbytes; |
||||
} |
||||
fprintf(stderr,"0); |
||||
lo_close(conn, lobj_fd); |
||||
} |
||||
|
||||
/* |
||||
* exportFile * export large object "lobjOid" to file "out_filename" |
||||
* |
||||
*/ |
||||
void exportFile(PGconn *conn, Oid lobjId, char *filename) |
||||
{ |
||||
int lobj_fd; |
||||
char buf[BUFSIZE]; |
||||
int nbytes, tmp; |
||||
int fd; |
||||
|
||||
/* |
||||
* create an inversion "object" |
||||
*/ |
||||
lobj_fd = lo_open(conn, lobjId, INV_READ); |
||||
if (lobj_fd < 0) { |
||||
fprintf(stderr,"can't open large object %d", |
||||
lobjId); |
||||
} |
||||
|
||||
/* |
||||
* open the file to be written to |
||||
*/ |
||||
fd = open(filename, O_CREAT|O_WRONLY, 0666); |
||||
if (fd < 0) { /* error */ |
||||
fprintf(stderr, "can't open unix file |
||||
filename); |
||||
} |
||||
|
||||
/* |
||||
* read in from the Unix file and write to the inversion file |
||||
*/ |
||||
while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE)) > 0) { |
||||
tmp = write(fd, buf, nbytes); |
||||
if (tmp < nbytes) { |
||||
fprintf(stderr,"error while writing |
||||
filename); |
||||
} |
||||
} |
||||
|
||||
(void) lo_close(conn, lobj_fd); |
||||
(void) close(fd); |
||||
|
||||
return; |
||||
} |
||||
|
||||
void |
||||
exit_nicely(PGconn* conn) |
||||
{ |
||||
PQfinish(conn); |
||||
exit(1); |
||||
} |
||||
|
||||
int |
||||
main(int argc, char **argv) |
||||
{ |
||||
char *in_filename, *out_filename; |
||||
char *database; |
||||
Oid lobjOid; |
||||
PGconn *conn; |
||||
PGresult *res; |
||||
|
||||
if (argc != 4) { |
||||
fprintf(stderr, "Usage: %s database_name in_filename out_filename0, |
||||
argv[0]); |
||||
exit(1); |
||||
} |
||||
|
||||
database = argv[1]; |
||||
in_filename = argv[2]; |
||||
out_filename = argv[3]; |
||||
|
||||
/* |
||||
* set up the connection |
||||
*/ |
||||
conn = PQsetdb(NULL, NULL, NULL, NULL, database); |
||||
|
||||
/* check to see that the backend connection was successfully made */ |
||||
if (PQstatus(conn) == CONNECTION_BAD) { |
||||
fprintf(stderr,"Connection to database '%s' failed.0, database); |
||||
fprintf(stderr,"%s",PQerrorMessage(conn)); |
||||
exit_nicely(conn); |
||||
} |
||||
|
||||
res = PQexec(conn, "begin"); |
||||
PQclear(res); |
||||
|
||||
printf("importing file |
||||
/* lobjOid = importFile(conn, in_filename); */ |
||||
lobjOid = lo_import(conn, in_filename); |
||||
/* |
||||
printf("as large object %d.0, lobjOid); |
||||
|
||||
printf("picking out bytes 1000-2000 of the large object0); |
||||
pickout(conn, lobjOid, 1000, 1000); |
||||
|
||||
printf("overwriting bytes 1000-2000 of the large object with X's0); |
||||
overwrite(conn, lobjOid, 1000, 1000); |
||||
*/ |
||||
|
||||
printf("exporting large object to file |
||||
/* exportFile(conn, lobjOid, out_filename); */ |
||||
lo_export(conn, lobjOid,out_filename); |
||||
|
||||
res = PQexec(conn, "end"); |
||||
PQclear(res); |
||||
PQfinish(conn); |
||||
exit(0); |
||||
} |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
</Chapter> |
||||
@ -0,0 +1,294 @@ |
||||
<Chapter> |
||||
<Title>Managing a Database</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
This section is currently a thinly disguised copy of the Tutorial. Needs to be augmented. |
||||
- thomas 1998-01-12 |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Although the <FirstTerm>site administrator</FirstTerm> is responsible for overall management of the |
||||
<ProductName>Postgres</ProductName> installation, some databases within the |
||||
installation may be managed by another person, designated the <FirstTerm>database administrator</FirstTerm>. |
||||
This assignment of responsibilities occurs when a database is created. A user may be assigned |
||||
explicit privileges to create databases and/or to create new users. A user assigned both privileges |
||||
can perform most administrative task within <ProductName>Postgres</ProductName>, but will |
||||
not by default have the same operating system privileges as the site administrator. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The Database Administrator's Guide covers these topics in more detail. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Database Creation</Title> |
||||
|
||||
<Para> |
||||
Databases are created by the <Command>create database</Command> issued from |
||||
within <ProductName>Postgres</ProductName>. <Application>createdb</Application> is a command-line |
||||
utility provided to give the same functionality from outside <ProductName>Postgres</ProductName>. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The <ProductName>Postgres</ProductName> backend must be running for either method |
||||
to succeed, and the user issuing the command must be the <ProductName>Postgres</ProductName> |
||||
<FirstTerm>superuser</FirstTerm> or have been assigned database creation privileges by the |
||||
superuser. |
||||
</Para> |
||||
|
||||
<Para> |
||||
To create a new database named <Quote>mydb</Quote> from the command line, type |
||||
<ProgramListing> |
||||
% createdb mydb |
||||
</ProgramListing> |
||||
|
||||
and to do the same from within <Application>psql</Application> type |
||||
<ProgramListing> |
||||
* CREATE DATABASE mydb; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
If you do not have the privileges required to create a database, you will see |
||||
the following: |
||||
<ProgramListing> |
||||
% createdb mydb |
||||
WARN:user "your username" is not allowed to create/destroy databases |
||||
createdb: database creation failed on mydb. |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> allows you to create any number of databases |
||||
at a given site and you automatically become the |
||||
database administrator of the database you just created. |
||||
Database names must have an alphabetic first |
||||
character and are limited to 32 characters in length. |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Alternate Database Locations</Title> |
||||
|
||||
<Para> |
||||
It is possible to create a database in a location other than the default |
||||
location for the installation. Remember that all database access actually |
||||
occurs through the database backend, so that any location specified must |
||||
be accessible by the backend. |
||||
|
||||
<Para> |
||||
Either an absolute path name or an environment variable |
||||
may be specified as a location. |
||||
Any environment variable specifying an alternate location must have |
||||
been defined before the backend was started. |
||||
Consult with the site administrator |
||||
regarding preconfigured alternate database locations. |
||||
|
||||
<Note> |
||||
<Para> |
||||
The environment variable style of specification |
||||
is to be preferred since it allows the site administrator more flexibility in |
||||
managing disk storage. |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
For security and integrity reasons, |
||||
any path or environment variable specified has some |
||||
additional path fields appended. |
||||
|
||||
<Para> |
||||
Alternate database locations must be prepared by running <Application>initlocation</Application>. |
||||
|
||||
<Para> |
||||
To create a data storage area in <FileName>/alt/postgres/data</FileName>, ensure |
||||
that <FileName>/alt/postgres</FileName> already exists. |
||||
From the command line, type |
||||
<ProgramListing> |
||||
% initlocation /alt/postgres/data |
||||
Creating Postgres database system directory /alt/postgres/data |
||||
|
||||
Creating Postgres database system directory /alt/postgres/data/base |
||||
|
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
To do the same using an environment variable PGDATA2, type |
||||
<ProgramListing> |
||||
% initlocation $PGDATA2 |
||||
Creating Postgres database system directory /alt/postgres/data |
||||
|
||||
Creating Postgres database system directory /alt/postgres/data/base |
||||
|
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
To create a database in the alternate storage area <FileName>/alt/postgres/data</FileName> |
||||
from the command line, |
||||
type |
||||
<ProgramListing> |
||||
% createdb -D /alt/postgres/data mydb |
||||
</ProgramListing> |
||||
|
||||
or |
||||
|
||||
<ProgramListing> |
||||
% createdb -D PGDATA2 mydb |
||||
</ProgramListing> |
||||
|
||||
and to do the same from within <Application>psql</Application> type |
||||
<ProgramListing> |
||||
* CREATE DATABASE mydb WITH LOCATION = 'PGDATA2'; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
If you do not have the privileges required to create a database, you will see |
||||
the following: |
||||
<ProgramListing> |
||||
% createdb mydb |
||||
WARN:user "your username" is not allowed to create/destroy databases |
||||
createdb: database creation failed on mydb. |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
If the specified location does not exist or the database backend does not have |
||||
permission to access it or to write to directories under it, you will see |
||||
the following: |
||||
<ProgramListing> |
||||
% createdb -D /alt/postgres/data mydb |
||||
ERROR: Unable to create database directory /alt/postgres/data/base/mydb |
||||
createdb: database creation failed on mydb. |
||||
</ProgramListing> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Accessing a Database</Title> |
||||
|
||||
<Para> |
||||
Once you have constructed a database, you can access it |
||||
by: |
||||
|
||||
<ItemizedList Mark="bullet" Spacing="compact"> |
||||
<ListItem> |
||||
<Para> |
||||
running the <ProductName>Postgres</ProductName> terminal monitor programs (e.g. |
||||
<Application>psql</Application>) which allows you to interactively |
||||
enter, edit, and execute <Acronym>SQL</Acronym> commands. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
writing a C program using the LIBPQ subroutine |
||||
library. This allows you to submit <Acronym>SQL</Acronym> commands |
||||
from C and get answers and status messages back to |
||||
your program. This interface is discussed further |
||||
in section ??. |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
You might want to start up <Application>psql</Application>, to try out the examples in this manual. |
||||
It can be activated for the <Database>mydb</Database> |
||||
database by typing the command: |
||||
<ProgramListing> |
||||
% psql mydb |
||||
</ProgramListing> |
||||
|
||||
You will be greeted with the following message: |
||||
<ProgramListing> |
||||
Welcome to the POSTGRESQL interactive sql monitor: |
||||
Please read the file COPYRIGHT for copyright terms of POSTGRESQL |
||||
|
||||
type \? for help on slash commands |
||||
type \q to quit |
||||
type \g or terminate with semicolon to execute query |
||||
You are currently connected to the database: template1 |
||||
|
||||
mydb=> |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
This prompt indicates that the terminal monitor is listening |
||||
to you and that you can type <Acronym>SQL</Acronym> queries into a |
||||
workspace maintained by the terminal monitor. |
||||
The <Application>psql</Application> program responds to escape codes that begin |
||||
with the backslash character, <Quote>\</Quote> For example, you |
||||
can get help on the syntax of various |
||||
<ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> commands by typing: |
||||
<ProgramListing> |
||||
mydb=> \h |
||||
</ProgramListing> |
||||
|
||||
Once you have finished entering your queries into the |
||||
workspace, you can pass the contents of the workspace |
||||
to the <ProductName>Postgres</ProductName> server by typing: |
||||
<ProgramListing> |
||||
mydb=> \g |
||||
</ProgramListing> |
||||
|
||||
This tells the server to process the query. If you |
||||
terminate your query with a semicolon, the <Quote>\g</Quote> is not |
||||
necessary. <Application>psql</Application> will automatically process semicolon terminated queries. |
||||
To read queries from a file, say myFile, instead of |
||||
entering them interactively, type: |
||||
<ProgramListing> |
||||
mydb=> \i fileName |
||||
</ProgramListing> |
||||
|
||||
To get out of <Application>psql</Application> and return to UNIX, type |
||||
<ProgramListing> |
||||
mydb=> \q |
||||
</ProgramListing> |
||||
|
||||
and <Application>psql</Application> will quit and return you to your command |
||||
shell. (For more escape codes, type <Command>\h</Command> at the monitor |
||||
prompt.) |
||||
White space (i.e., spaces, tabs and newlines) may be |
||||
used freely in <Acronym>SQL</Acronym> queries. Single-line comments are denoted by |
||||
<Quote>--</Quote>. Everything after the dashes up to the end of the |
||||
line is ignored. Multiple-line comments, and comments within a line, |
||||
are denoted by <Quote>/* ... */</Quote> |
||||
</Para> |
||||
|
||||
<Sect2> |
||||
<Title>Database Privileges</Title> |
||||
|
||||
<Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Table Privileges</Title> |
||||
|
||||
<Para> |
||||
TBD |
||||
</Para> |
||||
|
||||
</Sect2> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Destroying a Database</Title> |
||||
|
||||
<Para> |
||||
If you are the database administrator for the database |
||||
<Database>mydb</Database>, you can destroy it using the following UNIX command: |
||||
<ProgramListing> |
||||
% destroydb mydb |
||||
</ProgramListing> |
||||
This action physically removes all of the UNIX files |
||||
associated with the database and cannot be undone, so |
||||
this should only be done with a great deal of forethought. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,98 @@ |
||||
<Chapter> |
||||
<DocInfo> |
||||
<AuthorGroup> |
||||
<Author> |
||||
<FirstName>Tim</FirstName> |
||||
<Surname>Goeke</Surname> |
||||
</Author> |
||||
</AuthorGroup> |
||||
<Date>Transcribed 1998-02-12</Date> |
||||
</DocInfo> |
||||
|
||||
<Title>ODBC Interface</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
Contributed by <ULink url="mailto:tgoeke@xpressway.com">Tim Goeke</ULink> |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
ODBC is an abstract API which allows you to write standard "ODBC" code, |
||||
using the ODBC API. |
||||
|
||||
<Sect1> |
||||
<Title>Background</Title> |
||||
|
||||
<Para> |
||||
The ODBC API matches up on the backend to an ODBC compatible data source. |
||||
This could be anything from a text file to an Oracle RDBMS. |
||||
|
||||
<Para> |
||||
The backend access come from ODBC drivers, or vendor specifc drivers that |
||||
allow data access. PostODBC is such a driver, along with others that are |
||||
available, such as the OpenLink ODBC drivers. |
||||
|
||||
<Para> |
||||
Once you write an ODBC application, you SHOULD be able to connect to ANY |
||||
back end database, regardless of the vendor, as long as the database schema |
||||
is the same. |
||||
|
||||
<Para> |
||||
For example. you could have MS SQL Server and PostgreSQL servers which have |
||||
exactly the same data. Using ODBC, your Windows app would make exactly the |
||||
same calls and the back end data source would look the same (to the windows |
||||
app). |
||||
|
||||
<Para> |
||||
In the real world, differences in drivers and the level of ODBC support |
||||
lessens the potential of ODBC: |
||||
|
||||
<SimpleList> |
||||
<Member> |
||||
Access, Delphi, and Visual Basic all support ODBC directly. |
||||
|
||||
<Member> |
||||
Under C++, such as Visual C++, you can use the C++ ODBC API. |
||||
|
||||
<Member> |
||||
In Visual C++, you can use the CRecordSet class, which wraps the ODBC API |
||||
set within and MFC 4.2 class. This is the easiest route if you are doing |
||||
Windows C++ development under Windows NT. |
||||
</SimpleList> |
||||
|
||||
<Para> |
||||
If I write an app for PostgreSQL can I write it using ODBC calls |
||||
to the PostgreSQL server, or is that only when another database program |
||||
like MS SQL Server or Access needs to access the data? |
||||
|
||||
<Para> |
||||
Again, the ODBC API set is the way to go. You can find out more at |
||||
Microsoft's web site or in your Visual C++ docs (if that's what you are |
||||
using.) |
||||
|
||||
<Para> |
||||
Visual Basic and the other RAD tools have Recordset objects that use ODBC |
||||
directly to access data. Using the data-aware controls, you can quickly |
||||
link to the ODBC back end database (<Emphasis>very</Emphasis> quickly). |
||||
|
||||
<Para> |
||||
Playing around with MS Access will help you sort this out. Try using |
||||
File->Get External Data |
||||
|
||||
<Para> |
||||
<Tip> |
||||
<Para> |
||||
You'll have to set up a DSN first. |
||||
</Para> |
||||
</Tip> |
||||
|
||||
<Para> |
||||
<Tip> |
||||
<Para> |
||||
The PostgreSQL datetime type will break MS Access. |
||||
</Para> |
||||
</Tip> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,8 @@ |
||||
<Chapter> |
||||
<Title><Command>pgaccess</Command></Title> |
||||
|
||||
<Para> |
||||
This section needs to be written. Volunteers? |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,264 @@ |
||||
<Chapter> |
||||
<Title>Ports</Title> |
||||
|
||||
<Sect1> |
||||
<Title>Currently Supported Platforms</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> is available free of charge. This manual |
||||
describes version 6.3 of <ProductName>Postgres</ProductName>. The authors have |
||||
compiled and tested <ProductName>Postgres</ProductName> on the following |
||||
platforms: |
||||
|
||||
<TABLE TOCENTRY="1"> |
||||
<TITLE>Supported Platforms</TITLE> |
||||
<TGROUP COLS="4"> |
||||
<THEAD> |
||||
<ROW> |
||||
<ENTRY><Acronym>OS</Acronym></ENTRY> |
||||
<ENTRY>Processor</ENTRY> |
||||
<ENTRY>Version</ENTRY> |
||||
<ENTRY>Reported</ENTRY> |
||||
<ENTRY>Remarks</ENTRY> |
||||
</ROW> |
||||
</THEAD> |
||||
<TBODY> |
||||
<ROW> |
||||
<ENTRY>AIX 4.1.x-4.2</ENTRY> |
||||
<ENTRY>RS6000</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>4.1.4.0,4.2 (<ULink url="mailto:darrenk@insightdist.com">Darren King</ULink>), |
||||
4.1.5 (<ULink url="mailto:Andreas.Zeugswetter@telecom.at">Andreas Zeugswetter</ULink>); |
||||
3.2.5 confirmed on v6.2.1 (<ULink url="mailto:danaf@ans.net">Frank Dana</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>BSDi</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:maillist@candle.pha.pa.us">Bruce Momjian</ULink></ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>FreeBSD 2.2.x-3.x</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>, |
||||
<ULink url="mailto:scrappy@hub.org">Marc Fournier</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>NetBSD 1.3</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:brook@trillium.NMSU.Edu">Brook Milligan</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>NetBSD 1.3</ENTRY> |
||||
<ENTRY>Sparc</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:tih@hamartun.priv.no">Tom I Helbekkmo</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>NetBSD 1.3</ENTRY> |
||||
<ENTRY>VAX</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:tih@hamartun.priv.no">Tom I Helbekkmo</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>DGUX 5.4R4.11</ENTRY> |
||||
<ENTRY>m88k</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:geek+@cmu.edu">Brian E Gallew</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>HPUX 10.20</ENTRY> |
||||
<ENTRY>PA-RISC</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>9.0.x confirmed on v6.2.1 (<ULink url="mailto:stanb@awod.com">Stan Brown</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>IRIX 6.x</ENTRY> |
||||
<ENTRY>MIPS</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>5.x is different (<ULink url="mailto:martin@biochemistry.ucl.ac.uk">Andrew Martin</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>Digital 4.0</ENTRY> |
||||
<ENTRY>Alpha</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>in progress; v6.2.1 confirmed working (<ULink url="mailto:pjlobo@euitt.upm.es">Pedro J. Lobo</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>linux 2.0.x</ENTRY> |
||||
<ENTRY>Alpha</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>partial success (<ULink url="mailto:rkirkpat@nag.cs.colorado.edu">Ryan Kirkpatrick</ULink>, |
||||
<ULink url="mailto:jsturm@zenacomp.com"> Jeff Sturm </ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>linux 2.0.x</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:lockhart@alumni.caltech.edu">Thomas Lockhart</ULink>, |
||||
<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>linux 2.0.x</ENTRY> |
||||
<ENTRY>Sparc</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:szybist@boxhill.com">Tom Szybist</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>mklinux</ENTRY> |
||||
<ENTRY>PPC</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>SCO</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>partial success (<ULink url="mailto:Bill.Allie@mug.org">Billy G. Allie</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>Solaris</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:scrappy@hub.org">Marc Fournier</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>Solaris 2.5.1-2.6</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>(<ULink url="mailto:scrappy@hub.org">Marc Fournier</ULink>, |
||||
<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>SunOS 4.1.4</ENTRY> |
||||
<ENTRY>Sparc</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>patches submitted (<ULink url="mailto:t-ishii@sra.co.jp">Tatsuo Ishii</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>SVR4</ENTRY> |
||||
<ENTRY>MIPS</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>similar to v6.2.1; "mostly working" (<ULink url="mailto:ridderbusch.pad@sni.de">Frank Ridderbusch</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>SVR4 4.4</ENTRY> |
||||
<ENTRY>m88k</ENTRY> |
||||
<ENTRY>v6.2.1</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>confirmed with patching (<ULink url="mailto:dlw@seavme.xroads.com">Doug Winterburn</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>Unixware</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>aka UNIVEL (<ULink url="mailto:Bill.Allie@mug.org">Billy G. Allie</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>NextStep</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.x</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>client-only support; v1.0.9 worked with patches (<ULink url="mailto:dave@turbocat.de">David Wetzel</ULink>)</ENTRY> |
||||
</ROW> |
||||
</TBODY> |
||||
</TGROUP> |
||||
</TABLE> |
||||
|
||||
<Sect1> |
||||
<Title>Unsupported Platforms</Title> |
||||
|
||||
<Para> |
||||
A few platforms which have been attempted and which have been |
||||
reported to not work with the standard distribution. |
||||
Others listed here do not provide sufficient library support for an attempt. |
||||
|
||||
<TABLE TOCENTRY="1"> |
||||
<TITLE>Possibly Incompatible Platforms</TITLE> |
||||
<TITLEABBREV>Incompatibles</TITLEABBREV> |
||||
<TGROUP COLS="4"> |
||||
<THEAD> |
||||
<ROW> |
||||
<ENTRY><Acronym>OS</Acronym></ENTRY> |
||||
<ENTRY>Processor</ENTRY> |
||||
<ENTRY>Version</ENTRY> |
||||
<ENTRY>Reported</ENTRY> |
||||
<ENTRY>Remarks</ENTRY> |
||||
</ROW> |
||||
</THEAD> |
||||
<TBODY> |
||||
<ROW> |
||||
<ENTRY>MacOS</ENTRY> |
||||
<ENTRY>all</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>not library compatible; use ODBC/JDBC</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>NetBSD</ENTRY> |
||||
<ENTRY>arm32</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>not yet working (<ULink url="mailto:dmill@globalnet.co.uk">Dave Millen</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>NetBSD</ENTRY> |
||||
<ENTRY>m68k</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>Amiga, HP300, Mac; not yet working (<ULink url="mailto:hotz@jpl.nasa.gov">Henry Hotz</ULink>)</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>Ultrix</ENTRY> |
||||
<ENTRY>MIPS,VAX?</ENTRY> |
||||
<ENTRY>v6.x</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>no recent reports; obsolete?</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>Windows NT</ENTRY> |
||||
<ENTRY>all</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>not library compatible; client side maybe; use ODBC/JDBC</ENTRY> |
||||
</ROW> |
||||
<ROW> |
||||
<ENTRY>Windows</ENTRY> |
||||
<ENTRY>x86</ENTRY> |
||||
<ENTRY>v6.3</ENTRY> |
||||
<ENTRY>1998-03-01</ENTRY> |
||||
<ENTRY>not library compatible; client side maybe; use ODBC/JDBC</ENTRY> |
||||
</ROW> |
||||
</TBODY> |
||||
</TGROUP> |
||||
</TABLE> |
||||
|
||||
<Para> |
||||
Note that Windows ports of the frontend are apparently possible |
||||
using third-party Posix porting tools and libraries. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,244 @@ |
||||
<!-- postgres.sgml |
||||
- |
||||
- Postgres integrated documentation. |
||||
- Other subset docs should be copied and shrunk from here. |
||||
- thomas 1998-02-23 |
||||
- |
||||
- --> |
||||
<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [ |
||||
<!entity intro SYSTEM "intro.sgml"> |
||||
<!entity arch SYSTEM "arch.sgml"> |
||||
<!entity start SYSTEM "start.sgml"> |
||||
<!entity query SYSTEM "query.sgml"> |
||||
|
||||
<!entity advanced SYSTEM "advanced.sgml"> |
||||
<!entity environ SYSTEM "environ.sgml"> |
||||
<!entity manage SYSTEM "manage.sgml"> |
||||
<!entity datatype SYSTEM "datatype.sgml"> |
||||
<!entity array SYSTEM "array.sgml"> |
||||
<!entity inherit SYSTEM "inherit.sgml"> |
||||
<!entity query-ug SYSTEM "query-ug.sgml"> |
||||
<!entity storage SYSTEM "storage.sgml"> |
||||
<!entity psql SYSTEM "psql.sgml"> |
||||
<!entity pgaccess SYSTEM "pgaccess.sgml"> |
||||
|
||||
<!entity start-ag SYSTEM "start-ag.sgml"> |
||||
<!entity install SYSTEM "install.sgml"> |
||||
<!entity recovery SYSTEM "recovery.sgml"> |
||||
<!entity regress SYSTEM "regress.sgml"> |
||||
<!entity ports SYSTEM "ports.sgml"> |
||||
<!entity release SYSTEM "release.sgml"> |
||||
|
||||
<!entity intro-pg SYSTEM "intro-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 lobj SYSTEM "lobj.sgml"> |
||||
<!entity trigger SYSTEM "trigger.sgml"> |
||||
<!entity spi SYSTEM "spi.sgml"> |
||||
<!entity func-ref SYSTEM "func-ref.sgml"> |
||||
<!entity libpq SYSTEM "libpq.sgml"> |
||||
<!entity libpgtcl SYSTEM "libpgtcl.sgml"> |
||||
<!entity ecpg SYSTEM "ecpg.sgml"> |
||||
<!entity odbc SYSTEM "odbc.sgml"> |
||||
<!entity jdbc SYSTEM "jdbc.sgml"> |
||||
|
||||
<!entity arch-dev SYSTEM "arch-dev.sgml"> |
||||
<!entity geqo SYSTEM "geqo.sgml"> |
||||
<!entity protocol SYSTEM "protocol.sgml"> |
||||
<!entity compiler SYSTEM "compiler.sgml"> |
||||
<!entity docguide SYSTEM "docguide.sgml"> |
||||
<!entity biblio SYSTEM "biblio.sgml"> |
||||
<!entity contacts SYSTEM "contacts.sgml"> |
||||
]> |
||||
<!-- entity manpages SYSTEM "man/manpages.sgml" subdoc --> |
||||
<Book> |
||||
|
||||
<!-- Title information --> |
||||
|
||||
<Title>PostgreSQL</Title> |
||||
<BookInfo> |
||||
<ReleaseInfo>Covering v6.3 for general release</ReleaseInfo> |
||||
<BookBiblio> |
||||
<AuthorGroup> |
||||
<CorpAuthor>The PostgreSQL Development Team</CorpAuthor> |
||||
</AuthorGroup> |
||||
<!-- editor in authorgroup is not supported |
||||
<AuthorGroup> |
||||
--> |
||||
<Editor> |
||||
<FirstName>Thomas</FirstName> |
||||
<SurName>Lockhart</SurName> |
||||
<Affiliation> |
||||
<OrgName>Caltech/JPL</OrgName> |
||||
</Affiliation> |
||||
</Editor> |
||||
<!-- |
||||
</AuthorGroup> |
||||
--> |
||||
|
||||
<!-- |
||||
<AuthorInitials>TGL</AuthorInitials> |
||||
--> |
||||
|
||||
<Date>(last updated 1998-02-23)</Date> |
||||
</BookBiblio> |
||||
|
||||
<LegalNotice> |
||||
<Para> |
||||
<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group. |
||||
</Para> |
||||
</LegalNotice> |
||||
|
||||
</BookInfo> |
||||
|
||||
<!-- |
||||
<TOC> </TOC> |
||||
<LOT> </LOT> |
||||
--> |
||||
|
||||
<!-- |
||||
<Dedication> |
||||
<Para> |
||||
Your name here... |
||||
</Para> |
||||
</Dedication> |
||||
--> |
||||
|
||||
<Preface> |
||||
<Title>Summary</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName>, |
||||
developed originally in the UC Berkeley Computer Science Department, |
||||
pioneered many of the object-relational concepts |
||||
now becoming available in some commercial databases. |
||||
It provides SQL92/SQL3 language support, |
||||
transaction integrity, and type extensibility. |
||||
<ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant |
||||
of this original Berkeley code. |
||||
</Para> |
||||
</Preface> |
||||
|
||||
<Part> |
||||
<Title>Tutorial</Title> |
||||
<PartIntro> |
||||
<Para> |
||||
Introduction for new users. |
||||
</Para> |
||||
</PartIntro> |
||||
&intro; |
||||
&arch; |
||||
&start; |
||||
&query; |
||||
&advanced; |
||||
</Part> |
||||
|
||||
<Part> |
||||
<Title>User's Guide</Title> |
||||
<PartIntro> |
||||
<Para> |
||||
Information for users. |
||||
</Para> |
||||
</PartIntro> |
||||
&environ; |
||||
&manage; |
||||
&datatype; |
||||
&array; |
||||
&inherit; |
||||
&query-ug; |
||||
&storage; |
||||
&psql; |
||||
&pgaccess; |
||||
</Part> |
||||
|
||||
<Part> |
||||
<Title>Administrator's Guide</Title> |
||||
<PartIntro> |
||||
<Para> |
||||
Installation and maintenance information. |
||||
</Para> |
||||
</PartIntro> |
||||
&ports; |
||||
&install; |
||||
&start-ag; |
||||
&recovery; |
||||
®ress; |
||||
&release; |
||||
</Part> |
||||
|
||||
<Part> |
||||
<Title>Programmer's Guide</Title> |
||||
<PartIntro> |
||||
<Para> |
||||
Information for extending <ProductName>Postgres</ProductName>. |
||||
</Para> |
||||
</PartIntro> |
||||
&intro-pg; |
||||
&arch-pg; |
||||
&extend; |
||||
&xfunc; |
||||
&xtypes; |
||||
&xoper; |
||||
&xaggr; |
||||
&xindex; |
||||
&gist; |
||||
&dfunc; |
||||
&trigger; |
||||
&spi; |
||||
&libpq; |
||||
</Part> |
||||
|
||||
<Part> |
||||
<Title>Reference</Title> |
||||
<PartIntro> |
||||
<Para> |
||||
User and programmer interfaces. |
||||
</Para> |
||||
</PartIntro> |
||||
&func-ref; |
||||
&lobj; |
||||
&ecpg; |
||||
&libpq; |
||||
&libpgtcl; |
||||
&odbc; |
||||
&jdbc; |
||||
</Part> |
||||
|
||||
<Part> |
||||
<Title>Developer's Guide</Title> |
||||
<PartIntro> |
||||
<Para> |
||||
The Developer's Guide includes discussion of design decisions and suggestions for |
||||
future development. |
||||
</Para> |
||||
</PartIntro> |
||||
&arch-dev; |
||||
&geqo; |
||||
&protocol; |
||||
&compiler; |
||||
</Part> |
||||
|
||||
<Part> |
||||
<Title>Appendices</Title> |
||||
<PartIntro> |
||||
<Para> |
||||
Additional related information. |
||||
</Para> |
||||
</PartIntro> |
||||
&docguide; |
||||
&contacts; |
||||
&biblio; |
||||
</Part> |
||||
|
||||
<INDEX> </INDEX> |
||||
|
||||
</Book> |
||||
|
||||
@ -0,0 +1,173 @@ |
||||
<!-- programmer.sgml |
||||
- |
||||
- Postgres programmer's guide. |
||||
- Derived from postgres.sgml. |
||||
- thomas 1998-02-24 |
||||
- |
||||
- --> |
||||
<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [ |
||||
<!entity intro SYSTEM "intro.sgml"> |
||||
<!entity arch SYSTEM "arch.sgml"> |
||||
<!entity start SYSTEM "start.sgml"> |
||||
<!entity query SYSTEM "query.sgml"> |
||||
|
||||
<!entity advanced SYSTEM "advanced.sgml"> |
||||
<!entity environ SYSTEM "environ.sgml"> |
||||
<!entity manage SYSTEM "manage.sgml"> |
||||
<!entity datatype SYSTEM "datatype.sgml"> |
||||
<!entity array SYSTEM "array.sgml"> |
||||
<!entity inherit SYSTEM "inherit.sgml"> |
||||
<!entity query-ug SYSTEM "query-ug.sgml"> |
||||
<!entity storage SYSTEM "storage.sgml"> |
||||
<!entity psql SYSTEM "psql.sgml"> |
||||
<!entity pgaccess SYSTEM "pgaccess.sgml"> |
||||
|
||||
<!entity start-ag SYSTEM "start-ag.sgml"> |
||||
<!entity install SYSTEM "install.sgml"> |
||||
<!entity recovery SYSTEM "recovery.sgml"> |
||||
<!entity regress SYSTEM "regress.sgml"> |
||||
<!entity ports SYSTEM "ports.sgml"> |
||||
<!entity release SYSTEM "release.sgml"> |
||||
|
||||
<!entity intro-pg SYSTEM "intro-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 lobj SYSTEM "lobj.sgml"> |
||||
<!entity trigger SYSTEM "trigger.sgml"> |
||||
<!entity spi SYSTEM "spi.sgml"> |
||||
<!entity func-ref SYSTEM "func-ref.sgml"> |
||||
<!entity libpq SYSTEM "libpq.sgml"> |
||||
<!entity libpgtcl SYSTEM "libpgtcl.sgml"> |
||||
<!entity ecpg SYSTEM "ecpg.sgml"> |
||||
<!entity odbc SYSTEM "odbc.sgml"> |
||||
<!entity jdbc SYSTEM "jdbc.sgml"> |
||||
|
||||
<!entity arch-dev SYSTEM "arch-dev.sgml"> |
||||
<!entity geqo SYSTEM "geqo.sgml"> |
||||
<!entity protocol SYSTEM "protocol.sgml"> |
||||
<!entity compiler SYSTEM "compiler.sgml"> |
||||
<!entity docguide SYSTEM "docguide.sgml"> |
||||
<!entity biblio SYSTEM "biblio.sgml"> |
||||
<!entity contacts SYSTEM "contacts.sgml"> |
||||
]> |
||||
<!-- entity manpages SYSTEM "man/manpages.sgml" subdoc --> |
||||
<Book> |
||||
|
||||
<!-- Title information --> |
||||
|
||||
<Title>PostgreSQL Programmer's Guide</Title> |
||||
<BookInfo> |
||||
<ReleaseInfo>Covering v6.3 for general release</ReleaseInfo> |
||||
<BookBiblio> |
||||
<AuthorGroup> |
||||
<CorpAuthor>The PostgreSQL Development Team</CorpAuthor> |
||||
</AuthorGroup> |
||||
<!-- editor in authorgroup is not supported |
||||
<AuthorGroup> |
||||
--> |
||||
<Editor> |
||||
<FirstName>Thomas</FirstName> |
||||
<SurName>Lockhart</SurName> |
||||
<Affiliation> |
||||
<OrgName>Caltech/JPL</OrgName> |
||||
</Affiliation> |
||||
</Editor> |
||||
<!-- |
||||
</AuthorGroup> |
||||
--> |
||||
|
||||
<!-- |
||||
<AuthorInitials>TGL</AuthorInitials> |
||||
--> |
||||
|
||||
<Date>(last updated 1998-02-24)</Date> |
||||
</BookBiblio> |
||||
|
||||
<LegalNotice> |
||||
<Para> |
||||
<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group. |
||||
</Para> |
||||
</LegalNotice> |
||||
|
||||
</BookInfo> |
||||
|
||||
<!-- |
||||
<TOC> </TOC> |
||||
<LOT> </LOT> |
||||
--> |
||||
|
||||
<!-- |
||||
<Dedication> |
||||
<Para> |
||||
Your name here... |
||||
</Para> |
||||
</Dedication> |
||||
--> |
||||
|
||||
<Preface> |
||||
<Title>Summary</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName>, |
||||
developed originally in the UC Berkeley Computer Science Department, |
||||
pioneered many of the object-relational concepts |
||||
now becoming available in some commercial databases. |
||||
It provides SQL92/SQL3 language support, |
||||
transaction integrity, and type extensibility. |
||||
<ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant |
||||
of this original Berkeley code. |
||||
</Para> |
||||
</Preface> |
||||
|
||||
&intro-pg; |
||||
&arch-pg; |
||||
&extend; |
||||
&xfunc; |
||||
&xtypes; |
||||
&xoper; |
||||
&xaggr; |
||||
&xindex; |
||||
&gist; |
||||
&dfunc; |
||||
&trigger; |
||||
&spi; |
||||
|
||||
<!-- reference --> |
||||
|
||||
&func-ref; |
||||
&lobj; |
||||
&ecpg; |
||||
&libpq; |
||||
&libpgtcl; |
||||
&odbc; |
||||
&jdbc; |
||||
|
||||
<!-- development --> |
||||
|
||||
&arch-dev; |
||||
&geqo; |
||||
&protocol; |
||||
&compiler; |
||||
|
||||
<!-- appendices --> |
||||
|
||||
&docguide; |
||||
<!-- |
||||
&contacts; |
||||
--> |
||||
&biblio; |
||||
|
||||
<!-- |
||||
<INDEX> </INDEX> |
||||
--> |
||||
|
||||
</Book> |
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@ |
||||
<Chapter> |
||||
<Title><Command>psql</Command></Title> |
||||
|
||||
<Para> |
||||
This section needs to be written. Volunteers? |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,332 @@ |
||||
<Chapter> |
||||
<TITLE>The Query Language</TITLE> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
This chapter must go into depth on each area of the query language. Currently a copy of the tutorial. |
||||
- thomas 1998-01-12 |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The <ProductName>Postgres</ProductName> query language is a variant of |
||||
<Acronym>SQL3</Acronym>. It |
||||
has many extensions such as an extensible type system, |
||||
inheritance, functions and production rules. Those are |
||||
features carried over from the original <ProductName>Postgres</ProductName> query |
||||
language, <ProductName>PostQuel</ProductName>. This section provides an overview |
||||
of how to use <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> to perform simple operations. |
||||
This manual is only intended to give you an idea of our |
||||
flavor of <Acronym>SQL</Acronym> and is in no way a complete tutorial on |
||||
<Acronym>SQL</Acronym>. Numerous books have been written on <Acronym>SQL</Acronym>. For |
||||
instance, consult <Ulink url="refs.html#MELT93">[MELT93]</ULink> or |
||||
<Ulink url="refs.html#DATE93">[DATE93]</ULink>. You should also |
||||
be aware that some features are not part of the <Acronym>ANSI</Acronym> |
||||
standard. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Concepts</Title> |
||||
|
||||
<Para> |
||||
The fundamental notion in <ProductName>Postgres</ProductName> is that of a class, |
||||
which is a named collection of object instances. Each |
||||
instance has the same collection of named attributes, |
||||
and each attribute is of a specific type. Furthermore, |
||||
each instance has a permanent <FirstTerm>object identifier</FirstTerm> (<Acronym>OID</Acronym>) |
||||
that is unique throughout the installation. Because |
||||
<Acronym>SQL</Acronym> syntax refers to tables, we will use the terms |
||||
<FirstTerm>table</FirstTerm> and <FirstTerm>class</FirstTerm> interchangeably. |
||||
Likewise, an <Acronym>SQL</Acronym> <FirstTerm>row</FirstTerm> is an |
||||
<FirstTerm>instance</FirstTerm> and <Acronym>SQL</Acronym> <FirstTerm>columns</FirstTerm> |
||||
are <FirstTerm>attributes</FirstTerm>. |
||||
As previously discussed, classes are grouped into |
||||
databases, and a collection of databases managed by a |
||||
single <FileName>postmaster</FileName> process constitutes an installation |
||||
or site. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Creating a New Class</Title> |
||||
|
||||
<Para> |
||||
You can create a new class by specifying the class |
||||
name, along with all attribute names and their types: |
||||
|
||||
<ProgramListing> |
||||
CREATE TABLE weather ( |
||||
city varchar(80), |
||||
temp_lo int, -- low temperature |
||||
temp_hi int, -- high temperature |
||||
prcp real, -- precipitation |
||||
date date |
||||
); |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
Note that keywords are case-insensitive and identifiers |
||||
are usually case-insensitive. |
||||
<Acronym>Postgres</Acronym> allows <Acronym>SQL92</Acronym> <FirstTerm>delimited identifiers</FirstTerm> |
||||
(identifiers surrounded by double-quotes) to include mixed-case and spaces, tabs, etc. |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> supports the usual |
||||
<Acronym>SQL</Acronym> types <Type>int</Type>, |
||||
<Type>float</Type>, <Type>real</Type>, <Type>smallint</Type>, <Type>char(N)</Type>, |
||||
<Type>varchar(N)</Type>, <Type>date</Type>, <Type>time</Type>, |
||||
and <Type>timestamp</Type>, as well as other types of general utility and |
||||
a rich set of geometric types. As we will |
||||
see later, <ProductName>Postgres</ProductName> can be customized with an |
||||
arbitrary number of |
||||
user-defined data types. Consequently, type names are |
||||
not syntactical keywords, except where required to support special cases in the <Acronym>SQL92</Acronym> standard. |
||||
So far, the <ProductName>Postgres</ProductName> create command looks exactly like |
||||
the command used to create a table in a traditional |
||||
relational system. However, we will presently see that |
||||
classes have properties that are extensions of the |
||||
relational model. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Populating a Class with Instances</Title> |
||||
|
||||
<Para> |
||||
The <Command>insert</Command> statement is used to populate a class with |
||||
instances: |
||||
|
||||
<ProgramListing> |
||||
INSERT INTO weather |
||||
VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994') |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
You can also use the <Command>copy</Command> command to perform load large |
||||
amounts of data from flat (<Acronym>ASCII</Acronym>) files. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Querying a Class</Title> |
||||
|
||||
<Para> |
||||
The weather class can be queried with normal relational |
||||
selection and projection queries. A <Acronym>SQL</Acronym> <Command>select</Command> |
||||
statement is used to do this. The statement is divided into |
||||
a target list (the part that lists the attributes to be |
||||
returned) and a qualification (the part that specifies |
||||
any restrictions). For example, to retrieve all the |
||||
rows of weather, type: |
||||
<ProgramListing> |
||||
SELECT * FROM WEATHER; |
||||
</ProgramListing> |
||||
|
||||
and the output should be: |
||||
<ProgramListing> |
||||
+--------------+---------+---------+------+------------+ |
||||
|city | temp_lo | temp_hi | prcp | date | |
||||
+--------------+---------+---------+------+------------+ |
||||
|San Francisco | 46 | 50 | 0.25 | 11-27-1994 | |
||||
+--------------+---------+---------+------+------------+ |
||||
|San Francisco | 43 | 57 | 0 | 11-29-1994 | |
||||
+--------------+---------+---------+------+------------+ |
||||
|Hayward | 37 | 54 | | 11-29-1994 | |
||||
+--------------+---------+---------+------+------------+ |
||||
</ProgramListing> |
||||
You may specify any arbitrary expressions in the target list. For example, you can do: |
||||
<ProgramListing> |
||||
SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather; |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
Arbitrary Boolean operators |
||||
(<Command>and</Command>, <Command>or</Command> and <Command>not</Command>) are |
||||
allowed in the qualification of any query. For example, |
||||
|
||||
<ProgramListing> |
||||
SELECT * FROM weather |
||||
WHERE city = 'San Francisco' |
||||
AND prcp > 0.0; |
||||
|
||||
+--------------+---------+---------+------+------------+ |
||||
|city | temp_lo | temp_hi | prcp | date | |
||||
+--------------+---------+---------+------+------------+ |
||||
|San Francisco | 46 | 50 | 0.25 | 11-27-1994 | |
||||
+--------------+---------+---------+------+------------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
As a final note, you can specify that the results of a |
||||
select can be returned in a <FirstTerm>sorted order</FirstTerm> |
||||
or with <FirstTerm>duplicate instances</FirstTerm> removed. |
||||
|
||||
<ProgramListing> |
||||
SELECT DISTINCT city |
||||
FROM weather |
||||
ORDER BY city; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Redirecting SELECT Queries</Title> |
||||
|
||||
<Para> |
||||
Any select query can be redirected to a new class |
||||
<ProgramListing> |
||||
SELECT * INTO TABLE temp FROM weather; |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
This forms an implicit <Command>create</Command> command, creating a new |
||||
class temp with the attribute names and types specified |
||||
in the target list of the <Command>select into</Command> command. We can |
||||
then, of course, perform any operations on the resulting |
||||
class that we can perform on other classes. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Joins Between Classes</Title> |
||||
|
||||
<Para> |
||||
Thus far, our queries have only accessed one class at a |
||||
time. Queries can access multiple classes at once, or |
||||
access the same class in such a way that multiple |
||||
instances of the class are being processed at the same |
||||
time. A query that accesses multiple instances of the |
||||
same or different classes at one time is called a join |
||||
query. |
||||
As an example, say we wish to find all the records that |
||||
are in the temperature range of other records. In |
||||
effect, we need to compare the temp_lo and temp_hi |
||||
attributes of each EMP instance to the temp_lo and |
||||
temp_hi attributes of all other EMP instances. |
||||
<Note> |
||||
<Para> |
||||
This is only a conceptual model. The actual join may |
||||
be performed in a more efficient manner, but this is invisible to the user. |
||||
</Para> |
||||
</Note> |
||||
|
||||
We can do this with the following query: |
||||
|
||||
<ProgramListing> |
||||
SELECT W1.city, W1.temp_lo, W1.temp_hi, |
||||
W2.city, W2.temp_lo, W2.temp_hi |
||||
FROM weather W1, weather W2 |
||||
WHERE W1.temp_lo < W2.temp_lo |
||||
AND W1.temp_hi > W2.temp_hi; |
||||
|
||||
+--------------+---------+---------+---------------+---------+---------+ |
||||
|city | temp_lo | temp_hi | city | temp_lo | temp_hi | |
||||
+--------------+---------+---------+---------------+---------+---------+ |
||||
|San Francisco | 43 | 57 | San Francisco | 46 | 50 | |
||||
+--------------+---------+---------+---------------+---------+---------+ |
||||
|San Francisco | 37 | 54 | San Francisco | 46 | 50 | |
||||
+--------------+---------+---------+---------------+---------+---------+ |
||||
</ProgramListing> |
||||
|
||||
<Note> |
||||
<Para> |
||||
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, |
||||
<ProductName>Postgres</ProductName> computes and returns the values specified in the |
||||
target list. <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> does not assign any meaning to |
||||
duplicate values in such expressions. This means that <ProductName>Postgres</ProductName> |
||||
sometimes recomputes the same target list several times; |
||||
this frequently happens when Boolean expressions are connected |
||||
with an "or". To remove such duplicates, you must use |
||||
the <Command>select distinct</Command> statement. |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
In this case, both W1 and W2 are surrogates for an |
||||
instance of the class weather, and both range over all |
||||
instances of the class. (In the terminology of most |
||||
database systems, W1 and W2 are known as <FirstTerm>range variables</FirstTerm>.) |
||||
A query can contain an arbitrary number of |
||||
class names and surrogates. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Updates</Title> |
||||
|
||||
<Para> |
||||
You can update existing instances using the update command. |
||||
Suppose you discover the temperature readings are |
||||
all off by 2 degrees as of Nov 28, you may update the |
||||
data as follow: |
||||
|
||||
<ProgramListing> |
||||
UPDATE weather |
||||
SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2 |
||||
WHERE date > '11/28/1994'; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Deletions</Title> |
||||
|
||||
<Para> |
||||
Deletions are performed using the <Command>delete</Command> command: |
||||
<ProgramListing> |
||||
DELETE FROM weather WHERE city = 'Hayward'; |
||||
</ProgramListing> |
||||
|
||||
All weather recording belongs to Hayward is removed. |
||||
One should be wary of queries of the form |
||||
<ProgramListing> |
||||
DELETE FROM classname; |
||||
</ProgramListing> |
||||
|
||||
Without a qualification, <Command>delete</Command> will simply |
||||
remove all instances of the given class, leaving it |
||||
empty. The system will not request confirmation before |
||||
doing this. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Using Aggregate Functions</Title> |
||||
|
||||
<Para> |
||||
Like most other query languages, <ProductName>PostgreSQL</ProductName> supports |
||||
aggregate functions. |
||||
The current implementation of <ProductName>Postgres</ProductName> aggregate functions have some limitations. |
||||
Specifically, while there are aggregates to compute |
||||
such functions as the <Function>count</Function>, <Function>sum</Function>, |
||||
<Function>avg</Function> (average), <Function>max</Function> (maximum) and |
||||
<Function>min</Function> (minimum) over a set of instances, aggregates can only |
||||
appear in the target list of a query and not directly in the |
||||
qualification (the <FirstTerm>where</FirstTerm> clause). As an example, |
||||
|
||||
<ProgramListing> |
||||
SELECT max(temp_lo) FROM weather; |
||||
</ProgramListing> |
||||
|
||||
is allowed, while |
||||
|
||||
<ProgramListing> |
||||
SELECT city FROM weather WHERE temp_lo = max(temp_lo); |
||||
</ProgramListing> |
||||
|
||||
is not. However, as is often the case the query can be restated to accomplish |
||||
the intended result; here by using a <FirstTerm>subselect</FirstTerm>: |
||||
<ProgramListing> |
||||
SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather); |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Aggregates may also have <FirstTerm>group by</FirstTerm> clauses: |
||||
<ProgramListing> |
||||
SELECT city, max(temp_lo) |
||||
FROM weather |
||||
GROUP BY city; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,362 @@ |
||||
<Chapter ID="QUERY"> |
||||
<TITLE>The Query Language</TITLE> |
||||
|
||||
<Para> |
||||
The <ProductName>Postgres</ProductName> query language is a variant of |
||||
the <Acronym>SQL3</Acronym> draft next-generation standard. It |
||||
has many extensions such as an extensible type system, |
||||
inheritance, functions and production rules. These are |
||||
features carried over from the original <ProductName>Postgres</ProductName> query |
||||
language, <ProductName>PostQuel</ProductName>. This section provides an overview |
||||
of how to use <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> to perform simple operations. |
||||
This manual is only intended to give you an idea of our |
||||
flavor of <Acronym>SQL</Acronym> and is in no way a complete tutorial on |
||||
<Acronym>SQL</Acronym>. Numerous books have been written on <Acronym>SQL</Acronym>, including |
||||
<!-- |
||||
<XRef LinkEnd="MELT93"> and <XRef LinkEnd="DATE97">. |
||||
--> |
||||
[MELT93] and [DATE97]. |
||||
You should be aware that some language features |
||||
are not part of the <Acronym>ANSI</Acronym> standard. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Interactive Monitor</Title> |
||||
|
||||
<Para> |
||||
In the examples that follow, we assume that you have |
||||
created the mydb database as described in the previous |
||||
subsection and have started <Application>psql</Application>. |
||||
Examples in this manual can also be found in |
||||
<FileName>/usr/local/pgsql/src/tutorial/</FileName>. Refer to the |
||||
<FileName>README</FileName> file in that directory for how to use them. To |
||||
start the tutorial, do the following: |
||||
|
||||
<ProgramListing> |
||||
% cd /usr/local/pgsql/src/tutorial |
||||
% psql -s mydb |
||||
Welcome to the POSTGRESQL interactive sql monitor: |
||||
Please read the file COPYRIGHT for copyright terms of POSTGRESQL |
||||
|
||||
type \? for help on slash commands |
||||
type \q to quit |
||||
type \g or terminate with semicolon to execute query |
||||
You are currently connected to the database: postgres |
||||
|
||||
mydb=> \i basics.sql |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The <Literal>\i</Literal> command read in queries from the specified |
||||
files. The <Literal>-s</Literal> option puts you in single step mode which |
||||
pauses before sending a query to the backend. Queries |
||||
in this section are in the file <FileName>basics.sql</FileName>. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<Application>psql</Application> |
||||
has a variety of <Literal>\d</Literal> commands for showing system information. |
||||
Consult these commands for more details; |
||||
for a listing, type <Literal>\?</Literal> at the <Application>psql</Application> prompt. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Concepts</Title> |
||||
|
||||
<Para> |
||||
The fundamental notion in <ProductName>Postgres</ProductName> is that of a class, |
||||
which is a named collection of object instances. Each |
||||
instance has the same collection of named attributes, |
||||
and each attribute is of a specific type. Furthermore, |
||||
each instance has a permanent <FirstTerm>object identifier</FirstTerm> (<Acronym>OID</Acronym>) |
||||
that is unique throughout the installation. Because |
||||
<Acronym>SQL</Acronym> syntax refers to tables, we will use the terms |
||||
<FirstTerm>table</FirstTerm> and <FirstTerm>class</FirstTerm> interchangeably. |
||||
Likewise, an <Acronym>SQL</Acronym> <FirstTerm>row</FirstTerm> is an |
||||
<FirstTerm>instance</FirstTerm> and <Acronym>SQL</Acronym> <FirstTerm>columns</FirstTerm> |
||||
are <FirstTerm>attributes</FirstTerm>. |
||||
As previously discussed, classes are grouped into |
||||
databases, and a collection of databases managed by a |
||||
single <Application>postmaster</Application> process constitutes an installation |
||||
or site. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Creating a New Class</Title> |
||||
|
||||
<Para> |
||||
You can create a new class by specifying the class |
||||
name, along with all attribute names and their types: |
||||
|
||||
<ProgramListing> |
||||
CREATE TABLE weather ( |
||||
city varchar(80), |
||||
temp_lo int, -- low temperature |
||||
temp_hi int, -- high temperature |
||||
prcp real, -- precipitation |
||||
date date |
||||
); |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
Note that both keywords and identifiers are case-insensitive; identifiers can become |
||||
case-sensitive by surrounding them with double-quotes as allowed by <Acronym>SQL92</Acronym>. |
||||
<ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> supports the usual |
||||
<Acronym>SQL</Acronym> types <Type>int</Type>, |
||||
<Type>float</Type>, <Type>real</Type>, <Type>smallint</Type>, <Type>char(N)</Type>, |
||||
<Type>varchar(N)</Type>, <Type>date</Type>, <Type>time</Type>, |
||||
and <Type>timestamp</Type>, as well as other types of general utility and |
||||
a rich set of geometric types. As we will |
||||
see later, <ProductName>Postgres</ProductName> can be customized with an |
||||
arbitrary number of |
||||
user-defined data types. Consequently, type names are |
||||
not syntactical keywords, except where required to support special cases in the <Acronym>SQL92</Acronym> standard. |
||||
So far, the <ProductName>Postgres</ProductName> create command looks exactly like |
||||
the command used to create a table in a traditional |
||||
relational system. However, we will presently see that |
||||
classes have properties that are extensions of the |
||||
relational model. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Populating a Class with Instances</Title> |
||||
|
||||
<Para> |
||||
The <Command>insert</Command> statement is used to populate a class with |
||||
instances: |
||||
|
||||
<ProgramListing> |
||||
INSERT INTO weather |
||||
VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994') |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
You can also use the <Command>copy</Command> command to perform load large |
||||
amounts of data from flat (<Acronym>ASCII</Acronym>) files. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Querying a Class</Title> |
||||
|
||||
<Para> |
||||
The weather class can be queried with normal relational |
||||
selection and projection queries. A <Acronym>SQL</Acronym> <Command>select</Command> |
||||
statement is used to do this. The statement is divided into |
||||
a target list (the part that lists the attributes to be |
||||
returned) and a qualification (the part that specifies |
||||
any restrictions). For example, to retrieve all the |
||||
rows of weather, type: |
||||
<ProgramListing> |
||||
SELECT * FROM WEATHER; |
||||
</ProgramListing> |
||||
|
||||
and the output should be: |
||||
<ProgramListing> |
||||
+--------------+---------+---------+------+------------+ |
||||
|city | temp_lo | temp_hi | prcp | date | |
||||
+--------------+---------+---------+------+------------+ |
||||
|San Francisco | 46 | 50 | 0.25 | 11-27-1994 | |
||||
+--------------+---------+---------+------+------------+ |
||||
|San Francisco | 43 | 57 | 0 | 11-29-1994 | |
||||
+--------------+---------+---------+------+------------+ |
||||
|Hayward | 37 | 54 | | 11-29-1994 | |
||||
+--------------+---------+---------+------+------------+ |
||||
</ProgramListing> |
||||
You may specify any arbitrary expressions in the target list. For example, you can do: |
||||
<ProgramListing> |
||||
SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather; |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
Arbitrary Boolean operators |
||||
(<Command>and</Command>, <Command>or</Command> and <Command>not</Command>) are |
||||
allowed in the qualification of any query. For example, |
||||
|
||||
<ProgramListing> |
||||
SELECT * FROM weather |
||||
WHERE city = 'San Francisco' |
||||
AND prcp > 0.0; |
||||
|
||||
+--------------+---------+---------+------+------------+ |
||||
|city | temp_lo | temp_hi | prcp | date | |
||||
+--------------+---------+---------+------+------------+ |
||||
|San Francisco | 46 | 50 | 0.25 | 11-27-1994 | |
||||
+--------------+---------+---------+------+------------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
As a final note, you can specify that the results of a |
||||
select can be returned in a <FirstTerm>sorted order</FirstTerm> |
||||
or with <FirstTerm>duplicate instances</FirstTerm> removed. |
||||
|
||||
<ProgramListing> |
||||
SELECT DISTINCT city |
||||
FROM weather |
||||
ORDER BY city; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Redirecting SELECT Queries</Title> |
||||
|
||||
<Para> |
||||
Any select query can be redirected to a new class |
||||
<ProgramListing> |
||||
SELECT * INTO TABLE temp FROM weather; |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
This forms an implicit <Command>create</Command> command, creating a new |
||||
class temp with the attribute names and types specified |
||||
in the target list of the <Command>select into</Command> command. We can |
||||
then, of course, perform any operations on the resulting |
||||
class that we can perform on other classes. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Joins Between Classes</Title> |
||||
|
||||
<Para> |
||||
Thus far, our queries have only accessed one class at a |
||||
time. Queries can access multiple classes at once, or |
||||
access the same class in such a way that multiple |
||||
instances of the class are being processed at the same |
||||
time. A query that accesses multiple instances of the |
||||
same or different classes at one time is called a join |
||||
query. |
||||
As an example, say we wish to find all the records that |
||||
are in the temperature range of other records. In |
||||
effect, we need to compare the temp_lo and temp_hi |
||||
attributes of each EMP instance to the temp_lo and |
||||
temp_hi attributes of all other EMP instances. |
||||
<Note> |
||||
<Para> |
||||
This is only a conceptual model. The actual join may |
||||
be performed in a more efficient manner, but this is invisible to the user. |
||||
</Para> |
||||
</Note> |
||||
|
||||
We can do this with the following query: |
||||
|
||||
<ProgramListing> |
||||
SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high, |
||||
W2.city, W2.temp_lo AS low, W2.temp_hi AS high |
||||
FROM weather W1, weather W2 |
||||
WHERE W1.temp_lo < W2.temp_lo |
||||
AND W1.temp_hi > W2.temp_hi; |
||||
|
||||
+--------------+-----+------+---------------+-----+------+ |
||||
|city | low | high | city | low | high | |
||||
+--------------+-----+------+---------------+-----+------+ |
||||
|San Francisco | 43 | 57 | San Francisco | 46 | 50 | |
||||
+--------------+-----+------+---------------+-----+------+ |
||||
|San Francisco | 37 | 54 | San Francisco | 46 | 50 | |
||||
+--------------+-----+------+---------------+-----+------+ |
||||
</ProgramListing> |
||||
|
||||
<Note> |
||||
<Para> |
||||
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, |
||||
<ProductName>Postgres</ProductName> computes and returns the values specified in the |
||||
target list. <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> does not assign any meaning to |
||||
duplicate values in such expressions. This means that <ProductName>Postgres</ProductName> |
||||
sometimes recomputes the same target list several times; |
||||
this frequently happens when Boolean expressions are connected |
||||
with an "or". To remove such duplicates, you must use |
||||
the <Command>select distinct</Command> statement. |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
In this case, both W1 and W2 are surrogates for an |
||||
instance of the class weather, and both range over all |
||||
instances of the class. (In the terminology of most |
||||
database systems, W1 and W2 are known as <FirstTerm>range variables</FirstTerm>.) |
||||
A query can contain an arbitrary number of |
||||
class names and surrogates. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Updates</Title> |
||||
|
||||
<Para> |
||||
You can update existing instances using the update command. |
||||
Suppose you discover the temperature readings are |
||||
all off by 2 degrees as of Nov 28, you may update the |
||||
data as follow: |
||||
|
||||
<ProgramListing> |
||||
UPDATE weather |
||||
SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2 |
||||
WHERE date > '11/28/1994'; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Deletions</Title> |
||||
|
||||
<Para> |
||||
Deletions are performed using the <Command>delete</Command> command: |
||||
<ProgramListing> |
||||
DELETE FROM weather WHERE city = 'Hayward'; |
||||
</ProgramListing> |
||||
|
||||
All weather recording belongs to Hayward is removed. |
||||
One should be wary of queries of the form |
||||
<ProgramListing> |
||||
DELETE FROM classname; |
||||
</ProgramListing> |
||||
|
||||
Without a qualification, <Command>delete</Command> will simply |
||||
remove all instances of the given class, leaving it |
||||
empty. The system will not request confirmation before |
||||
doing this. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Using Aggregate Functions</Title> |
||||
|
||||
<Para> |
||||
Like most other query languages, <ProductName>PostgreSQL</ProductName> supports |
||||
aggregate functions. |
||||
The current implementation of <ProductName>Postgres</ProductName> aggregate functions have some limitations. |
||||
Specifically, while there are aggregates to compute |
||||
such functions as the <Function>count</Function>, <Function>sum</Function>, |
||||
<Function>avg</Function> (average), <Function>max</Function> (maximum) and |
||||
<Function>min</Function> (minimum) over a set of instances, aggregates can only |
||||
appear in the target list of a query and not directly in the |
||||
qualification (the where clause). As an example, |
||||
|
||||
<ProgramListing> |
||||
SELECT max(temp_lo) FROM weather; |
||||
</ProgramListing> |
||||
|
||||
is allowed, while |
||||
|
||||
<ProgramListing> |
||||
SELECT city FROM weather WHERE temp_lo = max(temp_lo); |
||||
</ProgramListing> |
||||
|
||||
is not. However, as is often the case the query can be restated to accomplish |
||||
the intended result; here by using a <FirstTerm>subselect</FirstTerm>: |
||||
<ProgramListing> |
||||
SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather); |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Aggregates may also have <FirstTerm>group by</FirstTerm> clauses: |
||||
<ProgramListing> |
||||
SELECT city, max(temp_lo) |
||||
FROM weather |
||||
GROUP BY city; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,8 @@ |
||||
<Chapter> |
||||
<Title>Database Recovery</Title> |
||||
|
||||
<Para> |
||||
This section needs to be written. Volunteers? |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,448 @@ |
||||
<Chapter> |
||||
<Title>Regression Test</Title> |
||||
|
||||
<Abstract> |
||||
<Para> |
||||
Regression test instructions and analysis. |
||||
</Para> |
||||
</Abstract> |
||||
|
||||
<Para> |
||||
The PostgreSQL regression tests are a comprehensive set of tests for the |
||||
SQL implementation embedded in PostgreSQL developed by Jolly Chen and |
||||
Andrew Yu. It tests standard SQL operations as well as the extended |
||||
capabilities of PostgreSQL. |
||||
</Para> |
||||
|
||||
<Para> |
||||
These tests have recently been revised by Marc Fournier and Thomas Lockhart |
||||
and are now packaged as |
||||
functional units which should make them easier to run and easier to interpret. |
||||
From <ProductName>PostgreSQL</ProductName> v6.1 onward |
||||
the regression tests are current for every official release. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Some properly installed and fully functional PostgreSQL installations |
||||
can fail some of these regression tests due to artifacts of floating point |
||||
representation and time zone support. The current tests are evaluated |
||||
using a simple "diff" algorithm, and are sensitive to small system |
||||
differences. For apparently failed tests, examining the differences |
||||
may reveal that the differences are not significant. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The regression testing notes below assume the following (except where noted): |
||||
<ItemizedList Mark="bullet" Spacing="compact"> |
||||
<ListItem> |
||||
<Para> |
||||
Commands are Unix-compatible. See note below. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
Defaults are used except where noted. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
User postgres is the <ProductName>Postgres</ProductName> superuser. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
The source path is /usr/src/pgsql (other paths are possible). |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
The runtime path is /usr/local/pgsql (other paths are possible). |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Regression Environment</Title> |
||||
|
||||
<Para> |
||||
The regression test is invoked by the <Command>make</Command> command which compiles |
||||
a <Acronym>C</Acronym> program into a shared library |
||||
in the current directory. Localized shell scripts are also created in |
||||
the current directory. The output file templates are massaged into the |
||||
<FileName>./expected/*.out</FileName> files. The localization replaces macros in the source |
||||
files with absolute pathnames and user names. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Normally, the regression test should be run as the pg_superuser since |
||||
the 'src/test/regress' directory and sub-directories are owned by the |
||||
pg_superuser. If you run the regression test as another user the |
||||
'src/test/regress' directory tree should be writeable to that user. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The postmaster should be invoked with the system time zone set for |
||||
Berkeley, California. This is done automatically by the regression |
||||
test script. However, it does require machine support for the PST8PDT |
||||
time zone. |
||||
</Para> |
||||
|
||||
<Para> |
||||
To verify that your machine does have this support, type |
||||
the following: |
||||
<ProgramListing> |
||||
setenv TZ PST8PDT |
||||
date |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The "date" command above should have returned the current system time |
||||
in the PST8PDT time zone. If the PST8PDT database is not available, then |
||||
your system may have returned the time in GMT. If the PST8PDT time zone |
||||
is not available, you can set the time zone rules explicitly: |
||||
<ProgramListing> |
||||
setenv PGTZ PST8PDT7,M04.01.0,M10.05.03 |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Directory Layout</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
This should become a table in the previous section. |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProgramListing> |
||||
input/ .... .source files that are converted using 'make all' into |
||||
some of the .sql files in the 'sql' subdirectory |
||||
|
||||
output/ ... .source files that are converted using 'make all' into |
||||
.out files in the 'expected' subdirectory |
||||
|
||||
sql/ ...... .sql files used to perform the regression tests |
||||
|
||||
expected/ . .out files that represent what we *expect* the results to |
||||
look like |
||||
|
||||
results/ .. .out files that represent what the results *actually* look |
||||
like. Also used as temporary storage for table copy testing. |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Regression Test Procedure</Title> |
||||
|
||||
<Para> |
||||
Commands were tested on RedHat Linux version 4.2 using the bash shell. |
||||
Except where noted, they will probably work on most systems. Commands |
||||
like <FileName>ps</FileName> and <FileName>tar</FileName> vary wildly on what options you should use on each |
||||
platform. <Emphasis>Use common sense</Emphasis> before typing in these commands. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<Procedure> |
||||
<Title><ProductName>Postgres</ProductName> Regression Configuration</Title> |
||||
|
||||
<Para> |
||||
For a fresh install or upgrading from previous releases of |
||||
<ProductName>Postgres</ProductName>: |
||||
</Para> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Build the regression test. Type |
||||
<ProgramListing> |
||||
cd /usr/src/pgsql/src/test/regress |
||||
gmake all |
||||
</ProgramListing> |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="optional"> |
||||
<Para> |
||||
If you have prevously invoked the regression test, clean up the |
||||
working directory with: |
||||
|
||||
<ProgramListing> |
||||
cd /usr/src/pgsql/src/test/regress |
||||
make clean |
||||
</ProgramListing> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
The file /usr/src/pgsql/src/test/regress/README has detailed |
||||
instructions for running and interpreting the regression tests. |
||||
A short version follows here: |
||||
</Para> |
||||
|
||||
<Para> |
||||
If the postmaster is not already running, start the postmaster on an |
||||
available window by typing |
||||
<ProgramListing> |
||||
postmaster |
||||
</ProgramListing> |
||||
|
||||
or start the postmaster daemon running in the background by typing |
||||
<ProgramListing> |
||||
cd |
||||
nohup postmaster > regress.log 2>&1 & |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Run postmaster from your <ProductName>Postgres</ProductName> super user account (typically |
||||
account postgres). |
||||
|
||||
<Note> |
||||
<Para> |
||||
Do not run <FileName>postmaster</FileName> from the root account. |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
Run the regression tests. Type |
||||
|
||||
<ProgramListing> |
||||
cd /usr/src/pgsql/src/test/regress |
||||
gmake runtest |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
|
||||
You do not need to type "gmake clean" if this is the first time you |
||||
are running the tests. |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
|
||||
You should get on the screen (and also written to file ./regress.out) |
||||
a series of statements stating which tests passed and which tests |
||||
failed. Please note that it can be normal for some of the tests to |
||||
"fail". For the failed tests, use diff to compare the files in |
||||
directories ./results and ./expected. If float8 failed, type |
||||
something like: |
||||
<ProgramListing> |
||||
cd /usr/src/pgsql/src/test/regress |
||||
diff -w expected/float8.out results |
||||
</ProgramListing> |
||||
</Para> |
||||
</Step> |
||||
|
||||
<Step Performance="required"> |
||||
<Para> |
||||
After running the tests, type |
||||
<ProgramListing> |
||||
destroydb regression |
||||
cd /usr/src/pgsql/src/test/regress |
||||
gmake clean |
||||
</ProgramListing> |
||||
</Para> |
||||
</Step> |
||||
|
||||
</Procedure> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Regression Analysis</Title> |
||||
|
||||
<Para> |
||||
<Quote>Failed</Quote> tests may have failed due to slightly different error messages, |
||||
math libraries, or output formatting. |
||||
"Failures" of this type do not indicate a problem with |
||||
<ProductName>Postgres</ProductName>. |
||||
</Para> |
||||
|
||||
<Para> |
||||
For a i686/Linux-ELF platform, no tests failed since this is the |
||||
v6.2.1 regression testing reference platform. |
||||
</Para> |
||||
|
||||
<Para> |
||||
For the SPARC/Linux-ELF platform, using the 970525 beta version of |
||||
<ProductName>Postgres</ProductName> v6.2 the following tests "failed": |
||||
float8 and geometry "failed" due to minor precision differences in |
||||
floating point numbers. select_views produces massively different output, |
||||
but the differences are due to minor floating point differences. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Conclusion? If you do see failures, try to understand the nature of |
||||
the differences and then decide if those differences will affect your |
||||
intended use of <ProductName>Postgres</ProductName>. However, keep in mind that this is likely |
||||
to be the most solid release of <ProductName>Postgres</ProductName> to date, incorporating many |
||||
bug fixes from v6.1, and that previous versions of <ProductName>Postgres</ProductName> have been |
||||
in use successfully for some time now. |
||||
</Para> |
||||
|
||||
<Sect2> |
||||
<Title>Comparing expected/actual output</Title> |
||||
|
||||
<Para> |
||||
The results are in files in the ./results directory. These results |
||||
can be compared with results in the ./expected directory using 'diff'. |
||||
The files might not compare exactly. The following paragraphs attempt |
||||
to explain the differences. |
||||
</Para> |
||||
|
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Error message differences</Title> |
||||
|
||||
<Para> |
||||
Some of the regression tests involve intentional invalid input values. |
||||
Error messages can come from either the Postgres code or from the host |
||||
platform system routines. In the latter case, the messages may vary |
||||
between platforms, but should reflect similar information. These |
||||
differences in messages will result in a "failed" regression test which |
||||
can be validated by inspection. |
||||
</Para> |
||||
|
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>OID differences</Title> |
||||
|
||||
<Para> |
||||
There are several places where PostgreSQL OID (object identifiers) appear |
||||
in 'regress.out'. OID's are unique 32-bit integers which are generated |
||||
by the PostgreSQL backend whenever a table row is inserted or updated. |
||||
If you run the regression test on a non-virgin database or run it multiple |
||||
times, the OID's reported will have different values. |
||||
|
||||
The following SQL statements in 'misc.out' have shown this behavior: |
||||
|
||||
QUERY: SELECT user_relns() AS user_relns ORDER BY user_relns; |
||||
|
||||
The 'a,523676' row is composed from an OID. |
||||
</Para> |
||||
|
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Date and time differences</Title> |
||||
|
||||
<Para> |
||||
On many supported platforms, you can force PostgreSQL to believe that it |
||||
is running in the same time zone as Berkeley, California. See details in |
||||
the section on how to run the regression tests. |
||||
|
||||
If you do not explicitly set your time zone environment to PST8PDT, then |
||||
most of the date and time results will reflect your local time zone and |
||||
will fail the regression testing. |
||||
|
||||
There appears to be some systems which do not accept the recommended syntax |
||||
for explicitly setting the local time zone rules. Some systems using the |
||||
public domain time zone package exhibit minor problems with pre-1970 PDT |
||||
times, representing them in PST instead. |
||||
</Para> |
||||
|
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Floating point differences</Title> |
||||
|
||||
<Para> |
||||
Some of the tests involve computing 64-bit (<Type>float8</Type>) number from table |
||||
columns. Differences in results involving mathematical functions of |
||||
<Type>float8</Type> columns have been observed. These differences occur where |
||||
different operating systems are used on the same platform ie: |
||||
BSDI and SOLARIS on Intel/86, and where the same operating system is |
||||
used used on different platforms, ie: SOLARIS on SPARC and Intel/86. |
||||
|
||||
Human eyeball comparison is needed to determine the real significance |
||||
of these differences which are usually 10 places to the right of |
||||
the decimal point. |
||||
|
||||
Some systems signal errors from pow() and exp() differently from |
||||
the mechanism expected by the current Postgres code. |
||||
</Para> |
||||
|
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Polygon differences</Title> |
||||
|
||||
<Para> |
||||
Several of the tests involve operations on geographic date about the |
||||
Oakland/Berkley CA street map. The map data is expressed as polygons |
||||
whose vertices are represented as pairs of <Type>float8</Type> numbers (decimal |
||||
latitude and longitude). Initially, some tables are created and |
||||
loaded with geographic data, then some views are created which join |
||||
two tables using the polygon intersection operator (##), then a select |
||||
is done on the view. |
||||
|
||||
When comparing the results from different platforms, differences occur |
||||
in the 2nd or 3rd place to the right of the decimal point. The SQL |
||||
statements where these problems occur are the folowing: |
||||
|
||||
<ProgramListing> |
||||
QUERY: SELECT * from street; |
||||
QUERY: SELECT * from iexit; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Random differences</Title> |
||||
|
||||
<Para> |
||||
There is at least one test case in random.out which is intended to produce |
||||
random results. This causes random to fail the regression testing. |
||||
Typing |
||||
<ProgramListing> |
||||
diff results/random.out expected/random.out |
||||
</ProgramListing> |
||||
|
||||
should produce only |
||||
one or a few lines of differences for this reason, but other floating |
||||
point differences on dissimilar architectures might cause many more |
||||
differences. See the release notes below. |
||||
</Para> |
||||
|
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>The <Quote>expected</Quote> files</Title> |
||||
|
||||
<Para> |
||||
The <FileName>./expected/*.out</FileName> files were adapted from the original monolithic |
||||
<FileName>expected.input</FileName> file provided by Jolly Chen et al. Newer versions of these |
||||
files generated on various development machines have been substituted after |
||||
careful (?) inspection. Many of the development machines are running a |
||||
Unix OS variant (FreeBSD, Linux, etc) on Ix86 hardware. |
||||
|
||||
The original <FileName>expected.input</FileName> file was created on a SPARC Solaris 2.4 |
||||
system using the <FileName>postgres5-1.02a5.tar.gz</FileName> source tree. It was compared |
||||
with a file created on an I386 Solaris 2.4 system and the differences |
||||
were only in the floating point polygons in the 3rd digit to the right |
||||
of the decimal point. (see below) |
||||
|
||||
The original <FileName>sample.regress.out</FileName> file was from the postgres-1.01 release |
||||
constructed by Jolly Chen and is included here for reference. It may |
||||
have been created on a DEC ALPHA machine as the <FileName>Makefile.global</FileName> |
||||
in the postgres-1.01 release has PORTNAME=alpha. |
||||
</Para> |
||||
|
||||
</Sect2> |
||||
|
||||
</Sect1> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,144 @@ |
||||
<Chapter> |
||||
<Title>Release Notes</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
Should include the migration notes from <FileName>migration/</FileName>. |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The release notes have not yet been integrated into the new documentation. |
||||
Check for plain text files in the top of the distribution directory tree |
||||
and in the <FileName>migration/</FileName> directory for current information. |
||||
|
||||
<Sect1> |
||||
<Title>Release 6.3</Title> |
||||
|
||||
<Para> |
||||
TBD |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Release 6.2.1</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
v6.2.1 was a bug-fix and usability release on v6.2. Needs only a few notes. |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Release 6.2</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
This should include information based on Bruce's release summary. |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Release 6.1</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
This should include information based on Bruce's release summary. |
||||
</Para> |
||||
</Note> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The regression tests have been adapted and extensively modified for the |
||||
v6.1 release of PostgreSQL. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Three new data types (datetime, timespan, and circle) have been added to |
||||
the native set of PostgreSQL types. Points, boxes, paths, and polygons |
||||
have had their output formats made consistant across the data types. |
||||
The polygon output in misc.out has only been spot-checked for correctness |
||||
relative to the original regression output. |
||||
</Para> |
||||
|
||||
<Para> |
||||
PostgreSQL v6.1 introduces a new, alternate optimizer which uses <FirstTerm>genetic</FirstTerm> |
||||
algorithms. These algorithms introduce a random behavior in the ordering |
||||
of query results when the query contains multiple qualifiers or multiple |
||||
tables (giving the optimizer a choice on order of evaluation). Several |
||||
regression tests have been modified to explicitly order the results, and |
||||
hence are insensitive to optimizer choices. A few regression tests are |
||||
for data types which are inherently unordered (e.g. points and time |
||||
intervals) and tests involving those types are explicitly bracketed with |
||||
<Command>set geqo to 'off'</Command> and <Command>reset geqo</Command>. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The interpretation of array specifiers (the curly braces around atomic |
||||
values) appears to have changed sometime after the original regression |
||||
tests were generated. The current <FileName>./expected/*.out</FileName> files reflect this |
||||
new interpretation, which may not be correct! |
||||
</Para> |
||||
|
||||
<Para> |
||||
The float8 regression test fails on at least some platforms. This is due |
||||
to differences in implementations of pow() and exp() and the signaling |
||||
mechanisms used for overflow and underflow conditions. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The "random" results in the random test should cause the "random" test |
||||
to be "failed", since the regression tests are evaluated using a simple |
||||
diff. However, "random" does not seem to produce random results on my |
||||
test machine (Linux/gcc/i686). |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Timing Results</Title> |
||||
|
||||
<Para> |
||||
These timing results are from running the regression test with the command |
||||
|
||||
<ProgramListing> |
||||
% time make runtest |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
Timing under Linux 2.0.27 seems to have a roughly 5% variation from run |
||||
to run, presumably due to the timing vagaries of multitasking systems. |
||||
|
||||
<Sect2> |
||||
<Title>v6.3</Title> |
||||
|
||||
<Para> |
||||
<ProgramListing> |
||||
Time System |
||||
02:30 Dual Pentium Pro 180, 96MB, UW-SCSI, Linux 2.0.30, gcc 2.7.2.1 -O2 -m486 |
||||
04:12 Dual Pentium Pro 180, 96MB, EIDE, Linux 2.0.30, gcc 2.7.2.1 -O2 -m486 |
||||
</ProgramListing> |
||||
|
||||
<Sect2> |
||||
<Title>v6.1</Title> |
||||
|
||||
<Para> |
||||
<ProgramListing> |
||||
Time System |
||||
06:12 Pentium Pro 180, 32MB, Linux 2.0.30, gcc 2.7.2 -O2 -m486 |
||||
12:06 P-100, 48MB, Linux 2.0.29, gcc |
||||
39:58 Sparc IPC 32MB, Solaris 2.5, gcc 2.7.2.1 -O -g |
||||
</ProgramListing> |
||||
|
||||
</Chapter> |
||||
|
||||
@ -0,0 +1,28 @@ |
||||
<Chapter> |
||||
<Title>The <ProductName>Postgres</ProductName> Rule System</Title> |
||||
|
||||
<Para> |
||||
Production rule systems are conceptually simple, but |
||||
there are many subtle points involved in actually using |
||||
them. Consequently, we will not attempt to explain the |
||||
actual syntax and operation of the <ProductName>Postgres</ProductName> rule system |
||||
here. Instead, you should read |
||||
<XRef LinkEnd="STON90b" EndTerm="[STON90b]"> to understand |
||||
some of these points and the theoretical foundations of |
||||
the <ProductName>Postgres</ProductName> rule system before trying to use rules. |
||||
The discussion in this section is intended to provide |
||||
an overview of the <ProductName>Postgres</ProductName> rule system and point the |
||||
user at helpful references and examples. |
||||
|
||||
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. The |
||||
power of this rule system is discussed in |
||||
<XRef LinkEnd="ONG90" EndTerm="[ONG90]"> |
||||
as well as |
||||
<XRef LinkEnd="STON90b" EndTerm="[STON90b]">. |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,432 @@ |
||||
<!-- |
||||
- This file currently contains several small chapters. |
||||
- Each chapter should be split off into a separate source file... |
||||
- - thomas 1998-02-24 |
||||
--> |
||||
|
||||
<Chapter> |
||||
<Title>Runtime Environment</Title> |
||||
|
||||
<Para> |
||||
<Figure Id="ADMIN-LAYOUT"> |
||||
<Title><ProductName>Postgres</ProductName> file layout</Title> |
||||
<Graphic Align="center" FileRef="layout.gif" Format="GIF"></Graphic> |
||||
</Figure> |
||||
|
||||
<XRef LinkEnd="ADMIN-LAYOUT" EndTerm="ADMIN-LAYOUT"> |
||||
shows how the <ProductName>Postgres</ProductName> distribution is laid |
||||
out when installed in the default way. For simplicity, |
||||
we will assume that <ProductName>Postgres</ProductName> has been installed in the |
||||
directory <FileName>/usr/local/pgsql</FileName>. Therefore, wherever |
||||
you see the directory <FileName>/usr/local/pgsql</FileName> you should |
||||
substitute the name of the directory where <ProductName>Postgres</ProductName> is |
||||
actually installed. |
||||
All <ProductName>Postgres</ProductName> commands are installed in the directory |
||||
<FileName>/usr/local/pgsql/bin</FileName>. Therefore, you should add |
||||
this directory to your shell command path. If you use |
||||
a variant of the Berkeley C shell, such as csh or tcsh, |
||||
you would add |
||||
<ProgramListing> |
||||
set path = ( /usr/local/pgsql/bin path ) |
||||
</ProgramListing> |
||||
in the .login file in your home directory. If you use |
||||
a variant of the Bourne shell, such as sh, ksh, or |
||||
bash, then you would add |
||||
<ProgramListing> |
||||
PATH=/usr/local/pgsql/bin PATH |
||||
export PATH |
||||
</ProgramListing> |
||||
to the .profile file in your home directory. |
||||
From now on, we will assume that you have added the |
||||
<ProductName>Postgres</ProductName> bin directory to your path. In addition, we |
||||
will make frequent reference to "setting a shell |
||||
variable" or "setting an environment variable" throughout |
||||
this document. If you did not fully understand the |
||||
last paragraph on modifying your search path, you |
||||
should consult the UNIX manual pages that describe your |
||||
shell before going any further. |
||||
</Para> |
||||
|
||||
<Para> |
||||
If your site administrator has not set things up in the |
||||
default way, you may have some more work to do. For example, if the database server machine is a remote machine, you |
||||
will need to set the <Acronym>PGHOST</Acronym> environment variable to the name |
||||
of the database server machine. The environment variable |
||||
<Acronym>PGPORT</Acronym> may also have to be set. The bottom line is this: if |
||||
you try to start an application program and it complains |
||||
that it cannot connect to the <Application>postmaster</Application>, you should immediately consult your site administrator to make sure that your |
||||
environment is properly set up. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Locale Support</Title> |
||||
|
||||
<Para> |
||||
<Note> |
||||
<Para> |
||||
Written by Oleg Bartunov. |
||||
See <ULink url="http://www.sai.msu.su/~megera/postgres/">Oleg's web page</ULink> |
||||
for additional information on locale and Russian language support. |
||||
|
||||
</Para> |
||||
</Note> |
||||
While doing a project for a company in Moscow, Russia, I encountered the problem that postgresql had no |
||||
support of national alphabets. After looking for possible workarounds I decided to develop support of locale myself. |
||||
I'm not a C-programer but already had some experience with locale programming when I work with perl |
||||
(debugging) and glimpse. After several days of digging through |
||||
the <ProductName>Postgres</ProductName> source tree I made very minor corections to |
||||
src/backend/utils/adt/varlena.c and src/backend/main/main.c and got what I needed! I did support only for |
||||
LC_CTYPE and LC_COLLATE, but later LC_MONETARY was added by others. I got many |
||||
messages from people about this patch so I decided to send it to developers and (to my surprise) it was |
||||
incorporated into postgresql distribution. |
||||
|
||||
<Para> |
||||
People often complain that locale doesn't work for them. There are several common mistakes: |
||||
|
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
Didn't properly configure postgresql before compilation. |
||||
You must run configure with --enable-locale option to enable locale support. |
||||
Didn't setup environment correctly when starting postmaster. |
||||
You must define environment variables $LC_CTYPE and $LC_COLLATE before running postmaster |
||||
because backend gets information about locale from environment. I use following shell script |
||||
(runpostgres): |
||||
|
||||
<ProgramListing> |
||||
#!/bin/sh |
||||
|
||||
export LC_CTYPE=koi8-r |
||||
export LC_COLLATE=koi8-r |
||||
postmaster -B 1024 -S -D/usr/local/pgsql/data/ -o '-Fe' |
||||
</ProgramListing> |
||||
|
||||
and run it from rc.local as |
||||
|
||||
<ProgramListing> |
||||
/bin/su - postgres -c "/home/postgres/runpostgres" |
||||
</ProgramListing> |
||||
|
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
Broken locale support in OS (for example, locale support in libc under Linux several times has changed |
||||
and this caused a lot of problems). Latest perl has also support of locale and if locale is broken perl -v will |
||||
complain something like: |
||||
|
||||
8:17[mira]:~/WWW/postgres>setenv LC_CTYPE not_exist |
||||
8:18[mira]:~/WWW/postgres>perl -v |
||||
perl: warning: Setting locale failed. |
||||
perl: warning: Please check that your locale settings: |
||||
LC_ALL = (unset), |
||||
LC_CTYPE = "not_exist", |
||||
LANG = (unset) |
||||
are supported and installed on your system. |
||||
perl: warning: Falling back to the standard locale ("C"). |
||||
|
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
Wrong location of locale files! |
||||
|
||||
Possible location: <FileName>/usr/lib/locale</FileName> (Linux, Solaris), <FileName>/usr/share/locale</FileName> (Linux), <FileName>/usr/lib/nls/loc</FileName> (DUX 4.0) |
||||
Check man locale for right place. Under Linux I did a symbolical link between <FileName>/usr/lib/locale</FileName> and |
||||
<FileName>/usr/share/locale</FileName> to be sure next libc will not break my locale. |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
<Sect2> |
||||
<Title>What are the Benefits?</Title> |
||||
|
||||
<Para> |
||||
You can use ~* and order by operators for strings contain characters from national alphabets. Non-english users |
||||
definitely need that. If you won't use locale stuff just undefine USE_LOCALE variable. |
||||
|
||||
<Sect2> |
||||
<Title>What are the Drawbacks?</Title> |
||||
|
||||
<Para> |
||||
There is one evident drawback of using locale - it's speed ! So, use locale only if you really need it. |
||||
|
||||
</Chapter> |
||||
|
||||
<Chapter> |
||||
<Title>Starting <Application>postmaster</Application></Title> |
||||
|
||||
<Para> |
||||
Nothing can happen to a database unless the <Application>postmaster</Application> |
||||
process is running. As the site administrator, there |
||||
are a number of things you should remember before |
||||
starting the <Application>postmaster</Application>. These are discussed in the |
||||
section of this manual titled, "Administering Postgres." |
||||
However, if <ProductName>Postgres</ProductName> has been installed by following |
||||
the installation instructions exactly as written, the |
||||
following simple command is all you should |
||||
need to start the <Application>postmaster</Application>: |
||||
<ProgramListing> |
||||
% postmaster |
||||
</ProgramListing> |
||||
The <Application>postmaster</Application> occasionally prints out messages which |
||||
are often helpful during troubleshooting. If you wish |
||||
to view debugging messages from the <Application>postmaster</Application>, you can |
||||
start it with the -d option and redirect the output to |
||||
the log file: |
||||
<ProgramListing> |
||||
% postmaster -d >& pm.log & |
||||
</ProgramListing> |
||||
If you do not wish to see these messages, you can type |
||||
<ProgramListing> |
||||
% postmaster -S |
||||
</ProgramListing> |
||||
and the <Application>postmaster</Application> will be "S"ilent. Notice that there |
||||
is no ampersand ("&") at the end of the last example. |
||||
</Para> |
||||
</Chapter> |
||||
|
||||
<Chapter> |
||||
<Title>Adding and Deleting Users</Title> |
||||
|
||||
<Para> |
||||
<Application>createuser</Application> enables specific users to access |
||||
<ProductName>Postgres</ProductName>. <Application>destroyuser</Application> removes users and |
||||
prevents them from accessing <ProductName>Postgres</ProductName>. Note that these |
||||
commands only affect users with respect to <ProductName>Postgres</ProductName>; |
||||
they have no effect on users other privileges or status with regards |
||||
to the underlying |
||||
operating system. |
||||
</Para> |
||||
</Chapter> |
||||
|
||||
<Chapter> |
||||
<Title>Disk Management</Title> |
||||
|
||||
<Para> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Alternate Locations</Title> |
||||
|
||||
<Para> |
||||
It is possible to create a database in a location other than the default |
||||
location for the installation. Remember that all database access actually |
||||
occurs through the database backend, so that any location specified must |
||||
be accessible by the backend. |
||||
|
||||
<Para> |
||||
Either an absolute path name or an environment variable |
||||
may be specified as a location. Note that for security and integrity reasons, |
||||
all paths and environment variables so specified have some |
||||
additional path fields appended. |
||||
|
||||
<Note> |
||||
<Para> |
||||
The environment variable style of specification |
||||
is to be preferred since it allows the site administrator more flexibility in |
||||
managing disk storage. |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
Remember that database creation is actually performed by the database backend. |
||||
Therefore, any environment variable specifying an alternate location must have |
||||
been defined before the backend was started. To define an alternate location |
||||
PGDATA2 pointing to <FileName>/home/postgres/data</FileName>, type |
||||
<ProgramListing> |
||||
% setenv PGDATA2 /home/postgres/data |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
Usually, you will want to define this variable in the <ProductName>Postgres</ProductName> superuser's |
||||
<FileName>.profile</FileName> |
||||
or |
||||
<FileName>.cshrc</FileName> |
||||
initialization file to ensure that it is defined upon system startup. |
||||
|
||||
<Para> |
||||
To create a data storage area in <FileName>/home/postgres/data</FileName>, ensure |
||||
that <FileName>/home/postgres</FileName> already exists and is writable. |
||||
From the command line, type |
||||
<ProgramListing> |
||||
% initlocation $PGDATA2 |
||||
Creating Postgres database system directory /home/postgres/data |
||||
|
||||
Creating Postgres database system directory /home/postgres/data/base |
||||
|
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
To test the new location, create a database <Database>test</Database> by typing |
||||
<ProgramListing> |
||||
% createdb -D PGDATA2 test |
||||
% destroydb test |
||||
</ProgramListing> |
||||
</Sect1> |
||||
</Chapter> |
||||
|
||||
<Chapter> |
||||
<Title>Troubleshooting</Title> |
||||
|
||||
<Para> |
||||
Assuming that your site administrator has properly |
||||
started the <Application>postmaster</Application> process and authorized you to |
||||
use the database, you (as a user) may begin to start up |
||||
applications. As previously mentioned, you should add |
||||
<FileName>/usr/local/pgsql/bin</FileName> to your shell search path. |
||||
In most cases, this is all you should have to do in |
||||
terms of preparation. |
||||
|
||||
<Para> |
||||
If you get the following error message from a <ProductName>Postgres</ProductName> |
||||
command (such as <Application>psql</Application> or <Application>createdb</Application>): |
||||
<ProgramListing> |
||||
connectDB() failed: Is the postmaster running at 'localhost' on port '4322'? |
||||
</ProgramListing> |
||||
it is usually because either the <Application>postmaster</Application> is not running, |
||||
or you are attempting to connect to the wrong server host. |
||||
If you get the following error message: |
||||
<ProgramListing> |
||||
FATAL 1:Feb 17 23:19:55:process userid (2360) != database owner (268) |
||||
</ProgramListing> |
||||
it means that the site administrator started the <Application>postmaster</Application> |
||||
as the wrong user. Tell him to restart it as |
||||
the <ProductName>Postgres</ProductName> superuser. |
||||
</Para> |
||||
</Chapter> |
||||
|
||||
<Chapter> |
||||
<Title>Managing a Database</Title> |
||||
|
||||
<Para> |
||||
Now that <ProductName>Postgres</ProductName> is up and running we can create some |
||||
databases to experiment with. Here, we describe the |
||||
basic commands for managing a database. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Creating a Database</Title> |
||||
|
||||
<Para> |
||||
Let's say you want to create a database named mydb. |
||||
You can do this with the following command: |
||||
<ProgramListing> |
||||
% createdb mydb |
||||
</ProgramListing> |
||||
|
||||
<ProductName>Postgres</ProductName> allows you to create any number of databases |
||||
at a given site and you automatically become the |
||||
database administrator of the database you just created. Database names must have an alphabetic first |
||||
character and are limited to 16 characters in length. |
||||
Not every user has authorization to become a database |
||||
administrator. If <ProductName>Postgres</ProductName> refuses to create databases |
||||
for you, then the site administrator needs to grant you |
||||
permission to create databases. Consult your site |
||||
administrator if this occurs. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Accessing a Database</Title> |
||||
|
||||
<Para> |
||||
Once you have constructed a database, you can access it |
||||
by: |
||||
|
||||
<ItemizedList Mark="bullet" Spacing="compact"> |
||||
<ListItem> |
||||
<Para> |
||||
running the <ProductName>Postgres</ProductName> terminal monitor programs ( |
||||
monitor or <Application>psql</Application>) which allows you to interactively |
||||
enter, edit, and execute <Acronym>SQL</Acronym> commands. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
writing a C program using the LIBPQ subroutine |
||||
library. This allows you to submit <Acronym>SQL</Acronym> commands |
||||
from C and get answers and status messages back to |
||||
your program. This interface is discussed further |
||||
in section ??. |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
You might want to start up <Application>psql</Application>, to try out the examples in this manual. It can be activated for the mydb |
||||
database by typing the command: |
||||
<ProgramListing> |
||||
% psql mydb |
||||
</ProgramListing> |
||||
|
||||
You will be greeted with the following message: |
||||
<ProgramListing> |
||||
Welcome to the Postgres interactive sql monitor: |
||||
|
||||
type \? for help on slash commands |
||||
type \q to quit |
||||
type \g or terminate with semicolon to execute query |
||||
You are currently connected to the database: mydb |
||||
|
||||
mydb=> |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
This prompt indicates that the terminal monitor is listening to you and that you can type <Acronym>SQL</Acronym> queries into a |
||||
workspace maintained by the terminal monitor. |
||||
The <Application>psql</Application> program responds to escape codes that begin |
||||
with the backslash character, "\". For example, you |
||||
can get help on the syntax of various <ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> commands by typing: |
||||
<ProgramListing> |
||||
mydb=> \h |
||||
</ProgramListing> |
||||
|
||||
Once you have finished entering your queries into the |
||||
workspace, you can pass the contents of the workspace |
||||
to the <ProductName>Postgres</ProductName> server by typing: |
||||
<ProgramListing> |
||||
mydb=> \g |
||||
</ProgramListing> |
||||
|
||||
This tells the server to process the query. If you |
||||
terminate your query with a semicolon, the backslash-g is not |
||||
necessary. <Application>psql</Application> will automatically process semicolon terminated queries. |
||||
To read queries from a file, say myFile, instead of |
||||
entering them interactively, type: |
||||
<ProgramListing> |
||||
mydb=> \i fileName |
||||
</ProgramListing> |
||||
|
||||
To get out of <Application>psql</Application> and return to UNIX, type |
||||
<ProgramListing> |
||||
mydb=> \q |
||||
</ProgramListing> |
||||
|
||||
and <Application>psql</Application> will quit and return you to your command |
||||
shell. (For more escape codes, type backslash-h at the monitor |
||||
prompt.) |
||||
White space (i.e., spaces, tabs and newlines) may be |
||||
used freely in <Acronym>SQL</Acronym> queries. Single-line comments are denoted by |
||||
<Quote>--</Quote>. Everything after the dashes up to the end of the |
||||
line is ignored. Multiple-line comments, and comments within a line, |
||||
are denoted by <Quote>/* ... */</Quote> |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Destroying a Database</Title> |
||||
|
||||
<Para> |
||||
If you are the database administrator for the database |
||||
mydb, you can destroy it using the following UNIX command: |
||||
<ProgramListing> |
||||
% destroydb mydb |
||||
</ProgramListing> |
||||
This action physically removes all of the UNIX files |
||||
associated with the database and cannot be undone, so |
||||
this should only be done with a great deal of forethought. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,315 @@ |
||||
<Chapter> |
||||
<Title>Getting Started</Title> |
||||
|
||||
<Abstract> |
||||
<Para> |
||||
How to begin work with <ProductName>Postgres</ProductName> for a new user. |
||||
</Para> |
||||
</Abstract> |
||||
|
||||
<Para> |
||||
Some of the steps required to use <ProductName>Postgres</ProductName> |
||||
can be performed by any Postgres user, and some must be done by |
||||
the site database administrator. This site administrator |
||||
is the person who installed the software, created |
||||
the database directories and started the <Application>postmaster</Application> |
||||
process. This person does not have to be the UNIX |
||||
superuser (<Quote>root</Quote>) |
||||
or the computer system administrator; a person can install and use |
||||
<ProductName>Postgres</ProductName> without any special accounts or privileges. |
||||
</Para> |
||||
|
||||
<Para> |
||||
If you are installing <ProductName>Postgres</ProductName> yourself, then |
||||
refer to the Administrator's Guide for instructions on installation, and return |
||||
to this guide when the installation is complete. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Throughout this manual, any examples that begin with |
||||
the character <Quote>&percnt</Quote> are commands that should be typed |
||||
at the UNIX shell prompt. Examples that begin with the |
||||
character <Quote>*</Quote> are commands in the Postgres query |
||||
language, Postgres <Acronym>SQL</Acronym>. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Setting Up Your Environment</Title> |
||||
|
||||
<Para> |
||||
This section discusses how to set up |
||||
your own environment so that you can use frontend |
||||
applications. We assume <ProductName>Postgres</ProductName> has already been |
||||
successfully installed and started; refer to the Administrator's Guide |
||||
and the installation notes |
||||
for how to install Postgres. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> is a client/server application. As a user, |
||||
you only need access to the client portions of the installation (an example |
||||
of a client application is the interactive monitor <Application>psql</Application>). |
||||
For simplicity, |
||||
we will assume that <ProductName>Postgres</ProductName> has been installed in the |
||||
directory <FileName>/usr/local/pgsql</FileName>. Therefore, wherever |
||||
you see the directory <FileName>/usr/local/pgsql</FileName> you should |
||||
substitute the name of the directory where <ProductName>Postgres</ProductName> is |
||||
actually installed. |
||||
All <ProductName>Postgres</ProductName> commands are installed in the directory |
||||
<FileName>/usr/local/pgsql/bin</FileName>. Therefore, you should add |
||||
this directory to your shell command path. If you use |
||||
a variant of the Berkeley C shell, such as csh or tcsh, |
||||
you would add |
||||
<ProgramListing> |
||||
% set path = ( /usr/local/pgsql/bin path ) |
||||
</ProgramListing> |
||||
in the <FileName>.login</FileName> file in your home directory. If you use |
||||
a variant of the Bourne shell, such as sh, ksh, or |
||||
bash, then you would add |
||||
<ProgramListing> |
||||
% PATH=/usr/local/pgsql/bin PATH |
||||
% export PATH |
||||
</ProgramListing> |
||||
to the .profile file in your home directory. |
||||
From now on, we will assume that you have added the |
||||
<ProductName>Postgres</ProductName> bin directory to your path. In addition, we |
||||
will make frequent reference to <Quote>setting a shell |
||||
variable</Quote> or <Quote>setting an environment variable</Quote> throughout |
||||
this document. If you did not fully understand the |
||||
last paragraph on modifying your search path, you |
||||
should consult the UNIX manual pages that describe your |
||||
shell before going any further. |
||||
</Para> |
||||
|
||||
<Para> |
||||
If your site administrator has not set things up in the |
||||
default way, you may have some more work to do. For example, if the database |
||||
server machine is a remote machine, you |
||||
will need to set the <Acronym>PGHOST</Acronym> environment variable to the name |
||||
of the database server machine. The environment variable |
||||
<Acronym>PGPORT</Acronym> may also have to be set. The bottom line is this: if |
||||
you try to start an application program and it complains |
||||
that it cannot connect to the <Application>postmaster</Application>, |
||||
you should immediately consult your site administrator to make sure that your |
||||
environment is properly set up. |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Starting the Interactive Monitor (psql)</Title> |
||||
|
||||
<Para> |
||||
Assuming that your site administrator has properly |
||||
started the <Application>postmaster</Application> process and authorized you to |
||||
use the database, you (as a user) may begin to start up |
||||
applications. As previously mentioned, you should add |
||||
<FileName>/usr/local/pgsql/bin</FileName> to your shell search path. |
||||
In most cases, this is all you should have to do in |
||||
terms of preparation. |
||||
</Para> |
||||
|
||||
<Para> |
||||
As of <ProductName>Postgres</ProductName> v6.3, two different styles of connections |
||||
are supported. The site administrator will have chosen to allow TCP/IP network connections |
||||
or will have restricted database access to local (same-machine) socket connections only. |
||||
These choices become significant if you encounter problems in connecting to a database. |
||||
</Para> |
||||
|
||||
<Para> |
||||
If you get the following error message from a <ProductName>Postgres</ProductName> |
||||
command (such as <Application>psql</Application> or <Application>createdb</Application>): |
||||
|
||||
<ProgramListing> |
||||
% psql template1 |
||||
Connection to database 'postgres' failed. |
||||
connectDB() failed: Is the postmaster running and accepting connections |
||||
at 'UNIX Socket' on port '5432'? |
||||
</ProgramListing> |
||||
|
||||
or |
||||
|
||||
<ProgramListing> |
||||
% psql -h localhost template1 |
||||
Connection to database 'postgres' failed. |
||||
connectDB() failed: Is the postmaster running and accepting TCP/IP |
||||
(with -i) connections at 'localhost' on port '5432'? |
||||
</ProgramListing> |
||||
|
||||
it is usually because (1) the <Application>postmaster</Application> is not running, |
||||
or (2) you are attempting to connect to the wrong server host. |
||||
If you get the following error message: |
||||
|
||||
<ProgramListing> |
||||
FATAL 1:Feb 17 23:19:55:process userid (2360) != database owner (268) |
||||
</ProgramListing> |
||||
|
||||
it means that the site administrator started the <Application>postmaster</Application> |
||||
as the wrong user. Tell him to restart it as |
||||
the <ProductName>Postgres</ProductName> superuser. |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Managing a Database</Title> |
||||
|
||||
<Para> |
||||
Now that <ProductName>Postgres</ProductName> is up and running we can create some |
||||
databases to experiment with. Here, we describe the |
||||
basic commands for managing a database. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Most <ProductName>Postgres</ProductName> |
||||
applications assume that the database name, if not specified, is the same as the name on your computer |
||||
account. |
||||
</Para> |
||||
|
||||
<Para> |
||||
If your database administrator has set up your account without database creation privileges, |
||||
then she should have told you what the name of your database is. If this is the case, then you |
||||
can skip the sections on creating and destroying databases. |
||||
</Para> |
||||
|
||||
<Sect2> |
||||
<Title>Creating a Database</Title> |
||||
|
||||
<Para> |
||||
Let's say you want to create a database named <Database>mydb</Database>. |
||||
You can do this with the following command: |
||||
<ProgramListing> |
||||
% createdb mydb |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
If you do not have the privileges required to create a database, you will see |
||||
the following: |
||||
<ProgramListing> |
||||
% createdb mydb |
||||
WARN:user "your username" is not allowed to create/destroy databases |
||||
createdb: database creation failed on mydb. |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> allows you to create any number of databases |
||||
at a given site and you automatically become the |
||||
database administrator of the database you just created. Database names must have an alphabetic first |
||||
character and are limited to 32 characters in length. |
||||
Not every user has authorization to become a database |
||||
administrator. If <ProductName>Postgres</ProductName> refuses to create databases |
||||
for you, then the site administrator needs to grant you |
||||
permission to create databases. Consult your site |
||||
administrator if this occurs. |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Accessing a Database</Title> |
||||
|
||||
<Para> |
||||
Once you have constructed a database, you can access it |
||||
by: |
||||
|
||||
<ItemizedList Mark="bullet" Spacing="compact"> |
||||
<ListItem> |
||||
<Para> |
||||
running the <ProductName>Postgres</ProductName> terminal monitor programs (e.g. |
||||
<Application>psql</Application>) which allows you to interactively |
||||
enter, edit, and execute <Acronym>SQL</Acronym> commands. |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> |
||||
writing a <Acronym>C</Acronym> program using the LIBPQ subroutine |
||||
library. This allows you to submit <Acronym>SQL</Acronym> commands |
||||
from <Acronym>C</Acronym> and get answers and status messages back to |
||||
your program. This interface is discussed further |
||||
in <XRef LinkEnd="PROGRAMMERS-GUIDE">. |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
You might want to start up <Application>psql</Application>, to try out the examples in this manual. |
||||
It can be activated for the <Database>mydb</Database> |
||||
database by typing the command: |
||||
<ProgramListing> |
||||
% psql mydb |
||||
</ProgramListing> |
||||
|
||||
You will be greeted with the following message: |
||||
<ProgramListing> |
||||
Welcome to the POSTGRESQL interactive sql monitor: |
||||
Please read the file COPYRIGHT for copyright terms of POSTGRESQL |
||||
|
||||
type \? for help on slash commands |
||||
type \q to quit |
||||
type \g or terminate with semicolon to execute query |
||||
You are currently connected to the database: template1 |
||||
|
||||
mydb=> |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
This prompt indicates that the terminal monitor is listening |
||||
to you and that you can type <Acronym>SQL</Acronym> queries into a |
||||
workspace maintained by the terminal monitor. |
||||
The <Application>psql</Application> program responds to escape codes that begin |
||||
with the backslash character, <Quote>\</Quote> For example, you |
||||
can get help on the syntax of various |
||||
<ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> commands by typing: |
||||
<ProgramListing> |
||||
mydb=> \h |
||||
</ProgramListing> |
||||
|
||||
Once you have finished entering your queries into the |
||||
workspace, you can pass the contents of the workspace |
||||
to the <ProductName>Postgres</ProductName> server by typing: |
||||
<ProgramListing> |
||||
mydb=> \g |
||||
</ProgramListing> |
||||
|
||||
This tells the server to process the query. If you |
||||
terminate your query with a semicolon, the <Quote>\g</Quote> is not |
||||
necessary. <Application>psql</Application> will automatically process semicolon terminated queries. |
||||
To read queries from a file, say myFile, instead of |
||||
entering them interactively, type: |
||||
<ProgramListing> |
||||
mydb=> \i fileName |
||||
</ProgramListing> |
||||
|
||||
To get out of <Application>psql</Application> and return to UNIX, type |
||||
<ProgramListing> |
||||
mydb=> \q |
||||
</ProgramListing> |
||||
|
||||
and <Application>psql</Application> will quit and return you to your command |
||||
shell. (For more escape codes, type <Command>\h</Command> at the monitor |
||||
prompt.) |
||||
White space (i.e., spaces, tabs and newlines) may be |
||||
used freely in <Acronym>SQL</Acronym> queries. Single-line comments are denoted by |
||||
<Quote>--</Quote>. Everything after the dashes up to the end of the |
||||
line is ignored. Multiple-line comments, and comments within a line, |
||||
are denoted by <Quote>/* ... */</Quote> |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Destroying a Database</Title> |
||||
|
||||
<Para> |
||||
If you are the database administrator for the database |
||||
<Database>mydb</Database>, you can destroy it using the following UNIX command: |
||||
<ProgramListing> |
||||
% destroydb mydb |
||||
</ProgramListing> |
||||
This action physically removes all of the UNIX files |
||||
associated with the database and cannot be undone, so |
||||
this should only be done with a great deal of forethought. |
||||
</Para> |
||||
</Sect2> |
||||
</Sect1> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,9 @@ |
||||
<Chapter> |
||||
<Title>Disk Storage</Title> |
||||
|
||||
<Para> |
||||
This section needs to be written. Some information is in the FAQ. Volunteers? |
||||
- thomas 1998-01-11 |
||||
</Para> |
||||
|
||||
</Chapter> |
||||
@ -0,0 +1,396 @@ |
||||
<Chapter> |
||||
<Title>Triggers</Title> |
||||
|
||||
<Para> |
||||
While the current version of <ProductName>Postgres</ProductName> has various client interfaces |
||||
such as Perl, Tcl, Python and C, it lacks an actual <FirstTerm>Procedural Language</FirstTerm> |
||||
(PL). We hope to have a proper PL one day. In the meantime it is possible |
||||
to call C functions as trigger actions. Note that STATEMENT-level trigger |
||||
events are not supported in the current version. You can currently specify |
||||
BEFORE or AFTER on INSERT, DELETE or UPDATE of a tuple as a trigger event. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Trigger Creation</Title> |
||||
|
||||
<Para> |
||||
If a trigger event occurs, the trigger manager (called by the Executor) |
||||
initializes the global structure TriggerData *CurrentTriggerData (described |
||||
below) and calls the trigger function to handle the event. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The trigger function must be created before the trigger is created as a |
||||
function taking no arguments and returns opaque. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The syntax for creating triggers is as follows: |
||||
|
||||
<ProgramListing> |
||||
CREATE TRIGGER <trigger name> <BEFORE|AFTER> <INSERT|DELETE|UPDATE> |
||||
ON <relation name> FOR EACH <ROW|STATEMENT> |
||||
EXECUTE PROCEDURE <procedure name> (<function args>); |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The name of the trigger is used if you ever have to delete the trigger. |
||||
It is used as an argument to the DROP TRIGGER command. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The next word determines whether the function is called before or after |
||||
the event. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The next element of the command determines on what event(s) will trigger |
||||
the function. Multiple events can be specified separated by OR. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The relation name determines which table the event applies to. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The FOR EACH statement determines whether the trigger is fired for each |
||||
affected row or before (or after) the entire statement has completed. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The procedure name is the C function called. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The args are passed to the function in the CurrentTriggerData structure. |
||||
The purpose of passing arguments to the function is to allow different |
||||
triggers with similar requirements to call the same function. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Also, function may be used for triggering different relations (these |
||||
functions are named as "general trigger functions"). |
||||
</Para> |
||||
|
||||
<Para> |
||||
As example of using both features above, there could be a general |
||||
function that takes as its arguments two field names and puts the current |
||||
user in one and the current timestamp in the other. This allows triggers to |
||||
be written on INSERT events to automatically track creation of records in a |
||||
transaction table for example. It could also be used as a "last updated" |
||||
function if used in an UPDATE event. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Trigger functions return HeapTuple to the calling Executor. This |
||||
is ignored for triggers fired after an INSERT, DELETE or UPDATE operation |
||||
but it allows BEFORE triggers to: |
||||
|
||||
- return NULL to skip the operation for the current tuple (and so the |
||||
tuple will not be inserted/updated/deleted); |
||||
- return a pointer to another tuple (INSERT and UPDATE only) which will |
||||
be inserted (as the new version of the updated tuple if UPDATE) instead |
||||
of original tuple. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Note, that there is no initialization performed by the CREATE TRIGGER |
||||
handler. This will be changed in the future. Also, if more than one trigger |
||||
is defined for the same event on the same relation, the order of trigger |
||||
firing is unpredictable. This may be changed in the future. |
||||
</Para> |
||||
|
||||
<Para> |
||||
If a trigger function executes SQL-queries (using SPI) then these queries |
||||
may fire triggers again. This is known as cascading triggers. There is no |
||||
explicit limitation on the number of cascade levels. |
||||
</Para> |
||||
|
||||
<Para> |
||||
If a trigger is fired by INSERT and inserts a new tuple in the same |
||||
relation then this trigger will be fired again. Currently, there is nothing |
||||
provided for synchronization (etc) of these cases but this may change. At |
||||
the moment, there is function funny_dup17() in the regress tests which uses |
||||
some techniques to stop recursion (cascading) on itself... |
||||
</Para> |
||||
|
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Interaction with the Trigger Manager</Title> |
||||
|
||||
<Para> |
||||
As mentioned above, when function is called by the trigger manager, |
||||
structure TriggerData *CurrentTriggerData is NOT NULL and initialized. So |
||||
it is better to check CurrentTriggerData against being NULL at the start |
||||
and set it to NULL just after fetching the information to prevent calls to |
||||
a trigger function not from the trigger manager. |
||||
</Para> |
||||
|
||||
<Para> |
||||
struct TriggerData is defined in src/include/commands/trigger.h: |
||||
|
||||
<ProgramListing> |
||||
typedef struct TriggerData |
||||
{ |
||||
TriggerEvent tg_event; |
||||
Relation tg_relation; |
||||
HeapTuple tg_trigtuple; |
||||
HeapTuple tg_newtuple; |
||||
Trigger *tg_trigger; |
||||
} TriggerData; |
||||
</ProgramListing> |
||||
|
||||
<ProgramListing> |
||||
tg_event |
||||
describes event for which the function is called. You may use the |
||||
following macros to examine tg_event: |
||||
|
||||
TRIGGER_FIRED_BEFORE(event) returns TRUE if trigger fired BEFORE; |
||||
TRIGGER_FIRED_AFTER(event) returns TRUE if trigger fired AFTER; |
||||
TRIGGER_FIRED_FOR_ROW(event) returns TRUE if trigger fired for |
||||
ROW-level event; |
||||
TRIGGER_FIRED_FOR_STATEMENT(event) returns TRUE if trigger fired for |
||||
STATEMENT-level event; |
||||
TRIGGER_FIRED_BY_INSERT(event) returns TRUE if trigger fired by INSERT; |
||||
TRIGGER_FIRED_BY_DELETE(event) returns TRUE if trigger fired by DELETE; |
||||
TRIGGER_FIRED_BY_UPDATE(event) returns TRUE if trigger fired by UPDATE. |
||||
|
||||
tg_relation |
||||
is pointer to structure describing the triggered relation. Look at |
||||
src/include/utils/rel.h for details about this structure. The most |
||||
interest things are tg_relation->rd_att (descriptor of the relation |
||||
tuples) and tg_relation->rd_rel->relname (relation's name. This is not |
||||
char*, but NameData. Use SPI_getrelname(tg_relation) to get char* if |
||||
you need a copy of name). |
||||
|
||||
tg_trigtuple |
||||
is a pointer to the tuple for which the trigger is fired. This is the tuple |
||||
being inserted (if INSERT), deleted (if DELETE) or updated (if UPDATE). |
||||
If INSERT/DELETE then this is what you are to return to Executor if |
||||
you don't want to replace tuple with another one (INSERT) or skip the |
||||
operation. |
||||
|
||||
tg_newtuple |
||||
is a pointer to the new version of tuple if UPDATE and NULL if this is |
||||
for an INSERT or a DELETE. This is what you are to return to Executor if |
||||
UPDATE and you don't want to replace this tuple with another one or skip |
||||
the operation. |
||||
|
||||
tg_trigger |
||||
is pointer to structure Trigger defined in src/include/utils/rel.h: |
||||
|
||||
typedef struct Trigger |
||||
{ |
||||
char *tgname; |
||||
Oid tgfoid; |
||||
func_ptr tgfunc; |
||||
int16 tgtype; |
||||
int16 tgnargs; |
||||
int16 tgattr[8]; |
||||
char **tgargs; |
||||
} Trigger; |
||||
|
||||
tgname is the trigger's name, tgnargs is number of arguments in tgargs, |
||||
tgargs is an array of pointers to the arguments specified in the CREATE |
||||
TRIGGER statement. Other members are for internal use only. |
||||
</ProgramListing> |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Visibility of Data Changes</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> data changes visibility rule: during a query execution, data |
||||
changes made by the query itself (via SQL-function, SPI-function, triggers) |
||||
are invisible to the query scan. For example, in query |
||||
|
||||
<ProgramListing> |
||||
INSERT INTO a SELECT * FROM a |
||||
</ProgramListing> |
||||
|
||||
tuples inserted are invisible for SELECT' scan. In effect, this |
||||
duplicates the database table within itself (subject to unique index |
||||
rules, of course) without recursing. |
||||
</Para> |
||||
|
||||
<Para> |
||||
But keep in mind this notice about visibility in the SPI documentation: |
||||
|
||||
<ProgramListing> |
||||
Changes made by query Q are visible by queries which are started after |
||||
query Q, no matter whether they are started inside Q (during the |
||||
execution of Q) or after Q is done. |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
This is true for triggers as well so, though a tuple being inserted |
||||
(tg_trigtuple) is not visible to queries in a BEFORE trigger, this tuple |
||||
(just inserted) is visible to queries in an AFTER trigger, and to queries |
||||
in BEFORE/AFTER triggers fired after this! |
||||
</Para> |
||||
</Sect1> |
||||
|
||||
<Sect1> |
||||
<Title>Examples</Title> |
||||
|
||||
<Para> |
||||
There are more complex examples in in src/test/regress/regress.c and |
||||
in contrib/spi. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Here is a very simple example of trigger usage. Function trigf reports |
||||
the number of tuples in the triggered relation ttest and skips the |
||||
operation if the query attempts to insert NULL into x (i.e - it acts as a |
||||
NOT NULL constraint but doesn't abort the transaction). |
||||
|
||||
<ProgramListing> |
||||
#include "executor/spi.h" /* this is what you need to work with SPI */ |
||||
#include "commands/trigger.h" /* -"- and triggers */ |
||||
|
||||
HeapTuple trigf(void); |
||||
|
||||
HeapTuple |
||||
trigf() |
||||
{ |
||||
TupleDesc tupdesc; |
||||
HeapTuple rettuple; |
||||
char *when; |
||||
bool checknull = false; |
||||
bool isnull; |
||||
int ret, i; |
||||
|
||||
if (!CurrentTriggerData) |
||||
elog(WARN, "trigf: triggers are not initialized"); |
||||
|
||||
/* tuple to return to Executor */ |
||||
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) |
||||
rettuple = CurrentTriggerData->tg_newtuple; |
||||
else |
||||
rettuple = CurrentTriggerData->tg_trigtuple; |
||||
|
||||
/* check for NULLs ? */ |
||||
if (!TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event) && |
||||
TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event)) |
||||
checknull = true; |
||||
|
||||
if (TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event)) |
||||
when = "before"; |
||||
else |
||||
when = "after "; |
||||
|
||||
tupdesc = CurrentTriggerData->tg_relation->rd_att; |
||||
CurrentTriggerData = NULL; |
||||
|
||||
/* Connect to SPI manager */ |
||||
if ((ret = SPI_connect()) < 0) |
||||
elog(WARN, "trigf (fired %s): SPI_connect returned %d", when, ret); |
||||
|
||||
/* Get number of tuples in relation */ |
||||
ret = SPI_exec("select count(*) from ttest", 0); |
||||
|
||||
if (ret < 0) |
||||
elog(WARN, "trigf (fired %s): SPI_exec returned %d", when, ret); |
||||
|
||||
i = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull); |
||||
|
||||
elog (NOTICE, "trigf (fired %s): there are %d tuples in ttest", when, i); |
||||
|
||||
SPI_finish(); |
||||
|
||||
if (checknull) |
||||
{ |
||||
i = SPI_getbinval(rettuple, tupdesc, 1, &isnull); |
||||
if (isnull) |
||||
rettuple = NULL; |
||||
} |
||||
|
||||
return (rettuple); |
||||
} |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Now, compile and |
||||
create table ttest (x int4); |
||||
create function trigf () returns opaque as |
||||
'...path_to_so' language 'c'; |
||||
|
||||
<ProgramListing> |
||||
vac=> create trigger tbefore before insert or update or delete on ttest |
||||
for each row execute procedure trigf(); |
||||
CREATE |
||||
vac=> create trigger tafter after insert or update or delete on ttest |
||||
for each row execute procedure trigf(); |
||||
CREATE |
||||
vac=> insert into ttest values (null); |
||||
NOTICE:trigf (fired before): there are 0 tuples in ttest |
||||
INSERT 0 0 |
||||
|
||||
-- Insertion skipped and AFTER trigger is not fired |
||||
|
||||
vac=> select * from ttest; |
||||
x |
||||
- |
||||
(0 rows) |
||||
|
||||
vac=> insert into ttest values (1); |
||||
NOTICE:trigf (fired before): there are 0 tuples in ttest |
||||
NOTICE:trigf (fired after ): there are 1 tuples in ttest |
||||
^^^^^^^^ |
||||
remember what we said about visibility. |
||||
INSERT 167793 1 |
||||
vac=> select * from ttest; |
||||
x |
||||
- |
||||
1 |
||||
(1 row) |
||||
|
||||
vac=> insert into ttest select x * 2 from ttest; |
||||
NOTICE:trigf (fired before): there are 1 tuples in ttest |
||||
NOTICE:trigf (fired after ): there are 2 tuples in ttest |
||||
^^^^^^^^ |
||||
remember what we said about visibility. |
||||
INSERT 167794 1 |
||||
vac=> select * from ttest; |
||||
x |
||||
- |
||||
1 |
||||
2 |
||||
(2 rows) |
||||
|
||||
vac=> update ttest set x = null where x = 2; |
||||
NOTICE:trigf (fired before): there are 2 tuples in ttest |
||||
UPDATE 0 |
||||
vac=> update ttest set x = 4 where x = 2; |
||||
NOTICE:trigf (fired before): there are 2 tuples in ttest |
||||
NOTICE:trigf (fired after ): there are 2 tuples in ttest |
||||
UPDATE 1 |
||||
vac=> select * from ttest; |
||||
x |
||||
- |
||||
1 |
||||
4 |
||||
(2 rows) |
||||
|
||||
vac=> delete from ttest; |
||||
NOTICE:trigf (fired before): there are 2 tuples in ttest |
||||
NOTICE:trigf (fired after ): there are 1 tuples in ttest |
||||
NOTICE:trigf (fired before): there are 1 tuples in ttest |
||||
NOTICE:trigf (fired after ): there are 0 tuples in ttest |
||||
^^^^^^^^ |
||||
remember what we said about visibility. |
||||
DELETE 2 |
||||
vac=> select * from ttest; |
||||
x |
||||
- |
||||
(0 rows) |
||||
</ProgramListing> |
||||
|
||||
</Para> |
||||
</Sect1> |
||||
</Chapter> |
||||
@ -0,0 +1,94 @@ |
||||
<!-- tutorial.sgml |
||||
- |
||||
- Postgres tutorial. Derived from postgres.sgml. |
||||
- thomas 1998-02-23 |
||||
- |
||||
- --> |
||||
<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [ |
||||
<!entity intro SYSTEM "intro.sgml"> |
||||
<!entity arch SYSTEM "arch.sgml"> |
||||
<!entity start SYSTEM "start.sgml"> |
||||
<!entity query SYSTEM "query.sgml"> |
||||
<!entity advanced SYSTEM "advanced.sgml"> |
||||
<!entity biblio SYSTEM "biblio.sgml"> |
||||
]> |
||||
<Book> |
||||
|
||||
<!-- Title information --> |
||||
|
||||
<Title>PostgreSQL Tutorial</Title> |
||||
<BookInfo> |
||||
<ReleaseInfo>Covering v6.3 for general release</ReleaseInfo> |
||||
<BookBiblio> |
||||
<AuthorGroup> |
||||
<CorpAuthor>The PostgreSQL Development Team</CorpAuthor> |
||||
</AuthorGroup> |
||||
<!-- editor in authorgroup is not supported |
||||
<AuthorGroup> |
||||
--> |
||||
<Editor> |
||||
<FirstName>Thomas</FirstName> |
||||
<SurName>Lockhart</SurName> |
||||
<Affiliation> |
||||
<OrgName>Caltech/JPL</OrgName> |
||||
</Affiliation> |
||||
</Editor> |
||||
<!-- |
||||
</AuthorGroup> |
||||
--> |
||||
|
||||
<!-- |
||||
<AuthorInitials>TGL</AuthorInitials> |
||||
--> |
||||
|
||||
<Date>(last updated 1998-02-23)</Date> |
||||
</BookBiblio> |
||||
|
||||
<LegalNotice> |
||||
<Para> |
||||
<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group. |
||||
</Para> |
||||
</LegalNotice> |
||||
|
||||
</BookInfo> |
||||
|
||||
<!-- |
||||
<TOC> </TOC> |
||||
<LOT> </LOT> |
||||
--> |
||||
|
||||
<!-- |
||||
<Dedication> |
||||
<Para> |
||||
Your name here... |
||||
</Para> |
||||
</Dedication> |
||||
--> |
||||
|
||||
<Preface> |
||||
<Title>Summary</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName>, |
||||
developed originally in the UC Berkeley Computer Science Department, |
||||
pioneered many of the object-relational concepts |
||||
now becoming available in some commercial databases. |
||||
It provides SQL92/SQL3 language support, |
||||
transaction integrity, and type extensibility. |
||||
<ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant |
||||
of this original Berkeley code. |
||||
</Para> |
||||
</Preface> |
||||
|
||||
&intro; |
||||
&arch; |
||||
&start; |
||||
&query; |
||||
&advanced; |
||||
|
||||
&biblio; |
||||
|
||||
<INDEX> </INDEX> |
||||
|
||||
</Book> |
||||
|
||||
@ -0,0 +1,110 @@ |
||||
<!-- user.sgml |
||||
- |
||||
- Postgres User's Manual. |
||||
- Derived from postgres.sgml. |
||||
- thomas 1998-02-24 |
||||
- |
||||
- --> |
||||
<!doctype book PUBLIC "-//Davenport//DTD DocBook V3.0//EN" [ |
||||
<!entity intro SYSTEM "intro.sgml"> |
||||
<!entity advanced SYSTEM "advanced.sgml"> |
||||
<!entity environ SYSTEM "environ.sgml"> |
||||
<!entity manage SYSTEM "manage.sgml"> |
||||
<!entity datatype SYSTEM "datatype.sgml"> |
||||
<!entity array SYSTEM "array.sgml"> |
||||
<!entity inherit SYSTEM "inherit.sgml"> |
||||
<!entity query-ug SYSTEM "query-ug.sgml"> |
||||
<!entity storage SYSTEM "storage.sgml"> |
||||
<!entity psql SYSTEM "psql.sgml"> |
||||
<!entity pgaccess SYSTEM "pgaccess.sgml"> |
||||
<!entity biblio SYSTEM "biblio.sgml"> |
||||
]> |
||||
<!-- entity manpages SYSTEM "man/manpages.sgml" subdoc --> |
||||
<Book> |
||||
|
||||
<!-- Title information --> |
||||
|
||||
<Title>PostgreSQL User's Guide</Title> |
||||
<BookInfo> |
||||
<ReleaseInfo>Covering v6.3 for general release</ReleaseInfo> |
||||
<BookBiblio> |
||||
<AuthorGroup> |
||||
<CorpAuthor>The PostgreSQL Development Team</CorpAuthor> |
||||
</AuthorGroup> |
||||
<!-- editor in authorgroup is not supported |
||||
<AuthorGroup> |
||||
--> |
||||
<Editor> |
||||
<FirstName>Thomas</FirstName> |
||||
<SurName>Lockhart</SurName> |
||||
<Affiliation> |
||||
<OrgName>Caltech/JPL</OrgName> |
||||
</Affiliation> |
||||
</Editor> |
||||
<!-- |
||||
</AuthorGroup> |
||||
--> |
||||
|
||||
<!-- |
||||
<AuthorInitials>TGL</AuthorInitials> |
||||
--> |
||||
|
||||
<Date>(last updated 1998-02-23)</Date> |
||||
</BookBiblio> |
||||
|
||||
<LegalNotice> |
||||
<Para> |
||||
<ProductName>PostgreSQL</ProductName> is copyright (C) 1998 by the Postgres Global Development Group. |
||||
</Para> |
||||
</LegalNotice> |
||||
|
||||
</BookInfo> |
||||
|
||||
<!-- |
||||
<TOC> </TOC> |
||||
<LOT> </LOT> |
||||
--> |
||||
|
||||
<!-- |
||||
<Dedication> |
||||
<Para> |
||||
Your name here... |
||||
</Para> |
||||
</Dedication> |
||||
--> |
||||
|
||||
<Preface> |
||||
<Title>Summary</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName>, |
||||
developed originally in the UC Berkeley Computer Science Department, |
||||
pioneered many of the object-relational concepts |
||||
now becoming available in some commercial databases. |
||||
It provides SQL92/SQL3 language support, |
||||
transaction integrity, and type extensibility. |
||||
<ProductName>PostgreSQL</ProductName> is a public-domain, open source descendant |
||||
of this original Berkeley code. |
||||
</Para> |
||||
</Preface> |
||||
|
||||
&intro; |
||||
&environ; |
||||
&manage; |
||||
&datatype; |
||||
&array; |
||||
&inherit; |
||||
&query-ug; |
||||
&storage; |
||||
&psql; |
||||
&pgaccess; |
||||
|
||||
<!-- |
||||
&contacts; |
||||
--> |
||||
&biblio; |
||||
|
||||
<INDEX> </INDEX> |
||||
|
||||
</Book> |
||||
|
||||
@ -0,0 +1,95 @@ |
||||
<Chapter> |
||||
<Title>Extending <Acronym>SQL</Acronym>: Aggregates</Title> |
||||
|
||||
<Para> |
||||
Aggregates in <ProductName>Postgres</ProductName> are expressed in terms of state |
||||
transition functions. That is, an aggregate can be |
||||
defined in terms of state that is modified whenever an |
||||
instance is processed. Some state functions look at a |
||||
particular value in the instance when computing the new |
||||
state (<Acronym>sfunc1</Acronym> in the create aggregate syntax) while |
||||
others only keep track of their own internal state |
||||
(<Acronym>sfunc2</Acronym>). |
||||
If we define an aggregate that uses only <Acronym>sfunc1</Acronym>, we |
||||
define an aggregate that computes a running function of |
||||
the attribute values from each instance. "Sum" is an |
||||
example of this kind of aggregate. "Sum" starts at |
||||
zero and always adds the current instance's value to |
||||
its running total. We will use the <Acronym>int4pl</Acronym> that is |
||||
built into <ProductName>Postgres</ProductName> to perform this addition. |
||||
|
||||
<ProgramListing> |
||||
CREATE AGGREGATE complex_sum ( |
||||
sfunc1 = complex_add, |
||||
basetype = complex, |
||||
stype1 = complex, |
||||
initcond1 = '(0,0)' |
||||
); |
||||
|
||||
SELECT complex_sum(a) FROM test_complex; |
||||
|
||||
+------------+ |
||||
|complex_sum | |
||||
+------------+ |
||||
|(34,53.9) | |
||||
+------------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
If we define only <Acronym>sfunc2</Acronym>, we are specifying an aggregate |
||||
that computes a running function that is independent of |
||||
the attribute values from each instance. |
||||
"Count" is the most common example of this kind of |
||||
aggregate. "Count" starts at zero and adds one to its |
||||
running total for each instance, ignoring the instance |
||||
value. Here, we use the built-in <Acronym>int4inc</Acronym> routine to do |
||||
the work for us. This routine increments (adds one to) |
||||
its argument. |
||||
|
||||
<ProgramListing> |
||||
CREATE AGGREGATE my_count (sfunc2 = int4inc, -- add one |
||||
basetype = int4, stype2 = int4, |
||||
initcond2 = '0') |
||||
|
||||
SELECT my_count(*) as emp_count from EMP; |
||||
|
||||
+----------+ |
||||
|emp_count | |
||||
+----------+ |
||||
|5 | |
||||
+----------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
"Average" is an example of an aggregate that requires |
||||
both a function to compute the running sum and a function |
||||
to compute the running count. When all of the |
||||
instances have been processed, the final answer for the |
||||
aggregate is the running sum divided by the running |
||||
count. We use the <Acronym>int4pl</Acronym> and <Acronym>int4inc</Acronym> routines we used |
||||
before as well as the <ProductName>Postgres</ProductName> integer division |
||||
routine, <Acronym>int4div</Acronym>, to compute the division of the sum by |
||||
the count. |
||||
|
||||
<ProgramListing> |
||||
CREATE AGGREGATE my_average (sfunc1 = int4pl, -- sum |
||||
basetype = int4, |
||||
stype1 = int4, |
||||
sfunc2 = int4inc, -- count |
||||
stype2 = int4, |
||||
finalfunc = int4div, -- division |
||||
initcond1 = '0', |
||||
initcond2 = '0') |
||||
|
||||
SELECT my_average(salary) as emp_average FROM EMP; |
||||
|
||||
+------------+ |
||||
|emp_average | |
||||
+------------+ |
||||
|1640 | |
||||
+------------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
</Chapter> |
||||
@ -0,0 +1,533 @@ |
||||
<Chapter> |
||||
<Title>Extending <Acronym>SQL</Acronym>: Functions</Title> |
||||
|
||||
<Para> |
||||
As it turns out, part of defining a new type is the |
||||
definition of functions that describe its behavior. |
||||
Consequently, while it is possible to define a new |
||||
function without defining a new type, the reverse is |
||||
not true. We therefore describe how to add new functions |
||||
to <ProductName>Postgres</ProductName> before describing how to add new |
||||
types. |
||||
<ProductName>Postgres</ProductName> <Acronym>SQL</Acronym> provides two types of functions: query |
||||
language functions (functions written in <Acronym>SQL</Acronym> and |
||||
programming language functions (functions written in a |
||||
compiled programming language such as <Acronym>C</Acronym>.) Either kind |
||||
of function can take a base type, a composite type or |
||||
some combination as arguments (parameters). In addition, |
||||
both kinds of functions can return a base type or |
||||
a composite type. It's easier 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>C-code/funcs.c</FileName>. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Query Language (<Acronym>SQL</Acronym>) Functions</Title> |
||||
|
||||
<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> |
||||
CREATE FUNCTION one() RETURNS int4 |
||||
AS 'SELECT 1 as RESULT' LANGUAGE 'sql'; |
||||
|
||||
SELECT one() AS answer; |
||||
|
||||
+-------+ |
||||
|answer | |
||||
+-------+ |
||||
|1 | |
||||
+-------+ |
||||
</ProgramListing> |
||||
|
||||
</Para> |
||||
<Para> |
||||
Notice that we defined a target list for the function |
||||
(with the name RESULT), but the target list of the |
||||
query that invoked the function overrode the function's |
||||
target list. Hence, the result is labelled answer |
||||
instead of one. |
||||
</Para> |
||||
<Para> |
||||
It's almost as easy to define <Acronym>SQL</Acronym> functions that take |
||||
base types as arguments. In the example below, notice |
||||
how we refer to the arguments within the function as $1 |
||||
and $2. |
||||
|
||||
<ProgramListing> |
||||
CREATE FUNCTION add_em(int4, int4) RETURNS int4 |
||||
AS 'SELECT $1 + $2;' LANGUAGE 'sql'; |
||||
|
||||
SELECT add_em(1, 2) AS answer; |
||||
|
||||
+-------+ |
||||
|answer | |
||||
+-------+ |
||||
|3 | |
||||
+-------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Sect2> |
||||
<Title><Acronym>SQL</Acronym> Functions on Composite Types</Title> |
||||
|
||||
<Para> |
||||
When specifying functions with arguments of composite |
||||
types (such as EMP), we must not only specify which |
||||
argument we want (as we did above with $1 and $2) but |
||||
also the attributes of that argument. For example, |
||||
take the function double_salary that computes what your |
||||
salary would be if it were doubled. |
||||
|
||||
<ProgramListing> |
||||
CREATE FUNCTION double_salary(EMP) RETURNS int4 |
||||
AS 'SELECT $1.salary * 2 AS salary;' LANGUAGE 'sql'; |
||||
|
||||
SELECT name, double_salary(EMP) AS dream |
||||
FROM EMP |
||||
WHERE EMP.dept = 'toy'; |
||||
|
||||
+-----+-------+ |
||||
|name | dream | |
||||
+-----+-------+ |
||||
|Sam | 2400 | |
||||
+-----+-------+ |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
Notice the use of the syntax $1.salary. |
||||
Before launching into the subject of functions that |
||||
return composite types, we must first introduce the |
||||
function notation for projecting attributes. The simple way |
||||
to explain this is that we can usually use the |
||||
notation attribute(class) and class.attribute interchangably. |
||||
|
||||
<ProgramListing> |
||||
-- |
||||
-- this is the same as: |
||||
-- SELECT EMP.name AS youngster FROM EMP WHERE EMP.age < 30 |
||||
-- |
||||
SELECT name(EMP) AS youngster |
||||
FROM EMP |
||||
WHERE age(EMP) < 30; |
||||
|
||||
+----------+ |
||||
|youngster | |
||||
+----------+ |
||||
|Sam | |
||||
+----------+ |
||||
</ProgramListing> |
||||
|
||||
<Para> |
||||
As we shall see, however, this is not always the case. |
||||
This function notation is important when we want to use |
||||
a function that returns a single instance. We do this |
||||
by assembling the entire instance within the function, |
||||
attribute by attribute. This is an example of a function |
||||
that returns a single EMP instance: |
||||
|
||||
<ProgramListing> |
||||
CREATE FUNCTION new_emp() RETURNS EMP |
||||
AS 'SELECT \'None\'::text AS name, |
||||
1000 AS salary, |
||||
25 AS age, |
||||
\'none\'::char16 AS dept;' |
||||
LANGUAGE 'sql'; |
||||
</ProgramListing> |
||||
|
||||
</Para> |
||||
<Para> |
||||
In this case we have specified each of the attributes |
||||
with a constant value, but any computation or expression |
||||
could have been substituted for these constants. |
||||
Defining a function like this can be tricky. Some of |
||||
the more important caveats are as follows: |
||||
|
||||
|
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
The target list order must be exactly the same as |
||||
that in which the attributes appear in the CREATE |
||||
TABLE statement (or when you execute a .* query). |
||||
</Para> |
||||
<ListItem> |
||||
<Para> |
||||
You must typecast the expressions |
||||
(using ::) very carefully or you will see the following error: |
||||
|
||||
<ProgramListing> |
||||
WARN::function declared to return type EMP does not retrieve (EMP.*) |
||||
</ProgramListing> |
||||
</Para> |
||||
<ListItem> |
||||
<Para> |
||||
When calling a function that returns an instance, we |
||||
cannot retrieve the entire instance. We must either |
||||
project an attribute out of the instance or pass the |
||||
entire instance into another function. |
||||
<ProgramListing> |
||||
SELECT name(new_emp()) AS nobody; |
||||
|
||||
+-------+ |
||||
|nobody | |
||||
+-------+ |
||||
|None | |
||||
+-------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
<ListItem> |
||||
<Para> |
||||
The reason why, in general, we must use the function |
||||
syntax for projecting attributes of function return |
||||
values is that the parser just doesn't understand |
||||
the other (dot) syntax for projection when combined |
||||
with function calls. |
||||
|
||||
<ProgramListing> |
||||
SELECT new_emp().name AS nobody; |
||||
WARN:parser: syntax error at or near "." |
||||
</ProgramListing> |
||||
</Para> |
||||
</ItemizedList> |
||||
|
||||
<Para> |
||||
Any collection of commands in the <Acronym>SQL</Acronym> query language |
||||
can be packaged together and defined as a function. |
||||
The commands can include updates (i.e., <Acronym>insert</Acronym>, <Acronym>update</Acronym> |
||||
and <Acronym>delete</Acronym>) as well as <Acronym>select</Acronym> queries. However, the |
||||
final command must be a <Acronym>select</Acronym> that returns whatever is |
||||
specified as the function's returntype. |
||||
|
||||
<ProgramListing> |
||||
CREATE FUNCTION clean_EMP () RETURNS int4 |
||||
AS 'DELETE FROM EMP WHERE EMP.salary <= 0; |
||||
SELECT 1 AS ignore_this' |
||||
LANGUAGE 'sql'; |
||||
|
||||
SELECT clean_EMP(); |
||||
|
||||
+--+ |
||||
|x | |
||||
+--+ |
||||
|1 | |
||||
+--+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>Programming Language Functions</Title> |
||||
|
||||
<Sect2> |
||||
<Title>Programming Language Functions on Base Types</Title> |
||||
|
||||
<Para> |
||||
Internally, <ProductName>Postgres</ProductName> regards a base type as a "blob of |
||||
memory." The user-defined functions that you define |
||||
over a type in turn define the way that <ProductName>Postgres</ProductName> can |
||||
operate on it. That is, <ProductName>Postgres</ProductName> will only store and |
||||
retrieve the data from disk and use your user-defined |
||||
functions to input, process, and output the data. |
||||
Base types can have one of three internal formats: |
||||
<ItemizedList> |
||||
<ListItem><Para>pass by value, fixed-length</Para> |
||||
<ListItem><Para>pass by reference, fixed-length</Para> |
||||
<ListItem><Para>pass by reference, variable-length</Para> |
||||
</ItemizedList> |
||||
</Para> |
||||
|
||||
<Para> |
||||
By-value types can only be 1, 2 or 4 bytes in length |
||||
(even if your computer supports by-value types of other |
||||
sizes). <ProductName>Postgres</ProductName> itself only passes integer types by |
||||
value. You should be careful to define your types such |
||||
that they will be the same size (in bytes) on all |
||||
architectures. For example, the <Acronym>long</Acronym> type is dangerous |
||||
because it is 4 bytes on some machines and 8 bytes on |
||||
others, whereas <Acronym>int</Acronym> type is 4 bytes on most <Acronym>UNIX</Acronym> |
||||
machines (though not on most personal computers). A |
||||
reasonable implementation of the <Acronym>int4</Acronym> type on <Acronym>UNIX</Acronym> |
||||
machines might be: |
||||
|
||||
<ProgramListing> |
||||
/* 4-byte integer, passed by value */ |
||||
typedef int int4; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
On the other hand, fixed-length types of any size may |
||||
be passed by-reference. For example, here is a sample |
||||
implementation of the <ProductName>Postgres</ProductName> char16 type: |
||||
|
||||
<ProgramListing> |
||||
/* 16-byte structure, passed by reference */ |
||||
typedef struct { |
||||
char data[16]; |
||||
} char16; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Only pointers to such types can be used when passing |
||||
them in and out of <ProductName>Postgres</ProductName> functions. |
||||
Finally, all variable-length types must also be passed |
||||
by reference. All variable-length types must begin |
||||
with a length field of exactly 4 bytes, and all data to |
||||
be stored within that type must be located in the memory |
||||
immediately following that length field. The |
||||
length field is the total length of the structure |
||||
(i.e., it includes the size of the length field |
||||
itself). We can define the text type as follows: |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProgramListing> |
||||
typedef struct { |
||||
int4 length; |
||||
char data[1]; |
||||
} text; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Obviously, the data field is not long enough to hold |
||||
all possible strings -- it's impossible to declare such |
||||
a structure in <Acronym>C</Acronym>. When manipulating variable-length |
||||
types, we must be careful to allocate the correct |
||||
amount of memory and initialize the length field. For |
||||
example, if we wanted to store 40 bytes in a text |
||||
structure, we might use a code fragment like this: |
||||
<ProgramListing> |
||||
#include "postgres.h" |
||||
#include "utils/palloc.h" |
||||
... |
||||
char buffer[40]; /* our source data */ |
||||
... |
||||
text *destination = (text *) palloc(VARHDRSZ + 40); |
||||
destination->length = VARHDRSZ + 40; |
||||
memmove(destination->data, buffer, 40); |
||||
... |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Now that we've gone over all of the possible structures |
||||
for base types, we can show some examples of real functions. |
||||
Suppose <FileName>funcs.c</FileName> look like: |
||||
<ProgramListing> |
||||
#include <string.h> |
||||
#include "postgres.h" /* for char16, etc. */ |
||||
#include "utils/palloc.h" /* for palloc */ |
||||
int |
||||
add_one(int arg) |
||||
{ |
||||
return(arg + 1); |
||||
} |
||||
char16 * |
||||
concat16(char16 *arg1, char16 *arg2) |
||||
{ |
||||
char16 *new_c16 = (char16 *) palloc(sizeof(char16)); |
||||
memset((void *) new_c16, 0, sizeof(char16)); |
||||
(void) strncpy(new_c16, arg1, 16); |
||||
return (char16 *)(strncat(new_c16, arg2, 16)); |
||||
} |
||||
text * |
||||
copytext(text *t) |
||||
{ |
||||
/* |
||||
* VARSIZE is the total size of the struct in bytes. |
||||
*/ |
||||
text *new_t = (text *) palloc(VARSIZE(t)); |
||||
memset(new_t, 0, VARSIZE(t)); |
||||
VARSIZE(new_t) = VARSIZE(t); |
||||
/* |
||||
* VARDATA is a pointer to the data region of the struct. |
||||
*/ |
||||
memcpy((void *) VARDATA(new_t), /* destination */ |
||||
(void *) VARDATA(t), /* source */ |
||||
VARSIZE(t)-VARHDRSZ); /* how many bytes */ |
||||
return(new_t); |
||||
} |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
On <Acronym>OSF/1</Acronym> we would type: |
||||
|
||||
<ProgramListing> |
||||
CREATE FUNCTION add_one(int4) RETURNS int4 |
||||
AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c'; |
||||
|
||||
CREATE FUNCTION concat16(char16, char16) RETURNS char16 |
||||
AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c'; |
||||
|
||||
CREATE FUNCTION copytext(text) RETURNS text |
||||
AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c'; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
On other systems, we might have to make the filename |
||||
end in .sl (to indicate that it's a shared library). |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Programming Language Functions on Composite Types</Title> |
||||
|
||||
<Para> |
||||
Composite types do not have a fixed layout like C |
||||
structures. Instances of a composite type may contain |
||||
null fields. In addition, composite types that are |
||||
part of an inheritance hierarchy may have different |
||||
fields than other members of the same inheritance hierarchy. |
||||
Therefore, <ProductName>Postgres</ProductName> provides a procedural |
||||
interface for accessing fields of composite types from |
||||
C. |
||||
As <ProductName>Postgres</ProductName> processes a set of instances, each instance |
||||
will be passed into your function as an opaque structure of type <Acronym>TUPLE</Acronym>. |
||||
Suppose we want to write a function to answer the query |
||||
<ProgramListing> |
||||
* SELECT name, c_overpaid(EMP, 1500) AS overpaid |
||||
FROM EMP |
||||
WHERE name = 'Bill' or name = 'Sam'; |
||||
</ProgramListing> |
||||
In the query above, we can define c_overpaid as: |
||||
|
||||
<ProgramListing> |
||||
#include "postgres.h" /* for char16, etc. */ |
||||
#include "libpq-fe.h" /* for TUPLE */ |
||||
bool |
||||
c_overpaid(TUPLE t,/* the current instance of EMP */ |
||||
int4 limit) |
||||
{ |
||||
bool isnull = false; |
||||
int4 salary; |
||||
salary = (int4) GetAttributeByName(t, "salary", &isnull); |
||||
if (isnull) |
||||
return (false); |
||||
return(salary > limit); |
||||
} |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
<Acronym>GetAttributeByName</Acronym> is the <ProductName>Postgres</ProductName> system function that |
||||
returns attributes out of the current instance. It has |
||||
three arguments: the argument of type TUPLE passed into |
||||
the function, the name of the desired attribute, and a |
||||
return parameter that describes whether the attribute |
||||
is null. <Acronym>GetAttributeByName</Acronym> will align data properly |
||||
so you can cast its return value to the desired type. |
||||
For example, if you have an attribute name which is of |
||||
the type char16, the <Acronym>GetAttributeByName</Acronym> call would look |
||||
like: |
||||
<ProgramListing> |
||||
char *str; |
||||
... |
||||
str = (char *) GetAttributeByName(t, "name", &isnull) |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The following query lets <ProductName>Postgres</ProductName> know about the |
||||
c_overpaid function: |
||||
<ProgramListing> |
||||
* CREATE FUNCTION c_overpaid(EMP, int4) RETURNS bool |
||||
AS 'PGROOT/tutorial/obj/funcs.so' LANGUAGE 'c'; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
While there are ways to construct new instances or modify |
||||
existing instances from within a C function, these |
||||
are far too complex to discuss in this manual. |
||||
</Para> |
||||
</Sect2> |
||||
|
||||
<Sect2> |
||||
<Title>Caveats</Title> |
||||
|
||||
<Para> |
||||
We now turn to the more difficult task of writing |
||||
programming language functions. Be warned: this section |
||||
of the manual will not make you a programmer. You must |
||||
have a good understanding of <Acronym>C</Acronym> (including the use of |
||||
pointers and the malloc memory manager) before trying |
||||
to write <Acronym>C</Acronym> functions for use with <ProductName>Postgres</ProductName>. |
||||
While it may be possible to load functions written in |
||||
languages other than <Acronym>C</Acronym> into <ProductName>Postgres</ProductName>, this is often |
||||
difficult (when it is possible at all) because other |
||||
languages, such as <Acronym>FORTRAN</Acronym> and <Acronym>Pascal</Acronym> often do not follow |
||||
the same "calling convention" as <Acronym>C</Acronym>. That is, other |
||||
languages do not pass argument and return values |
||||
between functions in the same way. For this reason, we |
||||
will assume that your programming language functions |
||||
are written in <Acronym>C</Acronym>. |
||||
The basic rules for building <Acronym>C</Acronym> functions are as follows: |
||||
|
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> |
||||
Most of the header (include) files for <ProductName>Postgres</ProductName> |
||||
should already be installed in |
||||
<FileName>PGROOT/include</FileName> (see Figure 2). |
||||
You should always include |
||||
|
||||
<ProgramListing> |
||||
-I$PGROOT/include |
||||
</ProgramListing> |
||||
on your cc command lines. Sometimes, you may |
||||
find that you require header files that are in |
||||
the server source itself (i.e., you need a file |
||||
we neglected to install in include). In those |
||||
cases you may need to add one or more of |
||||
<ProgramListing> |
||||
-I$PGROOT/src/backend |
||||
-I$PGROOT/src/backend/include |
||||
-I$PGROOT/src/backend/port/<PORTNAME> |
||||
-I$PGROOT/src/backend/obj |
||||
</ProgramListing> |
||||
(where <PORTNAME> is the name of the port, e.g., |
||||
alpha or sparc). |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> When allocating memory, use the <ProductName>Postgres</ProductName> |
||||
routines palloc and pfree instead of the |
||||
corresponding <Acronym>C</Acronym> library routines malloc and free. |
||||
The memory allocated by palloc will be freed |
||||
automatically at the end of each transaction, |
||||
preventing memory leaks. |
||||
</Para> |
||||
<ListItem> |
||||
<Para> Always zero the bytes of your structures using |
||||
memset or bzero. Several routines (such as the |
||||
hash access method, hash join and the sort algorithm) |
||||
compute functions of the raw bits contained in |
||||
your structure. Even if you initialize all fields |
||||
of your structure, there may be |
||||
several bytes of alignment padding (holes in the |
||||
structure) that may contain garbage values. |
||||
</Para> |
||||
<ListItem> |
||||
<Para> Most of the internal <ProductName>Postgres</ProductName> types are declared |
||||
in postgres.h, so it's usually a good idea to |
||||
include that file as well. |
||||
</Para> |
||||
<ListItem> |
||||
<Para> Compiling and loading your object code so that |
||||
it can be dynamically loaded into <ProductName>Postgres</ProductName> |
||||
always requires special flags. See Appendix A |
||||
for a detailed explanation of how to do it for |
||||
your particular operating system. |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
</Para> |
||||
</Sect2> |
||||
@ -0,0 +1,515 @@ |
||||
<Chapter> |
||||
<Title>Interfacing Extensions To Indices</Title> |
||||
|
||||
<Para> |
||||
The procedures described thus far let you define a new |
||||
type, new functions and new operators. However, we |
||||
cannot yet define a secondary index (such as a <Acronym>B-tree</Acronym>, |
||||
<Acronym>R-tree</Acronym> or hash access method) over a new type or its |
||||
operators. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Look back at |
||||
<XRef LinkEnd="EXTEND-CATALOGS" EndTerm="EXTEND-CATALOGS">. |
||||
The right half shows the catalogs |
||||
that we must modify in order to tell <ProductName>Postgres</ProductName> how |
||||
to use a user-defined type and/or user-defined operators |
||||
with an index (i.e., <FileName>pg_am, pg_amop, pg_amproc</FileName> and |
||||
<FileName>pg_opclass</FileName>). Unfortunately, there is no simple command |
||||
to do this. We will demonstrate how to modify these |
||||
catalogs through a running example: a new operator |
||||
class for the <Acronym>B-tree</Acronym> access method that sorts integers |
||||
in ascending absolute value order. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The <FileName>pg_am</FileName> class contains one instance for every user |
||||
defined access method. Support for the heap access |
||||
method is built into <ProductName>Postgres</ProductName>, but every other access |
||||
method is described here. The schema is |
||||
|
||||
<TABLE TOCENTRY="1"> |
||||
<Title>Index Schema</Title> |
||||
<TitleAbbrev>Indices</TitleAbbrev> |
||||
<TGroup Cols="2"> |
||||
<THead> |
||||
<Row> |
||||
<Entry>Attribute</Entry> |
||||
<Entry>Description</Entry> |
||||
</Row> |
||||
</THead> |
||||
<TBody> |
||||
<Row> |
||||
<Entry>amname</Entry> |
||||
<Entry>name of the access method</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>amowner</Entry> |
||||
<Entry>object id of the owner's instance in pg_user</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>amkind</Entry> |
||||
<Entry>not used at present, but set to 'o' as a place holder</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>amstrategies</Entry> |
||||
<Entry>number of strategies for this access method (see below)</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>amsupport</Entry> |
||||
<Entry>number of support routines for this access method (see below)</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>amgettuple |
||||
aminsert |
||||
...</Entry> |
||||
|
||||
<Entry>procedure identifiers for interface routines to the access |
||||
method. For example, regproc ids for opening, closing, and |
||||
getting instances from the access method appear here. </Entry> |
||||
</Row> |
||||
</TBody> |
||||
</TGroup> |
||||
</TABLE> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The <Acronym>object ID</Acronym> of the instance in <FileName>pg_am</FileName> is used as a |
||||
foreign key in lots of other classes. You don't need |
||||
to add a new instance to this class; all you're interested in |
||||
is the <Acronym>object ID</Acronym> of the access method instance |
||||
you want to extend: |
||||
|
||||
<ProgramListing> |
||||
SELECT oid FROM pg_am WHERE amname = 'btree'; |
||||
|
||||
+----+ |
||||
|oid | |
||||
+----+ |
||||
|403 | |
||||
+----+ |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The <FileName>amstrategies</FileName> attribute exists to standardize |
||||
comparisons across data types. For example, <Acronym>B-tree</Acronym>s |
||||
impose a strict ordering on keys, lesser to greater. |
||||
Since <ProductName>Postgres</ProductName> allows the user to define operators, |
||||
<ProductName>Postgres</ProductName> cannot look at the name of an operator (eg, ">" |
||||
or "<") and tell what kind of comparison it is. In fact, |
||||
some access methods don't impose any ordering at all. |
||||
For example, <Acronym>R-tree</Acronym>s express a rectangle-containment |
||||
relationship, whereas a hashed data structure expresses |
||||
only bitwise similarity based on the value of a hash |
||||
function. <ProductName>Postgres</ProductName> needs some consistent way of taking |
||||
a qualification in your query, looking at the operator |
||||
and then deciding if a usable index exists. This |
||||
implies that <ProductName>Postgres</ProductName> needs to know, for example, that |
||||
the "<=" and ">" operators partition a <Acronym>B-tree</Acronym>. <ProductName>Postgres</ProductName> |
||||
uses strategies to express these relationships between |
||||
operators and the way they can be used to scan indices. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Defining a new set of strategies is beyond the scope of |
||||
this discussion, but we'll explain how <Acronym>B-tree</Acronym> strategies |
||||
work because you'll need to know that to add a new |
||||
operator class. In the <FileName>pg_am</FileName> class, the amstrategies |
||||
attribute is the number of strategies defined for this |
||||
access method. For <Acronym>B-tree</Acronym>s, this number is 5. These |
||||
strategies correspond to |
||||
|
||||
<TABLE TOCENTRY="1"> |
||||
<Title>B-tree Strategies</Title> |
||||
<TitleAbbrev>B-tree</TitleAbbrev> |
||||
<TGroup Cols="2"> |
||||
<THead> |
||||
<Row> |
||||
<Entry>Operation</Entry> |
||||
<Entry>Index</Entry> |
||||
</Row> |
||||
</THead> |
||||
<TBody> |
||||
<Row> |
||||
<Entry>less than</Entry> |
||||
<Entry>1</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>less than or equal</Entry> |
||||
<Entry>2</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>equal</Entry> |
||||
<Entry>3</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>greater than or equal</Entry> |
||||
<Entry>4</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>greater than</Entry> |
||||
<Entry>5</Entry> |
||||
</Row> |
||||
</TBody> |
||||
</TGroup> |
||||
</TABLE> |
||||
</Para> |
||||
|
||||
<Para> |
||||
The idea is that you'll need to add procedures corresponding |
||||
to the comparisons above to the <FileName>pg_amop</FileName> relation |
||||
(see below). The access method code can use these |
||||
strategy numbers, regardless of data type, to figure |
||||
out how to partition the <Acronym>B-tree</Acronym>, compute selectivity, |
||||
and so on. Don't worry about the details of adding |
||||
procedures yet; just understand that there must be a |
||||
set of these procedures for <FileName>int2, int4, oid,</FileName> and every |
||||
other data type on which a <Acronym>B-tree</Acronym> can operate. |
||||
|
||||
Sometimes, strategies aren't enough information for the |
||||
system to figure out how to use an index. Some access |
||||
methods require other support routines in order to |
||||
work. For example, the <Acronym>B-tree</Acronym> 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 <Acronym>R-tree</Acronym> access method must be able to compute |
||||
intersections, unions, and sizes of rectangles. These |
||||
operations do not correspond to user qualifications in |
||||
SQL queries; they are administrative routines used by |
||||
the access methods, internally. |
||||
</Para> |
||||
|
||||
<Para> |
||||
In order to manage diverse support routines |
||||
consistently across all <ProductName>Postgres</ProductName> access methods, <FileName>pg_am</FileName> |
||||
includes an attribute called <FileName>amsupport</FileName>. This attribute |
||||
records the number of support routines used by an |
||||
access method. For <Acronym>B-tree</Acronym>s, this number is one -- the |
||||
routine to take two keys and return -1, 0, or +1, |
||||
depending on whether the first key is less than, equal |
||||
to, or greater than the second. |
||||
<Note> |
||||
<Para> |
||||
Strictly speaking, this routine can return a negative |
||||
number (< 0), 0, or a non-zero positive number (> 0). |
||||
</Para> |
||||
</Note> |
||||
|
||||
<Para> |
||||
The <FileName>amstrategies</FileName> entry in 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 <FileName>pg_am</FileName>. Similarly, <FileName>amsupport</FileName> is just |
||||
the number of support routines required by the access |
||||
method. The actual routines are listed elsewhere. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The next class of interest is pg_opclass. This class |
||||
exists only to associate a name with an oid. In |
||||
pg_amop, every <Acronym>B-tree</Acronym> operator class has a set of |
||||
procedures, one through five, above. Some existing |
||||
opclasses are <FileName>int2_ops, int4_ops, and oid_ops</FileName>. You |
||||
need to add an instance with your opclass name (for |
||||
example, <FileName>complex_abs_ops</FileName>) to <FileName>pg_opclass</FileName>. The <FileName>oid</FileName> of |
||||
this instance is a foreign key in other classes. |
||||
|
||||
<ProgramListing> |
||||
INSERT INTO pg_opclass (opcname) VALUES ('complex_abs_ops'); |
||||
|
||||
SELECT oid, opcname |
||||
FROM pg_opclass |
||||
WHERE opcname = 'complex_abs_ops'; |
||||
|
||||
+------+--------------+ |
||||
|oid | opcname | |
||||
+------+--------------+ |
||||
|17314 | int4_abs_ops | |
||||
+------+--------------+ |
||||
</ProgramListing> |
||||
|
||||
Note that the oid for your <FileName>pg_opclass</FileName> instance will be |
||||
different! You should substitute your value for 17314 |
||||
wherever it appears in this discussion. |
||||
</Para> |
||||
|
||||
<Para> |
||||
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 complex_abs_ops operator class on Btrees, |
||||
the operators we require are: |
||||
|
||||
<ProgramListing> |
||||
absolute value less-than |
||||
absolute value less-than-or-equal |
||||
absolute value equal |
||||
absolute value greater-than-or-equal |
||||
absolute value greater-than |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Suppose the code that implements the functions defined |
||||
is stored in the file |
||||
<FileName>PGROOT/src/tutorial/complex.c</FileName> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Part of the code look like this: (note that we will |
||||
only show the equality operator for the rest of the |
||||
examples. The other four operators are very similar. |
||||
Refer to <FileName>complex.c</FileName> or <FileName>complex.sql</FileName> for the details.) |
||||
|
||||
<ProgramListing> |
||||
#define Mag(c) ((c)->x*(c)->x + (c)->y*(c)->y) |
||||
|
||||
bool |
||||
complex_abs_eq(Complex *a, Complex *b) |
||||
{ |
||||
double amag = Mag(a), bmag = Mag(b); |
||||
return (amag==bmag); |
||||
} |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
There are a couple of important things that are happening below. |
||||
</Para> |
||||
|
||||
<Para> |
||||
First, note that operators for less-than, less-than-or |
||||
equal, equal, greater-than-or-equal, and greater-than |
||||
for <FileName>int4</FileName> are being defined. All of these operators are |
||||
already defined for <FileName>int4</FileName> under the names <, <=, =, >=, |
||||
and >. The new operators behave differently, of |
||||
course. In order to guarantee that <ProductName>Postgres</ProductName> 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 <ProductName>Postgres</ProductName>, but only |
||||
if the operator isn't already defined for the argument |
||||
types. That is, if you have < defined for (int4, |
||||
int4), you can't define it again. <ProductName>Postgres</ProductName> does not |
||||
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. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The other important point is that all the operator |
||||
functions return Boolean values. The access methods |
||||
rely on this fact. (On the other hand, the support |
||||
function returns whatever the particular access method |
||||
expects -- in this case, a signed integer.) |
||||
The final routine in the file is the "support routine" |
||||
mentioned when we discussed the amsupport attribute of |
||||
the <FileName>pg_am</FileName> class. We will use this later on. For now, |
||||
ignore it. |
||||
</Para> |
||||
|
||||
<Para> |
||||
<ProgramListing> |
||||
CREATE FUNCTION complex_abs_eq(complex, complex) |
||||
RETURNS bool |
||||
AS 'PGROOT/tutorial/obj/complex.so' |
||||
LANGUAGE 'c'; |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Now define the operators that use them. As noted, the |
||||
operator names must be unique among all operators that |
||||
take two <FileName>int4</FileName> operands. In order to see if the |
||||
operator names listed below are taken, we can do a query on |
||||
<FileName>pg_operator</FileName>: |
||||
|
||||
<ProgramListing> |
||||
/* |
||||
* this query uses the regular expression operator (~) |
||||
* to find three-character operator names that end in |
||||
* the character & |
||||
*/ |
||||
SELECT * |
||||
FROM pg_operator |
||||
WHERE oprname ~ '^..&$'::text; |
||||
</ProgramListing> |
||||
|
||||
</Para> |
||||
|
||||
<Para> |
||||
to see if your name is taken for the types you want. |
||||
The important things here are the procedure (which are |
||||
the <Acronym>C</Acronym> functions defined above) and the restriction and |
||||
join selectivity functions. You should just use the |
||||
ones used below--note that there are different such |
||||
functions for the less-than, equal, and greater-than |
||||
cases. These must be supplied, or the access method |
||||
will crash when it tries to use the operator. You |
||||
should copy the names for restrict and join, but use |
||||
the procedure names you defined in the last step. |
||||
|
||||
<ProgramListing> |
||||
CREATE OPERATOR = ( |
||||
leftarg = complex, rightarg = complex, |
||||
procedure = complex_abs_eq, |
||||
restrict = eqsel, join = eqjoinsel |
||||
) |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
Notice that five operators corresponding to less, less |
||||
equal, equal, greater, and greater equal are defined. |
||||
</Para> |
||||
|
||||
<Para> |
||||
We're just about finished. the last thing we need to do |
||||
is to update the <FileName>pg_amop</FileName> relation. To do this, we need |
||||
the following attributes: |
||||
|
||||
<TABLE TOCENTRY="1"> |
||||
<Title><FileName>pg_amproc</FileName> Schema</Title> |
||||
<TitleAbbrev><FileName>pg_amproc</FileName></TitleAbbrev> |
||||
<TGroup Cols="2"> |
||||
<THead> |
||||
<Row> |
||||
<Entry>Attribute</Entry> |
||||
<Entry>Description</Entry> |
||||
</Row> |
||||
</THead> |
||||
<TBody> |
||||
<Row> |
||||
<Entry>amopid</Entry> |
||||
<Entry>the <FileName>oid</FileName> of the <FileName>pg_am</FileName> instance |
||||
for B-tree (== 403, see above)</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>amopclaid</Entry> |
||||
<Entry>the <FileName>oid</FileName> of the |
||||
<FileName>pg_opclass</FileName> instance for <FileName>int4_abs_ops</FileName> |
||||
(== whatever you got instead of <FileName>17314</FileName>, see above)</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>amopopr</Entry> |
||||
<Entry>the <FileName>oid</FileName>s of the operators for the opclass |
||||
(which we'll get in just a minute)</Entry> |
||||
</Row> |
||||
<Row> |
||||
<Entry>amopselect, amopnpages</Entry> |
||||
<Entry>cost functions</Entry> |
||||
</Row> |
||||
</TBody> |
||||
</TGroup> |
||||
</TABLE> |
||||
|
||||
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 <FileName>btreesel</FileName>, which estimates the selectivity |
||||
of the <Acronym>B-tree</Acronym>, and <FileName>btreenpage</FileName>, which estimates the |
||||
number of pages a search will touch in the tree. |
||||
</Para> |
||||
|
||||
<Para> |
||||
So we need the <FileName>oid</FileName>s of the operators we just defined. |
||||
We'll look up the names of all the operators that take |
||||
two <FileName>int4</FileName>s, and pick ours out: |
||||
|
||||
<ProgramListing> |
||||
SELECT o.oid AS opoid, o.oprname |
||||
INTO TABLE complex_ops_tmp |
||||
FROM pg_operator o, pg_type t |
||||
WHERE o.oprleft = t.oid and o.oprright = t.oid |
||||
and t.typname = 'complex'; |
||||
|
||||
+------+---------+ |
||||
|oid | oprname | |
||||
+------+---------+ |
||||
|17321 | < | |
||||
+------+---------+ |
||||
|17322 | <= | |
||||
+------+---------+ |
||||
|17323 | = | |
||||
+------+---------+ |
||||
|17324 | >= | |
||||
+------+---------+ |
||||
|17325 | > | |
||||
+------+---------+ |
||||
</ProgramListing> |
||||
|
||||
(Again, some of your <FileName>oid</FileName> numbers will almost certainly |
||||
be different.) The operators we are interested in are |
||||
those with <FileName>oid</FileName>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. |
||||
</Para> |
||||
|
||||
<Para> |
||||
Now we're ready to update <FileName>pg_amop</FileName> 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 <FileName>pg_amop</FileName>. We add the |
||||
instances we need: |
||||
|
||||
<ProgramListing> |
||||
INSERT INTO pg_amop (amopid, amopclaid, |
||||
amopopr, amopstrategy, |
||||
amopselect, amopnpages) |
||||
SELECT am.oid, opcl.oid, c.opoid, 3, |
||||
'btreesel'::regproc, 'btreenpage'::regproc |
||||
FROM pg_am am, pg_opclass opcl, complex_ops_tmp c |
||||
WHERE amname = 'btree' |
||||
and opcname = 'complex_abs_ops' |
||||
and c.oprname = '='; |
||||
</ProgramListing> |
||||
|
||||
Note the order: "less than" is 1, "less than or equal" |
||||
is 2, "equal" is 3, "greater than or equal" is 4, and |
||||
"greater than" is 5. |
||||
</Para> |
||||
|
||||
<Para> |
||||
The last step (finally!) is registration of the |
||||
"support routine" previously described in our discussion of |
||||
<FileName>pg_am</FileName>. The <FileName>oid</FileName> of this support routine is stored in |
||||
the <FileName>pg_amproc</FileName> class, keyed by the access method <FileName>oid</FileName> and |
||||
the operator class <FileName>oid</FileName>. First, we need to register the |
||||
function in <ProductName>Postgres</ProductName> (recall that we put the <Acronym>C</Acronym> code |
||||
that implements this routine in the bottom of the file |
||||
in which we implemented the operator routines): |
||||
|
||||
<ProgramListing> |
||||
CREATE FUNCTION int4_abs_cmp(int4, int4) |
||||
RETURNS int4 |
||||
AS 'PGROOT/tutorial/obj/complex.so' |
||||
LANGUAGE 'c'; |
||||
|
||||
SELECT oid, proname FROM pg_proc |
||||
WHERE prname = 'int4_abs_cmp'; |
||||
|
||||
+------+--------------+ |
||||
|oid | proname | |
||||
+------+--------------+ |
||||
|17328 | int4_abs_cmp | |
||||
+------+--------------+ |
||||
</ProgramListing> |
||||
|
||||
(Again, your <FileName>oid</FileName> number will probably be different and |
||||
you should substitute the value you see for the value |
||||
below.) Recalling that the <Acronym>B-tree</Acronym> instance's oid is |
||||
403 and that of <FileName>int4_abs_ops</FileName> is 17314, we can add the |
||||
new instance as follows: |
||||
|
||||
<ProgramListing> |
||||
INSERT INTO pg_amproc (amid, amopclaid, amproc, amprocnum) |
||||
VALUES ('403'::oid, -- btree oid |
||||
'17314'::oid, -- pg_opclass tuple |
||||
'17328'::oid, -- new pg_proc oid |
||||
'1'::int2); |
||||
</ProgramListing> |
||||
</Para> |
||||
</Chapter> |
||||
@ -0,0 +1,52 @@ |
||||
<Chapter> |
||||
<Title>Extending <Acronym>SQL</Acronym>: Operators</Title> |
||||
|
||||
<Para> |
||||
<ProductName>Postgres</ProductName> supports left unary, right unary and binary |
||||
operators. Operators can be overloaded, or re-used |
||||
with different numbers and types of arguments. If |
||||
there is an ambiguous situation and the system cannot |
||||
determine the correct operator to use, it will return |
||||
an error and you may have to typecast the left and/or |
||||
right operands to help it understand which operator you |
||||
meant to use. |
||||
To create an operator for adding two complex numbers |
||||
can be done as follows. First we need to create a |
||||
function to add the new types. Then, we can create the |
||||
operator with the function. |
||||
|
||||
<ProgramListing> |
||||
CREATE FUNCTION complex_add(complex, complex) |
||||
RETURNS complex |
||||
AS '$PWD/obj/complex.so' |
||||
LANGUAGE 'c'; |
||||
|
||||
CREATE OPERATOR + ( |
||||
leftarg = complex, |
||||
rightarg = complex, |
||||
procedure = complex_add, |
||||
commutator = + |
||||
); |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
We've shown how to create a binary operator here. To |
||||
create unary operators, just omit one of leftarg (for |
||||
left unary) or rightarg (for right unary). |
||||
If we give the system enough type information, it can |
||||
automatically figure out which operators to use. |
||||
|
||||
<ProgramListing> |
||||
SELECT (a + b) AS c FROM test_complex; |
||||
|
||||
+----------------+ |
||||
|c | |
||||
+----------------+ |
||||
|(5.2,6.05) | |
||||
+----------------+ |
||||
|(133.42,144.95) | |
||||
+----------------+ |
||||
</ProgramListing> |
||||
</Para> |
||||
</Chapter> |
||||
@ -0,0 +1,149 @@ |
||||
<Chapter> |
||||
<Title>Extending <Acronym>SQL</Acronym>: Types</Title> |
||||
<Para> |
||||
As previously mentioned, there are two kinds of types |
||||
in <ProductName>Postgres</ProductName>: base types (defined in a programming language) |
||||
and composite types (instances). |
||||
Examples in this section up to interfacing indices can |
||||
be found in <FileName>complex.sql</FileName> and <FileName>complex.c</FileName>. Composite examples |
||||
are in <FileName>funcs.sql</FileName>. |
||||
</Para> |
||||
|
||||
<Sect1> |
||||
<Title>User-Defined Types</Title> |
||||
|
||||
<Sect2> |
||||
<Title>Functions Needed for a User-Defined Type</Title> |
||||
<Para> |
||||
A user-defined type must always have input and output |
||||
functions. 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. The |
||||
input function takes a null-delimited character string |
||||
as its input and returns the internal (in memory) |
||||
representation of the type. The output function takes the |
||||
internal representation of the type and returns a null |
||||
delimited character string. |
||||
Suppose we want to define a complex type which represents |
||||
complex numbers. Naturally, we choose to represent a |
||||
complex in memory as the following <Acronym>C</Acronym> structure: |
||||
<ProgramListing> |
||||
typedef struct Complex { |
||||
double x; |
||||
double y; |
||||
} Complex; |
||||
</ProgramListing> |
||||
and a string of the form (x,y) as the external string |
||||
representation. |
||||
These functions are usually not hard to write, especially |
||||
the output function. However, there are a number of points |
||||
to remember: |
||||
|
||||
<ItemizedList> |
||||
<ListItem> |
||||
<Para> When defining your external (string) representation, |
||||
remember that you must eventually write a |
||||
complete and robust parser for that representation |
||||
as your input function! |
||||
<ProgramListing> |
||||
Complex * |
||||
complex_in(char *str) |
||||
{ |
||||
double x, y; |
||||
Complex *result; |
||||
if (sscanf(str, " ( %lf , %lf )", &x, &y) != 2) { |
||||
elog(WARN, "complex_in: error in parsing |
||||
return NULL; |
||||
} |
||||
result = (Complex *)palloc(sizeof(Complex)); |
||||
result->x = x; |
||||
result->y = y; |
||||
return (result); |
||||
} |
||||
</ProgramListing> |
||||
|
||||
The output function can simply be: |
||||
<ProgramListing> |
||||
char * |
||||
complex_out(Complex *complex) |
||||
{ |
||||
char *result; |
||||
if (complex == NULL) |
||||
return(NULL); |
||||
result = (char *) palloc(60); |
||||
sprintf(result, "(%g,%g)", complex->x, complex->y); |
||||
return(result); |
||||
} |
||||
</ProgramListing> |
||||
</Para> |
||||
</ListItem> |
||||
<ListItem> |
||||
<Para> You should try to make the input and output |
||||
functions inverses of each other. If you do |
||||
not, you will have severe problems when you need |
||||
to dump your data into a file and then read it |
||||
back in (say, into someone else's database on |
||||
another computer). This is a particularly common |
||||
problem when floating-point numbers are |
||||
involved. |
||||
</Para> |
||||
</ListItem> |
||||
</ItemizedList> |
||||
|
||||
<Para> |
||||
To define the <Acronym>complex</Acronym> type, we need to create the two |
||||
user-defined functions complex_in and complex_out |
||||
before creating the type: |
||||
<ProgramListing> |
||||
CREATE FUNCTION complex_in(opaque) |
||||
RETURNS complex |
||||
AS 'PGROOT/tutorial/obj/complex.so' |
||||
LANGUAGE 'c'; |
||||
|
||||
CREATE FUNCTION complex_out(opaque) |
||||
RETURNS opaque |
||||
AS 'PGROOT/tutorial/obj/complex.so' |
||||
LANGUAGE 'c'; |
||||
|
||||
CREATE TYPE complex ( |
||||
internallength = 16, |
||||
input = complex_in, |
||||
output = complex_out |
||||
); |
||||
</ProgramListing> |
||||
</Para> |
||||
|
||||
<Para> |
||||
As discussed earlier, <ProductName>Postgres</ProductName> fully supports arrays of |
||||
base types. Additionally, <ProductName>Postgres</ProductName> supports arrays of |
||||
user-defined types as well. When you define a type, |
||||
<ProductName>Postgres</ProductName> automatically provides support for arrays of |
||||
that type. For historical reasons, the array type has |
||||
the same name as the user-defined type with the |
||||
underscore character _ prepended. |
||||
Composite types do not need any function defined on |
||||
them, since the system already understands what they |
||||
look like inside. |
||||
</Para> |
||||
|
||||
<Sect2> |
||||
<Title>Large Objects</Title> |
||||
|
||||
<Para> |
||||
The types discussed to this point are all "small" |
||||
objects -- that is, they are smaller than 8KB in size. |
||||
<Note> |
||||
<Para> |
||||
1024 longwords == 8192 bytes. In fact, the type must be considerably smaller than 8192 bytes, |
||||
since the <ProductName>Postgres</ProductName> tuple |
||||
and page overhead must also fit into this 8KB limitation. |
||||
The actual value that fits depends on the machine architecture. |
||||
</Para> |
||||
</Note> |
||||
If you require a larger type for something like a document |
||||
retrieval system or for storing bitmaps, you will |
||||
need to use the <ProductName>Postgres</ProductName> large object interface. |
||||
|
||||
</Sect2> |
||||
</Sect1> |
||||
</Chapter> |
||||
Loading…
Reference in new issue