diff --git a/doc/src/Makefile b/doc/src/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..88755599ee40bbc58e3057112fc09b1244bc3255 --- /dev/null +++ b/doc/src/Makefile @@ -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 . diff --git a/doc/src/sgml/admin.sgml b/doc/src/sgml/admin.sgml new file mode 100644 index 0000000000000000000000000000000000000000..de0f6a3f7a0005cb9add73ca3dd473f45ab92ecb --- /dev/null +++ b/doc/src/sgml/admin.sgml @@ -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> + diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml new file mode 100644 index 0000000000000000000000000000000000000000..ccbb054483d850931b452a5be8ecaa26b3081c26 --- /dev/null +++ b/doc/src/sgml/advanced.sgml @@ -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> diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml new file mode 100644 index 0000000000000000000000000000000000000000..aa83257a0b2bb348dc9651f6f86952d9c0e13630 --- /dev/null +++ b/doc/src/sgml/arch-dev.sgml @@ -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> diff --git a/doc/src/sgml/arch-pg.sgml b/doc/src/sgml/arch-pg.sgml new file mode 100644 index 0000000000000000000000000000000000000000..5a22fd36e7161797ccde9e9646eb69ea507bd79f --- /dev/null +++ b/doc/src/sgml/arch-pg.sgml @@ -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> diff --git a/doc/src/sgml/arch.sgml b/doc/src/sgml/arch.sgml new file mode 100644 index 0000000000000000000000000000000000000000..b1404b353ccb117019e73cee1e8a086e2321d757 --- /dev/null +++ b/doc/src/sgml/arch.sgml @@ -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> diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml new file mode 100644 index 0000000000000000000000000000000000000000..4b73608600150f895153f8221f0372895cf7bece --- /dev/null +++ b/doc/src/sgml/array.sgml @@ -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> diff --git a/doc/src/sgml/biblio.sgml b/doc/src/sgml/biblio.sgml new file mode 100644 index 0000000000000000000000000000000000000000..1cae84a3edd60af34d6a0f5c637cd05bf448a3c6 --- /dev/null +++ b/doc/src/sgml/biblio.sgml @@ -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> diff --git a/doc/src/sgml/compiler.sgml b/doc/src/sgml/compiler.sgml new file mode 100644 index 0000000000000000000000000000000000000000..5d9c0eb07555ce5288057f95a431813c04e40aff --- /dev/null +++ b/doc/src/sgml/compiler.sgml @@ -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> diff --git a/doc/src/sgml/contacts.sgml b/doc/src/sgml/contacts.sgml new file mode 100644 index 0000000000000000000000000000000000000000..8979cfdbdcc56580b201cec3f5faec9b1ee8a60d --- /dev/null +++ b/doc/src/sgml/contacts.sgml @@ -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> diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml new file mode 100644 index 0000000000000000000000000000000000000000..37da846b7bd469bd7af0477eab415eaded88a6ee --- /dev/null +++ b/doc/src/sgml/datatype.sgml @@ -0,0 +1,2064 @@ +<Chapter> +<Title>Data Types</Title> + +<Abstract> +<Para> +Describes the built-in data types available in <ProductName>Postgres</ProductName>. +</Para> +</Abstract> + +<Para> +<ProductName>Postgres</ProductName> has a rich set of native data types available to users. +Users may add new types to <ProductName>Postgres</ProductName> using the +<Command>define type</Command> +command described elsewhere. + +<Para> +In the context of data types, the following sections will discuss SQL standards +compliance, porting issues, and usage. + +Some <ProductName>Postgres</ProductName> types correspond directly to SQL92-compatible types. In other +cases, data types defined by SQL92 syntax are mapped directly +into native <ProductName>Postgres</ProductName> types. + +Many of the built-in types have obvious external formats. However, several +types are either unique to <ProductName>Postgres</ProductName>, such as open and closed paths, or have +several possibilities for formats, such as date and time types. +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Data Types</TITLE> +<TITLEABBREV>Data Types</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY><ProductName>Postgres</ProductName> Type</ENTRY> + <ENTRY><Acronym>SQL92</Acronym> or <Acronym>SQL3</Acronym> Type</ENTRY> + <ENTRY>Description</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>bool</ENTRY> + <ENTRY>boolean</ENTRY> + <ENTRY>logical boolean (true/false)</ENTRY> + </ROW> + <ROW> + <ENTRY>box</ENTRY> + <ENTRY></ENTRY> + <ENTRY>rectangular box in 2D plane</ENTRY> + </ROW> + <ROW> + <ENTRY>char(n)</ENTRY> + <ENTRY>character(n)</ENTRY> + <ENTRY>fixed-length character string</ENTRY> + </ROW> + <ROW> + <ENTRY>circle</ENTRY> + <ENTRY></ENTRY> + <ENTRY>circle in 2D plane</ENTRY> + </ROW> + <ROW> + <ENTRY>date</ENTRY> + <ENTRY>date</ENTRY> + <ENTRY>calendar date without time of day</ENTRY> + </ROW> + <ROW> + <ENTRY>float4/8</ENTRY> + <ENTRY>float(p)</ENTRY> + <ENTRY>floating-point number with precision p</ENTRY> + </ROW> + <ROW> + <ENTRY>float8</ENTRY> + <ENTRY>real, double precision</ENTRY> + <ENTRY>double-precision floating-point number</ENTRY> + </ROW> + <ROW> + <ENTRY>int2</ENTRY> + <ENTRY>smallint</ENTRY> + <ENTRY>signed two-byte integer</ENTRY> + </ROW> + <ROW> + <ENTRY>int4</ENTRY> + <ENTRY>int, integer</ENTRY> + <ENTRY>signed 4-byte integer</ENTRY> + </ROW> + <ROW> + <ENTRY>int4</ENTRY> + <ENTRY>decimal(p,s)</ENTRY> + <ENTRY>exact numeric for p <= 9, s = 0</ENTRY> + </ROW> + <ROW> + <ENTRY>int4</ENTRY> + <ENTRY>numeric(p,s)</ENTRY> + <ENTRY>exact numeric for p == 9, s = 0</ENTRY> + </ROW> + <ROW> + <ENTRY>line</ENTRY> + <ENTRY></ENTRY> + <ENTRY>infinite line in 2D plane</ENTRY> + </ROW> + <ROW> + <ENTRY>lseg</ENTRY> + <ENTRY></ENTRY> + <ENTRY>line segment in 2D plane</ENTRY> + </ROW> + <ROW> + <ENTRY>money</ENTRY> + <ENTRY>decimal(9,2)</ENTRY> + <ENTRY>US-style currency</ENTRY> + </ROW> + <ROW> + <ENTRY>path</ENTRY> + <ENTRY></ENTRY> + <ENTRY>open and closed geometric path in 2D plane</ENTRY> + </ROW> + <ROW> + <ENTRY>point</ENTRY> + <ENTRY></ENTRY> + <ENTRY>geometric point in 2D plane</ENTRY> + </ROW> + <ROW> + <ENTRY>polygon</ENTRY> + <ENTRY></ENTRY> + <ENTRY>closed geometric path in 2D plane</ENTRY> + </ROW> + <ROW> + <ENTRY>time</ENTRY> + <ENTRY>time</ENTRY> + <ENTRY>time of day</ENTRY> + </ROW> + <ROW> + <ENTRY>timespan</ENTRY> + <ENTRY>interval</ENTRY> + <ENTRY>general-use time span</ENTRY> + </ROW> + <ROW> + <ENTRY>timestamp</ENTRY> + <ENTRY>timestamp with time zone</ENTRY> + <ENTRY>date/time</ENTRY> + </ROW> + <ROW> + <ENTRY>varchar(n)</ENTRY> + <ENTRY>character varying(n)</ENTRY> + <ENTRY>variable-length character string</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Function Constants</TITLE> +<TITLEABBREV>Constants</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY><ProductName>Postgres</ProductName> Function</ENTRY> + <ENTRY><Acronym>SQL92</Acronym> Constant</ENTRY> + <ENTRY>Description</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>getpgusername()</ENTRY> + <ENTRY>current_user</ENTRY> + <ENTRY>user name in current session</ENTRY> + </ROW> + <ROW> + <ENTRY>date('now')</ENTRY> + <ENTRY>current_date</ENTRY> + <ENTRY>date of current transaction</ENTRY> + </ROW> + <ROW> + <ENTRY>time('now')</ENTRY> + <ENTRY>current_time</ENTRY> + <ENTRY>time of current transaction</ENTRY> + </ROW> + <ROW> + <ENTRY>timestamp('now')</ENTRY> + <ENTRY>current_timestamp</ENTRY> + <ENTRY>date and time of current transaction</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +<ProductName>Postgres</ProductName> has features at the forefront of ORDBMS development. In addition to +SQL3 conformance, substantial portions of SQL92 are also supported. +Although we strive for SQL92 compliance, there are some cases in the standard +which are ill considered and which should not live through subsequent standards. +<ProductName>Postgres</ProductName> will not make great efforts to conform to these cases. However, these +cases tend to be little-used and obsure, and a typical user is not likely to +run into them. + +<Para> +Although most of the input and output functions corresponding to the +base types (e.g., integers and floating point numbers) do some +error-checking, some are not particularly rigorous about it. More +importantly, few of the operators and functions (e.g., +addition and multiplication) perform any error-checking at all. +Consequently, many of the numeric operators can (for example) +silently underflow or overflow. +</Para> + +<Para> +Some of the input and output functions are not invertible. That is, +the result of an output function may lose precision when compared to +the original input. +</Para> + +<Sect1> +<Title>Numeric Types</Title> + +<Para> +Numeric types consist of two- and four-byte integers and four- and eight-byte +floating point numbers. + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Numeric Types</TITLE> +<TITLEABBREV>Numerics</TITLEABBREV> +<TGROUP COLS="4"> +<THEAD> + <ROW> + <ENTRY>Numeric Type</ENTRY> + <ENTRY>Storage</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Range</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>int2</ENTRY> + <ENTRY>2 bytes</ENTRY> + <ENTRY>Fixed-precision</ENTRY> + <ENTRY>-32768 to +32767</ENTRY> + </ROW> + <ROW> + <ENTRY>int4</ENTRY> + <ENTRY>4 bytes</ENTRY> + <ENTRY>Usual choice for fixed-precision</ENTRY> + <ENTRY>-2147483648 to +2147483647</ENTRY> + </ROW> + <ROW> + <ENTRY>float4</ENTRY> + <ENTRY>4 bytes</ENTRY> + <ENTRY>Variable-precision</ENTRY> + <ENTRY>7 decimal places</ENTRY> + </ROW> + <ROW> + <ENTRY>float8</ENTRY> + <ENTRY>8 bytes</ENTRY> + <ENTRY>Variable-precision</ENTRY> + <ENTRY>14 decimal places</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +The <FirstTerm>exact numerics</FirstTerm> <Type>decimal</Type> and <Type>numeric</Type> +have fully implemented syntax but currently (<ProductName>Postgres</ProductName> v6.3) + support only a small range of precision and/or range values. +</Para> + +</Sect1> + +<Sect1> +<Title>Monetary Type</Title> + +<Para> +The <Type>money</Type> type supports US-style currency with fixed decimal point representation. + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Numeric Types</TITLE> +<TITLEABBREV>Numerics</TITLEABBREV> +<TGROUP COLS="4"> +<THEAD> + <ROW> + <ENTRY>Monetary Type</ENTRY> + <ENTRY>Storage</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Range</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>money</ENTRY> + <ENTRY>4 bytes</ENTRY> + <ENTRY>Fixed-precision</ENTRY> + <ENTRY>-21474836.48 to +21474836.47</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +The <FirstTerm>exact numerics</FirstTerm> <Type>decimal</Type> and <Type>numeric</Type> +have fully implemented syntax but currently (<ProductName>Postgres</ProductName> v6.3) + support only a small range of precision and/or range values. +</Para> + +</Sect1> + +<Sect1> +<Title>Character Types</Title> + +<Para> +<Acronym>SQL92</Acronym> defines two primary character types: <Type>char</Type> and +<Type>varchar</Type>. <ProductName>Postgres</ProductName> supports these types, in +addition to the more general <Type>text</Type> type, which unlike <Type>varchar</Type> +does not require an upper +limit to be declared on the size of the field. +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Character Types</TITLE> +<TITLEABBREV>Characters</TITLEABBREV> +<TGROUP COLS="4"> +<THEAD> + <ROW> + <ENTRY>Character Type</ENTRY> + <ENTRY>Storage</ENTRY> + <ENTRY>Recommendation</ENTRY> + <ENTRY>Description</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>char</ENTRY> + <ENTRY>1 byte</ENTRY> + <ENTRY>SQL92-compatible</ENTRY> + <ENTRY>Single character</ENTRY> + </ROW> + <ROW> + <ENTRY>char(n)</ENTRY> + <ENTRY>(4+n) bytes</ENTRY> + <ENTRY>SQL92-compatible</ENTRY> + <ENTRY>Fixed-length blank padded</ENTRY> + </ROW> + <ROW> + <ENTRY>text</ENTRY> + <ENTRY>(4+x) bytes</ENTRY> + <ENTRY>Best choice</ENTRY> + <ENTRY>Variable-length</ENTRY> + </ROW> + <ROW> + <ENTRY>varchar(n)</ENTRY> + <ENTRY>(4+n) bytes</ENTRY> + <ENTRY>SQL92-compatible</ENTRY> + <ENTRY>Variable-length with limit</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +There are currently other fixed-length character types. These provide no additional +functionality and are likely to be deprecated in the future. +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Specialty Character Types</TITLE> +<TITLEABBREV>Specialty Characters</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>Character Type</ENTRY> + <ENTRY>Storage</ENTRY> + <ENTRY>Description</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>char2</ENTRY> + <ENTRY>2 bytes</ENTRY> + <ENTRY>Two characters</ENTRY> + </ROW> + <ROW> + <ENTRY>char4</ENTRY> + <ENTRY>4 bytes</ENTRY> + <ENTRY>Four characters</ENTRY> + </ROW> + <ROW> + <ENTRY>char8</ENTRY> + <ENTRY>8 bytes</ENTRY> + <ENTRY>Eight characters</ENTRY> + </ROW> + <ROW> + <ENTRY>char16</ENTRY> + <ENTRY>16 bytes</ENTRY> + <ENTRY>Sixteen characters</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +</Sect1> + +<Sect1> +<Title>Date/Time Types</Title> + +<Para> +There are two fundamental kinds of date and time measurements: clock time and time interval. +Both quantities have continuity and smoothness, as does time itself. +<ProductName>Postgres</ProductName> supplies two primary user-oriented date and time types, +<Type>datetime</Type> and timespan, as well as the related SQL92 types date and time. +</Para> + +<Para> +Other date and time types are available +also, mostly +for historical reasons. +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Date/Time Types</TITLE> +<TITLEABBREV>Date/Time</TITLEABBREV> +<TGROUP COLS="4"> +<THEAD> + <ROW> + <ENTRY>Date/Time Type</ENTRY> + <ENTRY>Storage</ENTRY> + <ENTRY>Recommendation</ENTRY> + <ENTRY>Description</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>abstime</ENTRY> + <ENTRY>4 bytes</ENTRY> + <ENTRY>original date and time</ENTRY> + <ENTRY>limited range</ENTRY> + </ROW> + <ROW> + <ENTRY>date</ENTRY> + <ENTRY>4 bytes</ENTRY> + <ENTRY>SQL92 type</ENTRY> + <ENTRY>wide range</ENTRY> + </ROW> + <ROW> + <ENTRY>datetime</ENTRY> + <ENTRY>8 bytes</ENTRY> + <ENTRY>best general date and time</ENTRY> + <ENTRY>wide range, high precision</ENTRY> + </ROW> + <ROW> + <ENTRY>interval</ENTRY> + <ENTRY>12 bytes</ENTRY> + <ENTRY>SQL92 type</ENTRY> + <ENTRY>equivalent to timespan</ENTRY> + </ROW> + <ROW> + <ENTRY>reltime</ENTRY> + <ENTRY>4 bytes</ENTRY> + <ENTRY>original time interval</ENTRY> + <ENTRY>limited range, low precision</ENTRY> + </ROW> + <ROW> + <ENTRY>time</ENTRY> + <ENTRY>4 bytes</ENTRY> + <ENTRY>SQL92 type</ENTRY> + <ENTRY>wide range</ENTRY> + </ROW> + <ROW> + <ENTRY>timespan</ENTRY> + <ENTRY>12 bytes</ENTRY> + <ENTRY>best general time interval</ENTRY> + <ENTRY>wide range, high precision</ENTRY> + </ROW> + <ROW> + <ENTRY>timestamp</ENTRY> + <ENTRY>4 bytes</ENTRY> + <ENTRY>SQL92 type</ENTRY> + <ENTRY>limited range</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Date/Time Ranges</TITLE> +<TITLEABBREV>Ranges</TITLEABBREV> +<TGROUP COLS="4"> +<THEAD> + <ROW> + <ENTRY>Date/Time Type</ENTRY> + <ENTRY>Earliest</ENTRY> + <ENTRY>Latest</ENTRY> + <ENTRY>Resolution</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>abstime</ENTRY> + <ENTRY>1901-12-14</ENTRY> + <ENTRY>2038-01-19</ENTRY> + <ENTRY>1 sec</ENTRY> + </ROW> + <ROW> + <ENTRY>date</ENTRY> + <ENTRY>4713 BC</ENTRY> + <ENTRY>no limit</ENTRY> + <ENTRY>1 day</ENTRY> + </ROW> + <ROW> + <ENTRY>datetime</ENTRY> + <ENTRY>4713 BC</ENTRY> + <ENTRY>no limit</ENTRY> + <ENTRY>1 microsec to 14 digits</ENTRY> + </ROW> + <ROW> + <ENTRY>interval</ENTRY> + <ENTRY>no limit</ENTRY> + <ENTRY>no limit</ENTRY> + <ENTRY>1 microsec</ENTRY> + </ROW> + <ROW> + <ENTRY>reltime</ENTRY> + <ENTRY>-68 years</ENTRY> + <ENTRY>+68 years</ENTRY> + <ENTRY>1 sec</ENTRY> + </ROW> + <ROW> + <ENTRY>time</ENTRY> + <ENTRY>00:00:00.00</ENTRY> + <ENTRY>23:59:59.99</ENTRY> + <ENTRY>1 microsec</ENTRY> + </ROW> + <ROW> + <ENTRY>timespan</ENTRY> + <ENTRY>no limit</ENTRY> + <ENTRY>no limit</ENTRY> + <ENTRY>1 microsec (14 digits)</ENTRY> + </ROW> + <ROW> + <ENTRY>timestamp</ENTRY> + <ENTRY>1901-12-14</ENTRY> + <ENTRY>2038-01-19</ENTRY> + <ENTRY>1 sec</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +<ProductName>Postgres</ProductName> endevours to be compatible with +<Acronym>SQL92</Acronym> definitions for typical usage. +The <Acronym>SQL92</Acronym> standard has an odd mix of date and +time types and capabilities. For example, although the date type does not have an associated time zone, the +time type can. The default time zone is specified as a constant offset from GMT/UTC; + however, time zones in the real world can have no meaning unless associated with a + date as well +as a time since the offset will vary through the year. + +<Para> +To obviate these difficulties, <ProductName>Postgres</ProductName> associates time zones + only with date and time +types which contain both date and time, and assumes local time for any type containing only +date or time. Further, time zone support is derived from the underlying operating system +time zone capabilities, and hence can handle daylight savings time and other expected behavior. + +<Para> +In future releases, the number of date/time types will decrease, with the current +implementation of <Type>datetime</Type> becoming <Type>timestamp</Type>, timespan becoming interval, +and (possibly) abstime +and reltime being deprecated in favor of <Type>timestamp</Type> and interval. +The more arcane features +of the date/time definitions from the <Acronym>SQL92</Acronym> standard are not likely to be pursued. +</Para> + +<Sect2> +<Title>Date/Time Styles</Title> + +<Para> +Output formats can be set to one of four styles: +ISO-8601, SQL (Ingres), traditional +Postgres, and German. + +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Date Styles</TITLE> +<TITLEABBREV>Styles</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>Style Specification</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Example</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>ISO</ENTRY> + <ENTRY>ISO-8601 standard</ENTRY> + <ENTRY>1997-12-17 07:37:16-08</ENTRY> + </ROW> + <ROW> + <ENTRY>SQL</ENTRY> + <ENTRY>Traditional style</ENTRY> + <ENTRY>12/17/1997 07:37:16.00 PST</ENTRY> + </ROW> + <ROW> + <ENTRY>Postgres</ENTRY> + <ENTRY>Original style</ENTRY> + <ENTRY>Wed Dec 17 07:37:16 1997 PST</ENTRY> + </ROW> + <ROW> + <ENTRY>German</ENTRY> + <ENTRY>Regional style</ENTRY> + <ENTRY>17.12.1997 07:37:16.00 PST</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +The SQL style has European and non-European (US) variants, which determines whether +month follows day or vica versa. + +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Date Order Conventions</TITLE> +<TITLEABBREV>Order</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>Style Specification</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Example</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>European</ENTRY> + <ENTRY>Regional convention</ENTRY> + <ENTRY>17/12/1997 15:37:16.00 MET</ENTRY> + </ROW> + <ROW> + <ENTRY>NonEuropean</ENTRY> + <ENTRY>Regional convention</ENTRY> + <ENTRY>12/17/1997 07:37:16.00 PST</ENTRY> + </ROW> + <ROW> + <ENTRY>US</ENTRY> + <ENTRY>Regional convention</ENTRY> + <ENTRY>12/17/1997 07:37:16.00 PST</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +There are several ways to affect the appearance of date/time types: + +<ItemizedList Mark="bullet" Spacing="compact"> +<ListItem> +<Para> +The PGDATESTYLE environment variable used by the backend directly on postmaster startup. +</Para> +</ListItem> +<ListItem> +<Para> +The PGDATESTYLE environment variable used by the frontend libpq on session startup. +</Para> +</ListItem> +<ListItem> +<Para> +SET DateStyle <Acronym>SQL</Acronym> command. +</Para> +</ListItem> +</ItemizedList> + +<Para> +For <ProductName>Postgres</ProductName> v6.3 (and earlier) the default date/time style is +"traditional Postgres". In future releases, the default may become ISO-8601, which alleviates +date specification ambiguities and Y2K collation problems. +</Para> + +</Sect2> + +<Sect2> +<Title>Time Zones</Title> + +<Para> +<ProductName>Postgres</ProductName> obtains time zone support from the underlying operating system. +All dates and times are stored internally in Universal Coordinated Time (UTC), alternately known as +Greenwich Mean Time (GMT). Times are converted to local time on the database server before being +sent to the client frontend, hence by default are in the server time zone. + +<Para> +There are several ways to affect the time zone behavior: + +<ItemizedList Mark="bullet" Spacing="compact"> +<ListItem> +<Para> +The TZ environment variable used by the backend directly + on postmaster startup as the default time zone. +</Para> +</ListItem> +<ListItem> +<Para> +The PGTZ environment variable set at the client used by libpq to send time zone information to the backend upon connection. +</Para> +</ListItem> +<ListItem> +<Para> +<Command>set timezone</Command> <Acronym>SQL</Acronym> sets the time zone for the session. +</Para> +</ListItem> +</ItemizedList> + +<Para> + If an invalid time zone is specified, +the time zone becomes GMT (on most systems anyway). +</Para> +</Sect2> + +<Sect2> +<Title>Date/Time Input</Title> + +<Para> +General-use date and time is input using a wide range of +styles, including ISO-compatible, SQL-compatible, traditional +<ProductName>Postgres</ProductName> +and other permutations of date and time. In cases where interpretation +can be ambiguous (quite possible with many traditional styles of date specification) +<ProductName>Postgres</ProductName> uses a style setting to resolve the ambiguity. +</Para> + +<Para> +Most date and time types share code for data input. For those types +the input can have any of a wide variety of styles. For numeric date representations, +European and US conventions can differ, and the proper interpretation is obtained +by using the +<Command>set datestyle</Command> +command before entering data. +Note that the style setting does not preclude use of various styles for input; it is +used primarily to determine the output style and to resolve ambiguities. +</Para> + +<Para> +The special values `current', +`infinity' and `-infinity' are provided. +`infinity' specifies a time later than any other valid time, and +`-infinity' specifies a time earlier than any other valid time. +`current' indicates that the current time should be +substituted whenever this value appears in a computation. + +The strings +`now', +`today', +`yesterday', +`tomorrow', +and `epoch' can be used to specify +time values. `now' means the current transaction time, and differs from +`current' in that the current time is immediately substituted +for it. `epoch' means Jan 1 00:00:00 1970 GMT. +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Date/Time Special Constants</TITLE> +<TITLEABBREV>Constants</TITLEABBREV> +<TGROUP COLS="2"> +<THEAD> + <ROW> + <ENTRY>Constant</ENTRY> + <ENTRY>Description</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>current</ENTRY> + <ENTRY>Current transaction time, deferred</ENTRY> + </ROW> + <ROW> + <ENTRY>epoch</ENTRY> + <ENTRY>1970-01-01 00:00:00+00 (Unix system time zero)</ENTRY> + </ROW> + <ROW> + <ENTRY>infinity</ENTRY> + <ENTRY>Later than other valid times</ENTRY> + </ROW> + <ROW> + <ENTRY>-infinity</ENTRY> + <ENTRY>Earlier than other valid times</ENTRY> + </ROW> + <ROW> + <ENTRY>invalid</ENTRY> + <ENTRY>Illegal entry</ENTRY> + </ROW> + <ROW> + <ENTRY>now</ENTRY> + <ENTRY>Current transaction time</ENTRY> + </ROW> + <ROW> + <ENTRY>today</ENTRY> + <ENTRY>Midnight today</ENTRY> + </ROW> + <ROW> + <ENTRY>tomorrow</ENTRY> + <ENTRY>Midnight tomorrow</ENTRY> + </ROW> + <ROW> + <ENTRY>yesterday</ENTRY> + <ENTRY>Midnight yesterday</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +</Sect2> + +<Sect2> +<Title>datetime</Title> + +<Para> +General-use date and time is input using a wide range of +styles, including ISO-compatible, SQL-compatible, traditional +<ProductName>Postgres</ProductName> (see section on "absolute time") +and other permutations of date and time. Output styles can be ISO-compatible, +SQL-compatible, or traditional <ProductName>Postgres</ProductName>, with the default set to be compatible +with <ProductName>Postgres</ProductName> v6.0. +</Para> + +<Para> +<Type>datetime</Type> is specified using the following syntax: + +<ProgramListing> +Year-Month-Day [ Hour : Minute : Second ] [AD,BC] [ Timezone ] + YearMonthDay [ Hour : Minute : Second ] [AD,BC] [ Timezone ] + Month Day [ Hour : Minute : Second ] Year [AD,BC] [ Timezone ] +where + Year is 4013 BC, ..., very large + Month is Jan, Feb, ..., Dec or 1, 2, ..., 12 + Day is 1, 2, ..., 31 + Hour is 00, 02, ..., 23 + Minute is 00, 01, ..., 59 + Second is 00, 01, ..., 59 (60 for leap second) + Timezone is 3 characters or ISO offset to GMT +</ProgramListing> + +<Para> +Valid dates are from Nov 13 00:00:00 4013 BC GMT to far into the future. +Timezones are either three characters (e.g. "GMT" or "PST") or ISO-compatible +offsets to GMT (e.g. "-08" or "-08:00" when in Pacific Standard Time). +Dates are stored internally in Greenwich Mean Time. Input and output routines +translate time to the local time zone of the server. +</Para> + +<Sect2> +<Title><Type>timespan</Type></Title> + +<Para> +General-use time span is input using a wide range of +syntaxes, including ISO-compatible, SQL-compatible, traditional +<ProductName>Postgres</ProductName> (see section on "relative time") + and other permutations of time span. Output formats can be ISO-compatible, +SQL-compatible, or traditional <ProductName>Postgres</ProductName>, with the default set to be <ProductName>Postgres</ProductName>-compatible. +Months and years are a "qualitative" time interval, and are stored separately +from the other "quantitative" time intervals such as day or hour. For date arithmetic, +the qualitative time units are instantiated in the context of the relevant date or time. + +<Para> +Time span is specified with the following syntax: + +<ProgramListing> + Quantity Unit [Quantity Unit...] [Direction] +@ Quantity Unit [Direction] +where + Quantity is ..., `-1', `0', `1', `2', ... + Unit is `second', `minute', `hour', `day', `week', `month', `year', + 'decade', 'century', millenium', or abbreviations or plurals of these units. + Direction is `ago'. +</ProgramListing> +</Para> +</Sect2> + +<Sect2> +<Title>abstime</Title> + +<Para> +Absolute time (abstime) is a limited-range (+/- 68 years) and limited-precision (1 sec) +date data type. <Type>datetime</Type> may be preferred, since it +covers a larger range with greater precision. + +<Para> +Absolute time is specified using the following syntax: + +<ProgramListing> +Month Day [ Hour : Minute : Second ] Year [ Timezone ] +where + Month is Jan, Feb, ..., Dec + Day is 1, 2, ..., 31 + Hour is 01, 02, ..., 24 + Minute is 00, 01, ..., 59 + Second is 00, 01, ..., 59 + Year is 1901, 1902, ..., 2038 +</ProgramListing> +</Para> + +<Para> +Valid dates are from Dec 13 20:45:53 1901 GMT to Jan 19 03:14:04 +2038 GMT. As of Version 3.0, times are no longer read and written +using Greenwich Mean Time; the input and output routines default to +the local time zone. + +All special values allowed for <Type>datetime</Type> are also allowed for "absolute time". +</Para> + +</Sect2> + +<Sect2> +<Title>reltime</Title> + +<Para> +Relative time <Type>reltime</Type> is a limited-range (+/- 68 years) + and limited-precision (1 sec) time span data type. +<Type>timespan</Type> should be preferred, since it +covers a larger range with greater precision and, more importantly, can distinguish between +relative units (months and years) and quantitative units (days, hours, etc). Instead, reltime +must force months to be exactly 30 days, so time arithmetic does not always work as expected. +For example, adding one reltime year to abstime today does not produce today's date one year from +now, but rather a date 360 days from today. +</Para> + +<Para> +<Type>reltime</Type> shares input and output routines with the other time span types. +The section on <Type>timespan</Type> covers this in more detail. +</Para> + +</Sect2> + +<Sect2> +<Title><Type>timestamp</Type></Title> + +<Para> +This is currently a limited-range absolute time which closely resembles the +abstime +data type. It shares the general input parser with the other date/time types. +In future releases this type will absorb the capabilities of the <Type>datetime</Type> type +and will move toward SQL92 compliance. +</Para> + +<Para> +<Type>timestamp</Type> is specified using the same syntax as for <Type>datetime</Type>. +</Para> +</Sect2> + +<Sect2> +<Title><Type>interval</Type></Title> + +<Para> +<Type>interval</Type> is an <Acronym>SQL92</Acronym> data type which is +currently mapped to the <Type>timespan</Type> <ProductName>Postgres</ProductName> +data type. +</Para> +</Sect2> + +<Sect2> +<Title>tinterval</Title> + +<Para> +Time ranges are specified as: + +<ProgramListing> +[ 'abstime' 'abstime'] +where + abstime is a time in the absolute time format. +</ProgramListing> + +Special abstime values such as +`current', `infinity' and `-infinity' can be used. +</Para> + +</Sect1> + +<Sect1> +<Title>Boolean Type</Title> + +<Para> +<ProductName>Postgres</ProductName> supports <Type>bool</Type> as +the <Acronym>SQL3</Acronym> boolean type. +<Type>bool</Type> can have one of only two states: 'true' or 'false'. A third state, 'unknown', is not +implemented and is not suggested in <Acronym>SQL3</Acronym>; <Acronym>NULL</Acronym> is an +effective substitute. <Type>bool</Type> can be used in any boolean expression, and boolean expressions +always evaluate to a result compatible with this type. + +<Para> +<Type>bool</Type> uses 4 bytes of storage. +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Boolean Type</TITLE> +<TITLEABBREV>Booleans</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>State</ENTRY> + <ENTRY>Output</ENTRY> + <ENTRY>Input</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>True</ENTRY> + <ENTRY>'t'</ENTRY> + <ENTRY>TRUE, 't', 'true', 'y', 'yes', '1'</ENTRY> + </ROW> + <ROW> + <ENTRY>False</ENTRY> + <ENTRY>'f'</ENTRY> + <ENTRY>FALSE, 'f', 'false', 'n', 'no', '0'</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> +</Sect1> + +<Sect1> +<Title>Geometric Types</Title> + +<Para> +Geometric types represent two-dimensional spatial objects. The most fundamental type, +the point, forms the basis for all of the other types. +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Geometric Types</TITLE> +<TITLEABBREV>Geometrics</TITLEABBREV> +<TGROUP COLS="4"> +<THEAD> + <ROW> + <ENTRY>Geometric Type</ENTRY> + <ENTRY>Storage</ENTRY> + <ENTRY>Representation</ENTRY> + <ENTRY>Description</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>point</ENTRY> + <ENTRY>16 bytes</ENTRY> + <ENTRY>(x,y)</ENTRY> + <ENTRY>Point in space</ENTRY> + </ROW> + <ROW> + <ENTRY>line</ENTRY> + <ENTRY>32 bytes</ENTRY> + <ENTRY>((x1,y1),(x2,y2))</ENTRY> + <ENTRY>Infinite line</ENTRY> + </ROW> + <ROW> + <ENTRY>lseg</ENTRY> + <ENTRY>32 bytes</ENTRY> + <ENTRY>((x1,y1),(x2,y2))</ENTRY> + <ENTRY>Finite line segment</ENTRY> + </ROW> + <ROW> + <ENTRY>box</ENTRY> + <ENTRY>32 bytes</ENTRY> + <ENTRY>((x1,y1),(x2,y2))</ENTRY> + <ENTRY>Rectangular box</ENTRY> + </ROW> + <ROW> + <ENTRY>path</ENTRY> + <ENTRY>4+32n bytes</ENTRY> + <ENTRY>((x1,y1),...)</ENTRY> + <ENTRY>Closed path (similar to polygon)</ENTRY> + </ROW> + <ROW> + <ENTRY>path</ENTRY> + <ENTRY>4+32n bytes</ENTRY> + <ENTRY>[(x1,y1),...]</ENTRY> + <ENTRY>Open path</ENTRY> + </ROW> + <ROW> + <ENTRY>polygon</ENTRY> + <ENTRY>4+32n bytes</ENTRY> + <ENTRY>((x1,y1),...)</ENTRY> + <ENTRY>Polygon (similar to closed path)</ENTRY> + </ROW> + <ROW> + <ENTRY>circle</ENTRY> + <ENTRY>24 bytes</ENTRY> + <ENTRY><(x,y),r></ENTRY> + <ENTRY>Circle (center and radius)</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +A rich set of functions and operators is available to perform various geometric +operations such as scaling, translation, rotation, and determining intersections. +</Para> + +<Sect2> +<Title>Point</Title> + +<Para> +Points are specified using the following syntax: + +<ProgramListing> +( x , y ) + x , y +where + x is the x-axis coordinate as a floating point number + y is the y-axis coordinate as a floating point number +</ProgramListing> +</Para> +</Sect2> + +<Sect2> +<Title>Line Segment</Title> + +<Para> +Line segments (lseg) are represented by pairs of points. +</Para> + +<Para> +lseg is specified using the following syntax: +<ProgramListing> +( ( x1 , y1 ) , ( x2 , y2 ) ) + ( x1 , y1 ) , ( x2 , y2 ) + x1 , y1 , x2 , y2 +where + (x1,y1) and (x2,y2) are the endpoints of the segment +</ProgramListing> +</Para> +</Sect2> + +<Sect2> +<Title>Box</Title> + +<Para> +Boxes are represented by pairs of points which are opposite +corners of the box. +</Para> + +<Para> +box is specified using the following syntax: + +<ProgramListing> +( ( x1 , y1 ) , ( x2 , y2 ) ) + ( x1 , y1 ) , ( x2 , y2 ) + x1 , y1 , x2 , y2 +where + (x1,y1) and (x2,y2) are opposite corners +</ProgramListing> + +Boxes are output using the first syntax. +The corners are reordered on input to store +the lower left corner first and the upper right corner last. +Other corners of the box can be entered, but the lower +left and upper right corners are determined from the input and stored. +</Para> +</Sect2> + +<Sect2> +<Title>Path</Title> + +<Para> +Paths are represented by connected sets of points. Paths can be "open", where +the first and last points in the set are not connected, and "closed", +where the first and last point are connected. Functions +<Function>popen(p)</Function> +and +<Function>pclose(p)</Function> +are supplied to force a path to be open or closed, and functions +<Function>isopen(p)</Function> +and +<Function>isclosed(p)</Function> +are supplied to select either type in a query. +</Para> + +<Para> +path is specified using the following syntax: + +<ProgramListing> +( ( x1 , y1 ) , ... , ( xn , yn ) ) +[ ( x1 , y1 ) , ... , ( xn , yn ) ] + ( x1 , y1 ) , ... , ( xn , yn ) + ( x1 , y1 , ... , xn , yn ) + x1 , y1 , ... , xn , yn +where + (x1,y1),...,(xn,yn) are points 1 through n + a leading "[" indicates an open path + a leading "(" indicates a closed path +</ProgramListing> +Paths are output using the first syntax. +Note that <ProductName>Postgres</ProductName> versions prior to +v6.1 used a format for paths which had a single leading parenthesis, a "closed" flag, +an integer count of the number of points, then the list of points followed by a +closing parenthesis. The built-in function <Function>upgradepath</Function> is supplied to convert +paths dumped and reloaded from pre-v6.1 databases. +</Para> +</Sect2> + +<Sect2> +<Title>Polygon</Title> + +<Para> +Polygons are represented by sets of points. Polygons should probably be +considered +equivalent to closed paths, but are stored differently and have their own +set of support routines. +</Para> + +<Para> +polygon is specified using the following syntax: + +<ProgramListing> +( ( x1 , y1 ) , ... , ( xn , yn ) ) + ( x1 , y1 ) , ... , ( xn , yn ) + ( x1 , y1 , ... , xn , yn ) + x1 , y1 , ... , xn , yn +where + (x1,y1),...,(xn,yn) are points 1 through n +</ProgramListing> + +Polygons are output using the first syntax. +Note that <ProductName>Postgres</ProductName> versions prior to +v6.1 used a format for polygons which had a single leading parenthesis, the list +of x-axis coordinates, the list of y-axis coordinates, followed by a closing parenthesis. +The built-in function <Function>upgradepoly</Function> is supplied to convert +polygons dumped and reloaded from pre-v6.1 databases. +</Para> +</Sect2> + +<Sect2> +<Title>Circle</Title> + +<Para> +Circles are represented by a center point and a radius. +</Para> + +<Para> +circle is specified using the following syntax: + +<ProgramListing> +< ( x , y ) , r > +( ( x , y ) , r ) + ( x , y ) , r + x , y , r +where + (x,y) is the center of the circle + r is the radius of the circle +</ProgramListing> + +Circles are output using the first syntax. +</Para> +</Sect2> + +</Sect1> + +<Chapter> +<Title>Operators</Title> + +<Para> +<ProductName>Postgres</ProductName> provides a large number of built-in operators on system types. +These operators are declared in the system catalog +pg_operator. Every entry in pg_operator includes +the name of the procedure that implements the operator and the +class <Acronym>OIDs</Acronym> of the input and output types. + +<Para> +To view all variations of the <Quote>||</Quote> string concatenation operator, try +<ProgramListing> + SELECT oprleft, oprright, oprresult, oprcode + FROM pg_operator WHERE oprname = '||'; + +oprleft|oprright|oprresult|oprcode +-------+--------+---------+------- + 25| 25| 25|textcat + 1042| 1042| 1042|textcat + 1043| 1043| 1043|textcat +(3 rows) +</ProgramListing> +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Operators</TITLE> +<TITLEABBREV>Operators</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>Operator</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Usage</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY> < </ENTRY> + <ENTRY>Less than?</ENTRY> + <ENTRY>1 < 2</ENTRY> + </ROW> + <ROW> + <ENTRY> <= </ENTRY> + <ENTRY>Less than or equal to?</ENTRY> + <ENTRY>1 <= 2</ENTRY> + </ROW> + <ROW> + <ENTRY> <> </ENTRY> + <ENTRY>Not equal?</ENTRY> + <ENTRY>1 <> 2</ENTRY> + </ROW> + <ROW> + <ENTRY> = </ENTRY> + <ENTRY>Equal?</ENTRY> + <ENTRY>1 = 1</ENTRY> + </ROW> + <ROW> + <ENTRY> > </ENTRY> + <ENTRY>Greater than?</ENTRY> + <ENTRY>2 > 1</ENTRY> + </ROW> + <ROW> + <ENTRY> >= </ENTRY> + <ENTRY>Greater than or equal to?</ENTRY> + <ENTRY>2 >= 1</ENTRY> + </ROW> + <ROW> + <ENTRY> || </ENTRY> + <ENTRY>Concatenate strings</ENTRY> + <ENTRY>'Postgre' || 'SQL'</ENTRY> + </ROW> + <ROW> + <ENTRY> !!= </ENTRY> + <ENTRY>NOT IN</ENTRY> + <ENTRY>3 !!= i</ENTRY> + </ROW> + <ROW> + <ENTRY> ~~ </ENTRY> + <ENTRY>LIKE</ENTRY> + <ENTRY>'scrappy,marc,hermit' ~~ '%scrappy%'</ENTRY> + </ROW> + <ROW> + <ENTRY> !~~ </ENTRY> + <ENTRY>NOT LIKE</ENTRY> + <ENTRY>'bruce' !~~ '%al%'</ENTRY> + </ROW> + <ROW> + <ENTRY> ~ </ENTRY> + <ENTRY>Match (regex), case sensitive</ENTRY> + <ENTRY>'thomas' ~ '*.thomas*.'</ENTRY> + </ROW> + <ROW> + <ENTRY> ~* </ENTRY> + <ENTRY>Match (regex), case insensitive</ENTRY> + <ENTRY>'thomas' ~* '*.Thomas*.'</ENTRY> + </ROW> + <ROW> + <ENTRY> !~ </ENTRY> + <ENTRY>Does not match (regex), case sensitive</ENTRY> + <ENTRY>'thomas' !~ '*.Thomas*.'</ENTRY> + </ROW> + <ROW> + <ENTRY> !~* </ENTRY> + <ENTRY>Does not match (regex), case insensitive</ENTRY> + <ENTRY>'thomas' !~ '*.vadim*.'</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Numerical Operators</TITLE> +<TITLEABBREV>Operators</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>Operator</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Usage</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY> ! </ENTRY> + <ENTRY>Factorial</ENTRY> + <ENTRY>3 !</ENTRY> + </ROW> + <ROW> + <ENTRY> !! </ENTRY> + <ENTRY>Factorial (left operator)</ENTRY> + <ENTRY>!! 3</ENTRY> + </ROW> + <ROW> + <ENTRY> % </ENTRY> + <ENTRY>Modulo</ENTRY> + <ENTRY>5 % 4</ENTRY> + </ROW> + <ROW> + <ENTRY> % </ENTRY> + <ENTRY>Truncate</ENTRY> + <ENTRY>% 4.5</ENTRY> + </ROW> + <ROW> + <ENTRY> * </ENTRY> + <ENTRY>Multiplication</ENTRY> + <ENTRY>2 * 3</ENTRY> + </ROW> + <ROW> + <ENTRY> + </ENTRY> + <ENTRY>Addition</ENTRY> + <ENTRY>2 + 3</ENTRY> + </ROW> + <ROW> + <ENTRY> - </ENTRY> + <ENTRY>Subtraction</ENTRY> + <ENTRY>2 - 3</ENTRY> + </ROW> + <ROW> + <ENTRY> / </ENTRY> + <ENTRY>Division</ENTRY> + <ENTRY>4 / 2</ENTRY> + </ROW> + <ROW> + <ENTRY> : </ENTRY> + <ENTRY>Natural Exponentiation</ENTRY> + <ENTRY>: 3.0</ENTRY> + </ROW> + <ROW> + <ENTRY> ; </ENTRY> + <ENTRY>Natural Logarithm</ENTRY> + <ENTRY>(; 5.0)</ENTRY> + </ROW> + <ROW> + <ENTRY> @ </ENTRY> + <ENTRY>Absolute value</ENTRY> + <ENTRY>@ -5.0</ENTRY> + </ROW> + <ROW> + <ENTRY> ^ </ENTRY> + <ENTRY>Exponentiation</ENTRY> + <ENTRY>2.0 ^ 3.0</ENTRY> + </ROW> + <ROW> + <ENTRY> |/ </ENTRY> + <ENTRY>Square root</ENTRY> + <ENTRY>|/ 25.0</ENTRY> + </ROW> + <ROW> + <ENTRY> ||/ </ENTRY> + <ENTRY>Cube root</ENTRY> + <ENTRY>||/ 27.0</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Geometric Operators</TITLE> +<TITLEABBREV>Operators</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>Operator</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Usage</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY> + </ENTRY> + <ENTRY>Translation</ENTRY> + <ENTRY>'((0,0),(1,1))'::box + '(2.0,0)'::point</ENTRY> + </ROW> + <ROW> + <ENTRY> - </ENTRY> + <ENTRY>Translation</ENTRY> + <ENTRY>'((0,0),(1,1))'::box - '(2.0,0)'::point</ENTRY> + </ROW> + <ROW> + <ENTRY> * </ENTRY> + <ENTRY>Scaling/rotation</ENTRY> + <ENTRY>'((0,0),(1,1))'::box * '(2.0,0)'::point</ENTRY> + </ROW> + <ROW> + <ENTRY> / </ENTRY> + <ENTRY>Scaling/rotation</ENTRY> + <ENTRY>'((0,0),(2,2))'::box / '(2.0,0)'::point</ENTRY> + </ROW> + <ROW> + <ENTRY> # </ENTRY> + <ENTRY>Intersection</ENTRY> + <ENTRY>'((1,-1),(-1,1))' # '((1,1),(-1,-1))'</ENTRY> + </ROW> + <ROW> + <ENTRY> # </ENTRY> + <ENTRY>Number of points in polygon</ENTRY> + <ENTRY># '((1,0),(0,1),(-1,0))'</ENTRY> + </ROW> + <ROW> + <ENTRY> ## </ENTRY> + <ENTRY>Point of closest proximity</ENTRY> + <ENTRY>'(0,0)'::point ## '((2,0),(0,2))'::lseg</ENTRY> + </ROW> + <ROW> + <ENTRY> && </ENTRY> + <ENTRY>Overlaps?</ENTRY> + <ENTRY>'((0,0),(1,1))'::box && '((0,0),(2,2))'::box</ENTRY> + </ROW> + <ROW> + <ENTRY> &< </ENTRY> + <ENTRY>Overlaps to left?</ENTRY> + <ENTRY>'((0,0),(1,1))'::box &< '((0,0),(2,2))'::box</ENTRY> + </ROW> + <ROW> + <ENTRY> &> </ENTRY> + <ENTRY>Overlaps to right?</ENTRY> + <ENTRY>'((0,0),(3,3))'::box &> '((0,0),(2,2))'::box</ENTRY> + </ROW> + <ROW> + <ENTRY> <-> </ENTRY> + <ENTRY>Distance between</ENTRY> + <ENTRY>'((0,0),1)'::circle <-> '((5,0),1)'::circle</ENTRY> + </ROW> + <ROW> + <ENTRY> << </ENTRY> + <ENTRY>Left of?</ENTRY> + <ENTRY>'((0,0),1)'::circle << '((5,0),1)'::circle</ENTRY> + </ROW> + <ROW> + <ENTRY> <^ </ENTRY> + <ENTRY>Is below?</ENTRY> + <ENTRY>'((0,0),1)'::circle <^ '((0,5),1)'::circle</ENTRY> + </ROW> + <ROW> + <ENTRY> >> </ENTRY> + <ENTRY>Is right of?</ENTRY> + <ENTRY>'((5,0),1)'::circle >> '((0,0),1)'::circle</ENTRY> + </ROW> + <ROW> + <ENTRY> >^ </ENTRY> + <ENTRY>Is above?</ENTRY> + <ENTRY>'((0,5),1)'::circle >^ '((0,0),1)'::circle</ENTRY> + </ROW> + <ROW> + <ENTRY> ?# </ENTRY> + <ENTRY>Intersects or overlaps</ENTRY> + <ENTRY>'((-1,0),(1,0))'::lseg ?# '((-2,-2),(2,2))'::box;</ENTRY> + </ROW> + <ROW> + <ENTRY> ?- </ENTRY> + <ENTRY>Is horizontal?</ENTRY> + <ENTRY>'(1,0)'::point ?- '(0,0)'::point</ENTRY> + </ROW> + <ROW> + <ENTRY> ?-| </ENTRY> + <ENTRY>Is perpendicular?</ENTRY> + <ENTRY>'((0,0),(0,1))'::lseg ?-| '((0,0),(1,0))'::lseg</ENTRY> + </ROW> + <ROW> + <ENTRY> @-@ </ENTRY> + <ENTRY>Length or circumference</ENTRY> + <ENTRY>@-@ '((0,0),(1,0))'::path</ENTRY> + </ROW> + <ROW> + <ENTRY> ?| </ENTRY> + <ENTRY>Is vertical?</ENTRY> + <ENTRY>'(0,1)'::point ?| '(0,0)'::point</ENTRY> + </ROW> + <ROW> + <ENTRY> ?|| </ENTRY> + <ENTRY>Is parallel?</ENTRY> + <ENTRY>'((-1,0),(1,0))'::lseg ?|| '((-1,2),(1,2))'::lseg</ENTRY> + </ROW> + <ROW> + <ENTRY> @ </ENTRY> + <ENTRY>Contained or on</ENTRY> + <ENTRY>'(1,1)'::point @ '((0,0),2)'::circle</ENTRY> + </ROW> + <ROW> + <ENTRY> @@ </ENTRY> + <ENTRY>Center of</ENTRY> + <ENTRY>@@ '((0,0),10)'::circle</ENTRY> + </ROW> + <ROW> + <ENTRY> ~= </ENTRY> + <ENTRY>Same as</ENTRY> + <ENTRY>'((0,0),(1,1))'::polygon ~= '((1,1),(0,0))'::polygon</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +The time interval data type <Type>tinterval</Type> is a legacy from the original +date/time types and is not as well supported as the more modern types. There +are several operators for this type. + +<TABLE TOCENTRY="1"> +<TITLE><ProductName>Postgres</ProductName> Time Interval Operators</TITLE> +<TITLEABBREV>Operators</TITLEABBREV> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>Operator</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Usage</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY> #< </ENTRY> + <ENTRY>Interval less than?</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> #<= </ENTRY> + <ENTRY>Interval less than or equal to?</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> #<> </ENTRY> + <ENTRY>Interval not equal?</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> #= </ENTRY> + <ENTRY>Interval equal?</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> #> </ENTRY> + <ENTRY>Interval greater than?</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> #>= </ENTRY> + <ENTRY>Interval greater than or equal to?</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> <#> </ENTRY> + <ENTRY>Convert to time interval</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> << </ENTRY> + <ENTRY>Interval less than?</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> | </ENTRY> + <ENTRY>Start of interval</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> ~= </ENTRY> + <ENTRY>Same as</ENTRY> + <ENTRY></ENTRY> + </ROW> + <ROW> + <ENTRY> <?> </ENTRY> + <ENTRY>Time inside interval?</ENTRY> + <ENTRY></ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + + +<Para> +Users may invoke operators using the operator name, as in: + +<ProgramListing> +select * from emp where salary < 40000; +</ProgramListing> + +Alternatively, users may call the functions that implement the +operators directly. In this case, the query above would be expressed +as: +<ProgramListing> +select * from emp where int4lt(salary, 40000); +</ProgramListing> + +<Para> +<Application>psql</Application> +has a <Command>\dd</Command> command to show these operators. +</Chapter> + +<Chapter> +<Title>Functions</Title> + +<Para> +Many data types have functions available for conversion to other related types. +In addition, there are some type-specific functions. Functions which are also +available through operators are documented as operators only. +</Para> + +<Para> +Some functions defined for text are also available for char() and varchar(). +</Para> + +<Para> +For the +<Function>date_part</Function> and <Function>date_trunc</Function> +functions, arguments can be +`year', `month', `day', `hour', `minute', and `second', +as well as the more specialized quantities +`decade', `century', `millenium', `millisecond', and `microsecond'. +<Function>date_part</Function> allows `dow' +to return day of week and `epoch' to return seconds since 1970 (for <Type>datetime</Type>) +or 'epoch' to return total elapsed seconds (for <Type>timespan</Type>). +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE>Mathematical Functions</TITLE> +<TGROUP COLS="4"> +<THEAD> + <ROW> + <ENTRY>Function</ENTRY> + <ENTRY>Returns</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Example</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> +<ENTRY> float(int) </ENTRY> +<ENTRY> float8 </ENTRY> +<ENTRY> convert integer to floating point </ENTRY> +<ENTRY> float(2) </ENTRY> + </ROW> + <ROW> +<ENTRY> float4(int) </ENTRY> +<ENTRY> float4 </ENTRY> +<ENTRY> convert integer to floating point </ENTRY> +<ENTRY> float4(2) </ENTRY> + </ROW> + <ROW> +<ENTRY> int </ENTRY> +<ENTRY> integer(float) </ENTRY> +<ENTRY> convert floating point to integer </ENTRY> +<ENTRY> integer(2.0) </ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +Many of the string functions are available for text, varchar(), and char() types. +At the moment, some functions are available only for the text type. + +<TABLE TOCENTRY="1"> +<TITLE>String Functions</TITLE> +<TGROUP COLS="4"> +<THEAD> + <ROW> + <ENTRY>Function</ENTRY> + <ENTRY>Returns</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Example</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> +<ENTRY> lower(text) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> convert text to lower case </ENTRY> +<ENTRY> lower('TOM') </ENTRY> + </ROW> + <ROW> +<ENTRY> lpad(text,int,text) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> left pad string to specified length </ENTRY> +<ENTRY> lpad('hi',4,'??') </ENTRY> + </ROW> + <ROW> +<ENTRY> ltrim(text,text) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> left trim characters from text </ENTRY> +<ENTRY> ltrim('xxxxtrim','x') </ENTRY> + </ROW> + <ROW> +<ENTRY> position(text,text) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> extract specified substring </ENTRY> +<ENTRY> position('high','ig') </ENTRY> + </ROW> + <ROW> +<ENTRY> rpad(text,int,text) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> right pad string to specified length </ENTRY> +<ENTRY> rpad('hi',4,'x') </ENTRY> + </ROW> + <ROW> +<ENTRY> rtrim(text,text) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> right trim characters from text </ENTRY> +<ENTRY> rtrim('trimxxxx','x') </ENTRY> + </ROW> + <ROW> +<ENTRY> substr(text,int[,int]) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> extract specified substring </ENTRY> +<ENTRY> substr('hi there',3,5) </ENTRY> + </ROW> + <ROW> +<ENTRY> upper(text) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> convert text to upper case </ENTRY> +<ENTRY> upper('tom') </ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE>Date/Time Functions</TITLE> +<TGROUP COLS="4"> +<THEAD> + <ROW> + <ENTRY>Function</ENTRY> + <ENTRY>Returns</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Example</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> +<ENTRY> isfinite(abstime) </ENTRY> +<ENTRY> bool </ENTRY> +<ENTRY> TRUE if this is a finite time </ENTRY> +<ENTRY> isfinite('now'::abstime) </ENTRY> + </ROW> + <ROW> +<ENTRY> datetime(abstime) </ENTRY> +<ENTRY> datetime </ENTRY> +<ENTRY> convert to datetime </ENTRY> +<ENTRY> datetime('now'::abstime) </ENTRY> + </ROW> + <ROW> +<ENTRY> datetime(date) </ENTRY> +<ENTRY> datetime </ENTRY> +<ENTRY> convert to datetime </ENTRY> +<ENTRY> datetime('today'::date) </ENTRY> + </ROW> + <ROW> +<ENTRY> datetime(date,time) </ENTRY> +<ENTRY> datetime </ENTRY> +<ENTRY> convert to datetime </ENTRY> +<ENTRY> datetime('1998-02-24':datetime, '23:07'::time); + </ROW> + <ROW> +<ENTRY> age(datetime,datetime) </ENTRY> +<ENTRY> timespan </ENTRY> +<ENTRY> span preserving months and years </ENTRY> +<ENTRY> age('now','1957-06-13':datetime) </ENTRY> + </ROW> + <ROW> +<ENTRY> date_part(text,datetime) </ENTRY> +<ENTRY> float8 </ENTRY> +<ENTRY> specified portion of date field </ENTRY> +<ENTRY> date_part('dow','now'::datetime) </ENTRY> + </ROW> + <ROW> +<ENTRY> date_trunc(text,datetime) </ENTRY> +<ENTRY> datetime </ENTRY> +<ENTRY> truncate date at specified units </ENTRY> +<ENTRY> date_trunc('month','now'::abstime) </ENTRY> + </ROW> + <ROW> +<ENTRY> isfinite(datetime) </ENTRY> +<ENTRY> bool </ENTRY> +<ENTRY> TRUE if this is a finite time </ENTRY> +<ENTRY> isfinite('now'::datetime) </ENTRY> + </ROW> + <ROW> +<ENTRY> abstime(datetime) </ENTRY> +<ENTRY> abstime </ENTRY> +<ENTRY> convert to abstime </ENTRY> +<ENTRY> abstime('now'::datetime) </ENTRY> + </ROW> + <ROW> +<ENTRY> timespan(reltime) </ENTRY> +<ENTRY> timespan </ENTRY> +<ENTRY> convert to timespan </ENTRY> +<ENTRY> timespan('4 hours'::reltime) </ENTRY> + </ROW> + <ROW> +<ENTRY> datetime(date,time) </ENTRY> +<ENTRY> datetime </ENTRY> +<ENTRY> convert to datetime </ENTRY> +<ENTRY> datetime('1998-02-25'::date,'06:41'::time) </ENTRY> + </ROW> + <ROW> +<ENTRY> date_part(text,timespan) </ENTRY> +<ENTRY> float8 </ENTRY> +<ENTRY> specified portion of time field </ENTRY> +<ENTRY> date_part('hour','4 hrs 3 mins'::timespan) </ENTRY> + </ROW> + <ROW> +<ENTRY> isfinite(timespan) </ENTRY> +<ENTRY> bool </ENTRY> +<ENTRY> TRUE if this is a finite time </ENTRY> +<ENTRY> isfinite('4 hrs'::timespan) </ENTRY> + </ROW> + <ROW> +<ENTRY> reltime(timespan) </ENTRY> +<ENTRY> reltime </ENTRY> +<ENTRY> convert to reltime </ENTRY> +<ENTRY> reltime('4 hrs'::timespan) </ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE>Geometric Functions</TITLE> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>Function</ENTRY> + <ENTRY>Returns</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Example</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> +<ENTRY> box(point,point) </ENTRY> +<ENTRY> box </ENTRY> +<ENTRY> convert points to box </ENTRY> +<ENTRY> box('(0,0)'::point,'(1,1)'::point) </ENTRY> + </ROW> + <ROW> +<ENTRY> area(box) </ENTRY> +<ENTRY> float8 </ENTRY> +<ENTRY> area of box </ENTRY> +<ENTRY> area('((0,0),(1,1))'::box) </ENTRY> + </ROW> + <ROW> +<ENTRY> isopen(path) </ENTRY> +<ENTRY> bool </ENTRY> +<ENTRY> TRUE if this is an open path </ENTRY> +<ENTRY> isopen('[(0,0),(1,1),(2,0)]'::path) </ENTRY> + </ROW> + <ROW> +<ENTRY> isclosed(path) </ENTRY> +<ENTRY> bool </ENTRY> +<ENTRY> TRUE if this is a closed path </ENTRY> +<ENTRY> isclosed('((0,0),(1,1),(2,0))'::path) </ENTRY> + </ROW> + <ROW> +<ENTRY> circle(point,float8) </ENTRY> +<ENTRY> circle </ENTRY> +<ENTRY> convert to circle </ENTRY> +<ENTRY> circle('(0,0)'::point,2.0) </ENTRY> + </ROW> + <ROW> +<ENTRY> polygon(npts,circle) </ENTRY> +<ENTRY> polygon </ENTRY> +<ENTRY> convert to polygon with npts points </ENTRY> +<ENTRY> polygon(12,'((0,0),2.0)'::circle) </ENTRY> + </ROW> + <ROW> +<ENTRY> center(circle) </ENTRY> +<ENTRY> float8 </ENTRY> +<ENTRY> center of object </ENTRY> +<ENTRY> center('((0,0),2.0)'::circle) </ENTRY> + </ROW> + <ROW> +<ENTRY> radius(circle) </ENTRY> +<ENTRY> float8 </ENTRY> +<ENTRY> radius of circle </ENTRY> +<ENTRY> radius('((0,0),2.0)'::circle) </ENTRY> + </ROW> + <ROW> +<ENTRY> diameter(circle) </ENTRY> +<ENTRY> float8 </ENTRY> +<ENTRY> diameter of circle </ENTRY> +<ENTRY> diameter('((0,0),2.0)'::circle) </ENTRY> + </ROW> + <ROW> +<ENTRY> area(circle) </ENTRY> +<ENTRY> float8 </ENTRY> +<ENTRY> area of circle </ENTRY> +<ENTRY> area('((0,0),2.0)'::circle) </ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +SQL92 defines functions with specific syntax. Some of these +are implemented using other <ProductName>Postgres</ProductName> functions. +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE><Acronym>SQL92</Acronym> Text Functions</TITLE> +<TGROUP COLS="3"> +<THEAD> + <ROW> + <ENTRY>Function</ENTRY> + <ENTRY>Returns</ENTRY> + <ENTRY>Description</ENTRY> + <ENTRY>Example</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> +<ENTRY> position(text in text) </ENTRY> +<ENTRY> int4 </ENTRY> +<ENTRY> extract specified substring </ENTRY> +<ENTRY> position('o' in 'Tom') </ENTRY> + </ROW> + <ROW> +<ENTRY> substring(text [from int] [for int]) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> extract specified substring </ENTRY> +<ENTRY> substring('Tom' from 2 for 2) </ENTRY> + </ROW> + <ROW> +<ENTRY> trim([leading|trailing|both] [text] from text) </ENTRY> +<ENTRY> text </ENTRY> +<ENTRY> trim characters from text </ENTRY> +<ENTRY> trim(both 'x' from 'xTomx') </ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + diff --git a/doc/src/sgml/dfunc.sgml b/doc/src/sgml/dfunc.sgml new file mode 100644 index 0000000000000000000000000000000000000000..7a719b7ed3e436d5597d815e1afa7b96b051199b --- /dev/null +++ b/doc/src/sgml/dfunc.sgml @@ -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> diff --git a/doc/src/sgml/docguide.sgml b/doc/src/sgml/docguide.sgml new file mode 100644 index 0000000000000000000000000000000000000000..4b2a59602a3063ca4175dcd2e5cc1f3333c13c94 --- /dev/null +++ b/doc/src/sgml/docguide.sgml @@ -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> diff --git a/doc/src/sgml/ecpg.sgml b/doc/src/sgml/ecpg.sgml new file mode 100644 index 0000000000000000000000000000000000000000..32fd459e52536b8a13a51ec9ec8f18ecaf280da3 --- /dev/null +++ b/doc/src/sgml/ecpg.sgml @@ -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> diff --git a/doc/src/sgml/environ.sgml b/doc/src/sgml/environ.sgml new file mode 100644 index 0000000000000000000000000000000000000000..64d9506423ea1e221c9df64472ef73a1126c0e82 --- /dev/null +++ b/doc/src/sgml/environ.sgml @@ -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> diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml new file mode 100644 index 0000000000000000000000000000000000000000..fe790b2542daf260f9497cb476b86921e391ca7a --- /dev/null +++ b/doc/src/sgml/extend.sgml @@ -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> diff --git a/doc/src/sgml/func-ref.sgml b/doc/src/sgml/func-ref.sgml new file mode 100644 index 0000000000000000000000000000000000000000..66f476fb2e9d21ad362c679a4e2408467e05a171 --- /dev/null +++ b/doc/src/sgml/func-ref.sgml @@ -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> diff --git a/doc/src/sgml/geqo.sgml b/doc/src/sgml/geqo.sgml new file mode 100644 index 0000000000000000000000000000000000000000..725504c28fb991cf8d2638374d274c341e0236a8 --- /dev/null +++ b/doc/src/sgml/geqo.sgml @@ -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> diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml new file mode 100644 index 0000000000000000000000000000000000000000..c522d2fa936c24749c5047f3c24b0cb3207a2c8b --- /dev/null +++ b/doc/src/sgml/gist.sgml @@ -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> diff --git a/doc/src/sgml/inherit.sgml b/doc/src/sgml/inherit.sgml new file mode 100644 index 0000000000000000000000000000000000000000..be2bcfa237fe1834fe3d266eece793f405359d8b --- /dev/null +++ b/doc/src/sgml/inherit.sgml @@ -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> diff --git a/doc/src/sgml/install.sgml b/doc/src/sgml/install.sgml new file mode 100644 index 0000000000000000000000000000000000000000..06b284882fe350109830ffef50069476d829d502 --- /dev/null +++ b/doc/src/sgml/install.sgml @@ -0,0 +1,1032 @@ +<Chapter> +<Title>Installation</Title> + +<Abstract> +<Para> +Complete installation instructions for <ProductName>Postgres</ProductName> v6.3. +</Para> +</Abstract> + +<Para> + This procedure is +This is based on the installation instructions +for <ProductName>Postgres</ProductName> v6.3 +found in <FileName>$PGROOT/INSTALL</FileName>. + Up to date information on <ProductName>Postgres</ProductName> may be found at +<ULink url="http://www.postgresql.org">www.postgresql.org</ULink>. +</Para> + +<Para> +The installation 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> +Commands were tested on RedHat Linux version 4.2 using the tcsh shell. +Except where noted, they will probably work on most systems. Commands +like ps and tar vary wildly on what options you should use on each +platform. <Emphasis>Use common sense</Emphasis> before typing in these commands. +</Para> + +<Para> +Our Makefiles require GNU <Application>make</Application> (called <Quote>gmake</Quote> in this document) and +also assume that <Application>install</Application> accepts BSD options. The INSTALL +variable in the Makefiles is set to the BSD-compatible version of +<Application>install</Application>. On some systems, you will have to find a BSD-compatible +<Application>install</Application> (eg. <Application>bsdinst</Application>, which comes with the MIT X Window System +distribution). +</Para> + +<Sect1> +<Title>Requirements to Run <ProductName>Postgres</ProductName></Title> + +<Para> +Information on supported platforms is another chapter. In general, most Unix-compatible +platforms with modern libraries should be able to run <ProductName>Postgres</ProductName>. + +<Para> +You should have at least 8 MB of memory and at least 45 MB of disk space +to hold the source, binaries, and user databases. After installation +you may reduce this to about 3 Mbytes plus space for user databases. +</Para> + +</Sect1> + +<Sect1> +<Title>Installation Procedure</Title> + +<Para> +<Procedure> +<Title><ProductName>Postgres</ProductName> Installation</Title> + +<Para> +For a fresh install or upgrading from previous releases of +<ProductName>Postgres</ProductName>: +</Para> + +<Step Performance="required"> +<Para> +Read any last minute information and platform specific porting + notes. There are some platform specific notes at the end of this + file for Ultrix4.x, Linux, BSD/OS and NeXT. There are other + files in directory <FileName>/usr/src/pgsql/doc</FileName>, including files FAQ-Irix + and FAQ-Linux. Also look in directory +<ULink url="ftp://ftp.postgresql.org/pub">ftp://ftp.postgresql.org/pub</ULink>. + If there is a file called INSTALL in this directory then this + file will contain the latest installation information. +</Para> + +<Para> + Please note that a "tested" platform in the list given earlier + simply means that someone went to the effort at some point of making + sure that a <ProductName>Postgres</ProductName> distribution would compile and run on this + platform without modifying the code. Since the current developers + will not have access to all of these platforms, some of them may not + compile cleanly and pass the regression tests in the current + release due to minor problems. Any such known problems and their + solutions will be posted in +<ULink url="ftp://ftp.postgresql.org/pub/INSTALL">ftp://ftp.postgresql.org/pub/INSTALL</ULink>. +</Para> +</Step> + +<Step Performance="optional"> +<Para> +Create account postgres if it does not already exist. +</Para> +</Step> + +<Step Performance="required"> +<Para> +Log into account postgres. +</Para> + +<SubSteps> +<Step Performance="required"> +<Para> +Check that you have sufficient disk space. You will need about + 17 Mbytes for /usr/src/pgsql, about 2 Mbytes for /usr/local/pgsql + (excluding your database) and 1 Mbyte for an empty database. + The database will temporarily grow to about 20 Mbytes during the + regression tests. You will also need about 3 Mbytes for the + distribution tar file. +</Para> + +<Para> + We therefore recommend that during installation and testing you + have well over 20 Mbytes free under /usr/local and another 25 Mbytes + free on the disk partition containing your database. Once you + delete the source files, tar file and regression database, you + will need 2 Mbytes for /usr/local/pgsql, 1 Mbyte for the empty + database, plus about five times the space you would require to + store your database data in a flat file. +</Para> + +<Para> + To check for disk space, use <Command>df -k</Command>. +</Para> +</Step> +</SubSteps> +</Step> + +<Step Performance="required"> +<Para> +Ftp file ftp://ftp.postgresql.org/pub/postgresql-v6.3.tar.gz from the + Internet. Store it in your home directory. +</Para> +</Step> + +<Step Performance="required"> +<Para> +Some platforms use flex. If your system uses flex then make sure + you have a good version. To check, type <Command>flex --version</Command>. +</Para> + +<Para> + If the flex command is not found then you probably do not need it. + If the version is 2.5.2 or 2.5.4 or greater then you are okay. If it + is 2.5.3 or before 2.5.2 then you will have to upgrade flex. You may + get it at ftp://prep.ai.mit.edu/pub/gnu/flex-2.5.4.tar.gz. +</Para> + +<Para> + If you need flex and don't have it or have the wrong version, then + you will be told so when you attempt to compile the program. Feel + free to skip this step if you aren't sure you need it. If you do + need it then you will be told to install/upgrade flex when you try to + compile. +</Para> + +<Para> + To install it, type the following: +<ProgramListing> + cd + gunzip -c flex-2.5.4.tar.gz | tar xvf - + cd flex-2.5.4 + configure --prefix=/usr + make + make check + # You must be root when typing the next line. + make install + cd + rm -rf flex-2.5.4 +</ProgramListing> +</Para> + +<Para> + This will update files /usr/man/man1/flex.1, /usr/bin/flex, + /usr/lib/libfl.a, /usr/include/FlexLexer.h and will add link + /usr/bin/flex++ which points to flex. +</Para> +</Step> + +<Step Performance="required"> +<Para> +If you are upgrading an existing system then back up your database. + For alpha- and beta-level releases, the database format is liable + to change often every few weeks with no notice besides a quick comment + in the HACKERS mailing list. Full releases always require a dump/reload + from previous releases. It is therefore a bad idea to skip this + step. Also, do not use the pg_dumpall script from v6.0 or everything + will be owned by the <ProductName>Postgres</ProductName> super user. + Type (with the gunzip line + and the following line typed as one line): +<ProgramListing> + cd + gunzip -c postgresql-v6.3.tar.gz | + tar xvf - src/bin/pg_dump/pg_dumpall + chmod a+x src/bin/pg_dump/pg_dumpall + src/bin/pg_dump/pg_dumpall > db.out + rm -rf src +</ProgramListing> +</Para> + +<Para> + If you wish to preserve object id's (oids), then use the -o + option when running pg_dumpall. However, unless you have a + special reason for doing this, don't do it. +</Para> + +<Para> + If the pg_dumpall command seems to take a long time and you think + it might have died, then, from another terminal, use "ls -l db.out" + several times to see if the size of the file is growing. +</Para> + +<Para> + Please note that if you are upgrading from a version prior to + <ProductName>Postgres95</ProductName> v1.09 then you must back up your database, install + <ProductName>Postgres95</ProductName> v1.09, restore your database, then back it up again. + You should also read files /usr/src/pgsql/migration/*. +</Para> + +<Para> + You must make sure that your database is not updated in the middle of + your backup. If necessary, bring down postmaster, edit the permissions + in file /usr/local/pgsql/data/pg_hba.conf to allow only you on, then + bring postmaster back up. +</Para> +</Step> + +<Step Performance="required"> +<Para> +If you are upgrading an existing system then kill the postmaster. Type +<ProgramListing> + ps -ax | grep postmaster +</ProgramListing> + This should list the process numbers for a number of processes. Type + the following line, with "???" replaced by the process id for process + "postmaster". (Do not use the id for process "grep postmaster".) Type + kill ??? + with "???" modified as indicated. +</Para> +</Step> + +<Step Performance="required"> +<Para> +If you are upgrading an existing system then move the old directories + out of the way. If you are short of disk space then you may have to + back up and delete the directories instead. If you do this, save the + old database in the /usr/local/pgsql/data directory tree. At a + minimum, save file /usr/local/pgsql/data/pg_hba.conf. +</Para> + +<Para> + Type the following: + su + cd /usr/src + mv pgsql pgsql_6_0 + cd /usr/local + mv pgsql pgsql_6_0 + exit +</Para> + +<Para> + If you are not using /usr/local/pgsql/data as your data directory + (check to see if environment variable PGDATA is set to something + else) then you will also want to move this directory in the same + manner. +</Para> +</Step> + +<Step Performance="required"> +<Para> + Make new source and install directories. The actual paths can be + different for your installation; be consistant throughout this procedure. + Type +<ProgramListing> + su + cd /usr/src + mkdir pgsql + chown postgres:postgres pgsql + cd /usr/local + mkdir pgsql + chown postgres:postgres pgsql + exit +</ProgramListing> +</Para> +</Step> + +<Step Performance="required"> +<Para> + Unzip and untar the new source file. Type +<ProgramListing> + cd /usr/src/pgsql + gunzip -c ~/postgresql-v6.3.tar.gz | tar xvf - +</ProgramListing> +</Para> +</Step> + +<Step Performance="required"> +<Para> + Configure the source code for your system. It is this step at which + you can specify your actual source path and installation paths for + the build process (see the --prefix option below). Type +<ProgramListing> + cd /usr/src/pgsql/src + ./configure +</ProgramListing> +</Para> + +<Para> + The configure program will list the template files available and + ask you to choose one. A lot of times, an appropriate template + file is chosen for you, and you can just press Enter to accept the + default. If the default is not appropriate, then type in the + appropriate template file and press Enter. (If you do this, then + send email to scrappy@hub.org stating the output of the program + './config.guess' and what the template file should be.) +</Para> + +<Para> + Once you have entered the template file, you will be asked a + number of questions about your particular configuration. These + can be skipped by adding parameters to the configure command above. + The following parameters can be tagged onto the end of the configure + command: + +<ProgramListing> + --prefix=BASEDIR Selects a different base directory for the + installation of the <ProductName>Postgres</ProductName> configuration. + The default is /usr/local/pgsql. + + --enable-hba Enables Host Based Authentication (DEFAULT) + + --disable-hba Disables Host Based Authentication + + --enable-locale Enables USE_LOCALE + + --disable-locale Disables USE_LOCALE (DEFAULT) + + --enable-cassert Enables ASSERT_CHECKING + + --disable-cassert Disables ASSERT_CHECKING (DEFAULT) + + --with-template=TEMPLATE + Use template file TEMPLATE - the template + files are assumed to be in the directory + src/template, so look there for proper values. + (If the configure script cannot find the + specified template file, it will ask you for + one). + + --with-pgport=PORT Sets the port that the postmaster process + listens for incoming connections on. The + default for this is port 5432. +</ProgramListing> +</Para> + +<Para> + As an example, here is the configure script I use on a Sparc + Solaris 2.5 system with /opt/postgres being the install base. + +<ProgramListing> + ./configure --prefix=/opt/postgres \ + --with-template=sparc_solaris-gcc --with-pgport=5432 \ + --enable-hba --disable-locale +</ProgramListing> + + Of course, in a real shell, you would type these three lines all + on the same line. +</Para> +</Step> + +<Step Performance="required"> +<Para> +Compile the program. Type +<ProgramListing> + cd /usr/src/pgsql/src + gmake all >& make.log & + tail -f make.log +</ProgramListing> +</Para> + +<Para> + The last line displayed will hopefully be "All of PostgreSQL is + successfully made. Ready to install." At this point, or earlier + if you wish, type control-C to get out of tail. (If you have + problems later on you may wish to examine file make.log for + warning and error messages.) +</Para> + +<Para> + If your computer does not have gmake (GNU make) then try running + make instead throughout the rest of these notes. +</Para> + +<Para> + Please note that you will probably find a number of warning + messages in make.log. Unless you have problems later on, these + messages may be safely ignored. +</Para> + +<Para> + If the compiler fails with an error stating that the flex command + cannot be found then install flex as described earlier. Next, + change directory back to this directory, type "make clean", then + recompile again. +</Para> +</Step> + +<Step Performance="required"> +<Para> + Install the program. Type +<ProgramListing> + cd /usr/src/pgsql/src + gmake install >& make.install.log & + tail -f make.install.log +</ProgramListing> +</Para> + +<Para> + The last line displayed will be "gmake[1]: Leaving directory + `/usr/src/pgsql/src/man'". At this point, or earlier if you wish, + type control-C to get out of tail. +</Para> +</Step> + +<Step Performance="required"> +<Para> + If necessary, tell UNIX how to find your shared libraries. If you + are using Linux-ELF do ONE of the following, preferably the first: +<SubSteps> +<Step Performance="optional"> +<Para> + As root, edit file /etc/ld.so.conf. Add line + <FileName>/usr/local/pgsql/lib</FileName> + to the file. Then run command <Command>/sbin/ldconfig</Command>. +</Para> +</Step> +<Step Performance="optional"> +<Para> + In a bash shell, type +<ProgramListing> + export LD_LIBRARY_PATH=/usr/local/pgsql/lib +</ProgramListing> +</Para> +</Step> +<Step Performance="optional"> +<Para> + In a csh shell, type +<ProgramListing> + setenv LD_LIBRARY_PATH /usr/local/pgsql/lib +</ProgramListing> +</Step> +</SubSteps> + +<Para> + Please note that the above commands may vary wildly for different + operating systems. Check the platform specific notes, such as + those for Ultrix4.x or and for non-ELF Linux. +</Para> + +<Para> + If, when you create the database, you get the message "pg_id: can't + load library 'libpq.so'" then the above step was necessary. Simply + do this step, then try to create the database again. +</Para> +</Step> + +<Step Performance="required"> +<Para> + If it has not already been done, then prepare account postgres + for using <ProductName>Postgres</ProductName>. Any account that will use <ProductName>Postgres</ProductName> must + be similarily prepared. (The following instructions are for a + bash shell. Adapt accordingly for other shells.) +</Para> + +<Para> + Add the following lines to your login shell, ~/.bash_profile: +<ProgramListing> + PATH=$PATH:/usr/local/pgsql/bin + MANPATH=$MANPATH:/usr/local/pgsql/man + PGLIB=/usr/local/pgsql/lib + PGDATA=/usr/local/pgsql/data + export PATH MANPATH PGLIB PGDATA +</ProgramListing> +</Para> + +<Para> + Make sure that you have defined these variables before continuing + with the remaining steps. The easiest way to do this is to type: +<ProgramListing> + source ~/.bash_profile +</ProgramListing> +</Para> +</Step> + +<Step Performance="required"> +<Para> + Create the database. <Emphasis>Do not do the following as root!</Emphasis> + This would be a major security hole. Type +<ProgramListing> + initdb +</ProgramListing> +</Para> +</Step> + +<Step Performance="required"> +<Para> + Set up permissions to access the database system. Do this by editing + file /usr/local/pgsql/data/pg_hba.conf. The instructions are + included in the file. (If your database is not located in the + default location, i.e. if PGDATA is set to point elsewhere, then the + location of this file will change accordingly.) This file should be + made read only again once you are finsihed. + + If you are upgrading from v6.0 you can copy file pg_hba.conf from + your old database on top of the one in your new database, rather than + redoing this from scratch. +</Para> +</Step> + +<Step Performance="required"> +<Para> +You may wish to skip the regression tests. + However, we think skipping the tests is a BAD idea! +</Para> + +<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> + 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). DO NOT RUN POSTMASTER FROM THE ROOT ACCOUNT. +</Para> +</Step> + +<Step Performance="required"> +<Para> + + Run the regression tests. Type + +<ProgramListing> + cd + cd /usr/src/pgsql/src/test/regress + gmake clean + gmake all runtest +</ProgramListing> +</Para> + +<Para> + + You do not need to type "gmake clean" if this is the first time you + are running the tests. +</Para> + +<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> + +<Para> + + "Failed" tests may have failed due to slightly different error messages, + output formatting, failure to set the timezone correctly for your + platform, etc. "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.3 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.2.1, and that previous versions of <ProductName>Postgres</ProductName> have been + in use successfully for some time now. +</Para> + +<Para> + After running the tests, type +<ProgramListing> + destroydb regression + cd /usr/src/pgsql/src/test/regress + gmake clean +</ProgramListing> +</Para> +</Step> + +<Step Performance="required"> +<Para> + + Stop the postmaster as described in step 7. Then restore the + timezone to it's normal setting. If you changed the timezone by + modifying environment variable TZ then one way to do this is to + log out of, then back into, account postgres. +</Para> +</Step> + +<Step Performance="required"> +<Para> + + Start the postmaster daemon running. Type +<ProgramListing> + cd + nohup postmaster > server.log 2>&1 & +</ProgramListing> + Run postmaster from your <ProductName>Postgres</ProductName> super user account (typically + account postgres). DO NOT RUN POSTMASTER FROM THE ROOT ACCOUNT. +</Para> +</Step> + +<Step Performance="required"> +<Para> + If you haven't already done so, this would be a good time to modify + your computer so that it will automatically start postmaster whenever + you boot your computer. + + Here are some suggestions on how to do this, contributed by various + users. + + Whatever you do, postmaster must be run by user postgres AND NOT BY + ROOT. This is why all of the examples below start by switching user + (su) to postgres. These commands also take into account the fact + that environment variables like PATH and PGDATA may not be set properly. + + The examples are as follows. Use them with extreme caution. + + a) Edit file rc.local on NetBSD or file rc2.d on SPARC Solaris + 2.5.1 to contain the following single line: + su postgres -c "/usr/local/pgsql/bin/postmaster -S -D + /usr/local/pgsql/data" + + b) In FreeBSD 2.2-RELEASE edit /usr/local/etc/rc.d/pgsql.sh to + contain the following lines and make it chmod 755 and chown + root:bin. + #!/bin/sh + [ -x /usr/local/pgsql/bin/postmaster ] && { + su -l pgsql -c 'exec /usr/local/pgsql/bin/postmaster + -D/usr/local/pgsql/data + -S -o -F > /usr/local/pgsql/errlog' & + echo -n ' pgsql' + } + You may put the line breaks as shown above. The shell is smart + enough to keep parsing beyond end-of-line if there is an + expression unfinished. The exec saves one layer of shell under + the postmaster process so the parent is init. Note: Unlike most + other examples, this one has been tested. + + c) In RedHat v4.0 Linux edit file /etc/inittab to contain the + following single line: + pg:2345:respawn:/bin/su - postgres -c + "/usr/local/pgsql/bin/postmaster -D/usr/local/pgsql/data + >> /usr/local/pgsql/server.log 2>&1" /dev/null + (The author of this example says this example will revive the + postmaster if it dies, but he doesn't know if there are other side + effects.) + + d) The contrib/linux area of the <ProductName>Postgres</ProductName> distribution has an example + init.d script compatible with and tested using recent RedHat packages. +</Para> +</Step> + +<Step Performance="required"> +<Para> + If you haven't already done so, this would be a good time to modify + your computer to do regular maintainence. The following should be + done at regular intervals: + + a) Run the SQL command vacuum. This will clean up your database. + b) Back up your system. (You should probably keep the last few + backups on hand.) Ideally, no one else should be using the + system at the time. + + Ideally, the above tasks should be done by a shell script that is + run nightly or weekly by cron. Look at the man page for crontab + for a starting point on how to do this. (If you do it, please + e-mail us a copy of your shell script. We would like to set up + our own systems to do this too.) +</Para> +</Step> + +<Step Performance="required"> +<Para> + If you are upgrading an existing system then install your old database. + Type +<ProgramListing> + cd + psql -e template1 < db.out +</ProgramListing> + + If your pre-v6.2 database uses either path or polygon geometric data types, + then you will need to upgrade any columns containing those types. To + do so, type (from within psql) +<ProgramListing> + update YourTable set PathCol = UpgradePath(PathCol); + update YourTable set PolyCol = UpgradePoly(PolyCol); + ... + vacuum; +</ProgramListing> + + UpgradePath() checks to see that a path value is consistant with the + old syntax, and will not update a column which fails that examination. + UpgradePoly() cannot verify that a polygon is in fact from an old + syntax, but RevertPoly() is provided to reverse the effects of a + mis-applied upgrade. +</Para> +</Step> + +<Step Performance="required"> +<Para> + If you are a new user, you may wish to play with <ProductName>Postgres</ProductName> as described + below. +</Para> +</Step> + +<Step Performance="required"> +<Para> + Clean up after yourself. Type +<ProgramListing> + rm -rf /usr/src/pgsql_6_0 + rm -rf /usr/local/pgsql_6_0 + # Also delete old database directory tree if it is not in + # /usr/local/pgsql_6_0/data + rm ~/postgresql-v6.2.1.tar.gz +</ProgramListing> +</Para> +</Step> + +<Step Performance="required"> +<Para> + You will probably want to print out the documentation. Here is how + you might do it if you have Ghostscript on your system and are + writing to a laserjet printer. + alias gshp='gs -sDEVICE=laserjet -r300 -dNOPAUSE' + export GS_LIB=/usr/share/ghostscript:/usr/share/ghostscript/fonts + # Print out the man pages. + man -a -t /usr/local/pgsql/man/*/* > manpage.ps + gshp -sOUTPUTFILE=manpage.hp manpage.ps + rm manpage.ps + lpr -l -s -r manpage.hp + # Print out the Postgres95 User Manual, version 1.0, + # Sept. 5, 1996. + cd /usr/src/pgsql/doc + gshp -sOUTPUTFILE=userguide.hp userguide.ps + lpr -l -s -r userguide.hp + + If you are a developer, you will probably want to also print out + the Postgres Implemention Guide, version 1.0, October 1, 1995. + This is a WWW document located at + http://www.postgresql.org/docs/impguide. +</Para> +</Step> + +<Step Performance="required"> +<Para> + The <ProductName>Postgres</ProductName> team wants to keep <ProductName>Postgres</ProductName> working on all of the + supported platforms. We therefore ask you to let us know if you did + or did not get <ProductName>Postgres</ProductName> to work on you system. Please send a + mail message to pgsql-ports@postgresql.org telling us the following: + - The version of <ProductName>Postgres</ProductName> (v6.2.1, 6.1.1, beta 970703, etc.). + - Your operating system (i.e. RedHat v4.0 Linux v2.0.26). + - Your hardware (SPARC, i486, etc.). + - Did you compile, install and run the regression tests cleanly? + If not, what source code did you change (i.e. patches you + applied, changes you made, etc.), what tests failed, etc. + It is normal to get many warning when you compile. You do + not need to report these. +</Para> +</Step> + +<Step Performance="required"> +<Para> + Now create, access and manipulate databases as desired. Write client + programs to access the database server. In other words, ENJOY! +</Para> +</Step> +</Procedure> + +<Sect1> +<Title>Playing with <ProductName>Postgres</ProductName></Title> + +<Para> +After <ProductName>Postgres</ProductName> is installed, a database system is created, a postmaster +daemon is running, and the regression tests have passed, you'll want to +see <ProductName>Postgres</ProductName> do something. That's easy. Invoke the interactive interface +to <ProductName>Postgres</ProductName>, <Application>psql</Application>: + +<ProgramListing> + % psql template1 +</ProgramListing> + +(psql has to open a particular database, but at this point the only one +that exists is the template1 database, which always exists. We will connect +to it only long enough to create another one and switch to it.) +</Para> + +<Para> +The response from psql is: + +<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 + +template1=> +</ProgramListing> +</Para> + +<Para> +Create the database foo: + +<ProgramListing> +template1=> create database foo; +CREATEDB +</ProgramListing> + +(Get in the habit of including those SQL semicolons. Psql won't execute +anything until it sees the semicolon or a "\g" and the semicolon is required +to delimit multiple statements.) +</Para> + +<Para> +Now connect to the new database: + +<ProgramListing> +template1=> \c foo +connecting to new database: foo +</ProgramListing> + +("slash" commands aren't SQL, so no semicolon. Use \? to see all the slash commands.) +</Para> + +<Para> +And create a table: + +<ProgramListing> +foo=> create table bar (i int4, c char(16)); +CREATE +</ProgramListing> +</Para> + +<Para> +Then inspect the new table: + +<ProgramListing> +foo=> \d bar + +Table = bar ++----------------------------------+----------------------------------+-------+ +| Field | Type | Length| ++----------------------------------+----------------------------------+-------+ +| i | int4 | 4 | +| c | (bp)char | 16 | ++----------------------------------+----------------------------------+-------+ +</ProgramListing> +</Para> + +<Para> +And so on. You get the idea. +</Para> +</Sect1> + +<Sect1> +<Title>The Next Step</Title> + +<Para> +Questions? Bugs? Feedback? +First, read the files in directory /usr/src/pgsql/doc. The FAQ in +this directory may be particularly useful. +</Para> + +<Para> +If <ProductName>Postgres</ProductName> failed to compile on your computer then fill out the form +in file /usr/src/pgsql/doc/bug.template and mail it to the location +indicated at the top of the form. +</Para> + +<Para> +Mail questions to +<ULink url="pgsql-questions@postgresql.org">pgsql-questions@postgresql.org</ULink>. +For more information on the various mailing lists, see +<ULink url="http://www.postgresql.org">http://www.postgresql.org</ULink> +and look for the mailing lists. +</Para> +</Sect1> + +<Sect1> +<Title>Porting Notes</Title> + +<Note> +<Para> +For some ports, these notes may be out of date. +</Para> +</Note> + +<Sect2> +<Title>Ultrix4.x</Title> + +<Para> + You need to install the libdl-1.1 package since Ultrix 4.x doesn't + have a dynamic loader. It's available in + s2k-ftp.CS.Berkeley.EDU:pub/personal/andrew/libdl-1.1.tar.Z +</Para> +</Sect2> + +<Sect2> +<Title>Linux</Title> + +<Sect3> +<Sect3Info> +<Author> +<FirstName>Thomas G.</FirstName> +<SurName>Lockhart</SurName> +</Author> +<Date>1998-02-19</Date> +</Sect3Info> +<Title>Linux ELF</Title> + +<Para> +The regression test reference machine is +a linux-2.0.30/libc-5.3.12/RedHat-4.2 installation running on a dual processor i686. +The linux-elf port installs cleanly. See the Linux FAQ for more details. +</Para> +</Sect3> + +<Sect3> +<Sect3Info> +<Date>1995-05-11</Date> +</Sect3Info> +<Title>Linux a.out</Title> + +<Para> + For non-ELF Linux, the dld library MUST be obtained and installed on + the system. It enables dynamic link loading capability to the <ProductName>Postgres</ProductName> + port. The dld library can be obtained from the sunsite linux + distributions. The current name is dld-3.2.5. +<ULink url="sneaker@powergrid.electriciti.com">Jalon Q. Zimmerman</ULink> +</Para> +</Sect3> +</Sect2> + +<Sect2> +<Title>BSD/OS</Title> + +<Para> + For BSD/OS 2.0 and 2.01, you will need to get the GNU dld library. +</Para> +</Sect2> + +<Sect2> +<Title>NeXT</Title> + +<Para> + The NeXT port for v1.09 was supplied by +<ULink url="mailto:tom@basil.icce.rug.nl">Tom R. Hageman</ULink>. + It requires a SysV IPC emulation library and header files for + shared libary and semaphore stuff. Tom just happens to sell such + a product so contact him for information. He has also indicated that + binary releases of <ProductName>Postgres</ProductName> for NEXTSTEP will be made available to + the general public. Contact Info@RnA.nl for information. + +<Para> +We have no recent reports of successful NeXT installations (for v6.2.1). +However, the client-side libraries should work even +if the backend is not supported. +</Para> +</Sect2> +</Sect1> + +</Chapter> diff --git a/doc/src/sgml/intro-pg.sgml b/doc/src/sgml/intro-pg.sgml new file mode 100644 index 0000000000000000000000000000000000000000..1f9cd52f56abc7a5d679bbff7fca725af99d43f5 --- /dev/null +++ b/doc/src/sgml/intro-pg.sgml @@ -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> diff --git a/doc/src/sgml/intro.sgml b/doc/src/sgml/intro.sgml new file mode 100644 index 0000000000000000000000000000000000000000..09a6ad3b02b42e8b0087b28a179ac3f5a31ed42e --- /dev/null +++ b/doc/src/sgml/intro.sgml @@ -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> diff --git a/doc/src/sgml/jdbc.sgml b/doc/src/sgml/jdbc.sgml new file mode 100644 index 0000000000000000000000000000000000000000..3b7279762dfa99faf014e0709f4f1340f35c7a0f --- /dev/null +++ b/doc/src/sgml/jdbc.sgml @@ -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> diff --git a/doc/src/sgml/libpgtcl.sgml b/doc/src/sgml/libpgtcl.sgml new file mode 100644 index 0000000000000000000000000000000000000000..5e51f07ce8f7cf3951187d93e3034c8ec9e2d701 --- /dev/null +++ b/doc/src/sgml/libpgtcl.sgml @@ -0,0 +1,1641 @@ +<Chapter> +<Title>pgtcl</Title> + +<Para> +pgtcl is a tcl package for front-end programs to interface with <ProductName>Postgres</ProductName> +backends. pgtcl does not use the libpq library but communicates to +the backend directly via the frontend-backend protocol. Thus, it is +more efficient than previous postgres->tcl bindings which are layered +on top of libpq. In addition, pgtcl can handle multiple backend +connections from a single frontend application. +</Para> + +<Para> +This package was originally written by Jolly Chen. +</Para> + +<Sect1> +<Title>Commands</Title> + +<Para> +The pg_lo* routines are interfaces to the Inversion Large Objects in <ProductName>Postgres</ProductName>. +The functions are designed to mimic the analogous file system functions in +the standard Unix file system interface. +</Para> + +<Para> +<TABLE TOCENTRY="1"> +<TITLE>PGTCL Commands</TITLE> +<TGROUP COLS="2"> +<THEAD> + <ROW> + <ENTRY>Command</ENTRY> + <ENTRY>Description</ENTRY> + </ROW> +</THEAD> +<TBODY> + <ROW> + <ENTRY>pg_connect</ENTRY> + <ENTRY>opens a connection to the backend server</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_disconnect</ENTRY> + <ENTRY>closes a connection</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_exec</ENTRY> + <ENTRY>send a query to the backend</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_select</ENTRY> + <ENTRY>loop over the result of a select statement</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_result</ENTRY> + <ENTRY>manipulate the results of a query</ENTRY> + </ROW> + + <ROW> + <ENTRY>pg_lo_creat</ENTRY> + <ENTRY>create a large object</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_lo_open</ENTRY> + <ENTRY>open a large object</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_lo_close</ENTRY> + <ENTRY>close a large object</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_lo_read</ENTRY> + <ENTRY>read a large object</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_lo_write</ENTRY> + <ENTRY>write a large object</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_lo_lseek</ENTRY> + <ENTRY>seek to a position on a large object</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_lo_tell</ENTRY> + <ENTRY>return the current seek position of a large object</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_lo_unlink</ENTRY> + <ENTRY>delete a large object</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_lo_import</ENTRY> + <ENTRY>import a Unix file into a large object</ENTRY> + </ROW> + <ROW> + <ENTRY>pg_lo_export</ENTRY> + <ENTRY>export a large object into a Unix file</ENTRY> + </ROW> +</TBODY> +</TGROUP> +</TABLE> +</Para> + +<Para> +Some commands equivalent to libpq commands are provided for connection +and query operations. +</Para> + +<Para> +The pg_lo* routines should typically be used within a BEGIN/END transaction +block because the file descriptor returned by pg_lo_open is only valid for +the current transaction. pg_lo_import and pg_lo_export MUST be used +in a BEGIN/END transaction block. +</Para> + +</Sect1> + +<Sect1> +<Title>Examples</Title> + +<Para> +Here's a small example of how to use the routines: + +<ProgramListing> +# getDBs : +# get the names of all the databases at a given host and port number +# with the defaults being the localhost and port 5432 +# return them in alphabetical order +proc getDBs { {host "localhost"} {port "5432"} } { + # datnames is the list to be result + set conn [pg_connect template1 -host $host -port $port] + set res [pg_exec $conn "SELECT datname FROM pg_database ORDER BY datname"] + set ntups [pg_result $res -numTuples] + for {set i 0} {$i < $ntups} {incr i} { + lappend datnames [pg_result $res -getTuple $i] + } + pg_disconnect $conn + return $datnames +} +</ProgramListing> + +</Para> +</Sect1> + +<Sect1> +<Title>Reference Information</Title> + +<REFENTRY ID="PGTCL-PGCONNECT-1"> +<REFMETA> +<REFENTRYTITLE>pg_connect</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_connect +</REFNAME> +<REFPURPOSE>opens a connection to the backend server +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGCONNECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGCONNECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_connect <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE> <OPTIONAL>-host <REPLACEABLE CLASS="PARAMETER">hostName</REPLACEABLE></OPTIONAL> + <OPTIONAL>-port <REPLACEABLE CLASS="PARAMETER">portNumber</REPLACEABLE></OPTIONAL> <OPTIONAL>-tty <REPLACEABLE CLASS="PARAMETER">pqtty</REPLACEABLE></OPTIONAL> <OPTIONAL>-options <REPLACEABLE CLASS="PARAMETER">optionalBackendArgs</REPLACEABLE></OPTIONAL> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGCONNECT-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database name. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <OPTIONAL>-host <REPLACEABLE CLASS="PARAMETER">hostName</REPLACEABLE></OPTIONAL> +</TERM> +<LISTITEM> +<PARA>Specifies the domain name of the backend server for <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE>. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <OPTIONAL>-port <REPLACEABLE CLASS="PARAMETER">portNumber</REPLACEABLE></OPTIONAL> +</TERM> +<LISTITEM> +<PARA>Specifies the IP port number of the backend server for <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE>. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <OPTIONAL>-tty <REPLACEABLE CLASS="PARAMETER">pqtty</REPLACEABLE></OPTIONAL> +</TERM> +<LISTITEM> +<PARA>(need information thomas 1997-12-24) +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <OPTIONAL>-options <REPLACEABLE CLASS="PARAMETER">optionalBackendArgs</REPLACEABLE></OPTIONAL> +</TERM> +<LISTITEM> +<PARA>Specifies options for the backend server for <REPLACEABLE CLASS="PARAMETER">dbName</REPLACEABLE>. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGCONNECT-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +The return result is either an error message or a handle for a database + connection. Handles start with the prefix "pgp" +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<!-- ********************************************************** --> + +<REFSECT1 ID="R1-PGTCL-PGCONNECT-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_connect</FUNCTION> opens a connection to the <ProductName>Postgres</ProductName> backend. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGCONNECT-2"> +<TITLE>Usage +</TITLE> +<PARA>XXX thomas 1997-12-24 +</PARA> +</REFSECT1> +</REFENTRY> + +<REFENTRY ID="PGTCL-PGDISCONNECT-1"> +<REFMETA> +<REFENTRYTITLE>pg_disconnect</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_disconnect +</REFNAME> +<REFPURPOSE>closes a connection to the backend server +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGDISCONNECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGDISCONNECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_disconnect <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGDISCONNECT-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database handle. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGDISCONNECT-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + None +</TERM> +<LISTITEM> +<PARA> +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGDISCONNECT-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_disconnect</FUNCTION> closes a connection to the <ProductName>Postgres</ProductName> backend. +</PARA> +</REFSECT1> + +</REFENTRY> + +<REFENTRY ID="PGTCL-PGEXEC-1"> +<REFMETA> +<REFENTRYTITLE>pg_exec</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_exec +</REFNAME> +<REFPURPOSE> +send a query string to the backend +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGEXEC-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGEXEC-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_exec <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE> +</SYNOPSIS> + +<!-- ********************************************************** --> + +<REFSECT2 ID="R2-PGTCL-PGEXEC-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database handle. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid SQL query. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGEXEC-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> + the return result is either an error message or a handle for a query result. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2></REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGEXEC-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>pg_exec</FUNCTION> submits a query to the <ProductName>Postgres</ProductName> backend and returns a result. + Handles start with the prefix "pgp". +</PARA> +</REFSECT1> + +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGSELECT-1"> +<REFMETA> +<REFENTRYTITLE>pg_select</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_select +</REFNAME> +<REFPURPOSE> +loop over the result of a select statement +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGSELECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGSELECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_select <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE> + <REPLACEABLE CLASS="PARAMETER">arrayVar</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">queryProcedure</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGSELECT-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">dbHandle</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database handle. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid SQL select query. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">arrayVar</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Array variable for tuples returned. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">queryProcedure</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Procedure run on each tuple found. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> + +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGSELECT-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> + the return result is either an error message or a handle for a query result. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2></REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGSELECT-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>pg_select</FUNCTION> submits a query to the <ProductName>Postgres</ProductName> backend. + and returns the results. + The <REPLACEABLE CLASS="PARAMETER">queryString</REPLACEABLE> + must be a select statement. Anything else returns an error. + The <REPLACEABLE CLASS="PARAMETER">arrayVar</REPLACEABLE> + variable is an array name used in the loop. It is filled + out with the result of the query for each tuple using the field + names as the associative indices. +</PARA> +</REFSECT1> + +<REFSECT1 ID="R1-PGTCL-PGSELECT-2"> +<TITLE>Usage +</TITLE> +<PARA> +<ProgramListing> + set DB "mydb" + set conn [pg_connect $DB] + pg_select $conn "SELECT * from table" array { + puts [format "%5d %s" array(control) array(name)] + } + pg_disconnect $conn +</ProgramListing> +</PARA> +</REFSECT1> + +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGRESULT-1"> +<REFMETA> +<REFENTRYTITLE>pg_result</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Connection Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_result +</REFNAME> +<REFPURPOSE> +get information about a query result +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGRESULT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGRESULT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_result <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">resultOption</REPLACEABLE> +</SYNOPSIS> +<REFSECT2 ID="R2-PGTCL-PGRESULT-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> + The handle for a query result. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">resultOption</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Specifies one of several possible options. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> + +<REFSECT3> +<TITLE>Options</TITLE> + +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +-status +</TERM> +<LISTITEM> +<PARA> +the status of the result. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +-oid +</TERM> +<LISTITEM> +<PARA> +if the last query was an insert, returns the oid of the +inserted tuple +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +-conn +</TERM> +<LISTITEM> +<PARA> +the connection that produced the result +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +-assign arrayName +</TERM> +<LISTITEM> +<PARA> +assign the results to an array +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +-numTuples +</TERM> +<LISTITEM> +<PARA> +the number of tuples in the query +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +-attributes +</TERM> +<LISTITEM> +<PARA> +returns a list of the name/type pairs of the tuple attributes +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +-getTuple tupleNumber +</TERM> +<LISTITEM> +<PARA> +returns the values of the tuple in a list +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +-clear +</TERM> +<LISTITEM> +<PARA> +clear the result buffer. Do not reuse after this +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT3> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGRESULT-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">queryHandle</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> + the return result is either an error message or a handle for a query result. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2></REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGRESULT-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>pg_result</FUNCTION> returns information about a query. +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOCREAT-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_creat</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_creat +</REFNAME> +<REFPURPOSE>create a large object +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOCREAT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>creating</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOCREAT-2"><PRIMARY>pg_lo_creat</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_creat <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">mode</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOCREAT-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">mode</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies the access mode for the large object</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOCREAT-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">objOid</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +The oid of the large object created. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOCREAT-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_creat</FUNCTION> creates an Inversion Large Object. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOCREAT-2"> +<TITLE>Usage +</TITLE> +<PARA> +mode can be any OR'ing together of INV_READ, INV_WRITE, and INV_ARCHIVE. +The OR delimiter character is "|". +<ProgramListing> +[pg_lo_creat $conn "INV_READ|INV_WRITE"] +</ProgramListing> +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOOPEN-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_open</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_open +</REFNAME> +<REFPURPOSE>open a large object +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOOPEN-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>opening</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOOPEN-2"><PRIMARY>pg_lo_open</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_open <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">objOid</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">mode</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOOPEN-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">objOid</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid large object oid. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">mode</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies the access mode for the large object</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOOPEN-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +A file descriptor for use in later pg_lo* routines. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOOPEN-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_open</FUNCTION> open an Inversion Large Object. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOOPEN-2"> +<TITLE>Usage +</TITLE> +<PARA> +Mode can be either "r", "w", or "rw". +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOCLOSE-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_close</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_close +</REFNAME> +<REFPURPOSE>close a large object +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOCLOSE-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>closing</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOCLOSE-2"><PRIMARY>pg_lo_close</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_close <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOCLOSE-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +A file descriptor for use in later pg_lo* routines. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOCLOSE-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<PARA>None</PARA> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOCLOSE-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_close</FUNCTION> closes an Inversion Large Object. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOCLOSE-2"> +<TITLE>Usage +</TITLE> +<PARA> +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOREAD-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_read</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_read +</REFNAME> +<REFPURPOSE>read a large object +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOREAD-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>reading</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOREAD-2"><PRIMARY>pg_lo_read</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_read <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">bufVar</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOREAD-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +File descriptor for the large object from pg_lo_open. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">bufVar</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid buffer variable to contain the large object segment. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies the maximum allowable size of the large object segment.</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOREAD-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<PARA>None</PARA> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOREAD-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_read</FUNCTION> reads +at most <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE> bytes from a large object into a variable + named <REPLACEABLE CLASS="PARAMETER">bufVar</REPLACEABLE>. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOREAD-2"> +<TITLE>Usage +</TITLE> +<PARA> +<REPLACEABLE CLASS="PARAMETER">bufVar</REPLACEABLE> must be a valid variable name. +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOWRITE-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_write</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_write +</REFNAME> +<REFPURPOSE>write a large object +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOWRITE-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>writing</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOWRITE-2"><PRIMARY>pg_lo_write</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_write <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">buf</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOWRITE-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +File descriptor for the large object from pg_lo_open. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">buf</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid string variable to write to the large object. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies the maximum size of the string to write.</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOWRITE-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<PARA>None</PARA> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOWRITE-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_write</FUNCTION> writes +at most <REPLACEABLE CLASS="PARAMETER">len</REPLACEABLE> bytes to a large object from a variable + <REPLACEABLE CLASS="PARAMETER">buf</REPLACEABLE>. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOWRITE-2"> +<TITLE>Usage +</TITLE> +<PARA> +<REPLACEABLE CLASS="PARAMETER">buf</REPLACEABLE> must be +the actual string to write, not a variable name. +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOLSEEK-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_lseek</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_lseek +</REFNAME> +<REFPURPOSE>seek to a position on a large object +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOLSEEK-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>positioning</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOLSEEK-2"><PRIMARY>pg_lo_lseek</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_lseek <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">whence</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOLSEEK-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +File descriptor for the large object from pg_lo_open. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a zero-based offset in bytes. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">whence</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> whence can be "SEEK_CUR", "SEEK_END", or "SEEK_SET" </PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOLSEEK-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<PARA>None</PARA> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOLSEEK-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_lseek</FUNCTION> positions +to <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE> bytes from the beginning of the large object. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOLSEEK-2"> +<TITLE>Usage +</TITLE> +<PARA> +<REPLACEABLE CLASS="PARAMETER">whence</REPLACEABLE> +can be "SEEK_CUR", "SEEK_END", or "SEEK_SET". +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOTELL-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_tell</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_tell +</REFNAME> +<REFPURPOSE>return the current seek position of a large object +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOTELL-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>positioning</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOTELL-2"><PRIMARY>pg_lo_tell</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_tell <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOTELL-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">fd</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +File descriptor for the large object from pg_lo_open. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOTELL-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>A zero-based offset in bytes suitable for input to <Function>pg_lo_lseek</Function>. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOTELL-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_tell</FUNCTION> returns the current +to <REPLACEABLE CLASS="PARAMETER">offset</REPLACEABLE> in bytes from the beginning of the large object. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOTELL-2"> +<TITLE>Usage +</TITLE> +<PARA> +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOUNLINK-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_unlink</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_unlink +</REFNAME> +<REFPURPOSE>delete a large object +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOUNLINK-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>delete</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOUNLINK-2"><PRIMARY>pg_lo_unlink</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_unlink <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">lobjId</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOUNLINK-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">lobjId</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Identifier for a large object. +XXX Is this the same as objOid in other calls?? - thomas 1998-01-11 +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOUNLINK-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<PARA> +None +</PARA> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOUNLINK-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_unlink</FUNCTION> deletes the specified large object. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOUNLINK-2"> +<TITLE>Usage +</TITLE> +<PARA> +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOIMPORT-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_import</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_import +</REFNAME> +<REFPURPOSE>import a large object from a Unix file +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOIMPORT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>import</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOIMPORT-2"><PRIMARY>pg_lo_import</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_import <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">filename</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOIMPORT-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">filename</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Unix file name. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOIMPORT-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<PARA> +None +XXX Does this return a lobjId? Is that the same as the objOid in other calls? thomas - 1998-01-11 +</PARA> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOIMPORT-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_import</FUNCTION> reads the specified file and places the contents into a large object. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOIMPORT-2"> +<TITLE>Usage +</TITLE> +<PARA> + <Function>pg_lo_import</Function> must be called within a BEGIN/END transaction block. +</PARA> +</REFSECT1> +</REFENTRY> + +<!-- ********************************************************** --> + +<REFENTRY ID="PGTCL-PGLOEXPORT-1"> +<REFMETA> +<REFENTRYTITLE>pg_lo_export</REFENTRYTITLE> +<REFMISCINFO>PGTCL - Large Objects</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>pg_lo_export +</REFNAME> +<REFPURPOSE>export a large object to a Unix file +</REFPURPOSE> +<INDEXTERM ID="IX-PGTCL-PGLOEXPORT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>export</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-PGTCL-PGLOEXPORT-2"><PRIMARY>pg_lo_export</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +pg_lo_export <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">lobjId</REPLACEABLE> <REPLACEABLE CLASS="PARAMETER">filename</REPLACEABLE> +</SYNOPSIS> + +<REFSECT2 ID="R2-PGTCL-PGLOEXPORT-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">conn</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA>Specifies a valid database connection. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">lobjId</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Large object identifier. +XXX Is this the same as the objOid in other calls?? thomas - 1998-01-11 +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> + <REPLACEABLE CLASS="PARAMETER">filename</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Unix file name. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-PGTCL-PGLOEXPORT-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<PARA> +None +XXX Does this return a lobjId? Is that the same as the objOid in other calls? thomas - 1998-01-11 +</PARA> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-PGTCL-PGLOEXPORT-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA><FUNCTION>pg_lo_export</FUNCTION> writes the specified large object into a Unix file. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-PGTCL-PGLOEXPORT-2"> +<TITLE>Usage +</TITLE> +<PARA> + <Function>pg_lo_export</Function> must be called within a BEGIN/END transaction block. +</PARA> +</REFSECT1> +</REFENTRY> + +</Sect1> +</Chapter> diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml new file mode 100644 index 0000000000000000000000000000000000000000..a01c4726607a8a3c7e4f9e76dd464824ea3c7f31 --- /dev/null +++ b/doc/src/sgml/libpq.sgml @@ -0,0 +1,1099 @@ +<Chapter> +<Title><FileName>libpq</FileName></Title> + +<Para> + <FileName>libpq</FileName> is the application programming interface to <ProductName>Postgres</ProductName>. + <FileName>libpq</FileName> is a set of library routines which allows + client programs to pass queries to the <ProductName>Postgres</ProductName> backend + server and to receive the results of these queries. + This version of the documentation describes the <Acronym>C</Acronym> + interface library. Three short programs are included + at the end of this section to show how to write programs that use <FileName>libpq</FileName>. + There are several examples of <FileName>libpq</FileName> applications in the + following directories: + +<ProgramListing> +../src/test/regress + ../src/test/examples + ../src/bin/psql +</ProgramListing> + +<Para> + Frontend programs which use <FileName>libpq</FileName> must include the + header file <FileName>libpq-fe.h</FileName> and must link with the <FileName>libpq</FileName> + library. +</Para> + +<Sect1> +<Title>Control and Initialization</Title> + +<Para> + The following environment variables can be used to set + up default environment values to avoid hard-coding + database names into an application program: + +<ItemizedList> +<ListItem> +<Para> +<Acronym>PGHOST</Acronym> sets the default server name. +</Para> +</ListItem> +<ListItem> +<Para> +<Acronym>PGOPTIONS</Acronym> sets additional runtime options for the <ProductName>Postgres</ProductName> backend. +</Para> +</ListItem> +<ListItem> +<Para> +<Acronym>PGPORT</Acronym> sets the default port for communicating with the <ProductName>Postgres</ProductName> backend. +</Para> +</ListItem> +<ListItem> +<Para> +<Acronym>PGTTY</Acronym> sets the file or tty on which debugging messages from the backend server are displayed. +</Para> +</ListItem> +<ListItem> +<Para> +<Acronym>PGDATABASE</Acronym> sets the default <ProductName>Postgres</ProductName> database name. +</Para> +</ListItem> +<ListItem> +<Para> +<Acronym>PGREALM</Acronym> sets the Kerberos realm to use with <ProductName>Postgres</ProductName>, + if it is different from the local realm. If +<Acronym>PGREALM</Acronym> is set, <ProductName>Postgres</ProductName> applications will attempt + authentication with servers for this realm and use + separate ticket files to avoid conflicts with local + ticket files. This environment variable is only + used if Kerberos authentication is enabled. +</Para> +</ListItem> +</ItemizedList> +</Para> +</Sect1> + +<Sect1> +<Title>Database Connection Functions</Title> + +<Para> + The following routines deal with making a connection to + a backend from a <Acronym>C</Acronym> program. +<ItemizedList> +<ListItem> +<Para> +<Function>PQsetdb</Function> + Makes a new connection to a backend. +<ProgramListing> +PGconn *PQsetdb(char *pghost, + char *pgport, + char *pgoptions, + char *pgtty, + char *dbName); +</ProgramListing> + If any argument is NULL, then the corresponding + environment variable is checked. If the environment variable is also not set, then hardwired + defaults are used. + PQsetdb always returns a valid PGconn pointer. + The PQstatus (see below) command should be called + to ensure that a connection was properly made + before queries are sent via the connection. <FileName>libpq</FileName> + programmers should be careful to maintain the + PGconn abstraction. Use the accessor functions + below to get at the contents of PGconn. Avoid + directly referencing the fields of the PGconn + structure as they are subject to change in the + future. +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQdb</Function> + Returns the database name of the connection. +<ProgramListing> +char *PQdb(PGconn *conn) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQhost</Function> + Returns the host name of the connection. +<ProgramListing> +char *PQhost(PGconn *conn) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQoptions</Function> + Returns the pgoptions used in the connection. +<ProgramListing> +char *PQoptions(PGconn *conn) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQport</Function> + Returns the pgport of the connection. +<ProgramListing> +char *PQport(PGconn *conn) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQtty</Function> + Returns the pgtty of the connection. +<ProgramListing> +char *PQtty(PGconn *conn) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQstatus</Function> + Returns the status of the connection. + The status can be CONNECTION_OK or CONNECTION_BAD. +<ProgramListing> +ConnStatusType *PQstatus(PGconn *conn) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQerrorMessage</Function> + Returns the error message associated with the connection +<ProgramListing> +char *PQerrorMessage(PGconn* conn); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQfinish</Function> + Close the connection to the backend. Also frees + memory used by the PGconn structure. The PGconn + pointer should not be used after PQfinish has been + called. +<ProgramListing> +void PQfinish(PGconn *conn) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQreset</Function> + Reset the communication port with the backend. + This function will close the IPC socket connection + to the backend and attempt to reestablish a new + connection to the same backend. +<ProgramListing> +void PQreset(PGconn *conn) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQtrace</Function> + Enables tracing of messages passed between the + frontend and the backend. The messages are echoed + to the debug_port file stream. +<ProgramListing> +void PQtrace(PGconn *conn, + FILE* debug_port); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQuntrace</Function> + Disables tracing of messages passed between the + frontend and the backend. +<ProgramListing> +void PQuntrace(PGconn *conn); +</ProgramListing> +</Para> +</ListItem> +</ItemizedList> +</Para> +</Sect1> + +<Sect1> +<Title>Query Execution Functions</Title> + +<Para> +<ItemizedList> +<ListItem> +<Para> +<Function>PQexec</Function> + Submit a query to <ProductName>Postgres</ProductName>. Returns a PGresult + pointer if the query was successful or a NULL otherwise. If a NULL is returned, PQerrorMessage can + be used to get more information about the error. +<ProgramListing> +PGresult *PQexec(PGconn *conn, + char *query); +</ProgramListing> + The <Function>PGresult</Function> structure encapsulates the query + result returned by the backend. <Function>libpq</Function> programmers + should be careful to maintain the PGresult + abstraction. Use the accessor functions described + below to retrieve the results of the query. Avoid + directly referencing the fields of the PGresult + structure as they are subject to change in the + future. +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQresultStatus</Function> + Returns the result status of the query. PQresultStatus can return one of the following values: +<ProgramListing> +PGRES_EMPTY_QUERY, +PGRES_COMMAND_OK, /* the query was a command */ +PGRES_TUPLES_OK, /* the query successfully returned tuples */ +PGRES_COPY_OUT, +PGRES_COPY_IN, +PGRES_BAD_RESPONSE, /* an unexpected response was received */ +PGRES_NONFATAL_ERROR, +PGRES_FATAL_ERROR +</ProgramListing> + If the result status is PGRES_TUPLES_OK, then the + following routines can be used to retrieve the + tuples returned by the query. +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQntuples</Function> returns the number of tuples (instances) + in the query result. +<ProgramListing> +int PQntuples(PGresult *res); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQnfields</Function> + Returns the number of fields + (attributes) in the query result. +<ProgramListing> +int PQnfields(PGresult *res); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQfname</Function> + Returns the field (attribute) name associated with the given field index. Field indices + start at 0. +<ProgramListing> +char *PQfname(PGresult *res, + int field_index); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQfnumber</Function> + Returns the field (attribute) index + associated with the given field name. +<ProgramListing> +int PQfnumber(PGresult *res, + char* field_name); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQftype</Function> + Returns the field type associated with the + given field index. The integer returned is an + internal coding of the type. Field indices start + at 0. +<ProgramListing> +Oid PQftype(PGresult *res, + int field_num); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQfsize</Function> + Returns the size in bytes of the field + associated with the given field index. If the size + returned is -1, the field is a variable length + field. Field indices start at 0. +<ProgramListing> +int2 PQfsize(PGresult *res, + int field_index); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQgetvalue</Function> + Returns the field (attribute) value. + For most queries, the value returned by PQgetvalue + is a null-terminated ASCII string representation + of the attribute value. If the query was a result + of a <Acronym>BINARY</Acronym> cursor, then the value returned by + PQgetvalue is the binary representation of the + type in the internal format of the backend server. + It is the programmer's responsibility to cast and + convert the data to the correct C type. The value + returned by PQgetvalue points to storage that is + part of the PGresult structure. One must explicitly + copy the value into other storage if it is to + be used past the lifetime of the PGresult structure itself. +<ProgramListing> +char* PQgetvalue(PGresult *res, + int tup_num, + int field_num); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQgetlength</Function> + Returns the length of a field + (attribute) in bytes. If the field is a struct + varlena, the length returned here does not include + the size field of the varlena, i.e., it is 4 bytes + less. +<ProgramListing> +int PQgetlength(PGresult *res, + int tup_num, + int field_num); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQcmdStatus</Function> + Returns the command status associated with the + last query command. +<ProgramListing> +char *PQcmdStatus(PGresult *res); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQoidStatus</Function> + Returns a string with the object id of the tuple + inserted if the last query is an INSERT command. + Otherwise, returns an empty string. +<ProgramListing> +char* PQoidStatus(PGresult *res); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQprintTuples</Function> + Prints out all the tuples and, optionally, the + attribute names to the specified output stream. + The programs psql and monitor both use PQprintTuples for output. +<ProgramListing> +void PQprintTuples( + PGresult* res, + FILE* fout, /* output stream */ + int printAttName,/* print attribute names or not*/ + int terseOutput, /* delimiter bars or not?*/ + int width /* width of column, variable width if 0*/ + ); +</ProgramListing> +</Para> +</ListItem> +<ListItem> +<Para> +<Function>PQclear</Function> + Frees the storage associated with the PGresult. + Every query result should be properly freed when + it is no longer used. Failure to do this will + result in memory leaks in the frontend application. +<ProgramListing> +void PQclear(PQresult *res); +</ProgramListing> +</Para> +</ListItem> +</ItemizedList> +</Para> +</Sect1> + +<Sect1> +<Title>Fast Path</Title> + +<Para> +<ItemizedList> +<ListItem> +<Para> +<ProductName>Postgres</ProductName> provides a fast path interface to send function + calls to the backend. This is a trapdoor into + system internals and can be a potential security hole. + Most users will not need this feature. +<ProgramListing> +PGresult* PQfn(PGconn* conn, + int fnid, + int *result_buf, + int *result_len, + int result_is_int, + PQArgBlock *args, + int nargs); +</ProgramListing> + The fnid argument is the object identifier of the function to be executed. result_buf is the buffer in which + to load the return value. The caller must have allocated sufficient space to store the return value. The + result length will be returned in the storage pointed + to by result_len. If the result is to be an integer + value, than result_is_int should be set to 1; otherwise + it should be set to 0. args and nargs specify the + arguments to the function. +<ProgramListing> +typedef struct { + int len; + int isint; + union { + int *ptr; + int integer; + } u; + } PQArgBlock; +</ProgramListing> + PQfn always returns a valid PGresult*. The resultStatus should be checked before the result is used. The + caller is responsible for freeing the PGresult with + PQclear when it is not longer needed. +</Para> +</ListItem> +</ItemizedList> +</Para> + +</Sect1> + +<Sect1> +<Title>Asynchronous Notification</Title> + +<Para> + <ProductName>Postgres</ProductName> supports asynchronous notification via the + LISTEN and NOTIFY commands. A backend registers its + interest in a particular relation with the LISTEN command. All backends listening on a particular relation + will be notified asynchronously when a NOTIFY of that + relation name is executed by another backend. No + additional information is passed from the notifier to + the listener. Thus, typically, any actual data that + needs to be communicated is transferred through the + relation. + <FileName>libpq</FileName> applications are notified whenever a connected + backend has received an asynchronous notification. + However, the communication from the backend to the + frontend is not asynchronous. Notification comes + piggy-backed on other query results. Thus, an application must submit queries, even empty ones, in order to + receive notice of backend notification. In effect, the + <FileName>libpq</FileName> application must poll the backend to see if there + is any pending notification information. After the + execution of a query, a frontend may call PQNotifies to + see if any notification data is available from the + backend. +</Para> + +<Para> +<ItemizedList> +<ListItem> +<Para> +<Function>PQNotifies</Function> + returns the notification from a list of unhandled + notifications from the backend. Returns NULL if + there are no pending notifications from the backend. PQNotifies behaves like the popping of a + stack. Once a notification is returned from PQnotifies, it is considered handled and will be + removed from the list of notifications. +<ProgramListing> +PGnotify* PQNotifies(PGconn *conn); +</ProgramListing> + The second sample program gives an example of the use + of asynchronous notification. +</Para> +</ListItem> +</ItemizedList> +</Para> + +</Sect1> + +<Sect1> +<Title>Functions Associated with the COPY Command</Title> + +<Para> + The copy command in <ProductName>Postgres</ProductName> has options to read from + or write to the network connection used by <FileName>libpq</FileName>. + Therefore, functions are necessary to access this network connection directly so applications may take full + advantage of this capability. +</Para> + +<Para> +<ItemizedList> +<ListItem> +<Para> +<Function>PQgetline</Function> + Reads a newline-terminated line of characters + (transmitted by the backend server) into a buffer + string of size length. Like fgets(3), this routine copies up to length-1 characters into string. + It is like gets(3), however, in that it converts + the terminating newline into a null character. + PQgetline returns EOF at EOF, 0 if the entire line + has been read, and 1 if the buffer is full but the + terminating newline has not yet been read. + Notice that the application must check to see if a + new line consists of the single character ".", + which indicates that the backend server has finished sending the results of the copy command. + Therefore, if the application ever expects to + receive lines that are more than length-1 characters long, the application must be sure to check + the return value of PQgetline very carefully. + The code in +<FileName> +../src/bin/psql/psql.c +</FileName> + contains routines that correctly handle the copy + protocol. +<ProgramListing> +int PQgetline(PGconn *conn, + char *string, + int length) +</ProgramListing> +</Para> +</ListItem> +<ListItem> +<Para> +<Function>PQputline</Function> + Sends a null-terminated string to the backend + server. + The application must explicitly send the single + character "." to indicate to the backend that it + has finished sending its data. +<ProgramListing> +void PQputline(PGconn *conn, + char *string); +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQendcopy</Function> + Syncs with the backend. This function waits until + the backend has finished the copy. It should + either be issued when the last string has been + sent to the backend using PQputline or when the + last string has been received from the backend + using PGgetline. It must be issued or the backend + may get "out of sync" with the frontend. Upon + return from this function, the backend is ready to + receive the next query. + The return value is 0 on successful completion, + nonzero otherwise. +<ProgramListing> +int PQendcopy(PGconn *conn); +</ProgramListing> +<ProgramListing> +PQexec(conn, "create table foo (a int4, b char16, d float8)"); +PQexec(conn, "copy foo from stdin"); +PQputline(conn, "3<TAB>hello world<TAB>4.5\n"); +PQputline(conn,"4<TAB>goodbye world<TAB>7.11\n"); +... +PQputline(conn,".\n"); +PQendcopy(conn); +</ProgramListing> +</Para> +</ListItem> +</ItemizedList> +</Para> +</Sect1> + +<Sect1> +<Title><FileName>libpq</FileName> Tracing Functions</Title> + +<Para> +<ItemizedList> +<ListItem> +<Para> +<Function>PQtrace</Function> + Enable tracing of the frontend/backend communication to a debugging file stream. +<ProgramListing> +void PQtrace(PGconn *conn + FILE *debug_port) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>PQuntrace</Function> + Disable tracing started by PQtrace +<ProgramListing> +void PQuntrace(PGconn *conn) +</ProgramListing> +</Para> +</ListItem> +</ItemizedList> +</Para> + +</Sect1> + +<Sect1> +<Title>User Authentication Functions</Title> + +<Para> + If the user has generated the appropriate authentication credentials + (e.g., obtaining <Acronym>Kerberos</Acronym> tickets), + the frontend/backend authentication process is handled + by <Function>PQexec</Function> without any further intervention. + The following routines may be called by <FileName>libpq</FileName> programs to tailor the behavior of the authentication process. +</Para> + +<Para> +<ItemizedList> +<ListItem> +<Para> +<Function>fe_getauthname</Function> + Returns a pointer to static space containing whatever name the user has authenticated. Use of this + routine in place of calls to getenv(3) or getpwuid(3) by applications is highly recommended, as + it is entirely possible that the authenticated + user name is not the same as value of the <Acronym>USER</Acronym> + environment variable or the user's entry in + <FileName>/etc/passwd</FileName>. +<ProgramListing> +char *fe_getauthname(char* errorMessage) +</ProgramListing> +</Para> +</ListItem> + +<ListItem> +<Para> +<Function>fe_setauthsvc</Function> + Specifies that <FileName>libpq</FileName> should use authentication + service name rather than its compiled-in default. + This value is typically taken from a command-line + switch. +<ProgramListing> +void fe_setauthsvc(char *name, + char* errorMessage) +</ProgramListing> + Any error messages from the authentication + attempts are returned in the errorMessage argument. +</Para> +</ListItem> +</ItemizedList> +</Para> + +</Sect1> + +<Sect1> +<Title>BUGS</Title> + +<Para> + The query buffer is 8192 bytes long, and queries over + that length will be silently truncated. +</Para> +</Sect1> + +<Sect1> +<Title>Sample Programs</Title> + +<Sect2> +<Title>Sample Program 1</Title> + +<Para> +<ProgramListing> + /* + * testlibpq.c + * Test the C version of LIBPQ, the <ProductName>Postgres</ProductName> frontend library. + * + * + */ + #include <stdio.h> + #include "libpq-fe.h" + + void + exit_nicely(PGconn* conn) + { + PQfinish(conn); + exit(1); + } + + main() + { + char *pghost, *pgport, *pgoptions, *pgtty; + char* dbName; + int nFields; + int i,j; + + /* FILE *debug; */ + + PGconn* conn; + PGresult* res; + + /* begin, by setting the parameters for a backend connection + if the parameters are null, then the system will try to use + reasonable defaults by looking up environment variables + or, failing that, using hardwired constants */ + pghost = NULL; /* host name of the backend server */ + pgport = NULL; /* port of the backend server */ + pgoptions = NULL; /* special options to start up the backend server */ + pgtty = NULL; /* debugging tty for the backend server */ + dbName = "template1"; + + /* make a connection to the database */ + conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName); + + /* check to see that the backend connection was successfully made */ + if (PQstatus(conn) == CONNECTION_BAD) { + fprintf(stderr,"Connection to database '%s' failed.0, dbName); + fprintf(stderr,"%s",PQerrorMessage(conn)); + exit_nicely(conn); + } + + /* debug = fopen("/tmp/trace.out","w"); */ + /* PQtrace(conn, debug); */ + + /* start a transaction block */ + + res = PQexec(conn,"BEGIN"); + if (PQresultStatus(res) != PGRES_COMMAND_OK) { + fprintf(stderr,"BEGIN command failed0); + PQclear(res); + exit_nicely(conn); + } + /* should PQclear PGresult whenever it is no longer needed to avoid + memory leaks */ + PQclear(res); + + /* fetch instances from the pg_database, the system catalog of databases*/ + res = PQexec(conn,"DECLARE myportal CURSOR FOR select * from pg_database"); + if (PQresultStatus(res) != PGRES_COMMAND_OK) { + fprintf(stderr,"DECLARE CURSOR command failed0); + PQclear(res); + exit_nicely(conn); + } + PQclear(res); + + res = PQexec(conn,"FETCH ALL in myportal"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) { + fprintf(stderr,"FETCH ALL command didn't return tuples properly0); + PQclear(res); + exit_nicely(conn); + } + + /* first, print out the attribute names */ + nFields = PQnfields(res); + for (i=0; i < nFields; i++) { + printf("%-15s",PQfname(res,i)); + } + printf("0); + + /* next, print out the instances */ + for (i=0; i < PQntuples(res); i++) { + for (j=0 ; j < nFields; j++) { + printf("%-15s", PQgetvalue(res,i,j)); + } + printf("0); + } + + PQclear(res); + + /* close the portal */ + res = PQexec(conn, "CLOSE myportal"); + PQclear(res); + + /* end the transaction */ + res = PQexec(conn, "END"); + PQclear(res); + + /* close the connection to the database and cleanup */ + PQfinish(conn); + + /* fclose(debug); */ + } +</ProgramListing> +</Para> +</Sect2> + +<Sect2> +<Title>Sample Program 2</Title> + +<Para> +<ProgramListing> + /* + * testlibpq2.c + * Test of the asynchronous notification interface + * + populate a database with the following: + + CREATE TABLE TBL1 (i int4); + + CREATE TABLE TBL2 (i int4); + + CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2]; + + * Then start up this program + * After the program has begun, do + + INSERT INTO TBL1 values (10); + + * + * + */ + #include <stdio.h> + #include "libpq-fe.h" + + void exit_nicely(PGconn* conn) + { + PQfinish(conn); + exit(1); + } + + main() + { + char *pghost, *pgport, *pgoptions, *pgtty; + char* dbName; + int nFields; + int i,j; + + PGconn* conn; + PGresult* res; + PGnotify* notify; + + /* begin, by setting the parameters for a backend connection + if the parameters are null, then the system will try to use + reasonable defaults by looking up environment variables + or, failing that, using hardwired constants */ + pghost = NULL; /* host name of the backend server */ + pgport = NULL; /* port of the backend server */ + pgoptions = NULL; /* special options to start up the backend server */ + pgtty = NULL; /* debugging tty for the backend server */ + dbName = getenv("USER"); /* change this to the name of your test database*/ + + /* make a connection to the database */ + conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName); + + /* check to see that the backend connection was successfully made */ + if (PQstatus(conn) == CONNECTION_BAD) { + fprintf(stderr,"Connection to database '%s' failed.0, dbName); + fprintf(stderr,"%s",PQerrorMessage(conn)); + exit_nicely(conn); + } + + res = PQexec(conn, "LISTEN TBL2"); + if (PQresultStatus(res) != PGRES_COMMAND_OK) { + fprintf(stderr,"LISTEN command failed0); + PQclear(res); + exit_nicely(conn); + } + /* should PQclear PGresult whenever it is no longer needed to avoid + memory leaks */ + PQclear(res); + + while (1) { + /* async notification only come back as a result of a query*/ + /* we can send empty queries */ + res = PQexec(conn, " "); + /* printf("res->status = %s0, pgresStatus[PQresultStatus(res)]); */ + /* check for asynchronous returns */ + notify = PQnotifies(conn); + if (notify) { + fprintf(stderr, + "ASYNC NOTIFY of '%s' from backend pid '%d' received0, + notify->relname, notify->be_pid); + free(notify); + break; + } + PQclear(res); + } + + /* close the connection to the database and cleanup */ + PQfinish(conn); + + } +</ProgramListing> +</Para> +</Sect2> + +<Sect2> +<Title>Sample Program 3</Title> + +<Para> +<ProgramListing> + /* + * testlibpq3.c + * Test the C version of LIBPQ, the <ProductName>Postgres</ProductName> frontend library. + * tests the binary cursor interface + * + * + * + populate a database by doing the following: + + CREATE TABLE test1 (i int4, d float4, p polygon); + + INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon); + + INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon); + + the expected output is: + + tuple 0: got + i = (4 bytes) 1, + d = (4 bytes) 3.567000, + p = (4 bytes) 2 points boundbox = (hi=3.000000/4.000000, lo = 1.000000,2.000000) + tuple 1: got + i = (4 bytes) 2, + d = (4 bytes) 89.050003, + p = (4 bytes) 2 points boundbox = (hi=4.000000/3.000000, lo = 2.000000,1.000000) + + * + */ + #include <stdio.h> + #include "libpq-fe.h" + #include "utils/geo-decls.h" /* for the POLYGON type */ + + void exit_nicely(PGconn* conn) + { + PQfinish(conn); + exit(1); + } + + main() + { + char *pghost, *pgport, *pgoptions, *pgtty; + char* dbName; + int nFields; + int i,j; + int i_fnum, d_fnum, p_fnum; + + PGconn* conn; + PGresult* res; + + /* begin, by setting the parameters for a backend connection + if the parameters are null, then the system will try to use + reasonable defaults by looking up environment variables + or, failing that, using hardwired constants */ + pghost = NULL; /* host name of the backend server */ + pgport = NULL; /* port of the backend server */ + pgoptions = NULL; /* special options to start up the backend server */ + pgtty = NULL; /* debugging tty for the backend server */ + + dbName = getenv("USER"); /* change this to the name of your test database*/ + + /* make a connection to the database */ + conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName); + + /* check to see that the backend connection was successfully made */ + if (PQstatus(conn) == CONNECTION_BAD) { + fprintf(stderr,"Connection to database '%s' failed.0, dbName); + fprintf(stderr,"%s",PQerrorMessage(conn)); + exit_nicely(conn); + } + + /* start a transaction block */ + res = PQexec(conn,"BEGIN"); + if (PQresultStatus(res) != PGRES_COMMAND_OK) { + fprintf(stderr,"BEGIN command failed0); + PQclear(res); + exit_nicely(conn); + } + /* should PQclear PGresult whenever it is no longer needed to avoid + memory leaks */ + PQclear(res); + + /* fetch instances from the pg_database, the system catalog of databases*/ + res = PQexec(conn,"DECLARE mycursor BINARY CURSOR FOR select * from test1"); + if (PQresultStatus(res) != PGRES_COMMAND_OK) { + fprintf(stderr,"DECLARE CURSOR command failed0); + PQclear(res); + exit_nicely(conn); + } + PQclear(res); + + res = PQexec(conn,"FETCH ALL in mycursor"); + if (PQresultStatus(res) != PGRES_TUPLES_OK) { + fprintf(stderr,"FETCH ALL command didn't return tuples properly0); + PQclear(res); + exit_nicely(conn); + } + + i_fnum = PQfnumber(res,"i"); + d_fnum = PQfnumber(res,"d"); + p_fnum = PQfnumber(res,"p"); + + for (i=0;i<3;i++) { + printf("type[%d] = %d, size[%d] = %d0, + i, PQftype(res,i), + i, PQfsize(res,i)); + } + for (i=0; i < PQntuples(res); i++) { + int *ival; + float *dval; + int plen; + POLYGON* pval; + /*/ + ival = (int*)PQgetvalue(res,i,i_fnum); + dval = (float*)PQgetvalue(res,i,d_fnum); + plen = PQgetlength(res,i,p_fnum); + + /* plen doesn't include the length field so need to increment by VARHDSZ*/ + pval = (POLYGON*) malloc(plen + VARHDRSZ); + pval->size = plen; + memmove((char*)&pval->npts, PQgetvalue(res,i,p_fnum), plen); + printf("tuple %d: got0, i); + printf(" i = (%d bytes) %d,0, + PQgetlength(res,i,i_fnum), *ival); + printf(" d = (%d bytes) %f,0, + PQgetlength(res,i,d_fnum), *dval); + printf(" p = (%d bytes) %d points boundbox = (hi=%f/%f, lo = %f,%f)0, + PQgetlength(res,i,d_fnum), + pval->npts, + pval->boundbox.xh, + pval->boundbox.yh, + pval->boundbox.xl, + pval->boundbox.yl); + } + + PQclear(res); + + /* close the portal */ + res = PQexec(conn, "CLOSE mycursor"); + PQclear(res); + + /* end the transaction */ + res = PQexec(conn, "END"); + PQclear(res); + + /* close the connection to the database and cleanup */ + PQfinish(conn); + + } +</ProgramListing> +<Para> + +</Sect2> +</Sect1> +</Chapter> diff --git a/doc/src/sgml/lobj.sgml b/doc/src/sgml/lobj.sgml new file mode 100644 index 0000000000000000000000000000000000000000..8462de950728982b8286b7fede908764cd665272 --- /dev/null +++ b/doc/src/sgml/lobj.sgml @@ -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> diff --git a/doc/src/sgml/manage.sgml b/doc/src/sgml/manage.sgml new file mode 100644 index 0000000000000000000000000000000000000000..332dc2459da98e9eb62795ec7fff5b6f846470e0 --- /dev/null +++ b/doc/src/sgml/manage.sgml @@ -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> diff --git a/doc/src/sgml/odbc.sgml b/doc/src/sgml/odbc.sgml new file mode 100644 index 0000000000000000000000000000000000000000..cb75579b6b6b1bfe88f40c459b7513db05400a50 --- /dev/null +++ b/doc/src/sgml/odbc.sgml @@ -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> diff --git a/doc/src/sgml/pgaccess.sgml b/doc/src/sgml/pgaccess.sgml new file mode 100644 index 0000000000000000000000000000000000000000..9404e71b4e1cae52d083b399c509b7500c4674ac --- /dev/null +++ b/doc/src/sgml/pgaccess.sgml @@ -0,0 +1,8 @@ +<Chapter> +<Title><Command>pgaccess</Command></Title> + +<Para> +This section needs to be written. Volunteers? +</Para> + +</Chapter> diff --git a/doc/src/sgml/ports.sgml b/doc/src/sgml/ports.sgml new file mode 100644 index 0000000000000000000000000000000000000000..0ee18b543fe2f8dac5c674b9265202f094db984c --- /dev/null +++ b/doc/src/sgml/ports.sgml @@ -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> diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml new file mode 100644 index 0000000000000000000000000000000000000000..897de1be1bdc058a02a91b09347d8de346a4604a --- /dev/null +++ b/doc/src/sgml/postgres.sgml @@ -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> + diff --git a/doc/src/sgml/programmer.sgml b/doc/src/sgml/programmer.sgml new file mode 100644 index 0000000000000000000000000000000000000000..3c73484e077b787a22f1a32bf275a307824c0cb2 --- /dev/null +++ b/doc/src/sgml/programmer.sgml @@ -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> + diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml new file mode 100644 index 0000000000000000000000000000000000000000..af5acc1e0f7533f55e7117ad3e20c606b3fe4f3a --- /dev/null +++ b/doc/src/sgml/protocol.sgml @@ -0,0 +1,1509 @@ +<Chapter> +<DocInfo> +<Author> +<FirstName>Phil</FirstName> +<Surname>Thompson</Surname> +</Author> +<Date>1998-02-02</Date> +</DocInfo> +<Title>Frontend/Backend Protocol</Title> + +<Para> +<Note> +<Para> +Written by <ULink url="mailto:phil@river-bank.demon.co.uk">Phil Thompson</ULink> +</Para> +</Note> + +<Para> +<ProductName>Postgres</ProductName> uses a message-based protocol for communication between frontends +and backends. The protocol is implemented over <Acronym>TCP/IP</Acronym> and also on Unix sockets. +<ProductName>Postgres</ProductName> v6.3 introduced version numbers into the protocol. +This was done in such +a way as to still allow connections from earlier versions of frontends, but +this document does not cover the protocol used by those earlier versions. + +<Para> +This document describes the initial version-numbered protocol, designated v1.0. +Higher level features built on this protocol (for example, how <FileName>libpq</FileName> passes +certain environment variables after the connection is established) +are covered elsewhere. + +<Sect1> +<Title>Overview</Title> + +<Para> +The three major components are the frontend (running on the client) and the +postmaster and backend (running on the server). The postmaster and backend +have different roles but may be implemented by the same executable. + +<Para> +A frontend sends a startup packet to the postmaster. This includes the names +of the user and the database the user wants to connect to. The postmaster then +uses this, and the information in the pg_hba.conf(5) file to determine what +further authentication information it requires the frontend to send (if any) +and responds to the frontend accordingly. + +<Para> +The frontend then sends any required authentication information. Once the +postmaster validates this it responds to the frontend that it is authenticated +and hands over to a backend. + +<Para> +Subsequent communications are query and result packets exchanged between the +frontend and the backend. The postmaster takes no further part in the +communication. + +<Para> +When the frontend wishes to disconnect it sends an appropriate packet and +closes the connection without waiting for a response for the backend. + +<Para> +Packets are sent as a data stream. The first byte determines what should be +expected in the rest of the packet. The exception is packets send from a +frontend to the postmaster, which comprise a packet length then the packet +itself. The difference is historical. + +<Sect1> +<Title>Protocol</Title> + +<Para> +This section describes the message flow. There are four different types of +flows depending on the state of the connection: + authentication, query, function call, and termination. + +<Sect2> +<Title>Authentication</Title> + +<Para> +The frontend sends a StartupPacket. The postmaster uses this and the contents +of the pg_hba.conf(5) file to determine what authentication method the frontend +must use. The postmaster then responds with one of the following messages: + +<Para> +<VariableList> +<VarListEntry> +<Term> + ErrorResponse +</Term> +<ListItem> +<Para> + The postmaster then immediately closes the connection. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + AuthenticationOk +</Term> +<ListItem> +<Para> + The postmaster then hands over to the backend. The postmaster + takes no further part in the communication. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + AuthenticationKerberosV4 +</Term> +<ListItem> +<Para> + The frontend must then take part in a Kerberos V4 + authentication dialog (not described here) with the postmaster. + If this is successful, the postmaster responds with an + AuthenticationOk, otherwise it responds with an ErrorResponse. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + AuthenticationKerberosV5 +</Term> +<ListItem> +<Para> + The frontend must then take part in a Kerberos V5 + authentication dialog (not described here) with the postmaster. + If this is successful, the postmaster responds with an + AuthenticationOk, otherwise it responds with an ErrorResponse. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + AuthenticationUnencryptedPassword +</Term> +<ListItem> +<Para> + The frontend must then send an UnencryptedPasswordPacket. + If this is the correct password, the postmaster responds with + an AuthenticationOk, otherwise it responds with an + ErrorResponse. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + AuthenticationEncryptedPassword +</Term> +<ListItem> +<Para> + The frontend must then send an EncryptedPasswordPacket. + If this is the correct password, the postmaster responds with + an AuthenticationOk, otherwise it responds with an + ErrorResponse. +</Para> +</ListItem> +</VarListEntry> +</VariableList> +</Para> + +<Para> +If the frontend does not support the authentication method requested by the +postmaster, then it should immediately close the connection. + +<Sect2> +<Title>Query</Title> + +<Para> +The frontend sends a Query message to the backend. The response sent by the +backend depends on the contents of the query. The possible responses are as +follows. + +<Para> +<VariableList> +<VarListEntry> +<Term> + CompletedResponse +</Term> +<ListItem> +<Para> + The query completed normally. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + CopyInResponse +</Term> +<ListItem> +<Para> + The backend is ready to copy data from the frontend to a + relation. The frontend should then send a CopyDataRows + message. The backend will then respond with a + CompletedResponse message with a tag of "COPY". +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + CopyOutResponse +</Term> +<ListItem> +<Para> + The backend is ready to copy data from a relation to the + frontend. It then sends a CopyDataRows message, and then a + CompletedResponse message with a tag of "COPY". +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + CursorResponse +</Term> +<ListItem> +<Para> + The query was either an insert(l), delete(l), update(l), + fetch(l) or a select(l) command. + If the transaction has been + aborted then the backend sends a CompletedResponse message with + a tag of "*ABORT STATE*". Otherwise the following responses + are sent. +</Para> +<Para> + For an insert(l) command, the backend then sends a + CompletedResponse message with a tag of "INSERT <Replaceable>oid</Replaceable> <Replaceable>rows</Replaceable>" + where <Replaceable>rows</Replaceable> is the number of rows inserted, and <Replaceable>oid</Replaceable> is the + object ID of the inserted row if <Replaceable>rows</Replaceable> is 1, otherwise <Replaceable>oid</Replaceable> + is 0. +</Para> +<Para> + For a delete(l) command, the backend then sends a + CompletedResponse message with a tag of "DELETE <Replaceable>rows</Replaceable>" where + <Replaceable>rows</Replaceable> is the number of rows deleted. +</Para> +<Para> + For an update(l) command, the backend then sends a + CompletedResponse message with a tag of "UPDATE <Replaceable>rows</Replaceable>" where + <Replaceable>rows</Replaceable> is the number of rows deleted. +</Para> +<Para> + For a fetch(l) or select(l) command, the backend sends a + RowDescription message. This is then followed by an AsciiRow + or BinaryRow message (depending on if a binary cursor was + specified) for each row being returned to the frontend. + Finally, the backend sends a CompletedResponse message with a + tag of "SELECT". +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + EmptyQueryResponse +</Term> +<ListItem> +<Para> + The query was empty. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + ErrorResponse +</Term> +<ListItem> +<Para> + An error has occurred. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + NoticeResponse +</Term> +<ListItem> +<Para> + A warning message has been issued in relation to the query. + Notices are in addition to other responses, ie. the backend + will send another response message immediately afterwards. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + NotificationResponse +</Term> +<ListItem> +<Para> + A notify(l) command has been executed for a relation for + which a previous listen(l) command was executed. Notifications + are in addition to other responses, ie. the backend will send + another response message immediately afterwards. +</Para> +</ListItem> +</VarListEntry> +</VariableList> +</Para> + +<Para> +A frontend must be prepared to accept ErrorResponse and NoticeResponse +messages whenever it is expecting any other type of message. + +<Sect2> +<Title>Function Call</Title> + +<Para> +The frontend sends a FunctionCall message to the backend. The response sent by +the backend depends on the result of the function call. The possible responses +are as follows. + +<Para> +<VariableList> +<VarListEntry> +<Term> + ErrorResponse +</Term> +<ListItem> +<Para> + An error has occurred. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + FunctionResultResponse +</Term> +<ListItem> +<Para> + The function call was executed and returned a result. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + FunctionVoidResponse +</Term> +<ListItem> +<Para> + The function call was executed and returned no result. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + NoticeResponse +</Term> +<ListItem> +<Para> + A warning message has been issued in relation to the function + call. Notices are in addition to other responses, ie. the + backend will send another response message immediately + afterwards. +</Para> +</ListItem> +</VarListEntry> +</VariableList> +</Para> + +<Para> +A frontend must be prepared to accept ErrorResponse and NoticeResponse +messages whenever it is expecting any other type of message. + +<Sect2> +<Title>Termination</Title> + +<Para> +The frontend sends a Terminate message and immediately closes the connection. +On receipt of the message, the backend immediately closes the connection and +terminates. + + +<Sect1> +<Title>Message Data Types</Title> + +<Para> +This section describes the base data types used in messages. + +<Para> +<VariableList> +<VarListEntry> +<Term> + Int<Replaceable>n</Replaceable>(<Replaceable>i</Replaceable>) +</Term> +<ListItem> +<Para> + An <Replaceable>n</Replaceable> bit integer in network byte order. + If <Replaceable>i</Replaceable> is specified it + is the literal value. Eg. Int16, Int32(42). +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + LimString<Replaceable>n</Replaceable>(<Replaceable>s</Replaceable>) +</Term> +<ListItem> +<Para> + A character array of exactly <Replaceable>n</Replaceable> bytes interpreted as a '\0' + terminated string. The '\0' is omitted if there is + insufficient room. If <Replaceable>s</Replaceable> is specified it is the literal value. + Eg. LimString32, LimString64("user"). +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String(<Replaceable>s</Replaceable>) +</Term> +<ListItem> +<Para> + A conventional C '\0' terminated string with no length + limitation. A frontend should always read the full string + even though it may have to discard characters if it's buffers + aren't big enough. +<Note> +<Para> +Is 8193 bytes the largest allowed size? +</Para> +</Note> + If <Replaceable>s</Replaceable> is specified it is the literal value. + Eg. String, String("user"). +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte<Replaceable>n</Replaceable>(<Replaceable>c</Replaceable>) +</Term> +<ListItem> +<Para> + Exactly <Replaceable>n</Replaceable> bytes. If <Replaceable>c</Replaceable> is specified it is the literal + value. Eg. Byte, Byte1('\n'). +</Para> +</ListItem> +</VarListEntry> +</VariableList> +</Para> + +<Sect1> +<Title>Message Formats</Title> + +<Para> +This section describes the detailed format of each message. Each can be sent +by either a frontend (F), a postmaster/backend (B), or both (F & B). + +<Para> + +<VariableList> +<VarListEntry> +<Term> +AsciiRow (B) +</Term> +<ListItem> +<Para> +<VariableList> +<VarListEntry> +<Term> + Byte1('D') +</Term> +<ListItem> +<Para> + Identifies the message, in the context in which it is sent (see + CopyInResponse), as an <Acronym>ASCII</Acronym> row. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte<Replaceable>n</Replaceable> +</Term> +<ListItem> +<Para> + + A bit map with one bit for each field in the row. The 1st + field corresponds to bit 7 of the 1st byte, the 2nd field + corresponds to bit 6 of the 1st byte, the 8th field corresponds + to bit 0 of the 1st byte, the 9th field corresponds to bit 8 of + the 2nd byte, and so on. The bit is set if the value of the + corresponding field is not NULL. +</Para> +<Para> + Then, for each field, there is the following: +<VariableList> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + Specifies the size of the value of the field, including + this size. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte<Replaceable>n</Replaceable> +</Term> +<ListItem> +<Para> + Specifies the value of the field itself in <Acronym>ASCII</Acronym> + characters. <Replaceable>n</Replaceable> is the above size minus 4. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +AuthenticationOk (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('R') +</Term> +<ListItem> +<Para> + Identifies the message as an authentication request. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32(0) +</Term> +<ListItem> +<Para> + Specifies that the authentication was successful. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +AuthenticationKerberosV4 (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('R') +</Term> +<ListItem> +<Para> + Identifies the message as an authentication request. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32(1) +</Term> +<ListItem> +<Para> + Specifies that Kerberos V4 authentication is required. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +AuthenticationKerberosV5 (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('R') +</Term> +<ListItem> +<Para> + Identifies the message as an authentication request. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32(2) +</Term> +<ListItem> +<Para> + Specifies that Kerberos V5 authentication is required. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +AuthenticationUnencryptedPassword (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('R') +</Term> +<ListItem> +<Para> + Identifies the message as an authentication request. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32(3) +</Term> +<ListItem> +<Para> + Specifies that an unencrypted password is required. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +AuthenticationEncryptedPassword (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('R') +</Term> +<ListItem> +<Para> + Identifies the message as an authentication request. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32(4) +</Term> +<ListItem> +<Para> + Specifies that an encrypted password is required. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte2 +</Term> +<ListItem> +<Para> + The salt to use when encrypting the password. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +BinaryRow (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('B') +</Term> +<ListItem> +<Para> + Identifies the message, in the context in which it is sent (see + CopyOutResponse), as a binary row. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte<Replaceable>n</Replaceable> +</Term> +<ListItem> +<Para> + A bit map with one bit for each field in the row. The 1st + field corresponds to bit 7 of the 1st byte, the 2nd field + corresponds to bit 6 of the 1st byte, the 8th field corresponds + to bit 0 of the 1st byte, the 9th field corresponds to bit 8 of + the 2nd byte, and so on. The bit is set if the value of the + corresponding field is not NULL. +</Para> +<Para> + Then, for each field, there is the following: +<VariableList> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + Specifies the size of the value of the field, excluding + this size. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte<Replaceable>n</Replaceable> +</Term> +<ListItem> +<Para> + Specifies the value of the field itself in binary + format. <Replaceable>n</Replaceable> is the above size. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +CompletedResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('C') +</Term> +<ListItem> +<Para> + Identifies the message as a completed response. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String +</Term> +<ListItem> +<Para> + The command tag. This is usually (but not always) a single + word that identifies which SQL command was completed. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +CopyDataRows (B & F) +</Term> +<ListItem> +<Para> + This is a stream of rows where each row is terminated by a Char1('\n'). + This is then followed by the sequence Char1('\\'), Char1('.'), + Char1('\n'). +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +CopyInResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('D') +</Term> +<ListItem> +<Para> + Identifies the message, in the context in which it is sent (see + AsciiRow), as a copy in started response. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +CopyOutResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('B') +</Term> +<ListItem> +<Para> + Identifies the message, in the context in which it is sent (see + BinaryRow), as a copy out started response. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +CursorResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('P') +</Term> +<ListItem> +<Para> + Identifies the message as a cursor response. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String +</Term> +<ListItem> +<Para> + The name of the cursor. This will be "blank" if the cursor is + implicit. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +EmptyQueryResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('I') +</Term> +<ListItem> +<Para> + Identifies the message as an empty query response. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String("") +</Term> +<ListItem> +<Para> + Unused. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +EncryptedPasswordPacket (F) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + The size of the packet in bytes. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String +</Term> +<ListItem> +<Para> + The encrypted (using crypt()) password. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +ErrorResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('E') +</Term> +<ListItem> +<Para> + Identifies the message as an error. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String +</Term> +<ListItem> +<Para> + The error message itself. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +FunctionCall (F) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('F') +</Term> +<ListItem> +<Para> + Identifies the message as a function call. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String("") +</Term> +<ListItem> +<Para> + Unused. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + Specifies the object ID of the function to call. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + Specifies the number of arguments being supplied to the + function. +</Para> +<Para> + Then, for each argument, there is the following: +<VariableList> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + Specifies the size of the value of the argument, + excluding this size. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte<Replaceable>n</Replaceable> +</Term> +<ListItem> +<Para> + Specifies the value of the field itself in binary + format. <Replaceable>n</Replaceable> is the above size. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +<Para> + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +FunctionResultResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('V') +</Term> +<ListItem> +<Para> + Identifies the message as a function call result. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte1('G') +</Term> +<ListItem> +<Para> + Specifies that an actual result was returned. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + Specifies the size of the value of the result, excluding this + size. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte<Replaceable>n</Replaceable> +</Term> +<ListItem> +<Para> + Specifies the value of the result itself in binary format. + <Replaceable>n</Replaceable> is the above size. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte1('0') +</Term> +<ListItem> +<Para> + Unused. (Strictly speaking, FunctionResultResponse and + FunctionVoidResponse are the same thing but with some optional + parts to the message.) +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +FunctionVoidResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('V') +</Term> +<ListItem> +<Para> + Identifies the message as a function call result. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Byte1('0') +</Term> +<ListItem> +<Para> + Specifies that no actual result was returned. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +NoticeResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('N') +</Term> +<ListItem> +<Para> + Identifies the message as a notice. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String +</Term> +<ListItem> +<Para> + The notice message itself. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +NotificationResponse (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('A') +</Term> +<ListItem> +<Para> + Identifies the message as a notification response. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + The process ID of the backend process. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String +</Term> +<ListItem> +<Para> + The name of the relation that the notify has been raised on. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +Query (F) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('Q') +</Term> +<ListItem> +<Para> + Identifies the message as query. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String +</Term> +<ListItem> +<Para> + The query itself. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +RowDescription (B) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('T') +</Term> +<ListItem> +<Para> + Identifies the message as a row description. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int16 +</Term> +<ListItem> +<Para> + Specifies the number of fields in a row (and may be zero). +</Para> +<Para> + Then, for each field, there is the following: +<VariableList> +<VarListEntry> +<Term> + String +</Term> +<ListItem> +<Para> + Specifies the field name. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + Specifies the object ID of the field type. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int16 +</Term> +<ListItem> +<Para> + Specifies the type size. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +StartupPacket (F) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Int32(296) +</Term> +<ListItem> +<Para> + The size of the packet in bytes. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + The protocol version number. The most significant 16 bits are + the major version number. The least 16 significant bits are + the minor version number. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + LimString64 +</Term> +<ListItem> +<Para> + The database name, defaults to the user name if omitted. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + LimString32 +</Term> +<ListItem> +<Para> + The user name. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + LimString64 +</Term> +<ListItem> +<Para> + Any additional command line arguments to be passed to the + backend by the postmaster. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + LimString64 +</Term> +<ListItem> +<Para> + Unused. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + LimString64 +</Term> +<ListItem> +<Para> + The optional tty the backend should use for debugging messages. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +Terminate (F) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Byte1('X') +</Term> +<ListItem> +<Para> + Identifies the message as a termination. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + + +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> +UnencryptedPasswordPacket (F) +</Term> +<ListItem> +<Para> + +<VariableList> +<VarListEntry> +<Term> + Int32 +</Term> +<ListItem> +<Para> + The size of the packet in bytes. +</Para> +</ListItem> +</VarListEntry> +<VarListEntry> +<Term> + String +</Term> +<ListItem> +<Para> + The unencrypted password. +</Para> +</ListItem> +</VarListEntry> +</VariableList> + +</Para> +</ListItem> +</VarListEntry> +</VariableList> +</Para> + +</Chapter> diff --git a/doc/src/sgml/psql.sgml b/doc/src/sgml/psql.sgml new file mode 100644 index 0000000000000000000000000000000000000000..3019396de7aa3f0647a8e30a02cec1510a7fd4b0 --- /dev/null +++ b/doc/src/sgml/psql.sgml @@ -0,0 +1,8 @@ +<Chapter> +<Title><Command>psql</Command></Title> + +<Para> +This section needs to be written. Volunteers? +</Para> + +</Chapter> diff --git a/doc/src/sgml/query-ug.sgml b/doc/src/sgml/query-ug.sgml new file mode 100644 index 0000000000000000000000000000000000000000..a5fc3463a1536687edf0aa427eeca94319d03a03 --- /dev/null +++ b/doc/src/sgml/query-ug.sgml @@ -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> diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml new file mode 100644 index 0000000000000000000000000000000000000000..df119fd365ad7ab1dfcb0abf35e8d0b5f5225c83 --- /dev/null +++ b/doc/src/sgml/query.sgml @@ -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> diff --git a/doc/src/sgml/recovery.sgml b/doc/src/sgml/recovery.sgml new file mode 100644 index 0000000000000000000000000000000000000000..2eec4e885e420df7cb637fc6528de0401c36fe02 --- /dev/null +++ b/doc/src/sgml/recovery.sgml @@ -0,0 +1,8 @@ +<Chapter> +<Title>Database Recovery</Title> + +<Para> +This section needs to be written. Volunteers? +</Para> + +</Chapter> diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml new file mode 100644 index 0000000000000000000000000000000000000000..f5a8d8a3d5f95becf0b1f562a85f0ae0a8f079e0 --- /dev/null +++ b/doc/src/sgml/regress.sgml @@ -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> diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml new file mode 100644 index 0000000000000000000000000000000000000000..93048018a056c909d4e48df309876403f04a2659 --- /dev/null +++ b/doc/src/sgml/release.sgml @@ -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> + diff --git a/doc/src/sgml/rules.sgml b/doc/src/sgml/rules.sgml new file mode 100644 index 0000000000000000000000000000000000000000..2dabb3ca35a7d5b89a61ced5a6819357a5a2faac --- /dev/null +++ b/doc/src/sgml/rules.sgml @@ -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> diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml new file mode 100644 index 0000000000000000000000000000000000000000..c403f816f876c36e83ac2baa91591aff2275db58 --- /dev/null +++ b/doc/src/sgml/spi.sgml @@ -0,0 +1,2831 @@ +<Chapter> +<DocInfo> +<AuthorGroup> +<Author> +<FirstName>Vadim</FirstName> +<Surname>Mikheev</Surname> +</Author> +</AuthorGroup> +<Date>Transcribed 1998-01-16</Date> +</DocInfo> + +<Title>Server Programming Interface</Title> + +<Para> + The <FirstTerm>Server Programming Interface</FirstTerm> (<Acronym>SPI</Acronym>) is an attempt to give users the +ability to run <Acronym>SQL</Acronym> queries inside user-defined <Acronym>C</Acronym> functions. +Given the lack +of a proper <FirstTerm>Procedural Language</FirstTerm> (<Acronym>PL</Acronym>) in the current version of +<ProductName>Postgres</ProductName>, +<Acronym>SPI</Acronym> is the only way to write server-stored procedures and triggers. In the future +<Acronym>SPI</Acronym> will be used as the "workhorse" for a <Acronym>PL</Acronym>. +</Para> + +<Para> + In fact, <Acronym>SPI</Acronym> is just a set of native interface functions to simplify +access to the Parser, Planner, Optimizer and Executor. <Acronym>SPI</Acronym> also does some +memory management. +</Para> + +<Para> + To avoid misunderstanding we'll use <FirstTerm>function</FirstTerm> to mean <Acronym>SPI</Acronym> interface +functions and <FirstTerm>procedure</FirstTerm> for user-defined C-functions using <Acronym>SPI</Acronym>. +</Para> + +<Para> + <Acronym>SPI</Acronym> procedures are always called by some (upper) Executor and the <Acronym>SPI</Acronym> +manager uses the Executor to run your queries. Other procedures may be +called by the Executor running queries from your procedure. +</Para> + +<Para> + Note, that if during execution of a query from a procedure the transaction +is aborted then control will not be returned to your procedure. Rather, all work +will be rolled back and the server will wait for the next command from the +client. This will be changed in future versions. +</Para> + +<Para> + Other restrictions are the inability to execute BEGIN, END and ABORT +(transaction control statements) and cursor operations. This will also be +changed in the future. +</Para> + +<Para> + If successful, <Acronym>SPI</Acronym> functions return a non-negative result (either via +a returned integer value or in SPI_result global variable, as described below). +On error, a negative or NULL result will be returned. +</Para> + +<Sect1> +<Title>Interface Functions</Title> + +<REFENTRY ID="SPI-SPICONNECT-1"> +<REFMETA> +<REFENTRYTITLE>SPI_connect</REFENTRYTITLE> +<REFMISCINFO>SPI - Connection Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_connect +</REFNAME> +<REFPURPOSE> + Connects your procedure to the SPI manager. +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPICONNECT-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPICONNECT-2"><PRIMARY>SPI_connect</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +int SPI_connect(void) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPICONNECT-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<PARA>None +</PARA> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPICONNECT-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>int +</TERM> +<LISTITEM> +<PARA> +Return status +<VARIABLELIST> +<VARLISTENTRY> +<TERM><ReturnValue>SPI_OK_CONNECT</ReturnValue> +</TERM> +<LISTITEM> +<PARA> + if connected +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM><ReturnValue>SPI_ERROR_CONNECT</ReturnValue> +</TERM> +<LISTITEM> +<PARA> + if not connected +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPICONNECT-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_connect</FUNCTION> opens a connection to the <ProductName>Postgres</ProductName> backend. + You should call this function if you will need to execute queries. Some + utility SPI functions may be called from un-connected procedures. +</PARA> +<PARA> + You may get <ReturnValue>SPI_ERROR_CONNECT</ReturnValue> error if <Function>SPI_connect</Function> is + called from an already connected procedure - e.g. if you directly call one + procedure from another connected one. Actually, while the child procedure + will be able to use SPI, your parent procedure will not be able to continue + to use SPI after the child returns (if <Function>SPI_finish</Function> is called by the child). + It's bad practice. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPICONNECT-2"> +<TITLE>Usage +</TITLE> +<PARA>XXX thomas 1997-12-24 +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPICONNECT-3"> +<TITLE>Algorithm +</TITLE> +<PARA><FUNCTION>SPI_connect</FUNCTION> performs the following: +</PARA> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>• +</TERM> +<LISTITEM> +<PARA> + Initializes the SPI internal + structures for query execution and memory management. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +<PARA> +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPICONNECT-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIFINISH-1"> +<REFMETA> +<REFENTRYTITLE>SPI_finish</REFENTRYTITLE> +<REFMISCINFO>SPI - Connection Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_finish +</REFNAME> +<REFPURPOSE> + Disconnects your procedure from the SPI manager. +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIFINISH-1"><PRIMARY>SPI</PRIMARY><SECONDARY>disconnecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIFINISH-2"><PRIMARY>SPI_finish</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_finish(void) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIFINISH-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<PARA>None +</PARA> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIFINISH-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>int +</TERM> +<LISTITEM> +<PARA> +<SimpleList> +<Member> +<ReturnValue>SPI_OK_FINISH</ReturnValue> + if properly disconnected +</Member> +<Member> +<ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> + if called from an un-connected procedure +</Member> +</SimpleList> +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIFINISH-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_finish</FUNCTION> closes an existing connection to the <ProductName>Postgres</ProductName> backend. + You should call this function after completing operations through the SPI manager. + +<PARA> + You may get the error return <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if <Function>SPI_finish</Function> is + called without having a current valid connection. + There is no fundamental problem + with this; it means that nothing was done by the SPI manager. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIFINISH-2"> +<TITLE>Usage +</TITLE> +<PARA> + <Function>SPI_finish</Function> <Emphasis>must</Emphasis> be called as a final step by a connected procedure + or you may get + unpredictable results! Note that you can safely skip the call to <Function>SPI_finish</Function> + if you abort the transaction (via elog(ERROR)). + +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIFINISH-3"> +<TITLE>Algorithm +</TITLE> +<PARA><FUNCTION>SPI_finish</FUNCTION> performs the following: +</PARA> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>• +</TERM> +<LISTITEM> +<PARA> + Disconnects your procedure from the SPI manager and frees all memory + allocations made by your procedure via <Function>palloc</Function> since + the <Function>SPI_connect</Function>. + These allocations can't be used any more! See Memory management. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +<PARA> +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIFINISH-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIEXEC-1"> +<REFMETA> +<REFENTRYTITLE>SPI_exec</REFENTRYTITLE> +<REFMISCINFO>SPI - Connection Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_exec +</REFNAME> +<REFPURPOSE> + Creates an execution plan (parser+planner+optimizer) and executes a query. +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIEXEC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>executing</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIEXEC-2"><PRIMARY>SPI_exec</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_exec(<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIEXEC-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +char *<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +String containing query plan +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +int <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Maximum number of tuples to return +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIEXEC-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>int +</TERM> +<LISTITEM> +<PARA> +<SimpleList> +<Member> + <ReturnValue>SPI_OK_EXEC</ReturnValue> if properly disconnected +</Member> +<Member> + <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if called from an un-connected procedure +</Member> +<Member> + <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0. +</Member> +<Member> + <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is unconnected. +</Member> +<Member> + <ReturnValue>SPI_ERROR_COPY</ReturnValue> if COPY TO/FROM stdin. +</Member> +<Member> + <ReturnValue>SPI_ERROR_CURSOR</ReturnValue> if DECLARE/CLOSE CURSOR, FETCH. +</Member> +<Member> + <ReturnValue>SPI_ERROR_TRANSACTION</ReturnValue> if BEGIN/ABORT/END. +</Member> +<Member> + <ReturnValue>SPI_ERROR_OPUNKNOWN</ReturnValue> if type of query is unknown (this shouldn't occur). +</Member> +</SimpleList> + +<Para> + If execution of your query was successful then one of the following + (non-negative) values will be returned: +<SimpleList> +<Member> + <ReturnValue>SPI_OK_UTILITY</ReturnValue> if some utility (e.g. CREATE TABLE ...) was executed +</Member> +<Member> + <ReturnValue>SPI_OK_SELECT</ReturnValue> if SELECT (but not SELECT ... INTO!) was executed +</Member> +<Member> + <ReturnValue>SPI_OK_SELINTO</ReturnValue> if SELECT ... INTO was executed +</Member> +<Member> + <ReturnValue>SPI_OK_INSERT</ReturnValue> if INSERT (or INSERT ... SELECT) was executed +</Member> +<Member> + <ReturnValue>SPI_OK_DELETE</ReturnValue> if DELETE was executed +</Member> +<Member> + <ReturnValue>SPI_OK_UPDATE</ReturnValue> if UPDATE was executed +</Member> +</SimpleList> +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIEXEC-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_exec</FUNCTION> creates an execution plan (parser+planner+optimizer) + and executes the query for <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> tuples. + +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIEXEC-2"> +<TITLE>Usage +</TITLE> +<PARA> + This should only be called from a connected procedure. + If <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> is zero then it executes the query for all tuples returned by the + query scan. Using <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> > 0 you may restrict the number of tuples for + which the query will be executed. For example, + +<ProgramListing> +SPI_exec ("insert into table select * from table", 5); +</ProgramListing> + +will allow at most 5 tuples to be inserted into table. + + If execution of your query was successful then a non-negative value will be returned. + +<Note> +<Para> +You may pass many queries in one string or query string may be + re-written by RULEs. <Function>SPI_exec</Function> returns the result for the last query + executed. +</Para> +</Note> + +<Para> + The actual number of tuples for which the (last) query was executed is + returned in the global variable SPI_processed (if not <ReturnValue>SPI_OK_UTILITY</ReturnValue>). + + If <ReturnValue>SPI_OK_SELECT</ReturnValue> returned and SPI_processed > 0 then you may use global + pointer SPITupleTable *SPI_tuptable to access the selected tuples: + + Also NOTE, that <Function>SPI_finish</Function> frees and makes all SPITupleTables + unusable! (See Memory management). +</Para> + +<Para> + <Function>SPI_exec</Function> may return one of the following (negative) values: +<SimpleList> +<Member> + <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0. +</Member> +<Member> + <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is unconnected. +</Member> +<Member> + <ReturnValue>SPI_ERROR_COPY</ReturnValue> if COPY TO/FROM stdin. +</Member> +<Member> + <ReturnValue>SPI_ERROR_CURSOR</ReturnValue> if DECLARE/CLOSE CURSOR, FETCH. +</Member> +<Member> + <ReturnValue>SPI_ERROR_TRANSACTION</ReturnValue> if BEGIN/ABORT/END. +</Member> +<Member> + <ReturnValue>SPI_ERROR_OPUNKNOWN</ReturnValue> if type of query is unknown (this shouldn't occur). +</Member> +</SimpleList> + +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIEXEC-3"> +<TITLE>Algorithm +</TITLE> +<PARA><FUNCTION>SPI_exec</FUNCTION> performs the following: +</PARA> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>• +</TERM> +<LISTITEM> +<PARA> + Disconnects your procedure from the SPI manager and frees all memory + allocations made by your procedure via <Function>palloc</Function> since the <Function>SPI_connect</Function>. + These allocations can't be used any more! See Memory management. +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +<PARA> +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIEXEC-4"> +<TITLE>Structures +</TITLE> +<PARA> + If <ReturnValue>SPI_OK_SELECT</ReturnValue> returned and SPI_processed > 0 then you may use the global + pointer SPITupleTable *SPI_tuptable to access the selected tuples. + +<Para> + Structure SPITupleTable is defined in spi.h: +<ProgramListing> + typedef struct + { + uint32 alloced; /* # of alloced vals */ + uint32 free; /* # of free vals */ + TupleDesc tupdesc; /* tuple descriptor */ + HeapTuple *vals; /* tuples */ + } SPITupleTable; +</ProgramListing> + +<Para> + HeapTuple *vals is an array of pointers to tuples. TupleDesc tupdesc is + a tuple descriptor which you may pass to SPI functions dealing with + tuples. + +<Para> + NOTE! Functions <Function>SPI_exec</Function>, <Function>SPI_execp</Function> and <Function>SPI_prepare</Function> change both + SPI_processed and SPI_tuptable (just the pointer, not the contents of the + structure)! So, save them in local procedure variables if you need them. + +<Para> + Also NOTE, that <Function>SPI_finish</Function> frees and makes all SPITupleTables + unusable! (See Memory management). +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIPREPARE-1"> +<REFMETA> +<REFENTRYTITLE>SPI_prepare</REFENTRYTITLE> +<REFMISCINFO>SPI - Plan Preparation</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_prepare +</REFNAME> +<REFPURPOSE> + Connects your procedure to the SPI manager. +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIPREPARE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIPREPARE-2"><PRIMARY>SPI_prepare</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_prepare(<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">nargs</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">argtypes</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIPREPARE-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Query string +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +<REPLACEABLE CLASS="PARAMETER">nargs</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Number of input parameters ($1 ... $nargs - as in SQL-functions) +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +<REPLACEABLE CLASS="PARAMETER">argtypes</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Pointer list of type <Acronym>OID</Acronym>s to input arguments +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIPREPARE-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>void * +</TERM> +<LISTITEM> +<PARA> +Pointer to an execution plan (parser+planner+optimizer) +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIPREPARE-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_prepare</FUNCTION> + creates and returns an execution plan (parser+planner+optimizer) but doesn't + execute the query. Should only be called from a connected procedure. + +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIPREPARE-2"> +<TITLE>Usage +</TITLE> +<PARA> + nargs is number of parameters ($1 ... $nargs - as in SQL-functions), + and nargs may be 0 only if there is not any $1 in query. + +<Para> + Execution of prepared execution plans is sometimes much faster so this + feature may be useful if the same query will be executed many times. + +<Para> +The plan returned by <Function>SPI_prepare</Function> may be used only in current + invocation of the procedure since <Function>SPI_finish</Function> frees memory allocated for a plan. + See <Function>SPI_saveplan</Function>. + +<Para> + If successful, a non-null pointer will be returned. Otherwise, you'll get + a NULL plan. In both cases SPI_result will be set like the value returned + by SPI_exec, except that it is set to + <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if query is NULL or nargs < 0 or nargs > 0 && argtypes + is NULL. + +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIPREPARE-3"> +<TITLE>Algorithm +</TITLE> +<PARA><FUNCTION>SPI_prepare</FUNCTION> performs the following: +</PARA> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>• +</TERM> +<LISTITEM> +<PARA> +TBD +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +<PARA> +</PARA> +</REFSECT1> +--> +<!-- +<REFSECT1 ID="R1-SPI-SPIPREPARE-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPISAVEPLAN-1"> +<REFMETA> +<REFENTRYTITLE>SPI_saveplan</REFENTRYTITLE> +<REFMISCINFO>SPI - Plan Storage</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_saveplan +</REFNAME> +<REFPURPOSE> + Saves a passed plan +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPISAVEPLAN-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPISAVEPLAN-2"><PRIMARY>SPI_saveplan</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_saveplan(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPISAVEPLAN-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +void *<REPLACEABLE CLASS="PARAMETER">query</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Passed plan +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPISAVEPLAN-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>void * +</TERM> +<LISTITEM> +<PARA> +Execution plan location. NULL if unsuccessful. +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM>SPI_result +</TERM> +<LISTITEM> +<PARA> +<SimpleList> +<Member> + <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if plan is NULL +</Member> +<Member> + <ReturnValue>SPI_ERROR_UNCONNECTED</ReturnValue> if procedure is un-connected +</Member> +</SimpleList> +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPISAVEPLAN-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_saveplan</FUNCTION> + stores a plan prepared by <Function>SPI_prepare</Function> in safe memory + protected from freeing by <Function>SPI_finish</Function> or the transaction manager. + +<Para> + In the current version of <ProductName>Postgres</ProductName> there is no ability to + store prepared plans in the system + catalog and fetch them from there for execution. This will be implemented + in future versions. + + As an alternative, there is the ability to reuse prepared plans in the + consequent invocations of your procedure in the current session. + Use <Function>SPI_execp</Function> to execute this saved plan. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPISAVEPLAN-2"> +<TITLE>Usage +</TITLE> +<Para> + <Function>SPI_saveplan</Function> saves a passed plan (prepared by <Function>SPI_prepare</Function>) in memory + protected from freeing by <Function>SPI_finish</Function> and by the transaction manager and + returns a pointer to the saved plan. You may save the pointer returned in + a local variable. Always check if this pointer is NULL or not either when + preparing a plan or using an already prepared plan in SPI_execp (see below). + +<Note> +<Para> + If one of the objects (a relation, function, etc.) referenced by the prepared + plan is dropped during your session (by your backend or another process) then the + results of <Function>SPI_execp</Function> for this plan will be unpredictable. +</Para> +</Note> + +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPISAVEPLAN-3"> +<TITLE>Algorithm +</TITLE> +<PARA><FUNCTION>SPI_saveplan</FUNCTION> performs the following: +</PARA> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>• +</TERM> +<LISTITEM> +<PARA> +TBD +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +<PARA> +</PARA> +</REFSECT1> +--> +<!-- +<REFSECT1 ID="R1-SPI-SPISAVEPLAN-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIEXECP-1"> +<REFMETA> +<REFENTRYTITLE>SPI_execp</REFENTRYTITLE> +<REFMISCINFO>SPI - Plan Execution</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_execp +</REFNAME> +<REFPURPOSE> + Executes a plan prepared or returned by <Function>SPI_saveplan</Function> +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIEXECP-1"><PRIMARY>SPI</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIEXECP-2"><PRIMARY>SPI_execp</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_execp(<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE>, +<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE>, +<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE>, +<REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIEXECP-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +void *<REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Execution plan +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +Datum *<REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Actual parameter values +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +char *<REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Array describing what parameters get NULLs +<SimpleList> +<Member>'n' indicates NULL allowed</Member> +<Member>' ' indicates NULL not allowed</Member> +</SimpleList> +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +int <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Number of tuples for which plan is to be executed +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIEXECP-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>int +</TERM> +<LISTITEM> +<PARA> + Returns the same value as <Function>SPI_exec</Function> as well as +<SimpleList> +<Member> + <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> + if <REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE> + is NULL or <REPLACEABLE CLASS="PARAMETER">tcount</REPLACEABLE> < 0 +</Member> +<Member> + <ReturnValue>SPI_ERROR_PARAM</ReturnValue> + if <REPLACEABLE CLASS="PARAMETER">values</REPLACEABLE> + is NULL + and <REPLACEABLE CLASS="PARAMETER">plan</REPLACEABLE> + was prepared with some parameters. +</Member> +</SimpleList> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM>SPI_tuptable +</TERM> +<LISTITEM> +<PARA> +initialized as in + <Function>SPI_exec</Function> if successful +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM>SPI_processed +</TERM> +<LISTITEM> +<PARA> +initialized as in + <Function>SPI_exec</Function> if successful +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIEXECP-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_execp</FUNCTION> + stores a plan prepared by <Function>SPI_prepare</Function> in safe memory + protected from freeing by <Function>SPI_finish</Function> or the transaction manager. + +<Para> + In the current version of <ProductName>Postgres</ProductName> there is no ability to + store prepared plans in the system + catalog and fetch them from there for execution. This will be implemented + in future versions. + + As a work arround, there is the ability to reuse prepared plans in the + consequent invocations of your procedure in the current session. + Use <Function>SPI_execp</Function> to execute this saved plan. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIEXECP-2"> +<TITLE>Usage +</TITLE> +<Para> + If <REPLACEABLE CLASS="PARAMETER">nulls</REPLACEABLE> +is NULL then + <Function>SPI_execp</Function> +assumes that all values (if any) are NOT NULL. + +<Note> +<Para> + If one of the objects (a relation, function, etc.) referenced by the prepared + plan is dropped during your session (by your backend or another process) then the + results of <Function>SPI_execp</Function> for this plan will be unpredictable. +</Para> +</Note> + +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIEXECP-3"> +<TITLE>Algorithm +</TITLE> +<PARA><FUNCTION>SPI_execp</FUNCTION> performs the following: +</PARA> +<VARIABLELIST> +<VARLISTENTRY> +<TERM>• +</TERM> +<LISTITEM> +<PARA> +TBD +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +<PARA> +</PARA> +</REFSECT1> +--> +<!-- +<REFSECT1 ID="R1-SPI-SPIEXECP-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +</Sect1> + +<Sect1> +<Title>Interface Support Functions</Title> + +<Para> +All functions described below may be used by connected and unconnected +procedures. +</Para> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPICOPYTUPLE-1"> +<REFMETA> +<REFENTRYTITLE>SPI_copytuple</REFENTRYTITLE> +<REFMISCINFO>SPI - Tuple Copy</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_copytuple +</REFNAME> +<REFPURPOSE> +Makes copy of tuple in upper Executor context +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPICOPYTUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>copying tuples</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPICOPYTUPLE-2"><PRIMARY>SPI_copytuple</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_copytuple(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPICOPYTUPLE-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple to be copied +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPICOPYTUPLE-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +HeapTuple +</TERM> +<LISTITEM> +<PARA> +Copied tuple +<SimpleList> +<Member> + <ReturnValue>non-NULL</ReturnValue> + if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> + is not NULL and the copy was successful +</Member> +<Member> + <ReturnValue>NULL</ReturnValue> + only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> + is NULL +</Member> +</SimpleList> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_copytuple</FUNCTION> + makes a copy of tuple in upper Executor context. See the section on Memory Management. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-2"> +<TITLE>Usage +</TITLE> +<Para> +TBD +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +</PARA> +</REFSECT1> +--> +<!-- +<REFSECT1 ID="R1-SPI-SPICOPYTUPLE-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIMODIFYTUPLE-1"> +<REFMETA> +<REFENTRYTITLE>SPI_modifytuple</REFENTRYTITLE> +<REFMISCINFO>SPI - Tuple Modify</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_modifytuple +</REFNAME> +<REFPURPOSE> +Modifies tuple of relation +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIMODIFYTUPLE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>modifying tuples</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIMODIFYTUPLE-2"><PRIMARY>SPI_modifytuple</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_modifytuple(<REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> , <REPLACEABLE CLASS="PARAMETER">nattrs</REPLACEABLE> +, <REPLACEABLE CLASS="PARAMETER">attnum</REPLACEABLE> , <REPLACEABLE CLASS="PARAMETER">Values</REPLACEABLE> , <REPLACEABLE CLASS="PARAMETER">Nulls</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIMODIFYTUPLE-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +Relation <REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple to be modified +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +int <REPLACEABLE CLASS="PARAMETER">nattrs</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Number of attribute numbers in attnum +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +int * <REPLACEABLE CLASS="PARAMETER">attnum</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Array of numbers of the attributes which are to be changed +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +Datum * <REPLACEABLE CLASS="PARAMETER">Values</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +New values for the attributes specified +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +char * <REPLACEABLE CLASS="PARAMETER">Nulls</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Which attributes are NULL, if any +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIMODIFYTUPLE-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +HeapTuple +</TERM> +<LISTITEM> +<PARA> +New tuple with modifications +<SimpleList> +<Member> + <ReturnValue>non-NULL</ReturnValue> + if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> + is not NULL and the modify was successful +</Member> +<Member> + <ReturnValue>NULL</ReturnValue> + only if <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> + is NULL +</Member> +</SimpleList> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +SPI_result +</TERM> +<LISTITEM> +<PARA> +<SimpleList> +<Member> + <ReturnValue>SPI_ERROR_ARGUMENT</ReturnValue> if rel is NULL or tuple is NULL or natts ≤ 0 or + attnum is NULL or Values is NULL. +</Member> +<Member> + <ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> if there is an invalid + attribute number in attnum (attnum ≤ 0 or > number of + attributes in tuple) +</Member> +</SimpleList> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_modifytuple</FUNCTION> +Modifies a tuple in upper Executor context. See the section on Memory Management. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-2"> +<TITLE>Usage +</TITLE> +<Para> +If successful, a pointer to the new tuple is returned. The new tuple is +allocated in upper Executor context (see Memory management). Passed tuple +is not changed. +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +</PARA> +</REFSECT1> +--> +<!-- +<REFSECT1 ID="R1-SPI-SPIMODIFYTUPLE-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIFNUMBER-1"> +<REFMETA> +<REFENTRYTITLE>SPI_fnumber</REFENTRYTITLE> +<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_fnumber +</REFNAME> +<REFPURPOSE> +Finds the attribute number for specified attribute +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIFNUMBER-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIFNUMBER-2"><PRIMARY>SPI_fnumber</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_fnumber(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIFNUMBER-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple description +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +char * <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Field name +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIFNUMBER-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +int +</TERM> +<LISTITEM> +<PARA> +Attribute number +<SimpleList> +<Member> +Valid one-based index number of attribute +</Member> +<Member> +<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> if the named attribute is not found +</Member> +</SimpleList> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIFNUMBER-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_fnumber</FUNCTION> + returns the attribute number for the attribute with name in fname. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIFNUMBER-2"> +<TITLE>Usage +</TITLE> +<Para> +Attribute numbers are 1 based. +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIFNUMBER-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +</PARA> +</REFSECT1> +--> +<!-- +<REFSECT1 ID="R1-SPI-SPIFNUMBER-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIFNAME-1"> +<REFMETA> +<REFENTRYTITLE>SPI_fname</REFENTRYTITLE> +<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_fname +</REFNAME> +<REFPURPOSE> +Finds the attribute name for the specified attribute +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIFNAME-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIFNAME-2"><PRIMARY>SPI_fname</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_fname(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fname</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIFNAME-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple description +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +char * <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Attribute number +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIFNAME-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +char * +</TERM> +<LISTITEM> +<PARA> +Attribute name +<SimpleList> +<Member> +NULL if fnumber is out of range +</Member> +<Member> +SPI_result set to +<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> on error +</Member> +</SimpleList> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIFNAME-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_fname</FUNCTION> + returns the attribute name for the specified attribute. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIFNAME-2"> +<TITLE>Usage +</TITLE> +<Para> +Attribute numbers are 1 based. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIFNAME-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +Returns a newly-allocated copy of the attribute name. +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIFNAME-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIGETVALUE-1"> +<REFMETA> +<REFENTRYTITLE>SPI_getvalue</REFENTRYTITLE> +<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_getvalue +</REFNAME> +<REFPURPOSE> +Returns the string value of the specified attribute +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIGETVALUE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIGETVALUE-2"><PRIMARY>SPI_getvalue</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_getvalue(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIGETVALUE-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple to be examined +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple description +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Attribute number +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIGETVALUE-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +char * +</TERM> +<LISTITEM> +<PARA> +Attribute value or NULL if +<SimpleList> +<Member> +attribute is NULL +</Member> +<Member> +fnumber is out of range +(SPI_result set to +<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue>) +</Member> +<Member> +no output function available +(SPI_result set to +<ReturnValue>SPI_ERROR_NOOUTFUNC</ReturnValue>) +</Member> +</SimpleList> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIGETVALUE-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_getvalue</FUNCTION> + returns an external (string) representation of the value of the specified attribute. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETVALUE-2"> +<TITLE>Usage +</TITLE> +<Para> +Attribute numbers are 1 based. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETVALUE-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +Allocates memory as required by the value. +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIGETVALUE-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIGETBINVAL-1"> +<REFMETA> +<REFENTRYTITLE>SPI_getbinval</REFENTRYTITLE> +<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_getbinval +</REFNAME> +<REFPURPOSE> +Returns the binary value of the specified attribute +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIGETBINVAL-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIGETBINVAL-2"><PRIMARY>SPI_getbinval</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_getbinval(<REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">isnull</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIGETBINVAL-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +HeapTuple <REPLACEABLE CLASS="PARAMETER">tuple</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple to be examined +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple description +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Attribute number +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIGETBINVAL-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +Datum +</TERM> +<LISTITEM> +<PARA> +Attribute binary value +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +bool * <REPLACEABLE CLASS="PARAMETER">isnull</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +flag for null value in attribute +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +SPI_result +</TERM> +<LISTITEM> +<PARA> +<SimpleList> +<Member> +<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> +</Member> +</SimpleList> +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIGETBINVAL-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_getbinval</FUNCTION> + returns the binary value of the specified attribute. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETBINVAL-2"> +<TITLE>Usage +</TITLE> +<Para> +Attribute numbers are 1 based. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETBINVAL-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +Does not allocate new space for the binary value. +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIGETBINVAL-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIGETTYPE-1"> +<REFMETA> +<REFENTRYTITLE>SPI_gettype</REFENTRYTITLE> +<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_gettype +</REFNAME> +<REFPURPOSE> +Returns the type name of the specified attribute +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIGETTYPE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIGETTYPE-2"><PRIMARY>SPI_gettype</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_gettype(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIGETTYPE-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple description +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Attribute number +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIGETTYPE-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +char * +</TERM> +<LISTITEM> +<PARA> +The type name for the specified attribute number +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +SPI_result +</TERM> +<LISTITEM> +<PARA> +<SimpleList> +<Member> +<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> +</Member> +</SimpleList> +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIGETTYPE-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_gettype</FUNCTION> + returns a copy of the type name for the specified attribute. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETTYPE-2"> +<TITLE>Usage +</TITLE> +<Para> +Attribute numbers are 1 based. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETTYPE-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +Does not allocate new space for the binary value. +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIGETTYPE-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIGETTYPEID-1"> +<REFMETA> +<REFENTRYTITLE>SPI_gettypeid</REFENTRYTITLE> +<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_gettypeid +</REFNAME> +<REFPURPOSE> +Returns the type <Acronym>OID</Acronym> of the specified attribute +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIGETTYPEID-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIGETTYPEID-2"><PRIMARY>SPI_gettypeid</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_gettypeid(<REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIGETTYPEID-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +TupleDesc <REPLACEABLE CLASS="PARAMETER">tupdesc</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input tuple description +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +int <REPLACEABLE CLASS="PARAMETER">fnumber</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Attribute number +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIGETTYPEID-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +<Acronym>OID</Acronym> +</TERM> +<LISTITEM> +<PARA> +The type <Acronym>OID</Acronym> for the specified attribute number +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +SPI_result +</TERM> +<LISTITEM> +<PARA> +<SimpleList> +<Member> +<ReturnValue>SPI_ERROR_NOATTRIBUTE</ReturnValue> +</Member> +</SimpleList> +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIGETTYPEID-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_gettypeid</FUNCTION> + returns the type <Acronym>OID</Acronym> for the specified attribute. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETTYPEID-2"> +<TITLE>Usage +</TITLE> +<Para> +Attribute numbers are 1 based. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETTYPEID-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +TBD +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIGETTYPEID-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIGETRELNAME-1"> +<REFMETA> +<REFENTRYTITLE>SPI_getrelname</REFENTRYTITLE> +<REFMISCINFO>SPI - Tuple Information</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_getrelname +</REFNAME> +<REFPURPOSE> +Returns the name of the specified relation +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIGETRELNAME-1"><PRIMARY>SPI</PRIMARY><SECONDARY>decoding tuples</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIGETRELNAME-2"><PRIMARY>SPI_getrelname</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_getrelname(<REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIGETRELNAME-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +Relation <REPLACEABLE CLASS="PARAMETER">rel</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Input relation +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIGETRELNAME-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +char * +</TERM> +<LISTITEM> +<PARA> +The name of the specified relation +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIGETRELNAME-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_getrelname</FUNCTION> + returns the name of the specified relation. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETRELNAME-2"> +<TITLE>Usage +</TITLE> +<Para> +TBD +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIGETRELNAME-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +Copies the relation name into new storage. +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIGETRELNAME-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIPALLOC-1"> +<REFMETA> +<REFENTRYTITLE>SPI_palloc</REFENTRYTITLE> +<REFMISCINFO>SPI - Memory Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_palloc +</REFNAME> +<REFPURPOSE> +Allocates memory in upper Executor context +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIPALLOC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIPALLOC-2"><PRIMARY>SPI_palloc</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_palloc(<REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIPALLOC-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +Size <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Octet size of storage to allocate +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIPALLOC-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +void * +</TERM> +<LISTITEM> +<PARA> +New storage space of specified size +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIPALLOC-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_palloc</FUNCTION> + allocates memory in upper Executor context. See section on memory management. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIPALLOC-2"> +<TITLE>Usage +</TITLE> +<Para> +TBD +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIPALLOC-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +TBD +</PARA> +</REFSECT1> +--> +<!-- +<REFSECT1 ID="R1-SPI-SPIPALLOC-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIREPALLOC-1"> +<REFMETA> +<REFENTRYTITLE>SPI_repalloc</REFENTRYTITLE> +<REFMISCINFO>SPI - Memory Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_repalloc +</REFNAME> +<REFPURPOSE> +Re-allocates memory in upper Executor context +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIREPALLOC-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIREPALLOC-2"><PRIMARY>SPI_repalloc</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_repalloc(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>, <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIREPALLOC-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +void * <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Pointer to existing storage +</PARA> +</LISTITEM> +</VARLISTENTRY> +<VARLISTENTRY> +<TERM> +Size <REPLACEABLE CLASS="PARAMETER">size</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Octet size of storage to allocate +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIREPALLOC-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +void * +</TERM> +<LISTITEM> +<PARA> +New storage space of specified size with contents copied from existing area +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIREPALLOC-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_repalloc</FUNCTION> + re-allocates memory in upper Executor context. See section on memory management. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIREPALLOC-2"> +<TITLE>Usage +</TITLE> +<Para> +TBD +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIREPALLOC-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +TBD +</PARA> +</REFSECT1> +--> +<!-- +<REFSECT1 ID="R1-SPI-SPIREPALLOC-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +<!-- *********************************************** --> +<!-- *********************************************** --> +<!-- *********************************************** --> + +<REFENTRY ID="SPI-SPIPFREE-1"> +<REFMETA> +<REFENTRYTITLE>SPI_pfree</REFENTRYTITLE> +<REFMISCINFO>SPI - Memory Management</REFMISCINFO> +</REFMETA> +<REFNAMEDIV> +<REFNAME>SPI_pfree +</REFNAME> +<REFPURPOSE> +Frees memory from upper Executor context +</REFPURPOSE> +<INDEXTERM ID="IX-SPI-SPIPFREE-1"><PRIMARY>SPI</PRIMARY><SECONDARY>allocating space</SECONDARY></INDEXTERM> +<INDEXTERM ID="IX-SPI-SPIPFREE-2"><PRIMARY>SPI_pfree</PRIMARY></INDEXTERM> +</REFNAMEDIV> +<REFSYNOPSISDIV> +<REFSYNOPSISDIVINFO> +<DATE>1997-12-24</DATE> +</REFSYNOPSISDIVINFO> +<SYNOPSIS> +SPI_pfree(<REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE>) +</SYNOPSIS> + +<REFSECT2 ID="R2-SPI-SPIPFREE-1"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Inputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +void * <REPLACEABLE CLASS="PARAMETER">pointer</REPLACEABLE> +</TERM> +<LISTITEM> +<PARA> +Pointer to existing storage +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> + +<REFSECT2 ID="R2-SPI-SPIPFREE-2"> +<REFSECT2INFO> +<DATE>1997-12-24</DATE> +</REFSECT2INFO> +<TITLE>Outputs +</TITLE> +<VARIABLELIST> +<VARLISTENTRY> +<TERM> +None +</TERM> +<LISTITEM> +<PARA> +</PARA> +</LISTITEM> +</VARLISTENTRY> +</VARIABLELIST> +</REFSECT2> +</REFSYNOPSISDIV> + +<REFSECT1 ID="R1-SPI-SPIPFREE-1"> +<REFSECT1INFO> +<DATE>1997-12-24</DATE> +</REFSECT1INFO> +<TITLE>Description +</TITLE> +<PARA> +<FUNCTION>SPI_pfree</FUNCTION> + frees memory in upper Executor context. See section on memory management. +</PARA> +</REFSECT1> +<REFSECT1 ID="R1-SPI-SPIPFREE-2"> +<TITLE>Usage +</TITLE> +<Para> +TBD +</PARA> +</REFSECT1> +<!-- +<REFSECT1 ID="R1-SPI-SPIPFREE-3"> +<TITLE>Algorithm +</TITLE> +<PARA> +TBD +</PARA> +</REFSECT1> +--> +<!-- +<REFSECT1 ID="R1-SPI-SPIPFREE-4"> +<TITLE>Structures +</TITLE> +<PARA>None +</PARA> +</REFSECT1> +--> +</REFENTRY> + +</Sect1> + +<Sect1> +<Title>Memory Management</Title> + +<Para> + Server allocates memory in memory contexts in such way that allocations +made in one context may be freed by context destruction without affecting +allocations made in other contexts. All allocations (via <Function>palloc</Function>, etc) are +made in the context which are chosen as current one. You'll get +unpredictable results if you'll try to free (or reallocate) memory allocated +not in current context. +</Para> + +<Para> + Creation and switching between memory contexts are subject of SPI manager +memory management. +</Para> + +<Para> + + SPI procedures deal with two memory contexts: upper Executor memory +context and procedure memory context (if connected). +</Para> + +<Para> + + Before a procedure is connected to the SPI manager, current memory context +is upper Executor context so all allocation made by the procedure itself via +<Function>palloc</Function>/<Function>repalloc</Function> or by SPI utility functions before connecting to SPI are +made in this context. +</Para> + +<Para> + + After <Function>SPI_connect</Function> is called current context is the procedure's one. All +allocations made via <Function>palloc</Function>/<Function>repalloc</Function> or by SPI utility functions (except +for <Function>SPI_copytuple</Function>, <Function>SPI_modifytuple</Function>, + <Function>SPI_palloc</Function> and <Function>SPI_repalloc</Function>) are +made in this context. +</Para> + +<Para> + + When a procedure disconnects from the SPI manager (via <Function>SPI_finish</Function>) the +current context is restored to the upper Executor context and all allocations +made in the procedure memory context are freed and can't be used any more! +</Para> + +<Para> + + If you want to return something to the upper Executor then you have to +allocate memory for this in the upper context! +</Para> + +<Para> + + SPI has no ability to automatically free allocations in the upper Executor +context! +</Para> + +<Para> + + SPI automatically frees memory allocated during execution of a query when +this query is done! +</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 + + INSERT INTO a SELECT * FROM a + + 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> + 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. +</Para> +</Sect1> + +<Sect1> +<Title>Examples</Title> + +<Para> + This example of SPI usage demonstrates the visibility rule. + There are more complex examples in in src/test/regress/regress.c and +in contrib/spi. +</Para> + +<Para> + This is a very simple example of SPI usage. The procedure execq accepts +an SQL-query in its first argument and tcount in its second, executes the +query using SPI_exec and returns the number of tuples for which the query +executed: + +<ProgramListing> +#include "executor/spi.h" /* this is what you need to work with SPI */ + +int execq(text *sql, int cnt); + +int +execq(text *sql, int cnt) +{ + int ret; + int proc = 0; + + SPI_connect(); + + ret = SPI_exec(textout(sql), cnt); + + proc = SPI_processed; + /* + * If this is SELECT and some tuple(s) fetched - + * returns tuples to the caller via elog (NOTICE). + */ + if ( ret == SPI_OK_SELECT && SPI_processed > 0 ) + { + TupleDesc tupdesc = SPI_tuptable->tupdesc; + SPITupleTable *tuptable = SPI_tuptable; + char buf[8192]; + int i; + + for (ret = 0; ret < proc; ret++) + { + HeapTuple tuple = tuptable->vals[ret]; + + for (i = 1, buf[0] = 0; i <= tupdesc->natts; i++) + sprintf(buf + strlen (buf), " %s%s", + SPI_getvalue(tuple, tupdesc, i), + (i == tupdesc->natts) ? " " : " |"); + elog (NOTICE, "EXECQ: %s", buf); + } + } + + SPI_finish(); + + return (proc); +} +</ProgramListing> +</Para> + +<Para> + Now, compile and create the function: + +<ProgramListing> +create function execq (text, int4) returns int4 as '...path_to_so' language 'c'; +</ProgramListing> + +<ProgramListing> +vac=> select execq('create table a (x int4)', 0); +execq +----- + 0 +(1 row) + +vac=> insert into a values (execq('insert into a values (0)',0)); +INSERT 167631 1 +vac=> select execq('select * from a',0); +NOTICE:EXECQ: 0 <<< inserted by execq + +NOTICE:EXECQ: 1 <<< value returned by execq and inserted by upper INSERT + +execq +----- + 2 +(1 row) + +vac=> select execq('insert into a select x + 2 from a',1); +execq +----- + 1 +(1 row) + +vac=> select execq('select * from a', 10); +NOTICE:EXECQ: 0 + +NOTICE:EXECQ: 1 + +NOTICE:EXECQ: 2 <<< 0 + 2, only one tuple inserted - as specified + +execq +----- + 3 <<< 10 is max value only, 3 is real # of tuples +(1 row) + +vac=> delete from a; +DELETE 3 +vac=> insert into a values (execq('select * from a', 0) + 1); +INSERT 167712 1 +vac=> select * from a; +x +- +1 <<< no tuples in a (0) + 1 +(1 row) + +vac=> insert into a values (execq('select * from a', 0) + 1); +NOTICE:EXECQ: 0 +INSERT 167713 1 +vac=> select * from a; +x +- +1 +2 <<< there was single tuple in a + 1 +(2 rows) + +-- This demonstrates data changes visibility rule: + +vac=> insert into a select execq('select * from a', 0) * x from a; +NOTICE:EXECQ: 1 +NOTICE:EXECQ: 2 +NOTICE:EXECQ: 1 +NOTICE:EXECQ: 2 +NOTICE:EXECQ: 2 +INSERT 0 2 +vac=> select * from a; +x +- +1 +2 +2 <<< 2 tuples * 1 (x in first tuple) +6 <<< 3 tuples (2 + 1 just inserted) * 2 (x in second tuple) +(4 rows) ^^^^^^^^ + tuples visible to execq() in different invocations +</ProgramListing> +</Para> +</Sect1> +</Chapter> diff --git a/doc/src/sgml/start-ag.sgml b/doc/src/sgml/start-ag.sgml new file mode 100644 index 0000000000000000000000000000000000000000..6ca52ddaf705ab4906bb2c4434fc5ba7bae33d20 --- /dev/null +++ b/doc/src/sgml/start-ag.sgml @@ -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> diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml new file mode 100644 index 0000000000000000000000000000000000000000..bd6dc001607cc40da2e89495f850e7e5d14727ac --- /dev/null +++ b/doc/src/sgml/start.sgml @@ -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> diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml new file mode 100644 index 0000000000000000000000000000000000000000..7a0495e22704baf4bdfb285cb40b1ee3e3c67683 --- /dev/null +++ b/doc/src/sgml/storage.sgml @@ -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> diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml new file mode 100644 index 0000000000000000000000000000000000000000..b8b7fc12ab318727dc4098d9fe2c241ef0ddbcf4 --- /dev/null +++ b/doc/src/sgml/trigger.sgml @@ -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> diff --git a/doc/src/sgml/tutorial.sgml b/doc/src/sgml/tutorial.sgml new file mode 100644 index 0000000000000000000000000000000000000000..6ff48eb750ea508e9826dfadfe180961fe3cdeab --- /dev/null +++ b/doc/src/sgml/tutorial.sgml @@ -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> + diff --git a/doc/src/sgml/user.sgml b/doc/src/sgml/user.sgml new file mode 100644 index 0000000000000000000000000000000000000000..151dd84b54e552bd9868e609ded9d8fc71260b7a --- /dev/null +++ b/doc/src/sgml/user.sgml @@ -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> + diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml new file mode 100644 index 0000000000000000000000000000000000000000..81df0a8577eb1bdfd7499d63564202adc31344c1 --- /dev/null +++ b/doc/src/sgml/xaggr.sgml @@ -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> diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml new file mode 100644 index 0000000000000000000000000000000000000000..f1275bbb462ff6d3dc50f21d015a1efa41765bb1 --- /dev/null +++ b/doc/src/sgml/xfunc.sgml @@ -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> diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml new file mode 100644 index 0000000000000000000000000000000000000000..b77af369e6a2ba6bb6998bc79dda18663cd28a00 --- /dev/null +++ b/doc/src/sgml/xindex.sgml @@ -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> diff --git a/doc/src/sgml/xoper.sgml b/doc/src/sgml/xoper.sgml new file mode 100644 index 0000000000000000000000000000000000000000..fa5e7342f674248774c0af23ca3f08eeba41e818 --- /dev/null +++ b/doc/src/sgml/xoper.sgml @@ -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> diff --git a/doc/src/sgml/xtypes.sgml b/doc/src/sgml/xtypes.sgml new file mode 100644 index 0000000000000000000000000000000000000000..980fa2f00936bd1296ba177c8cdf0325a3c5ef49 --- /dev/null +++ b/doc/src/sgml/xtypes.sgml @@ -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>