Commit 731204e0 authored by Peter Eisentraut's avatar Peter Eisentraut

Editorial review

parent a510bf43
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/biblio.sgml,v 1.16 2001/11/21 05:53:40 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/biblio.sgml,v 1.17 2002/01/07 02:29:11 petere Exp $
--> -->
<bibliography id="biblio"> <bibliography id="biblio">
...@@ -148,76 +148,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/biblio.sgml,v 1.16 2001/11/21 05:53:40 thom ...@@ -148,76 +148,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/biblio.sgml,v 1.16 2001/11/21 05:53:40 thom
<title>PostgreSQL-Specific Documentation</title> <title>PostgreSQL-Specific Documentation</title>
<para>This section is for related documentation.</para> <para>This section is for related documentation.</para>
<biblioentry id="admin-guide">
<title>The <productname>PostgreSQL</productname> Administrator's Guide</title>
<titleabbrev>The Administrator's Guide</titleabbrev>
<editor>
<firstname>Thomas</firstname>
<surname>Lockhart</surname>
</editor>
<pubdate>2001-04-13</pubdate>
<publisher>
<publishername>The PostgreSQL Global Development Group</publishername>
</publisher>
</biblioentry>
<biblioentry id="dev-guide">
<title>The <productname>PostgreSQL</productname> Developer's Guide</title>
<titleabbrev>The Developer's Guide</titleabbrev>
<editor>
<firstname>Thomas</firstname>
<surname>Lockhart</surname>
</editor>
<pubdate>2001-04-13</pubdate>
<publisher>
<publishername>The PostgreSQL Global Development Group</publishername>
</publisher>
</biblioentry>
<biblioentry id="pro-guide">
<title>The <productname>PostgreSQL</productname> Programmer's Guide</title>
<titleabbrev>The Programmer's Guide</titleabbrev>
<editor>
<firstname>Thomas</firstname>
<surname>Lockhart</surname>
</editor>
<pubdate>2001-04-13</pubdate>
<publisher>
<publishername>The PostgreSQL Global Development Group</publishername>
</publisher>
</biblioentry>
<biblioentry id="tutorial-guide">
<title>The <productname>PostgreSQL</productname> Tutorial Introduction</title>
<titleabbrev>The Tutorial</titleabbrev>
<editor>
<firstname>Thomas</firstname>
<surname>Lockhart</surname>
</editor>
<pubdate>2001-04-13</pubdate>
<publisher>
<publishername>The PostgreSQL Global Development Group</publishername>
</publisher>
</biblioentry>
<biblioentry id="users-guide">
<title>The <productname>PostgreSQL</productname> User's Guide</title>
<titleabbrev>The User's Guide</titleabbrev>
<editor>
<firstname>Thomas</firstname>
<surname>Lockhart</surname>
</editor>
<pubdate>2001-04-13</pubdate>
<publisher>
<publishername>The PostgreSQL Global Development Group</publishername>
</publisher>
</biblioentry>
<biblioentry id="SIM98"> <biblioentry id="SIM98">
<title>Enhancement of the ANSI SQL Implementation of PostgreSQL</title> <title>Enhancement of the ANSI SQL Implementation of PostgreSQL</title>
<titleabbrev>Simkovics, 1998</titleabbrev> <titleabbrev>Simkovics, 1998</titleabbrev>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.82 2002/01/04 17:02:02 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.83 2002/01/07 02:29:11 petere Exp $
--> -->
<chapter id="datatype"> <chapter id="datatype">
...@@ -270,7 +270,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.82 2002/01/04 17:02:02 th ...@@ -270,7 +270,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.82 2002/01/04 17:02:02 th
paths, or have several possibilities for formats, such as the date paths, or have several possibilities for formats, such as the date
and time types. and time types.
Most of the input and output functions corresponding to the Most of the input and output functions corresponding to the
base types (e.g., integers and floating point numbers) do some base types (e.g., integers and floating-point numbers) do some
error-checking. error-checking.
Some of the input and output functions are not invertible. That is, 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 result of an output function may lose precision when compared to
...@@ -354,7 +354,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.82 2002/01/04 17:02:02 th ...@@ -354,7 +354,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.82 2002/01/04 17:02:02 th
<para> <para>
Numeric types consist of two-, four-, and eight-byte integers, Numeric types consist of two-, four-, and eight-byte integers,
four- and eight-byte four- and eight-byte
floating point numbers and fixed-precision decimals. floating-point numbers and fixed-precision decimals.
</para> </para>
<para> <para>
...@@ -511,7 +511,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.82 2002/01/04 17:02:02 th ...@@ -511,7 +511,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.82 2002/01/04 17:02:02 th
numbers and carry out all calculations exactly. It is especially numbers and carry out all calculations exactly. It is especially
recommended for storing monetary amounts and other quantities recommended for storing monetary amounts and other quantities
where exactness is required. However, the <type>numeric</type> where exactness is required. However, the <type>numeric</type>
type is very slow compared to the floating point types described type is very slow compared to the floating-point types described
in the next section. in the next section.
</para> </para>
...@@ -568,11 +568,11 @@ NUMERIC ...@@ -568,11 +568,11 @@ NUMERIC
<sect2 id="datatype-float"> <sect2 id="datatype-float">
<title>Floating Point Types</title> <title>Floating-Point Types</title>
<para> <para>
The data types <type>real</type> and <type>double The data types <type>real</type> and <type>double
precision</type> are inexact, variable precision numeric types. precision</type> are inexact, variable-precision numeric types.
In practice, these types are usually implementations of <acronym>IEEE</acronym> 754 In practice, these types are usually implementations of <acronym>IEEE</acronym> 754
binary floating point (single and double precision, binary floating point (single and double precision,
respectively), to the extent that the underlying processor, respectively), to the extent that the underlying processor,
...@@ -606,7 +606,7 @@ NUMERIC ...@@ -606,7 +606,7 @@ NUMERIC
<listitem> <listitem>
<para> <para>
Comparing two floating point values for equality may or may Comparing two floating-point values for equality may or may
not work as expected. not work as expected.
</para> </para>
</listitem> </listitem>
...@@ -682,14 +682,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( ...@@ -682,14 +682,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
will never be duplicates, either. will never be duplicates, either.
</para> </para>
<important>
<para>
The implicit sequence created for the <type>serial</type> type will
<emphasis>not</emphasis> be automatically removed when the
table is dropped.
</para>
</important>
<para> <para>
The type names <type>serial</type> and <type>serial4</type> are The type names <type>serial</type> and <type>serial4</type> are
equivalent: both create <type>integer</type> columns. The type equivalent: both create <type>integer</type> columns. The type
...@@ -741,7 +733,7 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl ...@@ -741,7 +733,7 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (<replaceabl
<para> <para>
Input is accepted in a variety of formats, including integer and Input is accepted in a variety of formats, including integer and
floating point literals, as well as <quote>typical</quote> floating-point literals, as well as <quote>typical</quote>
currency formatting, such as <literal>'$1,000.00'</literal>. currency formatting, such as <literal>'$1,000.00'</literal>.
Output is in the latter form. Output is in the latter form.
</para> </para>
...@@ -1165,8 +1157,6 @@ SELECT b, char_length(b) FROM test2; ...@@ -1165,8 +1157,6 @@ SELECT b, char_length(b) FROM test2;
escape character. escape character.
</para> </para>
<sect2 id="datatype-binary-compat">
<title>Compatibility</title>
<para> <para>
<type>Bytea</type> provides most of the functionality of the binary <type>Bytea</type> provides most of the functionality of the binary
string type per SQL99 section 4.3. A comparison of SQL99 Binary string type per SQL99 section 4.3. A comparison of SQL99 Binary
...@@ -1248,7 +1238,6 @@ SELECT b, char_length(b) FROM test2; ...@@ -1248,7 +1238,6 @@ SELECT b, char_length(b) FROM test2;
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
</sect2>
</sect1> </sect1>
...@@ -1335,7 +1324,7 @@ SELECT b, char_length(b) FROM test2; ...@@ -1335,7 +1324,7 @@ SELECT b, char_length(b) FROM test2;
specifies the number of fractional digits retained in the seconds specifies the number of fractional digits retained in the seconds
field. By default, there is no explicit bound on precision. The field. By default, there is no explicit bound on precision. The
effective limit of precision is determined by the underlying double effective limit of precision is determined by the underlying double
precision floating point number used to store values (in seconds precision floating-point number used to store values (in seconds
for <type>interval</type> and for <type>interval</type> and
in seconds since 2000-01-01 for <type>timestamp</type>). The in seconds since 2000-01-01 for <type>timestamp</type>). The
useful range of <replaceable>p</replaceable> is from 0 to about useful range of <replaceable>p</replaceable> is from 0 to about
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.17 2001/11/21 05:53:41 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.18 2002/01/07 02:29:11 petere Exp $
--> -->
<sect2 id="dfunc"> <sect2 id="dfunc">
...@@ -40,7 +40,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.17 2001/11/21 05:53:41 thoma ...@@ -40,7 +40,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/dfunc.sgml,v 1.17 2001/11/21 05:53:41 thoma
<para> <para>
In the following examples we assume that your source code is in a In the following examples we assume that your source code is in a
file <filename>foo.c</filename> and we will create an shared library file <filename>foo.c</filename> and we will create a shared library
<filename>foo.so</filename>. The intermediate object file will be <filename>foo.so</filename>. The intermediate object file will be
called <filename>foo.o</filename> unless otherwise noted. A shared called <filename>foo.o</filename> unless otherwise noted. A shared
library can contain more than one object file, but we only use one library can contain more than one object file, but we only use one
...@@ -121,8 +121,8 @@ ld -b -o foo.sl foo.o ...@@ -121,8 +121,8 @@ ld -b -o foo.sl foo.o
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><productname>Irix</productname></term> <term><productname>IRIX</productname></term>
<indexterm><primary>Irix</></> <indexterm><primary>IRIX</></>
<listitem> <listitem>
<para> <para>
<acronym>PIC</acronym> is the default, no special compiler <acronym>PIC</acronym> is the default, no special compiler
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.32 2002/01/06 17:54:14 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.33 2002/01/07 02:29:11 petere Exp $
--> -->
<chapter id="ecpg"> <chapter id="ecpg">
...@@ -300,7 +300,7 @@ struct sqlca ...@@ -300,7 +300,7 @@ struct sqlca
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><computeroutput>-206 (ECPG_FLOAT_FORMAT): Not correctly formatted floating point type: %s line %d.</computeroutput></term> <term><computeroutput>-206 (ECPG_FLOAT_FORMAT): Not correctly formatted floating-point type: %s line %d.</computeroutput></term>
<listitem> <listitem>
<para> <para>
This means the host variable is of type <type>float</type> and This means the host variable is of type <type>float</type> and
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.15 2002/01/07 02:29:11 petere Exp $
--> -->
<chapter id="extend"> <chapter id="extend">
...@@ -18,7 +18,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom ...@@ -18,7 +18,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
types data types
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
...@@ -56,17 +56,16 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom ...@@ -56,17 +56,16 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom
extended by users. By comparison, conventional extended by users. By comparison, conventional
database systems can only be extended by changing hardcoded database systems can only be extended by changing hardcoded
procedures within the <acronym>DBMS</acronym> or by loading modules procedures within the <acronym>DBMS</acronym> or by loading modules
specially-written by the <acronym>DBMS</acronym> vendor. specially written by the <acronym>DBMS</acronym> vendor.
</para> </para>
<para> <para>
<productname>PostgreSQL</productname> is also unlike most other data managers in <productname>PostgreSQL</productname> is also unlike most other data managers in
that the server can incorporate user-written code into that the server can incorporate user-written code into
itself through dynamic loading. That is, the user can itself through dynamic loading. That is, the user can
specify an object code file (e.g., a compiled .o file specify an object code file (e.g., a shared library) that implements a new type or function
or shared library) that implements a new type or function
and <productname>PostgreSQL</productname> will load it as required. Code written and <productname>PostgreSQL</productname> will load it as required. Code written
in <acronym>SQL</acronym> are even more trivial to add to the server. in <acronym>SQL</acronym> is even more trivial to add to the server.
This ability to modify its operation <quote>on the fly</quote> makes This ability to modify its operation <quote>on the fly</quote> makes
<productname>PostgreSQL</productname> uniquely suited for rapid prototyping of new <productname>PostgreSQL</productname> uniquely suited for rapid prototyping of new
applications and storage structures. applications and storage structures.
...@@ -80,14 +79,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom ...@@ -80,14 +79,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom
The <productname>PostgreSQL</productname> type system The <productname>PostgreSQL</productname> type system
can be broken down in several ways. can be broken down in several ways.
Types are divided into base types and composite types. Types are divided into base types and composite types.
Base types are those, like <firstterm>int4</firstterm>, that are implemented Base types are those, like <type>int4</type>, that are implemented
in a language such as <productname>C</productname>. They generally correspond to in a language such as C. They generally correspond to
what are often known as <firstterm>abstract data types</firstterm>; <productname>PostgreSQL</productname> what are often known as <firstterm>abstract data types</firstterm>; <productname>PostgreSQL</productname>
can only operate on such types through methods provided can only operate on such types through methods provided
by the user and only understands the behavior of such by the user and only understands the behavior of such
types to the extent that the user describes them. types to the extent that the user describes them.
Composite types are created whenever the user creates a Composite types are created whenever the user creates a
table. EMP is an example of a composite type. table.
</para> </para>
<para> <para>
...@@ -100,10 +99,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom ...@@ -100,10 +99,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom
<productname>PostgreSQL</productname> base types are further <productname>PostgreSQL</productname> base types are further
divided into built-in divided into built-in
types and user-defined types. Built-in types (like types and user-defined types. Built-in types (like
<firstterm>int4</firstterm>) are those that are compiled <type>int4</type>) are those that are compiled
into the system. into the system.
User-defined types are those created by the user in the User-defined types are those created by the user in the
manner to be described below. manner to be described later.
</para> </para>
</sect1> </sect1>
...@@ -118,7 +117,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom ...@@ -118,7 +117,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom
information given here, so mark this page for later information given here, so mark this page for later
reference. reference.
All system catalogs have names that begin with All system catalogs have names that begin with
<firstterm>pg_</firstterm>. <literal>pg_</literal>.
The following tables contain information that may be The following tables contain information that may be
useful to the end user. (There are many other system useful to the end user. (There are many other system
catalogs, but there should rarely be a reason to query catalogs, but there should rarely be a reason to query
...@@ -149,15 +148,15 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom ...@@ -149,15 +148,15 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom
</row> </row>
<row> <row>
<entry>pg_index</entry> <entry>pg_index</entry>
<entry> secondary indexes</entry> <entry> indexes</entry>
</row> </row>
<row> <row>
<entry>pg_proc</entry> <entry>pg_proc</entry>
<entry> procedures (both C and SQL)</entry> <entry> procedures/functions </entry>
</row> </row>
<row> <row>
<entry>pg_type</entry> <entry>pg_type</entry>
<entry> types (both base and complex)</entry> <entry> data types (both base and complex)</entry>
</row> </row>
<row> <row>
<entry>pg_operator</entry> <entry>pg_operator</entry>
...@@ -165,7 +164,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom ...@@ -165,7 +164,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom
</row> </row>
<row> <row>
<entry>pg_aggregate</entry> <entry>pg_aggregate</entry>
<entry> aggregates and aggregate functions</entry> <entry> aggregate functions</entry>
</row> </row>
<row> <row>
<entry>pg_am</entry> <entry>pg_am</entry>
...@@ -198,7 +197,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom ...@@ -198,7 +197,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom
</mediaobject> </mediaobject>
</figure> </figure>
The Reference Manual gives a more detailed explanation The <citetitle>Developer's Guide</citetitle> gives a more detailed explanation
of these catalogs and their columns. However, of these catalogs and their columns. However,
<xref linkend="EXTEND-CATALOGS"> <xref linkend="EXTEND-CATALOGS">
shows the major entities and their relationships shows the major entities and their relationships
...@@ -257,10 +256,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom ...@@ -257,10 +256,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/extend.sgml,v 1.14 2001/11/21 05:53:41 thom
have obvious meanings, but there are many have obvious meanings, but there are many
(particularly those that have to do with access (particularly those that have to do with access
methods) that do not. The relationships between methods) that do not. The relationships between
pg_am, pg_amop, pg_amproc, pg_operator and <classname>pg_am</>, <classname>pg_amop</>, <classname>pg_amproc</>, <classname>pg_operator</>, and
pg_opclass are particularly hard to understand <classname>pg_opclass</> are particularly hard to understand
and will be described in depth (in the section and will be described in depth (in <xref linkend="xindex">)
on interfacing types and operators to indexes)
after we have discussed basic extensions. after we have discussed basic extensions.
</para> </para>
</listitem> </listitem>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.89 2001/12/27 21:36:57 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.90 2002/01/07 02:29:12 petere Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -4506,7 +4506,7 @@ SELECT NULLIF(value, '(none)') ... ...@@ -4506,7 +4506,7 @@ SELECT NULLIF(value, '(none)') ...
<type>bigint</type>, <type>real</type>, <type>double <type>bigint</type>, <type>real</type>, <type>double
precision</type>, <type>numeric</type>, <type>interval</type>. precision</type>, <type>numeric</type>, <type>interval</type>.
The result is of type <type>numeric</type> for any integer type The result is of type <type>numeric</type> for any integer type
input, <type>double precision</type> for floating point input, input, <type>double precision</type> for floating-point input,
otherwise the same as the input data type. otherwise the same as the input data type.
</entry> </entry>
</row> </row>
...@@ -4555,7 +4555,7 @@ SELECT NULLIF(value, '(none)') ... ...@@ -4555,7 +4555,7 @@ SELECT NULLIF(value, '(none)') ...
data types: <type>smallint</type>, <type>integer</type>, data types: <type>smallint</type>, <type>integer</type>,
<type>bigint</type>, <type>real</type>, <type>double <type>bigint</type>, <type>real</type>, <type>double
precision</type>, <type>numeric</type>. The result is of type precision</type>, <type>numeric</type>. The result is of type
<type>double precision</type> for floating point input, <type>double precision</type> for floating-point input,
otherwise <type>numeric</type>. otherwise <type>numeric</type>.
</entry> </entry>
</row> </row>
...@@ -4571,7 +4571,7 @@ SELECT NULLIF(value, '(none)') ... ...@@ -4571,7 +4571,7 @@ SELECT NULLIF(value, '(none)') ...
The result is of type <type>bigint</type> for <type>smallint</type> The result is of type <type>bigint</type> for <type>smallint</type>
or <type>integer</type> input, <type>numeric</type> for or <type>integer</type> input, <type>numeric</type> for
<type>bigint</type> <type>bigint</type>
input, <type>double precision</type> for floating point input, input, <type>double precision</type> for floating-point input,
otherwise the same as the input data type. otherwise the same as the input data type.
</entry> </entry>
</row> </row>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.19 2002/01/07 02:29:12 petere Exp $
--> -->
<sect1 id="history"> <sect1 id="history">
...@@ -9,7 +9,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -9,7 +9,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
The object-relational database management system now known as The object-relational database management system now known as
<productname>PostgreSQL</productname> (and briefly called <productname>PostgreSQL</productname> (and briefly called
<productname>Postgres95</productname>) is derived from the <productname>Postgres95</productname>) is derived from the
<productname>Postgres</productname> package written at the University of <productname>POSTGRES</productname> package written at the University of
California at Berkeley. With over a decade of California at Berkeley. With over a decade of
development behind it, <productname>PostgreSQL</productname> development behind it, <productname>PostgreSQL</productname>
is the most advanced open-source database available anywhere, is the most advanced open-source database available anywhere,
...@@ -20,10 +20,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -20,10 +20,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
</para> </para>
<sect2> <sect2>
<title>The Berkeley <productname>Postgres</productname> Project</title> <title>The Berkeley <productname>POSTGRES</productname> Project</title>
<para> <para>
Implementation of the <productname>Postgres</productname> Implementation of the <productname>POSTGRES</productname>
<acronym>DBMS</acronym> began in 1986. The <acronym>DBMS</acronym> began in 1986. The
initial concepts for the system were presented in initial concepts for the system were presented in
<xref linkend="STON86"> <xref linkend="STON86">
...@@ -60,24 +60,24 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -60,24 +60,24 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
</para> </para>
<para> <para>
<productname>Postgres</productname> has been used <productname>POSTGRES</productname> has been used
to implement many different to implement many different
research and production applications. These include: a research and production applications. These include: a
financial data analysis system, a jet engine financial data analysis system, a jet engine
performance monitoring package, an asteroid tracking performance monitoring package, an asteroid tracking
database, a medical information database, and several database, a medical information database, and several
geographic information systems. geographic information systems.
<productname>Postgres</productname> has also been <productname>POSTGRES</productname> has also been
used as an educational tool at several universities. used as an educational tool at several universities.
Finally, Finally,
<ulink url="http://www.illustra.com/">Illustra Information Technologies</ulink> Illustra Information Technologies (later merged into
(since merged into <ulink url="http://www.informix.com/"><productname>Informix</productname></ulink>,
<ulink url="http://www.informix.com/"><productname>Informix</productname></ulink>) which is now owned by <ulink url="http://www.ibm.com/">IBM</ulink>.)
picked up picked up
the code and commercialized it. the code and commercialized it.
<productname>Postgres</productname> became the primary data manager <productname>POSTGRES</productname> became the primary data manager
for the for the
<ulink url="http://www.sdsc.edu/0/Parts_Collabs/S2K/s2k_home.html">Sequoia 2000</ulink> <ulink url="http://meteora.ucsd.edu/s2k/s2k_home.html">Sequoia 2000</ulink>
scientific computing project in late 1992. scientific computing project in late 1992.
</para> </para>
...@@ -88,7 +88,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -88,7 +88,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
support was taking up large amounts of time that should support was taking up large amounts of time that should
have been devoted to database research. In an effort have been devoted to database research. In an effort
to reduce this support burden, the Berkeley to reduce this support burden, the Berkeley
<productname>Postgres</productname> project officially <productname>POSTGRES</productname> project officially
ended with Version 4.2. ended with Version 4.2.
</para> </para>
</sect2> </sect2>
...@@ -98,10 +98,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -98,10 +98,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
<para> <para>
In 1994, Andrew Yu and Jolly Chen In 1994, Andrew Yu and Jolly Chen
added a SQL language interpreter to <productname>Postgres</productname>. added a SQL language interpreter to <productname>POSTGRES</productname>.
<productname>Postgres95</productname> was subsequently released to <productname>Postgres95</productname> was subsequently released to
the Web to find its own way in the world as an the Web to find its own way in the world as an
open-source descendant of the original <productname>Postgres</productname> open-source descendant of the original <productname>POSTGRES</productname>
Berkeley code. Berkeley code.
</para> </para>
...@@ -109,15 +109,15 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -109,15 +109,15 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
<productname>Postgres95</productname> code was completely <productname>Postgres95</productname> code was completely
ANSI C and trimmed in size by 25%. Many ANSI C and trimmed in size by 25%. Many
internal changes improved performance and maintainability. internal changes improved performance and maintainability.
<productname>Postgres95</productname> v1.0.x ran about 30-50% <productname>Postgres95</productname> release 1.0.x ran about 30-50%
faster on the Wisconsin Benchmark compared to faster on the Wisconsin Benchmark compared to
<productname>Postgres</productname> v4.2. <productname>POSTGRES</productname>, Version 4.2.
Apart from bug fixes, these were the major enhancements: Apart from bug fixes, the following were the major enhancements:
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
The query language <productname>Postquel</productname> was replaced with The query language PostQUEL was replaced with
<acronym>SQL</acronym> (implemented in the server). <acronym>SQL</acronym> (implemented in the server).
Subqueries were not supported until Subqueries were not supported until
<productname>PostgreSQL</productname> (see below), but they <productname>PostgreSQL</productname> (see below), but they
...@@ -150,7 +150,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -150,7 +150,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
<listitem> <listitem>
<para> <para>
The large object interface was overhauled. The Inversion large objects were The large-object interface was overhauled. The Inversion large objects were
the only mechanism for storing large objects. the only mechanism for storing large objects.
(The Inversion file system was removed.) (The Inversion file system was removed.)
</para> </para>
...@@ -175,7 +175,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -175,7 +175,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
<para> <para>
<acronym>GNU</acronym> make (instead of <acronym>BSD</acronym> make) was used <acronym>GNU</acronym> make (instead of <acronym>BSD</acronym> make) was used
for the build. Also, <productname>Postgres95</productname> could be for the build. Also, <productname>Postgres95</productname> could be
compiled with an unpatched <productname>gcc</productname> compiled with an unpatched <productname>GCC</productname>
(data alignment of doubles was fixed). (data alignment of doubles was fixed).
</para> </para>
</listitem> </listitem>
...@@ -190,11 +190,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -190,11 +190,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
By 1996, it became clear that the name <quote>Postgres95</quote> would By 1996, it became clear that the name <quote>Postgres95</quote> would
not stand the test of time. We chose a new name, not stand the test of time. We chose a new name,
<productname>PostgreSQL</productname>, to reflect the relationship <productname>PostgreSQL</productname>, to reflect the relationship
between the original <productname>Postgres</productname> and the more between the original <productname>POSTGRES</productname> and the more
recent versions with <acronym>SQL</acronym> capability. At the same recent versions with <acronym>SQL</acronym> capability. At the same
time, we set the version numbering to start at 6.0, putting the time, we set the version numbering to start at 6.0, putting the
numbers back into the sequence originally begun by the numbers back into the sequence originally begun by the Berkeley
<productname>Postgres</productname> Project. <productname>POSTGRES</productname> project.
</para> </para>
<para> <para>
...@@ -212,9 +212,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -212,9 +212,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
Table-level locking has been replaced with multiversion concurrency control, Table-level locking has been replaced by multiversion concurrency control,
which allows readers to continue reading consistent data during writer activity which allows readers to continue reading consistent data during writer activity
and enables hot backups from pg_dump while the database stays available for and enables hot backups from <application>pg_dump</> while the database stays available for
queries. queries.
</para> </para>
</listitem> </listitem>
...@@ -244,7 +244,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet ...@@ -244,7 +244,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/history.sgml,v 1.18 2001/11/28 20:49:10 pet
<listitem> <listitem>
<para> <para>
Overall backend code speed has been increased by approximately 20-40%, Overall backend code speed has been increased by approximately 20-40%,
and backend start-up time has decreased 80% since version 6.0 was released. and backend start-up time has decreased by 80% since version 6.0 was released.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.30 2001/12/04 01:22:13 tgl Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.31 2002/01/07 02:29:12 petere Exp $ -->
<chapter id="indexes"> <chapter id="indexes">
<title id="indexes-title">Indexes</title> <title id="indexes-title">Indexes</title>
...@@ -397,8 +397,8 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> ...@@ -397,8 +397,8 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable>
<literal>bigbox_ops</literal> both support R-tree indexes on the <literal>bigbox_ops</literal> both support R-tree indexes on the
<literal>box</literal> data type. The difference between them is <literal>box</literal> data type. The difference between them is
that <literal>bigbox_ops</literal> scales box coordinates down, that <literal>bigbox_ops</literal> scales box coordinates down,
to avoid floating point exceptions from doing multiplication, to avoid floating-point exceptions from doing multiplication,
addition, and subtraction on very large floating point addition, and subtraction on very large floating-point
coordinates. If the field on which your rectangles lie is about coordinates. If the field on which your rectangles lie is about
20 000 units square or larger, you should use 20 000 units square or larger, you should use
<literal>bigbox_ops</literal>. <literal>bigbox_ops</literal>.
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/inherit.sgml,v 1.17 2001/11/21 05:53:41 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/inherit.sgml,v 1.18 2002/01/07 02:29:12 petere Exp $
--> -->
<chapter id="inherit"> <chapter id="inherit">
...@@ -28,7 +28,7 @@ CREATE TABLE capitals ( ...@@ -28,7 +28,7 @@ CREATE TABLE capitals (
<type>text</type>, a native <productname>PostgreSQL</productname> type for variable length <type>text</type>, a native <productname>PostgreSQL</productname> type for variable length
ASCII strings. The type of the attribute population is ASCII strings. The type of the attribute population is
<type>float</type>, a native <productname>PostgreSQL</productname> type for double precision <type>float</type>, a native <productname>PostgreSQL</productname> type for double precision
floating point numbers. State capitals have an extra floating-point numbers. State capitals have an extra
attribute, state, that shows their state. In <productname>PostgreSQL</productname>, attribute, state, that shows their state. In <productname>PostgreSQL</productname>,
a table can inherit from zero or more other tables, a table can inherit from zero or more other tables,
and a query can reference either all rows of a and a query can reference either all rows of a
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/intro.sgml,v 1.18 2001/11/23 22:06:20 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/intro.sgml,v 1.19 2002/01/07 02:29:12 petere Exp $
--> -->
<preface id="preface"> <preface id="preface">
...@@ -38,8 +38,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/intro.sgml,v 1.18 2001/11/23 22:06:20 tgl E ...@@ -38,8 +38,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/intro.sgml,v 1.18 2001/11/23 22:06:20 tgl E
type. In current commercial systems, possible types type. In current commercial systems, possible types
include floating point numbers, integers, character include floating point numbers, integers, character
strings, money, and dates. It is commonly recognized strings, money, and dates. It is commonly recognized
that this model is inadequate for future data that this model is inadequate for future data-processing applications.
processing applications.
The relational model successfully replaced previous The relational model successfully replaced previous
models in part because of its <quote>Spartan simplicity</quote>. models in part because of its <quote>Spartan simplicity</quote>.
However, this simplicity makes the However, this simplicity makes the
...@@ -76,7 +75,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/intro.sgml,v 1.18 2001/11/23 22:06:20 tgl E ...@@ -76,7 +75,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/intro.sgml,v 1.18 2001/11/23 22:06:20 tgl E
<simpara>rules</simpara> <simpara>rules</simpara>
</listitem> </listitem>
<listitem> <listitem>
<simpara>transaction integrity</simpara> <simpara>transactional integrity</simpara>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</para> </para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpgeasy.sgml,v 2.7 2001/10/01 21:47:24 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpgeasy.sgml,v 2.8 2002/01/07 02:29:12 petere Exp $
--> -->
<chapter id="pgeasy-chapter"> <chapter id="pgeasy">
<title id="pgeasy"><application>libpgeasy</application> - Simplified C Library</title> <title><application>libpgeasy</application> - Simplified C Library</title>
<note> <note>
<title>Author</title> <title>Author</title>
...@@ -16,9 +16,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpgeasy.sgml,v 2.7 2001/10/01 21:47 ...@@ -16,9 +16,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpgeasy.sgml,v 2.7 2001/10/01 21:47
</note> </note>
<para> <para>
<productname>pgeasy</productname> allows you to cleanly interface <application>pgeasy</application> allows you to cleanly interface
to the <productname>libpq</productname> library, to the <application>libpq</application> library, more like a 4GL
more like a 4GL SQL interface. SQL interface. Refer to <xref linkend="libpq"> for more
information about <application>libpq</application>
</para> </para>
<para> <para>
...@@ -111,8 +112,8 @@ void unset_result(PGresult *oldres); ...@@ -111,8 +112,8 @@ void unset_result(PGresult *oldres);
For <literal>SELECT</literal> queries, <function>fetch</function> For <literal>SELECT</literal> queries, <function>fetch</function>
allows you to pass pointers as parameters, and on return the variables allows you to pass pointers as parameters, and on return the variables
are filled with data from the binary cursor you opened. These binary are filled with data from the binary cursor you opened. These binary
cursors can not be used if you are running the cursors cannot be used if you are running the
<productname>pgeasy</productname> <application>pgeasy</application>
client on a system with a different architecture than the database client on a system with a different architecture than the database
server. If you pass a NULL pointer parameter, the column is skipped. server. If you pass a NULL pointer parameter, the column is skipped.
<function>fetchwithnulls</function> allows you to retrieve the NULL <function>fetchwithnulls</function> allows you to retrieve the NULL
......
...@@ -9,22 +9,28 @@ ...@@ -9,22 +9,28 @@
<primary>Tcl</primary> <primary>Tcl</primary>
</indexterm> </indexterm>
<Para> <sect1 id="pgtcl-intro">
<literal>pgtcl</literal> is a Tcl package for front-end programs <title>Introduction</title>
to interface with <ProductName>PostgreSQL</ProductName>
backends. It makes most of the functionality of <literal>libpq</literal> available to
Tcl scripts.
</Para>
<Para> <para>
This package was originally written by Jolly Chen. <application>pgtcl</application> is a Tcl package for client
</Para> programs to interface with <ProductName>PostgreSQL</ProductName>
servers. It makes most of the functionality of
<application>libpq</application> available to Tcl scripts.
</para>
<Sect1 id="libpgtcl-commands"> <para>
<Title>Commands</Title> This package was originally written by Jolly Chen.
</para>
<Para> <para>
<TABLE TOCENTRY="1"> <xref linkend="pgtcl-commands-table"> gives an overview over the
commands available in <application>pgtcl</application>. These
commands are described further on subsequent pages.
</para>
<TABLE TOCENTRY="1" id="pgtcl-commands-table">
<TITLE><literal>pgtcl</literal> Commands</TITLE> <TITLE><literal>pgtcl</literal> Commands</TITLE>
<TGROUP COLS="2"> <TGROUP COLS="2">
<THEAD> <THEAD>
...@@ -106,34 +112,30 @@ This package was originally written by Jolly Chen. ...@@ -106,34 +112,30 @@ This package was originally written by Jolly Chen.
</TBODY> </TBODY>
</TGROUP> </TGROUP>
</TABLE> </TABLE>
</Para>
<Para>
These commands are described further on subsequent pages.
</Para>
<Para> <para>
The pg_lo* routines are interfaces to the Large Object features of The <function>pg_lo_*</function> routines are interfaces to the
<ProductName>PostgreSQL</ProductName>. large object features of <ProductName>PostgreSQL</ProductName>.
The functions are designed to mimic the analogous file system functions in The functions are designed to mimic the analogous file system
the standard Unix file system interface. functions in the standard Unix file system interface. The
The pg_lo* routines should be used within a BEGIN/END transaction <function>pg_lo_*</function> routines should be used within a
block because the file descriptor returned by pg_lo_open is only valid for <command>BEGIN</command>/<command>COMMIT</command> transaction
the current transaction. pg_lo_import and pg_lo_export MUST be used block because the file descriptor returned by
in a BEGIN/END transaction block. <function>pg_lo_open</function> is only valid for the current
</Para> transaction. <function>pg_lo_import</function> and
<function>pg_lo_export</function> <emphasis>must</emphasis> be used
</Sect1> in a <command>BEGIN</command>/<command>COMMIT</command> transaction
block.
<Sect1 id="libpgtcl-examples"> </para>
<Title>Examples</Title>
<para>
<example> <xref linkend="pgtcl-example"> shows a small example of how to use
the routines.
</para>
<example id="pgtcl-example">
<title><application>pgtcl</application> Example Program</title> <title><application>pgtcl</application> Example Program</title>
<para>
Here's a small example of how to use the routines:
<programlisting> <programlisting>
# getDBs : # getDBs :
# get the names of all the databases at a given host and port number # get the names of all the databases at a given host and port number
...@@ -151,10 +153,9 @@ proc getDBs { {host "localhost"} {port "5432"} } { ...@@ -151,10 +153,9 @@ proc getDBs { {host "localhost"} {port "5432"} } {
pg_disconnect $conn pg_disconnect $conn
return $datnames return $datnames
} }
</ProgramListing> </programlisting>
</para>
</example> </example>
</Sect1> </sect1>
<Sect1 id="libpgtcl-loading"> <Sect1 id="libpgtcl-loading">
<Title>Loading <application>pgtcl</application> into your application</Title> <Title>Loading <application>pgtcl</application> into your application</Title>
...@@ -165,7 +166,7 @@ proc getDBs { {host "localhost"} {port "5432"} } { ...@@ -165,7 +166,7 @@ proc getDBs { {host "localhost"} {port "5432"} } {
done with the Tcl <literal>load</> command. Here is an example: done with the Tcl <literal>load</> command. Here is an example:
<programlisting> <programlisting>
load libpgtcl[info sharedlibextension] load libpgtcl[info sharedlibextension]
</programlisting> </programlisting>
The use of <literal>info sharedlibextension</> is recommended in The use of <literal>info sharedlibextension</> is recommended in
...@@ -174,11 +175,13 @@ proc getDBs { {host "localhost"} {port "5432"} } { ...@@ -174,11 +175,13 @@ proc getDBs { {host "localhost"} {port "5432"} } {
</para> </para>
<para> <para>
The <literal>load</> command will fail unless the system's dynamic loader The <literal>load</> command will fail unless the system's dynamic
knows where to look for the <filename>libpgtcl</> shared library file. loader knows where to look for the <filename>libpgtcl</> shared
You may need to work with <literal>ldconfig</>, or set the environment library file. You may need to work with <command>ldconfig</>, or
variable <envar>LD_LIBRARY_PATH</>, or use some equivalent facility for set the environment variable <envar>LD_LIBRARY_PATH</>, or use
your platform to make it work. some equivalent facility for your platform to make it work. Refer
to the <productname>PostgreSQL</> installation instructions for
more information.
</para> </para>
<para> <para>
...@@ -209,7 +212,7 @@ proc getDBs { {host "localhost"} {port "5432"} } { ...@@ -209,7 +212,7 @@ proc getDBs { {host "localhost"} {port "5432"} } {
<REFNAMEDIV> <REFNAMEDIV>
<REFNAME>pg_connect <REFNAME>pg_connect
</REFNAME> </REFNAME>
<REFPURPOSE>opens a connection to the backend server <REFPURPOSE>open a connection to the backend server
</REFPURPOSE> </REFPURPOSE>
<INDEXTERM ID="IX-PGTCL-PGCONNECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> <INDEXTERM ID="IX-PGTCL-PGCONNECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
<INDEXTERM ID="IX-PGTCL-PGCONNECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM> <INDEXTERM ID="IX-PGTCL-PGCONNECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM>
...@@ -363,7 +366,7 @@ for info about the available options in the newer syntax. ...@@ -363,7 +366,7 @@ for info about the available options in the newer syntax.
<REFNAMEDIV> <REFNAMEDIV>
<REFNAME>pg_disconnect <REFNAME>pg_disconnect
</REFNAME> </REFNAME>
<REFPURPOSE>closes a connection to the backend server <REFPURPOSE>close a connection to the backend server
</REFPURPOSE> </REFPURPOSE>
<INDEXTERM ID="IX-PGTCL-PGDISCONNECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> <INDEXTERM ID="IX-PGTCL-PGDISCONNECT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
<INDEXTERM ID="IX-PGTCL-PGDISCONNECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM> <INDEXTERM ID="IX-PGTCL-PGDISCONNECT-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM>
...@@ -522,7 +525,7 @@ current default value for each option. ...@@ -522,7 +525,7 @@ current default value for each option.
<REFNAME>pg_exec <REFNAME>pg_exec
</REFNAME> </REFNAME>
<REFPURPOSE> <REFPURPOSE>
send a query string to the backend send a command string to the server
</REFPURPOSE> </REFPURPOSE>
<INDEXTERM ID="IX-PGTCL-PGEXEC-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM> <INDEXTERM ID="IX-PGTCL-PGEXEC-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>connecting</SECONDARY></INDEXTERM>
<INDEXTERM ID="IX-PGTCL-PGEXEC-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM> <INDEXTERM ID="IX-PGTCL-PGEXEC-2"><PRIMARY>pg_connect</PRIMARY></INDEXTERM>
...@@ -999,7 +1002,7 @@ This would work if table <classname>table</> has fields <structfield>control</> ...@@ -999,7 +1002,7 @@ This would work if table <classname>table</> has fields <structfield>control</>
<REFNAMEDIV> <REFNAMEDIV>
<REFNAME>pg_listen <REFNAME>pg_listen
</REFNAME> </REFNAME>
<REFPURPOSE>sets or changes a callback for asynchronous NOTIFY messages <REFPURPOSE>set or change a callback for asynchronous NOTIFY messages
</REFPURPOSE> </REFPURPOSE>
<INDEXTERM ID="IX-PGTCL-PGLISTEN-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>notify</SECONDARY></INDEXTERM> <INDEXTERM ID="IX-PGTCL-PGLISTEN-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>notify</SECONDARY></INDEXTERM>
<INDEXTERM ID="IX-PGTCL-PGLISTEN-2"><PRIMARY>notify</PRIMARY></INDEXTERM> <INDEXTERM ID="IX-PGTCL-PGLISTEN-2"><PRIMARY>notify</PRIMARY></INDEXTERM>
...@@ -1859,7 +1862,7 @@ None ...@@ -1859,7 +1862,7 @@ None
<REFNAMEDIV> <REFNAMEDIV>
<REFNAME>pg_lo_import <REFNAME>pg_lo_import
</REFNAME> </REFNAME>
<REFPURPOSE>import a large object from a Unix file <REFPURPOSE>import a large object from a file
</REFPURPOSE> </REFPURPOSE>
<INDEXTERM ID="IX-PGTCL-PGLOIMPORT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>import</SECONDARY></INDEXTERM> <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> <INDEXTERM ID="IX-PGTCL-PGLOIMPORT-2"><PRIMARY>pg_lo_import</PRIMARY></INDEXTERM>
...@@ -1944,7 +1947,7 @@ None ...@@ -1944,7 +1947,7 @@ None
<REFNAMEDIV> <REFNAMEDIV>
<REFNAME>pg_lo_export <REFNAME>pg_lo_export
</REFNAME> </REFNAME>
<REFPURPOSE>export a large object to a Unix file <REFPURPOSE>export a large object to a file
</REFPURPOSE> </REFPURPOSE>
<INDEXTERM ID="IX-PGTCL-PGLOEXPORT-1"><PRIMARY>pgtcl</PRIMARY><SECONDARY>export</SECONDARY></INDEXTERM> <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> <INDEXTERM ID="IX-PGTCL-PGLOEXPORT-2"><PRIMARY>pg_lo_export</PRIMARY></INDEXTERM>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:15 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.40 2002/01/07 02:29:12 petere Exp $
--> -->
<chapter id="libpqplusplus"> <chapter id="libpqplusplus">
<title><application>libpq++</application> - C++ Binding Library</title> <title><application>libpq++</application> - C++ Binding Library</title>
<indexterm zone="libpqplusplus">
<primary>libpq++</primary>
</indexterm>
<indexterm zone="libpqplusplus">
<primary>C++</primary>
</indexterm>
<sect1 id="libpqpp-introduction">
<title>Introduction</title>
<para> <para>
<filename>libpq++</filename> is the C++ API to <application>libpq++</application> is the C++ API to
<productname>PostgreSQL</productname>. <productname>PostgreSQL</productname>.
<filename>libpq++</filename> is a set of classes that allow <application>libpq++</application> is a set of classes that allow
client programs to connect to the client programs to connect to the
<productname>PostgreSQL</productname> backend server. These connections <productname>PostgreSQL</productname> backend server. These connections
come in two forms: a Database Class and a Large Object class. come in two forms: a database class and a large object class.
</para> </para>
<para> <para>
The Database Class is intended for manipulating a database. You can The database class is intended for manipulating a database. You can
send all sorts of SQL queries to the <productname>PostgreSQL</productname> send all sorts of SQL queries and commands to the <productname>PostgreSQL</productname>
backend server and retrieve the responses of the server. backend server and retrieve the responses of the server.
</para> </para>
<para> <para>
The Large Object Class is intended for manipulating a large object The large object class is intended for manipulating a large object
in a database. Although a Large Object instance can send normal in a database. Although a large object instance can send normal
queries to the <productname>PostgreSQL</productname> backend server queries to the <productname>PostgreSQL</productname> backend server
it is only intended for simple it is only intended for simple
queries that do not return any data. A large object should be seen queries that do not return any data. A large object should be seen
...@@ -35,16 +45,15 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -35,16 +45,15 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
</para> </para>
<para> <para>
This chapter is based on the documentation This chapter is based on the documentation for the
for the <filename>libpq</filename> C library. Three <application>libpq</application> C library (see <xref
short programs are listed at the end of this section as examples of linkend="libpq">). There
<filename>libpq++</filename> programming are several examples of <application>libpq++</application>
(though not necessarily of good programming).
There are several examples of <filename>libpq++</filename>
applications in applications in
<filename>src/libpq++/examples</filename>, including the source <filename>src/interfaces/libpq++/examples</filename> in the source
code for the three examples in this chapter. distribution.
</para> </para>
</sect1>
<sect1 id="libpqpp-init"> <sect1 id="libpqpp-init">
<title>Control and Initialization</title> <title>Control and Initialization</title>
...@@ -217,45 +226,51 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -217,45 +226,51 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
<para> <para>
<function>PgConnection</function> <function>PgConnection</function>
makes a new connection to a backend database server. makes a new connection to a backend database server.
<synopsis> <synopsis>
PgConnection::PgConnection(const char *conninfo) PgConnection::PgConnection(const char *conninfo)
</synopsis> </synopsis>
The <quote>conninfo</> string is the same as for the underlying The <parameter>conninfo</> string is the same as for the underlying
libpq <function>PQconnectdb</> function. <application>libpq</> <function>PQconnectdb</> function.
</para>
<para>
Although typically called from one of the access classes, a connection to Although typically called from one of the access classes, a connection to
a backend server is possible by creating a <classname>PgConnection</> object. a backend server is possible by creating a <classname>PgConnection</> object.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>ConnectionBad</function> <function>ConnectionBad</function>
returns whether or not the connection to the backend server succeeded or returns whether or not the connection to the backend server succeeded or
failed. failed.
<synopsis> <synopsis>
bool PgConnection::ConnectionBad() const bool PgConnection::ConnectionBad() const
</synopsis> </synopsis>
Returns true if the connection failed. Returns true if the connection failed.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>Status</function> <function>Status</function>
returns the status of the connection to the backend server. returns the status of the connection to the backend server.
<synopsis> <synopsis>
ConnStatusType PgConnection::Status() ConnStatusType PgConnection::Status()
</synopsis> </synopsis>
Returns either CONNECTION_OK or CONNECTION_BAD depending on the state Returns either <symbol>CONNECTION_OK</> or
of the connection. <symbol>CONNECTION_BAD</> depending on the state of the
connection.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>PgDatabase</function> <function>PgDatabase</function>
makes a new connection to a backend database server. makes a new connection to a backend database server.
<synopsis> <synopsis>
PgDatabase(const char *conninfo) PgDatabase(const char *conninfo)
</synopsis> </synopsis>
After a <classname>PgDatabase</classname> has been created it should be checked to make sure After a <classname>PgDatabase</classname> has been created it should be checked to make sure
the connection to the database succeeded before sending the connection to the database succeeded before sending
queries to the object. This can easily be done by queries to the object. This can easily be done by
...@@ -263,24 +278,26 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -263,24 +278,26 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
<function>Status</function> or <function>ConnectionBad</function> methods. <function>Status</function> or <function>ConnectionBad</function> methods.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>DBName</function> <function>DBName</function>
Returns the name of the current database. returns the name of the current database.
<synopsis> <synopsis>
const char *PgConnection::DBName() const char *PgConnection::DBName()
</synopsis> </synopsis>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>Notifies</function> <function>Notifies</function>
Returns the next notification from a list of unhandled notification messages returns the next notification from a list of unhandled notification messages
received from the backend. received from the backend.
<synopsis> <synopsis>
PGnotify* PgConnection::Notifies() PGnotify* PgConnection::Notifies()
</synopsis> </synopsis>
See <function>PQnotifies</function> for details. See <function>PQnotifies</function> in <application>libpq</> for details.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
...@@ -297,19 +314,20 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -297,19 +314,20 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
<listitem> <listitem>
<para> <para>
<function>Exec</function> <function>Exec</function>
Sends a query to the backend server. It's probably more desirable to sends a command to the backend server. It's probably more desirable to
use one of the next two functions. use one of the next two functions.
<synopsis> <synopsis>
ExecStatusType PgConnection::Exec(const char* query) ExecStatusType PgConnection::Exec(const char* query)
</synopsis> </synopsis>
Returns the result of the query. The following status results can be expected: Returns the result status of the command. The following status
results can be expected:
<simplelist> <simplelist>
<member> <member>
<symbol>PGRES_EMPTY_QUERY</symbol> <symbol>PGRES_EMPTY_QUERY</symbol>
</member> </member>
<member> <member>
<symbol>PGRES_COMMAND_OK</symbol>, if the query was a command <symbol>PGRES_COMMAND_OK</symbol>, if the command was not a query
</member> </member>
<member> <member>
<symbol>PGRES_TUPLES_OK</symbol>, if the query successfully returned tuples <symbol>PGRES_TUPLES_OK</symbol>, if the query successfully returned tuples
...@@ -332,353 +350,342 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -332,353 +350,342 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
</simplelist> </simplelist>
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>ExecCommandOk</function> <function>ExecCommandOk</function> sends a non-query command
Sends a command query to the backend server. (one that does not return rows) to the backend server.
<synopsis> <synopsis>
int PgConnection::ExecCommandOk(const char *query) int PgConnection::ExecCommandOk(const char *query)
</synopsis> </synopsis>
Returns TRUE if the command query succeeds. Returns true (1) if the command succeeds.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>ExecTuplesOk</function> <function>ExecTuplesOk</function>
Sends a command query to the backend server. Sends a query command (one that returns rows) to the backend server.
<synopsis> <synopsis>
int PgConnection::ExecTuplesOk(const char *query) int PgConnection::ExecTuplesOk(const char *query)
</synopsis> </synopsis>
Returns TRUE if the command query succeeds. Returns true (1) if the query succeeds.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>ErrorMessage</function> <function>ErrorMessage</function>
Returns the last error message text. returns the last error message text.
<synopsis> <synopsis>
const char *PgConnection::ErrorMessage() const char *PgConnection::ErrorMessage()
</synopsis> </synopsis>
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</para> </para>
</sect2> </sect2>
<sect2 id="libpqpp-exec-select-info"> <sect2 id="libpqpp-exec-select-info">
<title>Retrieving SELECT Result Information</title> <title>Retrieving SELECT Result Information</title>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
<function>Tuples</function> <function>Tuples</function>
Returns the number of tuples (rows) in the query result. returns the number of tuples (rows) in the query result.
<synopsis> <synopsis>
int PgDatabase::Tuples() const int PgDatabase::Tuples() const
</synopsis> </synopsis>
</para> </para>
</listitem> </listitem>
<listitem>
<para> <listitem>
<function>Fields</function> <para>
Returns the number of fields (attributes) in each tuple of the query result. <function>Fields</function>
<synopsis> returns the number of fields (rows) in each tuple of the query result.
int PgDatabase::Fields() <synopsis>
</synopsis> int PgDatabase::Fields()
</para> </synopsis>
</listitem> </para>
<listitem> </listitem>
<para>
<function>FieldName</function> <listitem>
Returns the field (attribute) name associated with the given field index. <para>
Field indices start at 0. <function>FieldName</function>
<synopsis> returns the field (column) name associated with the given field index.
const char *PgDatabase::FieldName(int field_num) const Field indices start at 0.
</synopsis> <synopsis>
</para> const char *PgDatabase::FieldName(int field_num) const
</listitem> </synopsis>
<listitem> </para>
<para> </listitem>
<function>FieldNum</function>
<function>PQfnumber</function> Returns the field (attribute) index associated with <listitem>
the given field name. <para>
<synopsis> <function>FieldNum</function>
int PgDatabase::FieldNum(const char* field_name) const returns the field (column) index associated with
</synopsis> the given field name.
-1 is returned if the given name does not match any field. <synopsis>
</para> int PgDatabase::FieldNum(const char* field_name) const
</listitem> </synopsis>
<listitem> -1 is returned if the given name does not match any field.
<para> </para>
<function>FieldType</function> </listitem>
Returns the field type associated with the given field index. The
integer returned is an internal coding of the type. Field indices <listitem>
start at 0. <para>
<synopsis> <function>FieldType</function>
Oid PgDatabase::FieldType(int field_num) const returns the field type associated with the given field index. The
</synopsis> integer returned is an internal coding of the type. Field indices
</para> start at 0.
</listitem> <synopsis>
<listitem> Oid PgDatabase::FieldType(int field_num) const
<para> </synopsis>
<function>FieldType</function> </para>
Returns the field type associated with the given field name. The </listitem>
integer returned is an internal coding of the type. Field indices
start at 0. <listitem>
<synopsis> <para>
Oid PgDatabase::FieldType(const char* field_name) const <function>FieldType</function>
</synopsis> returns the field type associated with the given field name. The
</para> integer returned is an internal coding of the type. Field indices
</listitem> start at 0.
<listitem> <synopsis>
<para> Oid PgDatabase::FieldType(const char* field_name) const
<function>FieldSize</function> </synopsis>
Returns the size in bytes of the field associated with the given </para>
field index. Field indices start at 0. </listitem>
<synopsis>
int PgDatabase::FieldSize(int field_num) const <listitem>
</synopsis> <para>
Returns the space allocated for this field in a database tuple given <function>FieldSize</function>
the field number. In other words the size of the server's binary returns the size in bytes of the field associated with the given
representation of the data type. -1 is returned if the field is field index. Field indices start at 0.
variable size. <synopsis>
</para> int PgDatabase::FieldSize(int field_num) const
</listitem> </synopsis>
<listitem> Returns the space allocated for this field in a database tuple
<para> given the field number. In other words the size of the server's
<function>FieldSize</function> binary representation of the data type. -1 is returned if the
Returns the size in bytes of the field associated with the given field is variable size.
field index. Field indices start at 0. </para>
<synopsis> </listitem>
int PgDatabase::FieldSize(const char *field_name) const
</synopsis> <listitem>
Returns the space allocated for this field in a database tuple given <para>
the field name. In other words the size of the server's binary <function>FieldSize</function>
representation of the data type. -1 is returned if the field is returns the size in bytes of the field associated with the given
variable size. field index. Field indices start at 0.
</para> <synopsis>
</listitem> int PgDatabase::FieldSize(const char *field_name) const
</itemizedlist> </synopsis>
</sect2> Returns the space allocated for this field in a database tuple
given the field name. In other words the size of the server's
binary representation of the data type. -1 is returned if the
field is variable size.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="libpqpp-exec-select-values"> <sect2 id="libpqpp-exec-select-values">
<title>Retrieving SELECT Result Values</title> <title>Retrieving SELECT Result Values</title>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
<function>GetValue</function> <function>GetValue</function> returns a single field (column)
Returns a single field (attribute) value of one tuple of a <structname>PGresult</structname>. value of one tuple of a <structname>PGresult</structname>.
Tuple and field indices start at 0. Tuple and field indices start at 0.
<synopsis> <synopsis>
const char *PgDatabase::GetValue(int tup_num, int field_num) const const char *PgDatabase::GetValue(int tup_num, int field_num) const
</synopsis> </synopsis>
For most queries, the value returned by <function>GetValue</function> is a null-terminated For most queries, the value returned by
string representation of the attribute value. But if <function>BinaryTuples</function> <function>GetValue</function> is a null-terminated string
is TRUE, the value returned by <function>GetValue</function> is the binary representation representation of the attribute value. But if
of the type in the internal format of the backend server (but not including <function>BinaryTuples</function> is true, the value returned by
the size word, if the field is variable-length). It is then the programmer's <function>GetValue</function> is the binary representation of
responsibility to cast and convert the data to the correct C type. The the type in the internal format of the backend server (but not
pointer returned by <function>GetValue</function> points to storage that is part of the including the size word, if the field is variable-length). It is
<structname>PGresult</structname> structure. One should not modify it, and one must explicitly then the programmer's responsibility to cast and convert the
copy the value into other storage if it is to be used past the lifetime data to the correct C type. The pointer returned by
of the <structname>PGresult</structname> structure itself. <function>BinaryTuples</function> is not yet implemented. <function>GetValue</function> points to storage that is part of
</para> the <structname>PGresult</structname> structure. One should not
</listitem> modify it, and one must explicitly copy the value into other
<listitem> storage if it is to be used past the lifetime of the
<para> <structname>PGresult</structname> structure itself.
<function>GetValue</function> <function>BinaryTuples</function> is not yet implemented.
Returns a single field (attribute) value of one tuple of a <structname>PGresult</structname>. </para>
Tuple and field indices start at 0. </listitem>
<synopsis>
const char *PgDatabase::GetValue(int tup_num, const char *field_name) const
</synopsis>
For most queries, the value returned by <function>GetValue</function> is a null-terminated
string representation of the attribute value. But if <function>BinaryTuples</function>
is TRUE, the value returned by <function>GetValue</function> is the binary representation
of the type in the internal format of the backend server (but not including
the size word, if the field is variable-length). It is then the programmer's
responsibility to cast and convert the data to the correct C type. The
pointer returned by <function>GetValue</function> points to storage that is part of the
<structname>PGresult</structname> structure. One should not modify it, and one must explicitly
copy the value into other storage if it is to be used past the lifetime
of the <structname>PGresult</structname> structure itself. <function>BinaryTuples</function> is not yet implemented.
</para>
</listitem>
<listitem>
<para>
<function>GetLength</function>
Returns the length of a field (attribute) in bytes. Tuple and field
indices start at 0.
<synopsis>
int PgDatabase::GetLength(int tup_num, int field_num) const
</synopsis>
This is the actual data length for the particular data value, that
is the size of the object pointed to by <function>GetValue</function>. Note that for
ASCII-represented values, this size has little to do with the binary
size reported by <function>PQfsize</function>.
</para>
</listitem>
<listitem>
<para>
<function>GetLength</function>
Returns the length of a field (attribute) in bytes. Tuple and field
indices start at 0.
<synopsis>
int PgDatabase::GetLength(int tup_num, const char* field_name) const
</synopsis>
This is the actual data length for the particular data value, that
is the size of the object pointed to by <function>GetValue</function>. Note that for
ASCII-represented values, this size has little to do with the binary
size reported by <function>PQfsize</function>.
</para>
</listitem>
<listitem>
<para>
<function>GetIsNull</function>
Returns whether a field has the null value.
<synopsis>
bool GetIsNull(int tup_num, int field_num) const
</synopsis>
Note that <function>GetValue</function> will return the empty string for null fields, not
the NULL pointer.
</para>
</listitem>
<listitem>
<para>
<function>GetIsNull</function>
Returns whether a field has the null value.
<synopsis>
bool GetIsNull(int tup_num, const char *field_name) const
</synopsis>
Note that <function>GetValue</function> will return the empty string for null fields, not
the NULL pointer.
</para>
</listitem>
<listitem>
<para>
<function>DisplayTuples</function>
OBSOLESCENT: Prints out all the tuples and, optionally, the attribute names to the
specified output stream.
<synopsis>
void PgDatabase::DisplayTuples(FILE *out = 0, bool fillAlign = true,
const char* fieldSep = "|",bool printHeader = true, bool quiet = false) const
</synopsis>
</para>
</listitem>
<listitem>
<para>
<function>PrintTuples</function>
OBSOLESCENT: Prints out all the tuples and, optionally, the attribute names to the
specified output stream.
<synopsis>
void PgDatabase::PrintTuples(FILE *out = 0, bool printAttName = true,
bool terseOutput = false, bool fillAlign = false) const
</synopsis>
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="libpqpp-exec-nonselect"> <listitem>
<title>Retrieving Non-SELECT Result Information</title> <para>
<function>GetValue</function> returns a single field (column)
value of one tuple of a <structname>PGresult</structname>.
Tuple and field indices start at 0.
<synopsis>
const char *PgDatabase::GetValue(int tup_num, const char *field_name) const
</synopsis>
For most queries, the value returned by
<function>GetValue</function> is a null-terminated string
representation of the attribute value. But if
<function>BinaryTuples</function> is true, the value returned by
<function>GetValue</function> is the binary representation of
the type in the internal format of the backend server (but not
including the size word, if the field is variable-length). It is
then the programmer's responsibility to cast and convert the
data to the correct C type. The pointer returned by
<function>GetValue</function> points to storage that is part of
the <structname>PGresult</structname> structure. One should not
modify it, and one must explicitly copy the value into other
storage if it is to be used past the lifetime of the
<structname>PGresult</structname> structure itself.
<function>BinaryTuples</function> is not yet implemented.
</para>
</listitem>
<itemizedlist> <listitem>
<listitem> <para>
<para> <function>GetLength</function> returns the length of a field
<function>CmdTuples</function> (column) in bytes. Tuple and field indices start at 0.
Returns the number of rows affected after an INSERT, UPDATE or DELETE. <synopsis>
If the command was anything else, it returns -1. int PgDatabase::GetLength(int tup_num, int field_num) const
<synopsis> </synopsis>
int PgDatabase::CmdTuples() const This is the actual data length for the particular data value,
</synopsis> that is the size of the object pointed to by
</para> <function>GetValue</function>. Note that for
</listitem> character-represented values, this size has little to do with
the binary size reported by <function>PQfsize</function>.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
<function>OidStatus</function> <function>GetLength</function> returns the length of a field
<synopsis> (column) in bytes. Tuple and field indices start at 0.
const char *PgDatabase::OidStatus() const <synopsis>
</synopsis> int PgDatabase::GetLength(int tup_num, const char* field_name) const
</para> </synopsis>
</listitem> This is the actual data length for the particular data value,
</itemizedlist> that is the size of the object pointed to by
</sect2> <function>GetValue</function>. Note that for
character-represented values, this size has little to do with
the binary size reported by <function>PQfsize</function>.
</para>
</listitem>
<sect2 id="libpqpp-exec-copy"> <listitem>
<title>Handling COPY Queries</title> <para>
<function>GetIsNull</function>
returns whether a field has the null value.
<synopsis>
bool GetIsNull(int tup_num, int field_num) const
</synopsis>
Note that <function>GetValue</function> will return the empty
string for null fields, not the NULL pointer.
</para>
</listitem>
<itemizedlist> <listitem>
<listitem> <para>
<para> <function>GetIsNull</function> returns whether a field has the
<function>GetLine</function> null value.
<synopsis> <synopsis>
int PgDatabase::GetLine(char* string, int length) bool GetIsNull(int tup_num, const char *field_name) const
</synopsis> </synopsis>
</para> Note that <function>GetValue</function> will return the empty
</listitem> string for null fields, not the NULL pointer.
<listitem> </para>
<para> </listitem>
<function>PutLine</function>
<synopsis>
void PgDatabase::PutLine(const char* string)
</synopsis>
</para>
</listitem>
<listitem>
<para>
<function>EndCopy</function>
<synopsis>
int PgDatabase::EndCopy()
</synopsis>
</para>
</listitem>
</itemizedlist>
</sect2> <listitem>
</sect1> <para>
<function>DisplayTuples</function> prints out all the tuples
and, optionally, the attribute names to the specified output
stream.
<synopsis>
void PgDatabase::DisplayTuples(FILE *out = 0, bool fillAlign = true,
const char* fieldSep = "|", bool printHeader = true, bool quiet = false) const
</synopsis>
This function is obsolescent.
</para>
</listitem>
<listitem>
<para>
<function>PrintTuples</function> prints out all the tuples and,
optionally, the attribute names to the specified output stream.
<synopsis>
void PgDatabase::PrintTuples(FILE *out = 0, bool printAttName = true,
bool terseOutput = false, bool fillAlign = false) const
</synopsis>
This function is obsolescent.
</para>
</listitem>
</itemizedlist>
</sect2>
<sect2 id="libpqpp-exec-nonselect">
<title>Retrieving Non-SELECT Result Information</title>
<itemizedlist>
<listitem>
<para>
<function>CmdTuples</function> returns the number of rows
affected after an <command>INSERT</command>,
<command>UPDATE</command>, or <command>DELETE</command>. If the
command was anything else, it returns -1.
<synopsis>
int PgDatabase::CmdTuples() const
</synopsis>
</para>
</listitem>
<listitem>
<para>
<function>OidStatus</function>
<synopsis>
const char *PgDatabase::OidStatus() const
</synopsis>
</para>
</listitem>
</itemizedlist>
</sect2>
</sect1>
<sect1 id="libpqpp-notify"> <sect1 id="libpqpp-notify">
<title>Asynchronous Notification</title> <title>Asynchronous Notification</title>
<para> <para>
<productname>PostgreSQL</productname> supports asynchronous notification <productname>PostgreSQL</productname> supports asynchronous
via the <command>LISTEN</command> and <command>NOTIFY</command> notification via the <command>LISTEN</command> and
commands. A backend registers its interest in a particular semaphore <command>NOTIFY</command> commands. A backend registers its
with the <command>LISTEN</command> command. interest in a particular notification condition with the
All backends that are listening on a <command>LISTEN</command> command. All backends that are
particular named semaphore will be notified asynchronously when listening on a particular condition will be notified
a <command>NOTIFY</command> of asynchronously when a <command>NOTIFY</command> of that name is
that name is executed by another backend. No additional executed by another backend. No additional information is passed
information is passed from the notifier to the listener. Thus, from the notifier to the listener. Thus, typically, any actual
typically, any actual data that needs to be communicated is transferred data that needs to be communicated is transferred through a
through the relation. relation.
<note>
<para>
In the past, the documentation has associated the names used for asynchronous
notification with relations or classes. However, there is in fact no
direct linkage of the two concepts in the implementation, and the
named semaphore in fact does not need to have a corresponding relation
previously defined.
</para>
</note>
</para> </para>
<para> <para>
<filename>libpq++</filename> applications are notified whenever a <application>libpq++</application> applications are notified whenever a
connected backend has connected backend has
received an asynchronous notification. However, the communication from received an asynchronous notification. However, the communication from
the backend to the frontend is not asynchronous. the backend to the frontend is not asynchronous.
The <filename>libpq++</filename> application The <application>libpq++</application> application
must poll the backend to see if there is any pending notification must poll the backend to see if there is any pending notification
information. After the execution of a query, a frontend may call information. After the execution of a command, a frontend may call
<function>PgDatabase::Notifies</function> <function>PgDatabase::Notifies</function>
to see if any notification data is currently available from the backend. to see if any notification data is currently available from the backend.
<function>PgDatabase::Notifies</function> <function>PgDatabase::Notifies</function>
returns the notification from a list of unhandled notifications from the returns the notification from a list of unhandled notifications from the
backend. The function returns NULL if there are no pending notifications backend. The function returns <symbol>NULL</symbol> if there are no pending notifications
from the backend. from the backend.
<function>PgDatabase::Notifies</function> <function>PgDatabase::Notifies</function>
behaves like the popping of a stack. Once a notification is returned behaves like the popping of a stack. Once a notification is returned
...@@ -692,9 +699,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -692,9 +699,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
<function>PgDatabase::Notifies</function> <function>PgDatabase::Notifies</function>
retrieves pending notifications from the server. retrieves pending notifications from the server.
<synopsis> <synopsis>
PGnotify* PgDatabase::Notifies() PGnotify* PgDatabase::Notifies()
</synopsis> </synopsis>
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
...@@ -709,9 +716,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -709,9 +716,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
<title>Functions Associated with the COPY Command</title> <title>Functions Associated with the COPY Command</title>
<para> <para>
The <command>copy</command> command in <productname>PostgreSQL</productname> The <command>COPY</command> command in <productname>PostgreSQL</productname>
has options to read from or write to the network has options to read from or write to the network
connection used by <filename>libpq++</filename>. connection used by <application>libpq++</application>.
Therefore, functions are necessary to Therefore, functions are necessary to
access this network connection directly so applications may take full access this network connection directly so applications may take full
advantage of this capability. advantage of this capability.
...@@ -724,32 +731,33 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -724,32 +731,33 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
backend server) into a buffer backend server) into a buffer
<replaceable class="parameter">string</replaceable> <replaceable class="parameter">string</replaceable>
of size <replaceable class="parameter">length</replaceable>. of size <replaceable class="parameter">length</replaceable>.
<synopsis> <synopsis>
int PgDatabase::GetLine(char* string, int length) int PgDatabase::GetLine(char* string, int length)
</synopsis> </synopsis>
</para> </para>
<para> <para>
Like the Unix system routine Like the Unix system routine
<function>fgets (3)</function>, <function>fgets()</function>,
this routine copies up to this routine copies up to
<literal><replaceable class="parameter">length</replaceable>-1</literal> <literal><replaceable class="parameter">length</replaceable>-1</literal>
characters into characters into
<replaceable class="parameter">string</replaceable>. <replaceable class="parameter">string</replaceable>.
It is like It is like
<function>gets (3)</function>, <function>gets()</function>,
however, in that it converts the terminating newline into a null however, in that it converts the terminating newline into a zero byte.
character.
</para> </para>
<para> <para>
<function>PgDatabase::GetLine</function> <function>PgDatabase::GetLine</function>
returns EOF at end of file, 0 if the entire line has been read, and 1 if the returns <symbol>EOF</symbol> at end of file, 0 if the entire line has been read, and 1 if the
buffer is full but the terminating newline has not yet been read. buffer is full but the terminating newline has not yet been read.
</para> </para>
<para> <para>
Notice that the application must check to see if a new line consists Notice that the application must check to see if a new line consists
of a single period ("."), which indicates that the backend of a backslash followed by a period (<literal>\.</>), which indicates
that the backend
server has finished sending the results of the server has finished sending the results of the
<command>copy</command>. <command>COPY</command>.
Therefore, if the application ever expects to receive lines Therefore, if the application ever expects to receive lines
that are more than that are more than
<literal><replaceable class="parameter">length</replaceable>-1</literal> <literal><replaceable class="parameter">length</replaceable>-1</literal>
...@@ -762,24 +770,24 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -762,24 +770,24 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
<function>PgDatabase::PutLine</function> <function>PgDatabase::PutLine</function>
Sends a null-terminated <replaceable class="parameter">string</replaceable> Sends a null-terminated <replaceable class="parameter">string</replaceable>
to the backend server. to the backend server.
<synopsis> <synopsis>
void PgDatabase::PutLine(char* string) void PgDatabase::PutLine(char* string)
</synopsis> </synopsis>
</para> </para>
<para> <para>
The application must explicitly send a single period character (".") The application must explicitly send the characters <literal>\.</literal>
to indicate to the backend that it has finished sending its data. to indicate to the backend that it has finished sending its data.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>PgDatabase::EndCopy</function> <function>PgDatabase::EndCopy</function>
syncs with the backend. synchronizes with the backend.
<synopsis> <synopsis>
int PgDatabase::EndCopy() int PgDatabase::EndCopy()
</synopsis> </synopsis>
This function waits until the backend has This function waits until the backend has
finished processing the <command>copy</command>. finished processing the <command>COPY</command>.
It should either be issued when the It should either be issued when the
last string has been sent to the backend using last string has been sent to the backend using
<function>PgDatabase::PutLine</function> <function>PgDatabase::PutLine</function>
...@@ -787,7 +795,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -787,7 +795,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
<function>PgDatabase::GetLine</function>. <function>PgDatabase::GetLine</function>.
It must be issued or the backend may get <quote>out of sync</quote> with It must be issued or the backend may get <quote>out of sync</quote> with
the frontend. Upon return from this function, the backend is ready to the frontend. Upon return from this function, the backend is ready to
receive the next query. receive the next command.
</para> </para>
<para> <para>
The return value is 0 on successful completion, nonzero otherwise. The return value is 0 on successful completion, nonzero otherwise.
...@@ -795,19 +803,20 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01: ...@@ -795,19 +803,20 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.39 2001/11/29 16:01:
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</para> </para>
<para> <para>
As an example: As an example:
<programlisting> <programlisting>
PgDatabase data; PgDatabase data;
data.Exec("CREATE TABLE foo (a int4, b char(16), d double precision)"); data.Exec("CREATE TABLE foo (a int4, b char(16), d double precision)");
data.Exec("COPY foo FROM STDIN"); data.Exec("COPY foo FROM STDIN");
data.PutLine("3\tHello World\t4.5\n"); data.PutLine("3\tHello World\t4.5\n");
data.PutLine("4\tGoodbye World\t7.11\n"); data.PutLine("4\tGoodbye World\t7.11\n");
&amp;... ...
data.PutLine("\\.\n"); data.PutLine("\\.\n");
data.EndCopy(); data.EndCopy();
</programlisting> </programlisting>
</para> </para>
</sect1> </sect1>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.84 2001/11/29 16:01:15 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.85 2002/01/07 02:29:12 petere Exp $
--> -->
<chapter id="libpq"> <chapter id="libpq">
...@@ -9,6 +9,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.84 2001/11/29 16:01:15 peter ...@@ -9,6 +9,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.84 2001/11/29 16:01:15 peter
<primary>libpq</primary> <primary>libpq</primary>
</indexterm> </indexterm>
<sect1 id="libpq-intro">
<title>Introduction</title>
<para> <para>
<application>libpq</application> is the <acronym>C</acronym> <application>libpq</application> is the <acronym>C</acronym>
application programmer's interface to application programmer's interface to
...@@ -40,6 +43,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.84 2001/11/29 16:01:15 peter ...@@ -40,6 +43,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.84 2001/11/29 16:01:15 peter
header file <filename>libpq-fe.h</filename> and must link with the header file <filename>libpq-fe.h</filename> and must link with the
<filename>libpq</filename> library. <filename>libpq</filename> library.
</para> </para>
</sect1>
<sect1 id="libpq-connect"> <sect1 id="libpq-connect">
<title>Database Connection Functions</title> <title>Database Connection Functions</title>
...@@ -303,11 +307,11 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn) ...@@ -303,11 +307,11 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn)
proceed with the connection sequence. Loop thus: Consider a connection proceed with the connection sequence. Loop thus: Consider a connection
<quote>inactive</quote> by default. If <function>PQconnectPoll</function> last returned <symbol>PGRES_POLLING_ACTIVE</>, <quote>inactive</quote> by default. If <function>PQconnectPoll</function> last returned <symbol>PGRES_POLLING_ACTIVE</>,
consider it <quote>active</quote> instead. If <function>PQconnectPoll(conn)</function> last returned consider it <quote>active</quote> instead. If <function>PQconnectPoll(conn)</function> last returned
<symbol>PGRES_POLLING_READING</symbol>, perform a SELECT for reading on <function>PQsocket(conn)</function>. If <symbol>PGRES_POLLING_READING</symbol>, perform a <function>select()</> for reading on <function>PQsocket(conn)</function>. If
it last returned <symbol>PGRES_POLLING_WRITING</symbol>, perform a SELECT for writing on it last returned <symbol>PGRES_POLLING_WRITING</symbol>, perform a <function>select()</> for writing on
<function>PQsocket(conn)</function>. If you have yet to call <function>PQconnectPoll</function>, i.e. after the call <function>PQsocket(conn)</function>. If you have yet to call <function>PQconnectPoll</function>, i.e. after the call
to <function>PQconnectStart</function>, behave as if it last returned <symbol>PGRES_POLLING_WRITING</symbol>. If to <function>PQconnectStart</function>, behave as if it last returned <symbol>PGRES_POLLING_WRITING</symbol>. If
the SELECT shows that the socket is ready, consider it <quote>active</quote>. If it has the <function>select()</> shows that the socket is ready, consider it <quote>active</quote>. If it has
been decided that this connection is <quote>active</quote>, call <function>PQconnectPoll(conn)</function> been decided that this connection is <quote>active</quote>, call <function>PQconnectPoll(conn)</function>
again. If this call returns <symbol>PGRES_POLLING_FAILED</symbol>, the connection procedure again. If this call returns <symbol>PGRES_POLLING_FAILED</symbol>, the connection procedure
has failed. If this call returns <symbol>PGRES_POLLING_OK</symbol>, the connection has been has failed. If this call returns <symbol>PGRES_POLLING_OK</symbol>, the connection has been
...@@ -353,7 +357,7 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn) ...@@ -353,7 +357,7 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn)
<term><symbol>CONNECTION_AWAITING_RESPONSE</symbol></term> <term><symbol>CONNECTION_AWAITING_RESPONSE</symbol></term>
<listitem> <listitem>
<para> <para>
Waiting for a response from the postmaster. Waiting for a response from the server.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -362,7 +366,7 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn) ...@@ -362,7 +366,7 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn)
<term><symbol>CONNECTION_AUTH_OK</symbol></term> <term><symbol>CONNECTION_AUTH_OK</symbol></term>
<listitem> <listitem>
<para> <para>
Received authentication; waiting for backend start-up. Received authentication; waiting for connection start-up to continue.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -372,14 +376,14 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn) ...@@ -372,14 +376,14 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn)
<listitem> <listitem>
<para> <para>
Negotiating environment. Negotiating environment (part of the connection start-up).
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
Note that, although these constants will remain (in order to maintain Note that, although these constants will remain (in order to maintain
compatibility) an application should never rely upon these appearing in a compatibility), an application should never rely upon these appearing in a
particular order, or at all, or on the status always being one of these particular order, or at all, or on the status always being one of these
documented values. An application may do something like this: documented values. An application may do something like this:
<programlisting> <programlisting>
...@@ -487,7 +491,7 @@ void PQreset(PGconn *conn) ...@@ -487,7 +491,7 @@ void PQreset(PGconn *conn)
</synopsis> </synopsis>
This function will close the connection This function will close the connection
to the backend and attempt to reestablish a new to the backend and attempt to reestablish a new
connection to the same postmaster, using all the same connection to the same server, using all the same
parameters previously used. This may be useful for parameters previously used. This may be useful for
error recovery if a working connection is lost. error recovery if a working connection is lost.
</para> </para>
...@@ -505,7 +509,7 @@ int PQresetStart(PGconn *conn); ...@@ -505,7 +509,7 @@ int PQresetStart(PGconn *conn);
PostgresPollingStatusType PQresetPoll(PGconn *conn); PostgresPollingStatusType PQresetPoll(PGconn *conn);
</synopsis> </synopsis>
These functions will close the connection to the backend and attempt to These functions will close the connection to the backend and attempt to
reestablish a new connection to the same postmaster, using all the same reestablish a new connection to the same server, using all the same
parameters previously used. This may be useful for error recovery if a parameters previously used. This may be useful for error recovery if a
working connection is lost. They differ from <function>PQreset</function> (above) in that they working connection is lost. They differ from <function>PQreset</function> (above) in that they
act in a nonblocking manner. These functions suffer from the same act in a nonblocking manner. These functions suffer from the same
...@@ -528,7 +532,7 @@ PostgresPollingStatusType PQresetPoll(PGconn *conn); ...@@ -528,7 +532,7 @@ PostgresPollingStatusType PQresetPoll(PGconn *conn);
maintain the <structname>PGconn</structname> abstraction. Use the accessor functions below to get maintain the <structname>PGconn</structname> abstraction. Use the accessor functions below to get
at the contents of <structname>PGconn</structname>. Avoid directly referencing the fields of the at the contents of <structname>PGconn</structname>. Avoid directly referencing the fields of the
<structname>PGconn</> structure because they are subject to change in the future. <structname>PGconn</> structure because they are subject to change in the future.
(Beginning in <productname>PostgreSQK</productname> release 6.4, the (Beginning in <productname>PostgreSQL</productname> release 6.4, the
definition of struct <structname>PGconn</structname> is not even provided in <filename>libpq-fe.h</filename>. definition of struct <structname>PGconn</structname> is not even provided in <filename>libpq-fe.h</filename>.
If you have old code that accesses <structname>PGconn</structname> fields directly, you can keep using it If you have old code that accesses <structname>PGconn</structname> fields directly, you can keep using it
by including <filename>libpq-int.h</filename> too, but you are encouraged to fix the code by including <filename>libpq-int.h</filename> too, but you are encouraged to fix the code
...@@ -623,7 +627,7 @@ ConnStatusType PQstatus(const PGconn *conn) ...@@ -623,7 +627,7 @@ ConnStatusType PQstatus(const PGconn *conn)
seen outside of an asynchronous connection procedure - seen outside of an asynchronous connection procedure -
<literal>CONNECTION_OK</literal> or <literal>CONNECTION_OK</literal> or
<literal>CONNECTION_BAD</literal>. A good <literal>CONNECTION_BAD</literal>. A good
connection to the database has the status CONNECTION_OK. connection to the database has the status <literal>CONNECTION_OK</literal>.
A failed connection A failed connection
attempt is signaled by status attempt is signaled by status
<literal>CONNECTION_BAD</literal>. <literal>CONNECTION_BAD</literal>.
...@@ -705,7 +709,7 @@ SSL *PQgetssl(const PGconn *conn); ...@@ -705,7 +709,7 @@ SSL *PQgetssl(const PGconn *conn);
</sect1> </sect1>
<sect1 id="libpq-exec"> <sect1 id="libpq-exec">
<title>Query Execution Functions</title> <title>Command Execution Functions</title>
<para> <para>
Once a connection to a database server has been successfully Once a connection to a database server has been successfully
...@@ -719,7 +723,7 @@ SQL queries and commands. ...@@ -719,7 +723,7 @@ SQL queries and commands.
<listitem> <listitem>
<para> <para>
<function>PQexec</function> <function>PQexec</function>
Submit a query to the server Submit a command to the server
and wait for the result. and wait for the result.
<synopsis> <synopsis>
PGresult *PQexec(PGconn *conn, PGresult *PQexec(PGconn *conn,
...@@ -728,7 +732,7 @@ PGresult *PQexec(PGconn *conn, ...@@ -728,7 +732,7 @@ PGresult *PQexec(PGconn *conn,
Returns a <structname>PGresult</structname> pointer or possibly a NULL pointer. Returns a <structname>PGresult</structname> pointer or possibly a NULL pointer.
A non-NULL pointer will generally be returned except in A non-NULL pointer will generally be returned except in
out-of-memory conditions or serious errors such as inability out-of-memory conditions or serious errors such as inability
to send the query to the backend. to send the command to the backend.
If a NULL is returned, it If a NULL is returned, it
should be treated like a <symbol>PGRES_FATAL_ERROR</symbol> result. Use should be treated like a <symbol>PGRES_FATAL_ERROR</symbol> result. Use
<function>PQerrorMessage</function> to get more information about the error. <function>PQerrorMessage</function> to get more information about the error.
...@@ -737,7 +741,7 @@ PGresult *PQexec(PGconn *conn, ...@@ -737,7 +741,7 @@ PGresult *PQexec(PGconn *conn,
</itemizedlist> </itemizedlist>
<para> <para>
The <function>PGresult</function> structure encapsulates the query result The <function>PGresult</function> structure encapsulates the result
returned by the backend. returned by the backend.
<filename>libpq</filename> application programmers should be careful to <filename>libpq</filename> application programmers should be careful to
maintain the <structname>PGresult</structname> abstraction. Use the accessor functions below to get maintain the <structname>PGresult</structname> abstraction. Use the accessor functions below to get
...@@ -754,7 +758,7 @@ soon.) ...@@ -754,7 +758,7 @@ soon.)
<listitem> <listitem>
<para> <para>
<function>PQresultStatus</function> <function>PQresultStatus</function>
Returns the result status of the query. Returns the result status of the command.
<synopsis> <synopsis>
ExecStatusType PQresultStatus(const PGresult *res) ExecStatusType PQresultStatus(const PGresult *res)
</synopsis> </synopsis>
...@@ -789,9 +793,9 @@ ExecStatusType PQresultStatus(const PGresult *res) ...@@ -789,9 +793,9 @@ ExecStatusType PQresultStatus(const PGresult *res)
If the result status is <literal>PGRES_TUPLES_OK</literal>, then the If the result status is <literal>PGRES_TUPLES_OK</literal>, then the
routines described below can be used to retrieve the routines described below can be used to retrieve the
tuples returned by the query. Note that a SELECT that rows returned by the query. Note that a SELECT command that
happens to retrieve zero tuples still shows <literal>PGRES_TUPLES_OK</literal>. happens to retrieve zero rows still shows <literal>PGRES_TUPLES_OK</literal>.
<literal>PGRES_COMMAND_OK</literal> is for commands that can never return tuples <literal>PGRES_COMMAND_OK</literal> is for commands that can never return rows
(INSERT, UPDATE, etc.). A response of <literal>PGRES_EMPTY_QUERY</literal> often (INSERT, UPDATE, etc.). A response of <literal>PGRES_EMPTY_QUERY</literal> often
exposes a bug in the client software. exposes a bug in the client software.
</para> </para>
...@@ -875,8 +879,8 @@ as with a <structname>PGresult</structname> returned by <application>libpq</appl ...@@ -875,8 +879,8 @@ as with a <structname>PGresult</structname> returned by <application>libpq</appl
size_t PQescapeString (char *to, const char *from, size_t length); size_t PQescapeString (char *to, const char *from, size_t length);
</synopsis> </synopsis>
If you want to include strings that have been received If you want to include strings that have been received
from a source that is not trustworthy (for example, because they were from a source that is not trustworthy (for example, because a random user
transmitted across a network), you cannot directly include them in SQL entered them), you cannot directly include them in SQL
queries for security reasons. Instead, you have to quote special queries for security reasons. Instead, you have to quote special
characters that are otherwise interpreted by the SQL parser. characters that are otherwise interpreted by the SQL parser.
</para> </para>
...@@ -884,20 +888,20 @@ characters that are otherwise interpreted by the SQL parser. ...@@ -884,20 +888,20 @@ characters that are otherwise interpreted by the SQL parser.
<function>PQescapeString</> performs this operation. The <function>PQescapeString</> performs this operation. The
<parameter>from</> points to the first character of the string that <parameter>from</> points to the first character of the string that
is to be escaped, and the <parameter>length</> parameter counts the is to be escaped, and the <parameter>length</> parameter counts the
number of characters in this string (a terminating NUL character is number of characters in this string (a terminating zero byte is
neither necessary nor counted). <parameter>to</> shall point to a neither necessary nor counted). <parameter>to</> shall point to a
buffer that is able to hold at least one more character than twice buffer that is able to hold at least one more character than twice
the value of <parameter>length</>, otherwise the behavior is the value of <parameter>length</>, otherwise the behavior is
undefined. A call to <function>PQescapeString</> writes an escaped undefined. A call to <function>PQescapeString</> writes an escaped
version of the <parameter>from</> string to the <parameter>to</> version of the <parameter>from</> string to the <parameter>to</>
buffer, replacing special characters so that they cannot cause any buffer, replacing special characters so that they cannot cause any
harm, and adding a terminating NUL character. The single quotes that harm, and adding a terminating zero byte. The single quotes that
must surround <productname>PostgreSQL</> string literals are not part of the result must surround <productname>PostgreSQL</> string literals are not part of the result
string. string.
</para> </para>
<para> <para>
<function>PQescapeString</> returns the number of characters written <function>PQescapeString</> returns the number of characters written
to <parameter>to</>, not including the terminating NUL character. to <parameter>to</>, not including the terminating zero byte.
Behavior is undefined when the <parameter>to</> and <parameter>from</> Behavior is undefined when the <parameter>to</> and <parameter>from</>
strings overlap. strings overlap.
</para> </para>
...@@ -911,21 +915,22 @@ strings overlap. ...@@ -911,21 +915,22 @@ strings overlap.
</indexterm> </indexterm>
<para> <para>
<function>PQescapeBytea</function> <function>PQescapeBytea</function>
Escapes a binary string (bytea type) for use within an SQL query. Escapes a binary string (<type>bytea</type> type) for use within an SQL query.
<synopsis> <synopsis>
unsigned char *PQescapeBytea(unsigned char *from, unsigned char *PQescapeBytea(unsigned char *from,
size_t from_length, size_t from_length,
size_t *to_length); size_t *to_length);
</synopsis> </synopsis>
Certain <acronym>ASCII</acronym> characters MUST be escaped (but all Certain <acronym>ASCII</acronym> characters <emphasis>must</emphasis>
characters MAY be escaped) when used as part of a <type>BYTEA</type> be escaped (but all characters <emphasis>may</emphasis> be escaped)
when used as part of a <type>bytea</type>
string literal in an <acronym>SQL</acronym> statement. In general, to string literal in an <acronym>SQL</acronym> statement. In general, to
escape a character, it is converted into the three digit octal number escape a character, it is converted into the three digit octal number
equal to the decimal <acronym>ASCII</acronym> value, and preceded by equal to the decimal <acronym>ASCII</acronym> value, and preceded by
two backslashes. The single quote (') and backslash (\) characters have two backslashes. The single quote (') and backslash (\) characters have
special alternate escape sequences. See the Binary String data type special alternate escape sequences. See the <citetitle>User's Guide</citetitle>
in the User's Guide for more information. <function>PQescapeBytea for more information. <function>PQescapeBytea
</function> performs this operation, escaping only the minimally </function> performs this operation, escaping only the minimally
required characters. required characters.
</para> </para>
...@@ -934,20 +939,20 @@ strings overlap. ...@@ -934,20 +939,20 @@ strings overlap.
The <parameter>from</parameter> parameter points to the first The <parameter>from</parameter> parameter points to the first
character of the string that is to be escaped, and the character of the string that is to be escaped, and the
<parameter>from_length</parameter> parameter reflects the number of <parameter>from_length</parameter> parameter reflects the number of
characters in this binary string (a terminating NUL character is characters in this binary string (a terminating zero byte is
neither necessary nor counted). The <parameter>to_length</parameter> neither necessary nor counted). The <parameter>to_length</parameter>
parameter shall point to a buffer suitable to hold the resultant parameter shall point to a buffer suitable to hold the resultant
escaped string length. The result string length does not escaped string length. The result string length does not
include the terminating NUL character of the result. include the terminating zero byte of the result.
</para> </para>
<para> <para>
<function>PQescapeBytea</> returns an escaped version of the <function>PQescapeBytea</> returns an escaped version of the
<parameter>from</parameter> parameter binary string, to a caller <parameter>from</parameter> parameter binary string, to a caller-provided
provided buffer. The return string has all special characters replaced buffer. The return string has all special characters replaced
so that they can be properly processed by the PostgreSQL string literal so that they can be properly processed by the PostgreSQL string literal
parser, and the <type>bytea</type> input function. A terminating NUL parser, and the <type>bytea</type> input function. A terminating zero
character is also added. The single quotes that must surround byte is also added. The single quotes that must surround
PostgreSQL string literals are not part of the result string. PostgreSQL string literals are not part of the result string.
</para> </para>
</sect2> </sect2>
...@@ -972,7 +977,7 @@ int PQntuples(const PGresult *res); ...@@ -972,7 +977,7 @@ int PQntuples(const PGresult *res);
<para> <para>
<function>PQnfields</function> <function>PQnfields</function>
Returns the number of fields Returns the number of fields
(attributes) in each tuple of the query result. (columns) in each row of the query result.
<synopsis> <synopsis>
int PQnfields(const PGresult *res); int PQnfields(const PGresult *res);
</synopsis> </synopsis>
...@@ -983,7 +988,7 @@ int PQnfields(const PGresult *res); ...@@ -983,7 +988,7 @@ int PQnfields(const PGresult *res);
<listitem> <listitem>
<para> <para>
<function>PQfname</function> <function>PQfname</function>
Returns the field (attribute) name associated with the given field index. Returns the field (column) name associated with the given field index.
Field indices start at 0. Field indices start at 0.
<synopsis> <synopsis>
char *PQfname(const PGresult *res, char *PQfname(const PGresult *res,
...@@ -995,7 +1000,7 @@ char *PQfname(const PGresult *res, ...@@ -995,7 +1000,7 @@ char *PQfname(const PGresult *res,
<listitem> <listitem>
<para> <para>
<function>PQfnumber</function> <function>PQfnumber</function>
Returns the field (attribute) index Returns the field (column) index
associated with the given field name. associated with the given field name.
<synopsis> <synopsis>
int PQfnumber(const PGresult *res, int PQfnumber(const PGresult *res,
...@@ -1065,7 +1070,7 @@ int PQfsize(const PGresult *res, ...@@ -1065,7 +1070,7 @@ int PQfsize(const PGresult *res,
int PQbinaryTuples(const PGresult *res); int PQbinaryTuples(const PGresult *res);
</synopsis> </synopsis>
Currently, binary tuple data can only be returned by a query that Currently, binary tuple data can only be returned by a query that
extracts data from a <acronym>BINARY</acronym> cursor. extracts data from a binary cursor.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
...@@ -1078,7 +1083,7 @@ extracts data from a <acronym>BINARY</acronym> cursor. ...@@ -1078,7 +1083,7 @@ extracts data from a <acronym>BINARY</acronym> cursor.
<listitem> <listitem>
<para> <para>
<function>PQgetvalue</function> <function>PQgetvalue</function>
Returns a single field (attribute) value of one tuple Returns a single field (column) value of one tuple (row)
of a <structname>PGresult</structname>. of a <structname>PGresult</structname>.
Tuple and field indices start at 0. Tuple and field indices start at 0.
<synopsis> <synopsis>
...@@ -1087,7 +1092,7 @@ char* PQgetvalue(const PGresult *res, ...@@ -1087,7 +1092,7 @@ char* PQgetvalue(const PGresult *res,
int field_num); int field_num);
</synopsis> </synopsis>
For most queries, the value returned by <function>PQgetvalue</function> For most queries, the value returned by <function>PQgetvalue</function>
is a null-terminated <acronym>ASCII</acronym> string representation is a null-terminated character string representation
of the attribute value. But if <function>PQbinaryTuples()</function> is 1, of the attribute value. But if <function>PQbinaryTuples()</function> is 1,
the value returned by <function>PQgetvalue</function> is the binary the value returned by <function>PQgetvalue</function> is the binary
representation of the representation of the
...@@ -1199,7 +1204,7 @@ char * PQcmdTuples(const PGresult *res); ...@@ -1199,7 +1204,7 @@ char * PQcmdTuples(const PGresult *res);
<listitem> <listitem>
<para> <para>
<function>PQoidValue</function> <function>PQoidValue</function>
Returns the object id of the tuple inserted, if the Returns the object ID of the inserted row, if the
<acronym>SQL</acronym> command was an INSERT <acronym>SQL</acronym> command was an INSERT
that inserted exactly one row into a table that has OIDs. that inserted exactly one row into a table that has OIDs.
Otherwise, returns <literal>InvalidOid</literal>. Otherwise, returns <literal>InvalidOid</literal>.
...@@ -1215,7 +1220,7 @@ Oid PQoidValue(const PGresult *res); ...@@ -1215,7 +1220,7 @@ Oid PQoidValue(const PGresult *res);
<listitem> <listitem>
<para> <para>
<function>PQoidStatus</function> <function>PQoidStatus</function>
Returns a string with the object id of the tuple inserted, if the Returns a string with the object ID of the inserted row, if the
<acronym>SQL</acronym> command was an INSERT. <acronym>SQL</acronym> command was an INSERT.
(The string will be <literal>0</> if the INSERT did not insert exactly one (The string will be <literal>0</> if the INSERT did not insert exactly one
row, or if the target table does not have OIDs.) If the command row, or if the target table does not have OIDs.) If the command
...@@ -1238,14 +1243,14 @@ and is not thread-safe. ...@@ -1238,14 +1243,14 @@ and is not thread-safe.
<indexterm zone="libpq-async"><primary>nonblocking connection</></> <indexterm zone="libpq-async"><primary>nonblocking connection</></>
<para> <para>
The <function>PQexec</function> function is adequate for submitting queries in The <function>PQexec</function> function is adequate for submitting commands in
simple synchronous simple synchronous
applications. It has a couple of major deficiencies however: applications. It has a couple of major deficiencies however:
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
<function>PQexec</function> waits for the query to be completed. The application may have other <function>PQexec</function> waits for the command to be completed. The application may have other
work to do (such as maintaining a user interface), in which case it won't work to do (such as maintaining a user interface), in which case it won't
want to block waiting for the response. want to block waiting for the response.
</para> </para>
...@@ -1253,13 +1258,13 @@ want to block waiting for the response. ...@@ -1253,13 +1258,13 @@ want to block waiting for the response.
<listitem> <listitem>
<para> <para>
Since control is buried inside <function>PQexec</function>, it is hard for the frontend Since control is buried inside <function>PQexec</function>, it is hard for the frontend
to decide it would like to try to cancel the ongoing query. (It can be to decide it would like to try to cancel the ongoing command. (It can be
done from a signal handler, but not otherwise.) done from a signal handler, but not otherwise.)
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>PQexec</function> can return only one <structname>PGresult</structname> structure. If the submitted query <function>PQexec</function> can return only one <structname>PGresult</structname> structure. If the submitted command
string contains multiple <acronym>SQL</acronym> commands, all but the last <structname>PGresult</structname> are string contains multiple <acronym>SQL</acronym> commands, all but the last <structname>PGresult</structname> are
discarded by <function>PQexec</function>. discarded by <function>PQexec</function>.
</para> </para>
...@@ -1275,7 +1280,7 @@ underlying functions that <function>PQexec</function> is built from: ...@@ -1275,7 +1280,7 @@ underlying functions that <function>PQexec</function> is built from:
<para> <para>
Older programs that used this functionality as well as Older programs that used this functionality as well as
<function>PQputline</function> and <function>PQputnbytes</function> <function>PQputline</function> and <function>PQputnbytes</function>
could block waiting to send data to the backend, to could block waiting to send data to the backend. To
address that issue, the function <function>PQsetnonblocking</function> address that issue, the function <function>PQsetnonblocking</function>
was added. was added.
</para> </para>
...@@ -1304,7 +1309,7 @@ int PQsetnonblocking(PGconn *conn, int arg) ...@@ -1304,7 +1309,7 @@ int PQsetnonblocking(PGconn *conn, int arg)
again. again.
</para> </para>
<para> <para>
When a database connection has been set to non-blocking mode and When a database connection has been set to nonblocking mode and
<function>PQexec</function> is called, it will temporarily set the state <function>PQexec</function> is called, it will temporarily set the state
of the connection to blocking until the <function>PQexec</function> of the connection to blocking until the <function>PQexec</function>
completes. completes.
...@@ -1330,19 +1335,19 @@ int PQisnonblocking(const PGconn *conn) ...@@ -1330,19 +1335,19 @@ int PQisnonblocking(const PGconn *conn)
<listitem> <listitem>
<para> <para>
<function>PQsendQuery</function> <function>PQsendQuery</function>
Submit a query to <productname>PostgreSQL</productname> without Submit a command to the server without
waiting for the result(s). 1 is returned if the query was waiting for the result(s). 1 is returned if the command was
successfully dispatched, 0 if not (in which case, use successfully dispatched, 0 if not (in which case, use
PQerrorMessage to get more information about the failure). <function>PQerrorMessage</> to get more information about the failure).
<synopsis> <synopsis>
int PQsendQuery(PGconn *conn, int PQsendQuery(PGconn *conn,
const char *query); const char *query);
</synopsis> </synopsis>
After successfully calling <function>PQsendQuery</function>, call After successfully calling <function>PQsendQuery</function>, call
<function>PQgetResult</function> one or more <function>PQgetResult</function> one or more
times to obtain the query results. <function>PQsendQuery</function> may not be called times to obtain the results. <function>PQsendQuery</function> may not be called
again (on the same connection) until <function>PQgetResult</function> has returned NULL, again (on the same connection) until <function>PQgetResult</function> has returned NULL,
indicating that the query is done. indicating that the command is done.
</para> </para>
</listitem> </listitem>
...@@ -1356,9 +1361,9 @@ int PQsendQuery(PGconn *conn, ...@@ -1356,9 +1361,9 @@ int PQsendQuery(PGconn *conn,
PGresult *PQgetResult(PGconn *conn); PGresult *PQgetResult(PGconn *conn);
</synopsis> </synopsis>
<function>PQgetResult</function> must be called repeatedly until it returns NULL, <function>PQgetResult</function> must be called repeatedly until it returns NULL,
indicating that the query is done. (If called when no query is indicating that the command is done. (If called when no command is
active, <function>PQgetResult</function> will just return NULL at once.) active, <function>PQgetResult</function> will just return NULL at once.)
Each non-null result from <function>PQgetResult</function> should be processed using Each non-NULL result from <function>PQgetResult</function> should be processed using
the same PGresult accessor functions previously described. the same PGresult accessor functions previously described.
Don't forget to free each result object with <function>PQclear</function> when done with it. Don't forget to free each result object with <function>PQclear</function> when done with it.
Note that <function>PQgetResult</function> will block only if a query is active and the Note that <function>PQgetResult</function> will block only if a query is active and the
...@@ -1372,11 +1377,11 @@ PGresult *PQgetResult(PGconn *conn); ...@@ -1372,11 +1377,11 @@ PGresult *PQgetResult(PGconn *conn);
<para> <para>
Using <function>PQsendQuery</function> and <function>PQgetResult</function> Using <function>PQsendQuery</function> and <function>PQgetResult</function>
solves one of <function>PQexec</function>'s problems: solves one of <function>PQexec</function>'s problems:
If a query string contains multiple <acronym>SQL</acronym> commands, the results of those If a command string contains multiple <acronym>SQL</acronym> commands, the results of those
commands can be obtained individually. (This allows a simple form of commands can be obtained individually. (This allows a simple form of
overlapped processing, by the way: the frontend can be handling the overlapped processing, by the way: the frontend can be handling the
results of one query while the backend is still working on later results of one query while the backend is still working on later
queries in the same query string.) However, calling <function>PQgetResult</function> will queries in the same command string.) However, calling <function>PQgetResult</function> will
still cause the frontend to block until the backend completes the still cause the frontend to block until the backend completes the
next <acronym>SQL</acronym> command. This can be avoided by proper use of three more next <acronym>SQL</acronym> command. This can be avoided by proper use of three more
functions: functions:
...@@ -1401,9 +1406,9 @@ their state has changed. ...@@ -1401,9 +1406,9 @@ their state has changed.
<function>PQconsumeInput</function> may be called even if the application is not <function>PQconsumeInput</function> may be called even if the application is not
prepared to deal with a result or notification just yet. The prepared to deal with a result or notification just yet. The
routine will read available data and save it in a buffer, thereby routine will read available data and save it in a buffer, thereby
causing a <function>select</function>(2) read-ready indication to go away. The causing a <function>select()</function> read-ready indication to go away. The
application can thus use <function>PQconsumeInput</function> to clear the application can thus use <function>PQconsumeInput</function> to clear the
<function>select</function> condition immediately, and then examine the results at leisure. <function>select()</function> condition immediately, and then examine the results at leisure.
</para> </para>
</listitem> </listitem>
...@@ -1425,13 +1430,13 @@ state will never end. ...@@ -1425,13 +1430,13 @@ state will never end.
<listitem> <listitem>
<para> <para>
<function>PQflush</function> Attempt to flush any data queued to the backend, <function>PQflush</function> Attempt to flush any data queued to the backend,
returns 0 if successful (or if the send queue is empty) or EOF if it failed for returns 0 if successful (or if the send queue is empty) or <symbol>EOF</symbol> if it failed for
some reason. some reason.
<synopsis> <synopsis>
int PQflush(PGconn *conn); int PQflush(PGconn *conn);
</synopsis> </synopsis>
<function>PQflush</function> needs to be called on a nonblocking connection <function>PQflush</function> needs to be called on a nonblocking connection
before calling <function>select</function> to determine if a response has before calling <function>select()</function> to determine if a response has
arrived. If 0 is returned it ensures that there is no data queued to the arrived. If 0 is returned it ensures that there is no data queued to the
backend that has not actually been sent. Only applications that have used backend that has not actually been sent. Only applications that have used
<function>PQsetnonblocking</function> have a need for this. <function>PQsetnonblocking</function> have a need for this.
...@@ -1448,17 +1453,17 @@ backend that has not actually been sent. Only applications that have used ...@@ -1448,17 +1453,17 @@ backend that has not actually been sent. Only applications that have used
int PQsocket(const PGconn *conn); int PQsocket(const PGconn *conn);
</synopsis> </synopsis>
<function>PQsocket</function> should be used to obtain the backend socket descriptor <function>PQsocket</function> should be used to obtain the backend socket descriptor
in preparation for executing <function>select</function>(2). This allows an in preparation for executing <function>select()</function>. This allows an
application using a blocking connection to wait for either backend responses or application using a blocking connection to wait for either backend responses or
other conditions. other conditions.
If the result of <function>select</function>(2) indicates that data can be read from If the result of <function>select()</function> indicates that data can be read from
the backend socket, then <function>PQconsumeInput</function> should be called to read the the backend socket, then <function>PQconsumeInput</function> should be called to read the
data; after which, <function>PQisBusy</function>, <function>PQgetResult</function>, data; after which, <function>PQisBusy</function>, <function>PQgetResult</function>,
and/or <function>PQnotifies</function> can be used to process the response. and/or <function>PQnotifies</function> can be used to process the response.
</para> </para>
<para> <para>
Nonblocking connections (that have used <function>PQsetnonblocking</function>) Nonblocking connections (that have used <function>PQsetnonblocking</function>)
should not use <function>select</function> until <function>PQflush</function> should not use <function>select()</function> until <function>PQflush</function>
has returned 0 indicating that there is no buffered data waiting to be sent has returned 0 indicating that there is no buffered data waiting to be sent
to the backend. to the backend.
</para> </para>
...@@ -1469,7 +1474,7 @@ to the backend. ...@@ -1469,7 +1474,7 @@ to the backend.
<para> <para>
A typical frontend using these functions will have a main loop that uses A typical frontend using these functions will have a main loop that uses
<function>select</function>(2) to wait for all the conditions that it must <function>select</function> to wait for all the conditions that it must
respond to. One of the conditions will be input available from the backend, respond to. One of the conditions will be input available from the backend,
which in <function>select</function>'s terms is readable data on the file which in <function>select</function>'s terms is readable data on the file
descriptor identified by <function>PQsocket</function>. descriptor identified by <function>PQsocket</function>.
...@@ -1482,7 +1487,7 @@ if <function>PQisBusy</function> returns false (0). It can also call ...@@ -1482,7 +1487,7 @@ if <function>PQisBusy</function> returns false (0). It can also call
<para> <para>
A frontend that uses <function>PQsendQuery</function>/<function>PQgetResult</function> A frontend that uses <function>PQsendQuery</function>/<function>PQgetResult</function>
can also attempt to cancel a query that is still being processed by the backend. can also attempt to cancel a command that is still being processed by the backend.
</para> </para>
<para> <para>
...@@ -1491,7 +1496,7 @@ can also attempt to cancel a query that is still being processed by the backend. ...@@ -1491,7 +1496,7 @@ can also attempt to cancel a query that is still being processed by the backend.
<para> <para>
<function>PQrequestCancel</function> <function>PQrequestCancel</function>
Request that <productname>PostgreSQL</productname> abandon Request that <productname>PostgreSQL</productname> abandon
processing of the current query. processing of the current command.
<synopsis> <synopsis>
int PQrequestCancel(PGconn *conn); int PQrequestCancel(PGconn *conn);
</synopsis> </synopsis>
...@@ -1501,9 +1506,9 @@ Successful dispatch is no guarantee that the request will have any ...@@ -1501,9 +1506,9 @@ Successful dispatch is no guarantee that the request will have any
effect, however. Regardless of the return value of <function>PQrequestCancel</function>, effect, however. Regardless of the return value of <function>PQrequestCancel</function>,
the application must continue with the normal result-reading the application must continue with the normal result-reading
sequence using <function>PQgetResult</function>. If the cancellation sequence using <function>PQgetResult</function>. If the cancellation
is effective, the current query will terminate early and return is effective, the current command will terminate early and return
an error result. If the cancellation fails (say, because the an error result. If the cancellation fails (say, because the
backend was already done processing the query), then there will backend was already done processing the command), then there will
be no visible result at all. be no visible result at all.
</para> </para>
</listitem> </listitem>
...@@ -1511,7 +1516,7 @@ be no visible result at all. ...@@ -1511,7 +1516,7 @@ be no visible result at all.
</para> </para>
<para> <para>
Note that if the current query is part of a transaction, cancellation Note that if the current command is part of a transaction, cancellation
will abort the whole transaction. will abort the whole transaction.
</para> </para>
...@@ -1523,16 +1528,16 @@ handler. For example, <application>psql</application> invokes ...@@ -1523,16 +1528,16 @@ handler. For example, <application>psql</application> invokes
<function>PQrequestCancel</function> from a <systemitem>SIGINT</> signal handler, thus allowing <function>PQrequestCancel</function> from a <systemitem>SIGINT</> signal handler, thus allowing
interactive cancellation of queries that it issues through <function>PQexec</function>. interactive cancellation of queries that it issues through <function>PQexec</function>.
Note that <function>PQrequestCancel</function> will have no effect if the connection Note that <function>PQrequestCancel</function> will have no effect if the connection
is not currently open or the backend is not currently processing a query. is not currently open or the backend is not currently processing a command.
</para> </para>
</sect1> </sect1>
<sect1 id="libpq-fastpath"> <sect1 id="libpq-fastpath">
<title>Fast Path</title> <title>The Fast-Path Interface</title>
<para> <para>
<productname>PostgreSQL</productname> provides a fast path interface to send <productname>PostgreSQL</productname> provides a fast-path interface to send
function calls to the backend. This is a trapdoor into system internals and 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. can be a potential security hole. Most users will not need this feature.
...@@ -1540,7 +1545,7 @@ can be a potential security hole. Most users will not need this feature. ...@@ -1540,7 +1545,7 @@ can be a potential security hole. Most users will not need this feature.
<listitem> <listitem>
<para> <para>
<function>PQfn</function> <function>PQfn</function>
Request execution of a backend function via the fast path interface. Request execution of a backend function via the fast-path interface.
<synopsis> <synopsis>
PGresult* PQfn(PGconn* conn, PGresult* PQfn(PGconn* conn,
int fnid, int fnid,
...@@ -1560,7 +1565,7 @@ PGresult* PQfn(PGconn* conn, ...@@ -1560,7 +1565,7 @@ PGresult* PQfn(PGconn* conn,
<parameter>result_is_int</parameter> to 1; otherwise set it to 0. (Setting <parameter>result_is_int</parameter> to 1 <parameter>result_is_int</parameter> to 1; otherwise set it to 0. (Setting <parameter>result_is_int</parameter> to 1
tells <application>libpq</> to byte-swap the value if necessary, so that it is tells <application>libpq</> to byte-swap the value if necessary, so that it is
delivered as a proper int value for the client machine. When delivered as a proper int value for the client machine. When
result_is_int is 0, the byte string sent by the backend is returned <parameter>result_is_int</> is 0, the byte string sent by the backend is returned
unmodified.) unmodified.)
<parameter>args</> and <parameter>nargs</> specify the arguments to be passed to the function. <parameter>args</> and <parameter>nargs</> specify the arguments to be passed to the function.
<synopsis> <synopsis>
...@@ -1604,7 +1609,7 @@ not necessary for there to be any associated relation. ...@@ -1604,7 +1609,7 @@ not necessary for there to be any associated relation.
<para> <para>
<filename>libpq</filename> applications submit <command>LISTEN</command> and <command>UNLISTEN</command> <filename>libpq</filename> applications submit <command>LISTEN</command> and <command>UNLISTEN</command>
commands as ordinary SQL queries. Subsequently, arrival of <command>NOTIFY</command> commands as ordinary SQL command. Subsequently, arrival of <command>NOTIFY</command>
messages can be detected by calling <function>PQnotifies</function>. messages can be detected by calling <function>PQnotifies</function>.
<itemizedlist> <itemizedlist>
...@@ -1658,10 +1663,10 @@ A better way to check for NOTIFY ...@@ -1658,10 +1663,10 @@ A better way to check for NOTIFY
messages when you have no useful queries to make is to call messages when you have no useful queries to make is to call
<function>PQconsumeInput()</function>, then check <function>PQconsumeInput()</function>, then check
<function>PQnotifies()</function>. <function>PQnotifies()</function>.
You can use <function>select</function>(2) to wait for backend data to You can use <function>select()</function> to wait for backend data to
arrive, thereby using no <acronym>CPU</acronym> power unless there is something arrive, thereby using no <acronym>CPU</acronym> power unless there is something
to do. (See <function>PQsocket()</function> to obtain the file descriptor to do. (See <function>PQsocket()</function> to obtain the file descriptor
number to use with <function>select</function>.) number to use with <function>select()</function>.)
Note that this will work OK whether you submit queries with Note that this will work OK whether you submit queries with
<function>PQsendQuery</function>/<function>PQgetResult</function> or simply <function>PQsendQuery</function>/<function>PQgetResult</function> or simply
use <function>PQexec</function>. You should, however, remember to use <function>PQexec</function>. You should, however, remember to
...@@ -1706,10 +1711,10 @@ int PQgetline(PGconn *conn, ...@@ -1706,10 +1711,10 @@ int PQgetline(PGconn *conn,
char *string, char *string,
int length) int length)
</synopsis> </synopsis>
Like <function>fgets</function>(3), this routine copies up to length-1 characters Like <function>fgets</function>, this routine copies up to length-1 characters
into string. It is like <function>gets</function>(3), however, in that it converts into string. It is like <function>gets</function>, however, in that it converts
the terminating newline into a null character. the terminating newline into a zero byte.
<function>PQgetline</function> returns <literal>EOF</literal> at EOF, 0 if the <function>PQgetline</function> returns <symbol>EOF</symbol> at the end of input, 0 if the
entire line has been read, and 1 if the buffer is full but the entire line has been read, and 1 if the buffer is full but the
terminating newline has not yet been read. terminating newline has not yet been read.
</para> </para>
...@@ -1776,7 +1781,7 @@ actually available.) ...@@ -1776,7 +1781,7 @@ actually available.)
<para> <para>
<function>PQputline</function> <function>PQputline</function>
Sends a null-terminated string to the backend server. Sends a null-terminated string to the backend server.
Returns 0 if OK, <literal>EOF</literal> if unable to send the string. Returns 0 if OK, <symbol>EOF</symbol> if unable to send the string.
<synopsis> <synopsis>
int PQputline(PGconn *conn, int PQputline(PGconn *conn,
const char *string); const char *string);
...@@ -1791,7 +1796,7 @@ the backend that it has finished sending its data. ...@@ -1791,7 +1796,7 @@ the backend that it has finished sending its data.
<para> <para>
<function>PQputnbytes</function> <function>PQputnbytes</function>
Sends a non-null-terminated string to the backend server. Sends a non-null-terminated string to the backend server.
Returns 0 if OK, EOF if unable to send the string. Returns 0 if OK, <symbol>EOF</symbol> if unable to send the string.
<synopsis> <synopsis>
int PQputnbytes(PGconn *conn, int PQputnbytes(PGconn *conn,
const char *buffer, const char *buffer,
...@@ -1806,7 +1811,7 @@ specified directly. ...@@ -1806,7 +1811,7 @@ specified directly.
<listitem> <listitem>
<para> <para>
<function>PQendcopy</function> <function>PQendcopy</function>
Syncs with the backend. This function waits until Synchronizes with the backend. This function waits until
the backend has finished the copy. It should the backend has finished the copy. It should
either be issued when the last string has been either be issued when the last string has been
sent to the backend using <function>PQputline</function> or when the sent to the backend using <function>PQputline</function> or when the
...@@ -1814,7 +1819,7 @@ specified directly. ...@@ -1814,7 +1819,7 @@ specified directly.
using <function>PGgetline</function>. It must be issued or the backend using <function>PGgetline</function>. It must be issued or the backend
may get <quote>out of sync</quote> with the frontend. Upon may get <quote>out of sync</quote> with the frontend. Upon
return from this function, the backend is ready to return from this function, the backend is ready to
receive the next query. receive the next SQL command.
The return value is 0 on successful completion, The return value is 0 on successful completion,
nonzero otherwise. nonzero otherwise.
<synopsis> <synopsis>
...@@ -1856,7 +1861,7 @@ Older applications are likely to submit a copy in or copy out ...@@ -1856,7 +1861,7 @@ Older applications are likely to submit a copy in or copy out
via <function>PQexec</function> and assume that the transaction is done after via <function>PQexec</function> and assume that the transaction is done after
<function>PQendcopy</function>. <function>PQendcopy</function>.
This will work correctly only if the copy in/out is the only This will work correctly only if the copy in/out is the only
<acronym>SQL</acronym> command in the query string. <acronym>SQL</acronym> command in the command string.
</para> </para>
</sect1> </sect1>
...@@ -2065,7 +2070,7 @@ sets the default time zone. ...@@ -2065,7 +2070,7 @@ sets the default time zone.
<listitem> <listitem>
<para> <para>
<envar>PGCLIENTENCODING</envar> <envar>PGCLIENTENCODING</envar>
sets the default client encoding (if MULTIBYTE support was selected sets the default client encoding (if multibyte support was selected
when configuring <productname>PostgreSQL</productname>). when configuring <productname>PostgreSQL</productname>).
</para> </para>
</listitem> </listitem>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.24 2001/11/12 19:19:39 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.25 2002/01/07 02:29:12 petere Exp $
--> -->
<chapter id="largeObjects"> <chapter id="largeObjects">
...@@ -106,19 +106,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.24 2001/11/12 19:19:39 petere ...@@ -106,19 +106,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.24 2001/11/12 19:19:39 petere
<para> <para>
The <productname>PostgreSQL</productname> large object interface is modeled after The <productname>PostgreSQL</productname> large object interface is modeled after
the <acronym>Unix</acronym> file system interface, with analogues of the <acronym>Unix</acronym> file-system interface, with analogues of
<function>open(2)</function>, <function>read(2)</function>, <function>open(2)</function>, <function>read(2)</function>,
<function>write(2)</function>, <function>write(2)</function>,
<function>lseek(2)</function>, etc. User <function>lseek(2)</function>, etc. User
functions call these routines to retrieve only the data of functions call these routines to retrieve only the data of
interest from a large object. For example, if a large interest from a large object. For example, if a large
object type called <type>mugshot</type> existed that stored object type called <type>mugshot</type> existed that stored
photographs of faces, then a function called beard could photographs of faces, then a function called <function>beard</function> could
be declared on <type>mugshot</type> data. Beard could look at the be declared on <type>mugshot</type> data. <function>beard</> could look at the
lower third of a photograph, and determine the color of lower third of a photograph, and determine the color of
the beard that appeared there, if any. The entire the beard that appeared there, if any. The entire
large object value need not be buffered, or even large-object value need not be buffered, or even
examined, by the beard function. examined, by the <function>beard</function> function.
Large objects may be accessed from dynamically-loaded <acronym>C</acronym> Large objects may be accessed from dynamically-loaded <acronym>C</acronym>
functions or database client programs that link the functions or database client programs that link the
library. <productname>PostgreSQL</productname> provides a set of routines that library. <productname>PostgreSQL</productname> provides a set of routines that
...@@ -140,7 +140,7 @@ Oid lo_creat(PGconn *<replaceable class="parameter">conn</replaceable>, int <rep ...@@ -140,7 +140,7 @@ Oid lo_creat(PGconn *<replaceable class="parameter">conn</replaceable>, int <rep
object. The symbolic constants listed here are defined object. The symbolic constants listed here are defined
in the header file <filename>libpq/libpq-fs.h</filename>. in the header file <filename>libpq/libpq-fs.h</filename>.
The access type (read, write, or both) is controlled by The access type (read, write, or both) is controlled by
OR'ing together the bits <symbol>INV_READ</symbol> and or'ing together the bits <symbol>INV_READ</symbol> and
<symbol>INV_WRITE</symbol>. The low-order sixteen bits of the mask have <symbol>INV_WRITE</symbol>. The low-order sixteen bits of the mask have
historically been used at Berkeley to designate the storage manager number on which the large object historically been used at Berkeley to designate the storage manager number on which the large object
should reside. These should reside. These
...@@ -156,12 +156,12 @@ inv_oid = lo_creat(INV_READ|INV_WRITE); ...@@ -156,12 +156,12 @@ inv_oid = lo_creat(INV_READ|INV_WRITE);
<title>Importing a Large Object</title> <title>Importing a Large Object</title>
<para> <para>
To import a <acronym>UNIX</acronym> file as a large object, call To import an operating system file as a large object, call
<synopsis> <synopsis>
Oid lo_import(PGconn *<replaceable class="parameter">conn</replaceable>, const char *<replaceable class="parameter">filename</replaceable>) Oid lo_import(PGconn *<replaceable class="parameter">conn</replaceable>, const char *<replaceable class="parameter">filename</replaceable>)
</synopsis> </synopsis>
<replaceable class="parameter">filename</replaceable> <replaceable class="parameter">filename</replaceable>
specifies the <acronym>Unix</acronym> path name of specifies the operating system name of
the file to be imported as a large object. the file to be imported as a large object.
</para> </para>
</sect2> </sect2>
...@@ -171,13 +171,13 @@ Oid lo_import(PGconn *<replaceable class="parameter">conn</replaceable>, const c ...@@ -171,13 +171,13 @@ Oid lo_import(PGconn *<replaceable class="parameter">conn</replaceable>, const c
<para> <para>
To export a large object To export a large object
into <acronym>UNIX</acronym> file, call into an operating system file, call
<synopsis> <synopsis>
int lo_export(PGconn *<replaceable class="parameter">conn</replaceable>, Oid <replaceable class="parameter">lobjId</replaceable>, const char *<replaceable class="parameter">filename</replaceable>) int lo_export(PGconn *<replaceable class="parameter">conn</replaceable>, Oid <replaceable class="parameter">lobjId</replaceable>, const char *<replaceable class="parameter">filename</replaceable>)
</synopsis> </synopsis>
The <parameter>lobjId</parameter> argument specifies the Oid of the large The <parameter>lobjId</parameter> argument specifies the Oid of the large
object to export and the <parameter>filename</parameter> argument specifies object to export and the <parameter>filename</parameter> argument specifies
the <acronym>UNIX</acronym> path name of the file. the operating system name name of the file.
</para> </para>
</sect2> </sect2>
...@@ -191,7 +191,7 @@ int lo_open(PGconn *conn, Oid lobjId, int mode) ...@@ -191,7 +191,7 @@ int lo_open(PGconn *conn, Oid lobjId, int mode)
</synopsis> </synopsis>
The <parameter>lobjId</parameter> argument specifies the Oid of the large The <parameter>lobjId</parameter> argument specifies the Oid of the large
object to open. The <parameter>mode</parameter> bits control whether the object to open. The <parameter>mode</parameter> bits control whether the
object is opened for reading (<symbol>INV_READ</>), writing or object is opened for reading (<symbol>INV_READ</>), writing (<symbol>INV_WRITE</symbol>), or
both. both.
A large object cannot be opened before it is created. A large object cannot be opened before it is created.
<function>lo_open</function> returns a large object descriptor <function>lo_open</function> returns a large object descriptor
...@@ -241,9 +241,9 @@ int lo_read(PGconn *conn, int fd, char *buf, size_t len) ...@@ -241,9 +241,9 @@ int lo_read(PGconn *conn, int fd, char *buf, size_t len)
int lo_lseek(PGconn *conn, int fd, int offset, int whence) int lo_lseek(PGconn *conn, int fd, int offset, int whence)
</programlisting> </programlisting>
This routine moves the current location pointer for the This routine moves the current location pointer for the
large object described by fd to the new location specified large object described by <parameter>fd</> to the new location specified
by offset. The valid values for whence are by <parameter>offset</>. The valid values for <parameter>whence</> are
SEEK_SET, SEEK_CUR, and SEEK_END. <symbol>SEEK_SET</>, <symbol>SEEK_CUR</>, and <symbol>SEEK_END</>.
</para> </para>
</sect2> </sect2>
...@@ -255,7 +255,7 @@ int lo_lseek(PGconn *conn, int fd, int offset, int whence) ...@@ -255,7 +255,7 @@ int lo_lseek(PGconn *conn, int fd, int offset, int whence)
<programlisting> <programlisting>
int lo_close(PGconn *conn, int fd) int lo_close(PGconn *conn, int fd)
</programlisting> </programlisting>
where fd is a large object descriptor returned by where <parameter>fd</> is a large object descriptor returned by
<function>lo_open</function>. On success, <function>lo_close</function> <function>lo_open</function>. On success, <function>lo_close</function>
returns zero. On error, the return value is negative. returns zero. On error, the return value is negative.
</para> </para>
...@@ -281,8 +281,8 @@ Oid lo_unlink(PGconn *<replaceable class="parameter">conn</replaceable>, Oid lob ...@@ -281,8 +281,8 @@ Oid lo_unlink(PGconn *<replaceable class="parameter">conn</replaceable>, Oid lob
<title>Server-side Built-in Functions</title> <title>Server-side Built-in Functions</title>
<para> <para>
There are two built-in registered functions, <acronym>lo_import</acronym> There are two built-in registered functions, <function>lo_import</function>
and <acronym>lo_export</acronym> which are convenient for use and <function>lo_export</function> which are convenient for use
in <acronym>SQL</acronym> in <acronym>SQL</acronym>
queries. queries.
Here is an example of their use Here is an example of their use
...@@ -295,7 +295,7 @@ CREATE TABLE image ( ...@@ -295,7 +295,7 @@ CREATE TABLE image (
INSERT INTO image (name, raster) INSERT INTO image (name, raster)
VALUES ('beautiful image', lo_import('/etc/motd')); VALUES ('beautiful image', lo_import('/etc/motd'));
SELECT lo_export(image.raster, '/tmp/motd') from image SELECT lo_export(image.raster, '/tmp/motd') FROM image
WHERE name = 'beautiful image'; WHERE name = 'beautiful image';
</programlisting> </programlisting>
</para> </para>
...@@ -305,24 +305,18 @@ SELECT lo_export(image.raster, '/tmp/motd') from image ...@@ -305,24 +305,18 @@ SELECT lo_export(image.raster, '/tmp/motd') from image
<title>Accessing Large Objects from <application>Libpq</application></title> <title>Accessing Large Objects from <application>Libpq</application></title>
<para> <para>
Below is a sample program which shows how the large object <xref linkend="lo-example"> is a sample program which shows how the large object
interface interface
in <application>libpq</> can be used. Parts of the program are in <application>libpq</> can be used. Parts of the program are
commented out but are left in the source for the readers commented out but are left in the source for the reader's
benefit. This program can be found in benefit. This program can be found in
<filename> <filename>src/test/examples/testlo.c</filename> in the source distribution.
../src/test/examples
</filename>
Frontend applications which use the large object interface Frontend applications which use the large object interface
in <application>libpq</application> should include the header file in <application>libpq</application> should include the header file
<filename>libpq/libpq-fs.h</filename> and link with the <application>libpq</application> library. <filename>libpq/libpq-fs.h</filename> and link with the <application>libpq</application> library.
</para> </para>
</sect1>
<sect1 id="lo-example">
<title>Example Program</title>
<example> <example id="lo-example">
<title>Large Objects with <application>Libpq</application> Example Program</title> <title>Large Objects with <application>Libpq</application> Example Program</title>
<programlisting> <programlisting>
/*-------------------------------------------------------------- /*--------------------------------------------------------------
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.29 2002/01/07 02:29:12 petere Exp $
--> -->
<chapter id="odbc"> <chapter id="odbc">
...@@ -23,6 +23,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41 ...@@ -23,6 +23,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41
<primary>ODBC</primary> <primary>ODBC</primary>
</indexterm> </indexterm>
<sect1 id="odbc-intro">
<title>Introduction</title>
<note> <note>
<para> <para>
Background information originally by Tim Goeke Background information originally by Tim Goeke
...@@ -38,12 +41,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41 ...@@ -38,12 +41,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41
<acronym>ODBC</acronym> provides a product-neutral interface <acronym>ODBC</acronym> provides a product-neutral interface
between frontend applications and database servers, between frontend applications and database servers,
allowing a user or developer to write applications that are allowing a user or developer to write applications that are
transportable between servers from different manufacturers.. portable between servers from different manufacturers..
</para> </para>
<sect1 id="odbc-background">
<title>Background</title>
<para> <para>
The <acronym>ODBC</acronym> <acronym>API</acronym> matches up The <acronym>ODBC</acronym> <acronym>API</acronym> matches up
on the backend to an <acronym>ODBC</acronym>-compatible data source. on the backend to an <acronym>ODBC</acronym>-compatible data source.
...@@ -52,9 +52,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41 ...@@ -52,9 +52,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41
</para> </para>
<para> <para>
The backend access come from <acronym>ODBC</acronym> drivers, The backend access comes from <acronym>ODBC</acronym> drivers,
or vendor-specific drivers that or vendor-specific drivers that
allow data access. <productname>psqlODBC</productname> is such a driver, allow data access. <productname>psqlODBC</productname>, which is included in the <productname>PostgreSQL</> distribution, is such a driver,
along with others that are along with others that are
available, such as the <productname>OpenLink</productname> <acronym>ODBC</acronym> drivers. available, such as the <productname>OpenLink</productname> <acronym>ODBC</acronym> drivers.
</para> </para>
...@@ -62,7 +62,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41 ...@@ -62,7 +62,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41
<para> <para>
Once you write an <acronym>ODBC</acronym> application, Once you write an <acronym>ODBC</acronym> application,
you <emphasis>should</emphasis> be able to connect to <emphasis>any</emphasis> you <emphasis>should</emphasis> be able to connect to <emphasis>any</emphasis>
back end database, regardless of the vendor, as long as the database schema back-end database, regardless of the vendor, as long as the database schema
is the same. is the same.
</para> </para>
...@@ -71,8 +71,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41 ...@@ -71,8 +71,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/odbc.sgml,v 1.28 2001/11/21 05:53:41
and <productname>PostgreSQL</productname> servers that have and <productname>PostgreSQL</productname> servers that have
exactly the same data. Using <acronym>ODBC</acronym>, exactly the same data. Using <acronym>ODBC</acronym>,
your Windows application would make exactly the your Windows application would make exactly the
same calls and the back end data source would look the same (to the Windows same calls and the back-end data source would look the same (to the Windows
app). application).
</para> </para>
</sect1> </sect1>
...@@ -173,7 +173,7 @@ psql -d template1 -f <replaceable>LOCATION</>/odbc.sql ...@@ -173,7 +173,7 @@ psql -d template1 -f <replaceable>LOCATION</>/odbc.sql
<filename>~/.odbc.ini</filename> contains user-specified access information <filename>~/.odbc.ini</filename> contains user-specified access information
for the <productname>psqlODBC</productname> driver. for the <productname>psqlODBC</productname> driver.
The file uses conventions typical for <productname>Windows</productname> The file uses conventions typical for <productname>Windows</productname>
Registry files, but despite this restriction can be made to work. Registry files.
</para> </para>
<para> <para>
...@@ -186,12 +186,12 @@ psql -d template1 -f <replaceable>LOCATION</>/odbc.sql ...@@ -186,12 +186,12 @@ psql -d template1 -f <replaceable>LOCATION</>/odbc.sql
Each section must be labeled with the name given in Each section must be labeled with the name given in
<literal>[ODBC Data Sources]</literal> and must contain the following entries: <literal>[ODBC Data Sources]</literal> and must contain the following entries:
<programlisting> <programlisting>
Driver = <replaceable>prefix</replaceable>/lib/libpsqlodbc.so Driver = <replaceable>prefix</replaceable>/lib/libpsqlodbc.so
Database=<replaceable>DatabaseName</replaceable> Database = <replaceable>DatabaseName</replaceable>
Servername=localhost Servername = localhost
Port=5432 Port = 5432
</programlisting> </programlisting>
<tip> <tip>
<para> <para>
...@@ -212,7 +212,7 @@ Port=5432 ...@@ -212,7 +212,7 @@ Port=5432
Here is an example <filename>.odbc.ini</filename> file, Here is an example <filename>.odbc.ini</filename> file,
showing access information for three databases: showing access information for three databases:
<programlisting> <programlisting>
[ODBC Data Sources] [ODBC Data Sources]
DataEntry = Read/Write Database DataEntry = Read/Write Database
QueryOnly = Read-only Database QueryOnly = Read-only Database
...@@ -246,7 +246,7 @@ Driver = /opt/postgres/current/lib/libpsqlodbc.so ...@@ -246,7 +246,7 @@ Driver = /opt/postgres/current/lib/libpsqlodbc.so
[ODBC] [ODBC]
InstallDir = /opt/applix/axdata/axshlib InstallDir = /opt/applix/axdata/axshlib
</programlisting> </programlisting>
</para> </para>
</sect1> </sect1>
...@@ -298,19 +298,20 @@ InstallDir = /opt/applix/axdata/axshlib ...@@ -298,19 +298,20 @@ InstallDir = /opt/applix/axdata/axshlib
The <acronym>ODBC</acronym> <acronym>API</acronym> The <acronym>ODBC</acronym> <acronym>API</acronym>
is the way to go. is the way to go.
For <productname>Visual C++</productname> coding you can find out more at For <productname>Visual C++</productname> coding you can find out more at
Microsoft's web site or in your <productname>VC++</productname> docs. Microsoft's web site or in your <productname>Visual C++</productname>
documentation.
</para> </para>
<para> <para>
Visual Basic and the other <acronym>RAD</acronym> tools have <classname>Recordset</classname> objects Visual Basic and the other <acronym>RAD</acronym> tools have <classname>Recordset</classname> objects
that use <acronym>ODBC</acronym> that use <acronym>ODBC</acronym>
directly to access data. Using the data-aware controls, you can quickly directly to access data. Using the data-aware controls, you can quickly
link to the <acronym>ODBC</acronym> back end database link to the <acronym>ODBC</acronym> back-end database
(<emphasis>very</emphasis> quickly). (<emphasis>very</emphasis> quickly).
</para> </para>
<para> <para>
Playing around with MS Access will help you sort this out. Try using Playing around with <productname>MS Access</> will help you sort this out. Try using
<menuchoice><guimenu>File</><guimenuitem>Get External Data</></menuchoice>. <menuchoice><guimenu>File</><guimenuitem>Get External Data</></menuchoice>.
</para> </para>
...@@ -354,7 +355,7 @@ InstallDir = /opt/applix/axdata/axshlib ...@@ -354,7 +355,7 @@ InstallDir = /opt/applix/axdata/axshlib
<title>Enabling <application>ApplixWare</application> Database Access</title> <title>Enabling <application>ApplixWare</application> Database Access</title>
<para> <para>
These instructions are for the <literal>4.4.2</literal> release of These instructions are for the 4.4.2 release of
<productname>ApplixWare</productname> on <productname>Linux</productname>. <productname>ApplixWare</productname> on <productname>Linux</productname>.
Refer to the <citetitle>Linux Sys Admin</citetitle> on-line book Refer to the <citetitle>Linux Sys Admin</citetitle> on-line book
for more detailed information. for more detailed information.
...@@ -411,7 +412,7 @@ libFor elfodbc <replaceable>applixroot</replaceable>/applix/axdata/axshlib/lib ...@@ -411,7 +412,7 @@ libFor elfodbc <replaceable>applixroot</replaceable>/applix/axdata/axshlib/lib
<step performance="required"> <step performance="required">
<para> <para>
Create <filename>.odbc.ini</filename> as Create <filename>.odbc.ini</filename> as
described above. You may also want to add the flag described in <xref linkend="odbc-config">. You may also want to add the flag
<programlisting> <programlisting>
TextAsLongVarchar=0 TextAsLongVarchar=0
...@@ -476,7 +477,7 @@ TextAsLongVarchar=0 ...@@ -476,7 +477,7 @@ TextAsLongVarchar=0
</step> </step>
<step performance="required"> <step performance="required">
<para> <para>
The <literal>Ready</literal> message will appear in the lower left corner of the data The <quote>Ready</quote> message will appear in the lower left corner of the data
window. This indicates that you can now enter queries. window. This indicates that you can now enter queries.
</para> </para>
</step> </step>
...@@ -549,7 +550,7 @@ TextAsLongVarchar=0 ...@@ -549,7 +550,7 @@ TextAsLongVarchar=0
<listitem> <listitem>
<para> <para>
The September release of <application>ApplixWare</application> v4.4.1 (the first release with official The September release of <application>ApplixWare</application> 4.4.1 (the first release with official
<acronym>ODBC</acronym> support under Linux) shows problems when user names <acronym>ODBC</acronym> support under Linux) shows problems when user names
exceed eight (8) characters in length. exceed eight (8) characters in length.
Problem description contributed by Steve Campbell Problem description contributed by Steve Campbell
...@@ -574,7 +575,7 @@ TextAsLongVarchar=0 ...@@ -574,7 +575,7 @@ TextAsLongVarchar=0
The <application>axnet</application> program's security system The <application>axnet</application> program's security system
seems a little suspect. <application>axnet</application> does things seems a little suspect. <application>axnet</application> does things
on behalf of the user and on a true on behalf of the user and on a true
multiple user system it really should be run with root security multiuser system it really should be run with root security
(so it can read/write in each user's directory). (so it can read/write in each user's directory).
I would hesitate to recommend this, however, since we have no idea what I would hesitate to recommend this, however, since we have no idea what
security holes this creates. security holes this creates.
...@@ -633,7 +634,7 @@ cary 27883 0.9 31.0 12692 4596 ? S 10:24 0:04 axmain ...@@ -633,7 +634,7 @@ cary 27883 0.9 31.0 12692 4596 ? S 10:24 0:04 axmain
Many of the error messages from <productname>ApplixWare</productname> Many of the error messages from <productname>ApplixWare</productname>
go to <filename>stderr</filename>, go to <filename>stderr</filename>,
but I'm not sure where <filename>stderr</filename> but I'm not sure where <filename>stderr</filename>
is sent, so <application>strace</application> is the way to find out. is sent, so <command>strace</command> is the way to find out.
</para> </para>
</note> </note>
</step> </step>
...@@ -641,16 +642,13 @@ cary 27883 0.9 31.0 12692 4596 ? S 10:24 0:04 axmain ...@@ -641,16 +642,13 @@ cary 27883 0.9 31.0 12692 4596 ? S 10:24 0:04 axmain
<para> <para>
For example, after getting For example, after getting
a <literal>Cannot launch gateway on server</literal>, a <errorname>Cannot launch gateway on server</errorname>,
I ran <command>strace</command> on <literal>axnet</literal> and got I ran <command>strace</command> on <literal>axnet</literal> and got
<screen> <screen>
[pid 27947] open("/usr/lib/libodbc.so", O_RDONLY) = -1 ENOENT [pid 27947] open("/usr/lib/libodbc.so", O_RDONLY) = -1 ENOENT (No such file or directory)
(No such file or directory) [pid 27947] open("/lib/libodbc.so", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid 27947] open("/lib/libodbc.so", O_RDONLY) = -1 ENOENT [pid 27947] write(2, "/usr2/applix/axdata/elfodbc: can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error)
(No such file or directory)
[pid 27947] write(2, "/usr2/applix/axdata/elfodbc:
can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error)
</screen> </screen>
So what is happening is that <literal>applix elfodbc</literal> is searching for <filename>libodbc.so</filename>, but it So what is happening is that <literal>applix elfodbc</literal> is searching for <filename>libodbc.so</filename>, but it
cannot find it. That is why <filename>axnet.cnf</filename> needed to be changed. cannot find it. That is why <filename>axnet.cnf</filename> needed to be changed.
...@@ -660,6 +658,8 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error) ...@@ -660,6 +658,8 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error)
<sect2> <sect2>
<title>Running the <application>ApplixWare</application> Demo</title> <title>Running the <application>ApplixWare</application> Demo</title>
<comment>I think the condition this refers to is gone. -- petere 2002-01-07</comment>
<para> <para>
In order to go through the In order to go through the
<citetitle>ApplixWare Data Tutorial</citetitle>, you need to create <citetitle>ApplixWare Data Tutorial</citetitle>, you need to create
...@@ -668,6 +668,7 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error) ...@@ -668,6 +668,7 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error)
on many of the database columns, on many of the database columns,
and <productname>PostgreSQL</productname> does not currently allow this option. and <productname>PostgreSQL</productname> does not currently allow this option.
</para> </para>
<para> <para>
To get around this problem, you can do the following: To get around this problem, you can do the following:
</para> </para>
...@@ -717,7 +718,7 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error) ...@@ -717,7 +718,7 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error)
<step performance="required"> <step performance="required">
<para> <para>
Select <command>File->Compile and Save</command>. Select <menuchoice><guimenu>File</><guimenuitem>Compile and Save</></menuchoice>.
</para> </para>
</step> </step>
...@@ -735,13 +736,13 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error) ...@@ -735,13 +736,13 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error)
<step performance="required"> <step performance="required">
<para> <para>
Select <command>*->Run Macro</command> Select <menuchoice><guimenu>*</><guimenuitem>Run Macro</guimenuitem></menuchoice>.
</para> </para>
</step> </step>
<step performance="required"> <step performance="required">
<para> <para>
Enter the value <literal>sqldemo</literal>, then click <command>OK</command>. Enter the value <literal>sqldemo</literal>, then click <guibutton>OK</guibutton>.
</para> </para>
<para> <para>
...@@ -757,6 +758,7 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error) ...@@ -757,6 +758,7 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error)
</step> </step>
</procedure> </procedure>
</sect2> </sect2>
<sect2> <sect2>
<title>Useful Macros</title> <title>Useful Macros</title>
...@@ -766,12 +768,12 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error) ...@@ -766,12 +768,12 @@ can't load library 'libodbc.so'\n", 61) = -1 EIO (I/O error)
macro file. This is an example macro file. This is an example
<filename>~/axhome/macros/login.am</filename> file: <filename>~/axhome/macros/login.am</filename> file:
<programlisting> <programlisting>
macro login macro login
set_set_system_var@("sql_username@","tgl") set_set_system_var@("sql_username@","tgl")
set_system_var@("sql_passwd@","no$way") set_system_var@("sql_passwd@","no$way")
endmacro endmacro
</programlisting> </programlisting>
<caution> <caution>
<para> <para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.11 2001/11/21 05:53:41 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.12 2002/01/07 02:29:13 petere Exp $
--> -->
<chapter id="plperl"> <chapter id="plperl">
...@@ -13,15 +13,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.11 2001/11/21 05:53:41 thom ...@@ -13,15 +13,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.11 2001/11/21 05:53:41 thom
<primary>Perl</primary> <primary>Perl</primary>
</indexterm> </indexterm>
<sect1 id="intro">
<title>Introduction</title>
<para> <para>
PL/Perl allows you to write functions in the Perl programming PL/Perl allows you to write functions in the <ulink
language that may be used in SQL queries as if they were built into url="http://www.perl.com">Perl</ulink> programming language that may
be used in SQL queries as if they were built into
<productname>PostgreSQL</productname>. <productname>PostgreSQL</productname>.
</para> </para>
<para> <para>
The PL/Perl interpreter (when installed as trusted interpreter with The PL/Perl interpreter (when installed as trusted interpreter with
default name <literal>plperl</>) interpreter is a full Perl interpreter. However, certain default name <literal>plperl</>) is a full Perl interpreter. However, certain
operations have been disabled in order to maintain the security of operations have been disabled in order to maintain the security of
the system. In general, the operations that are restricted are the system. In general, the operations that are restricted are
those that interact with the environment. This includes file handle those that interact with the environment. This includes file handle
...@@ -33,8 +37,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.11 2001/11/21 05:53:41 thom ...@@ -33,8 +37,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.11 2001/11/21 05:53:41 thom
</para> </para>
<para> <para>
When PL/Perl is installed as <quote>untrusted</> interpreter (with name <literal>plperlu</literal>), When PL/Perl is installed as <quote>untrusted</> interpreter (with name <literal>plperlu</literal>),
everything is permitted, and any Perl code can be loaded (by superuser only). everything is permitted, and any Perl code can be loaded (by a superuser only).
</para> </para>
</sect1>
<sect1 id="plperl-install"> <sect1 id="plperl-install">
<title>Building and Installing</title> <title>Building and Installing</title>
...@@ -54,10 +59,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.11 2001/11/21 05:53:41 thom ...@@ -54,10 +59,9 @@ $Header: /cvsroot/pgsql/doc/src/sgml/plperl.sgml,v 2.11 2001/11/21 05:53:41 thom
fact: fact:
<screen> <screen>
<computeroutput> <computeroutput>
***** *** Cannot build PL/Perl because libperl is not a shared library.
* Cannot build PL/Perl because libperl is not a shared library. *** You might have to rebuild your Perl installation. Refer to
* Skipped. *** the documentation for details.
*****
</computeroutput> </computeroutput>
</screen> </screen>
Therefore it is likely that you will have to re-build and install Therefore it is likely that you will have to re-build and install
...@@ -84,7 +88,7 @@ gmake install ...@@ -84,7 +88,7 @@ gmake install
<prompt>$</prompt> <userinput>createlang plperl template1</userinput> <prompt>$</prompt> <userinput>createlang plperl template1</userinput>
</screen> </screen>
Alternatively, to create untrusted interpreter (where functions can only Alternatively, to create untrusted interpreter (where functions can only
be created by superuser, but the functions are not restricted), use: be created by a superuser, but the functions are not restricted), use:
<screen> <screen>
<prompt>$</prompt> <userinput>createlang plperlu template1</userinput> <prompt>$</prompt> <userinput>createlang plperlu template1</userinput>
</screen> </screen>
...@@ -99,7 +103,7 @@ be created by superuser, but the functions are not restricted), use: ...@@ -99,7 +103,7 @@ be created by superuser, but the functions are not restricted), use:
<para> <para>
Assume you have the following table: Assume you have the following table:
<programlisting> <programlisting>
CREATE TABLE EMPLOYEE ( CREATE TABLE employee (
name text, name text,
basesalary integer, basesalary integer,
bonus integer bonus integer
...@@ -111,7 +115,7 @@ CREATE TABLE EMPLOYEE ( ...@@ -111,7 +115,7 @@ CREATE TABLE EMPLOYEE (
<programlisting> <programlisting>
CREATE FUNCTION totalcomp(integer, integer) RETURNS integer CREATE FUNCTION totalcomp(integer, integer) RETURNS integer
AS 'return $_[0] + $_[1]' AS 'return $_[0] + $_[1]'
LANGUAGE 'plperl'; LANGUAGE plperl;
</programlisting> </programlisting>
Notice that the arguments to the function are passed in Notice that the arguments to the function are passed in
...@@ -131,7 +135,7 @@ SELECT name, totalcomp(basesalary, bonus) FROM employee; ...@@ -131,7 +135,7 @@ SELECT name, totalcomp(basesalary, bonus) FROM employee;
CREATE FUNCTION empcomp(employee) RETURNS integer AS ' CREATE FUNCTION empcomp(employee) RETURNS integer AS '
my $emp = shift; my $emp = shift;
return $emp->{''basesalary''} + $emp->{''bonus''}; return $emp->{''basesalary''} + $emp->{''bonus''};
' LANGUAGE 'plperl'; ' LANGUAGE plperl;
</programlisting> </programlisting>
A tuple is passed as a reference to a hash. The keys are the names A tuple is passed as a reference to a hash. The keys are the names
of the fields in the tuples. The hash values are values of the of the fields in the tuples. The hash values are values of the
...@@ -151,7 +155,7 @@ CREATE FUNCTION empcomp(employee) RETURNS integer AS ' ...@@ -151,7 +155,7 @@ CREATE FUNCTION empcomp(employee) RETURNS integer AS '
</tip> </tip>
<para> <para>
The new function <function>empcomp</function> can used like: The new function <function>empcomp</function> can be used like:
<programlisting> <programlisting>
SELECT name, empcomp(employee) FROM employee; SELECT name, empcomp(employee) FROM employee;
</programlisting> </programlisting>
...@@ -165,18 +169,22 @@ CREATE FUNCTION badfunc() RETURNS integer AS ' ...@@ -165,18 +169,22 @@ CREATE FUNCTION badfunc() RETURNS integer AS '
open(TEMP, ">/tmp/badfile"); open(TEMP, ">/tmp/badfile");
print TEMP "Gotcha!\n"; print TEMP "Gotcha!\n";
return 1; return 1;
' LANGUAGE 'plperl'; ' LANGUAGE plperl;
</programlisting> </programlisting>
The creation of the function will succeed, but executing it will not. The creation of the function will succeed, but executing it will not.
</para>
<para>
Note that if same function was created by superuser using language Note that if same function was created by superuser using language
<literal>plperlu</>, execution would succeed. <literal>plperlu</>, execution would succeed.
</para> </para>
<para> <para>
Access to database itself from your Perl function can be done via Access to database itself from your Perl function can be done via
an experimental module <ulink url="http://www.formenos.org/PgSPI/"><literal>DBD::PgSPI</literal></ulink>. This module makes available a <acronym>DBI</>-compliant an experimental module <ulink
database-handle named <varname>$pg_dbh</varname>, and you can use that to make queries with url="http://www.formenos.org/PgSPI/"><literal>DBD::PgSPI</literal></ulink>
normal <acronym>DBI</> syntax. (also on <ulink url="http://www.cpan.org">CPAN</ulink>). This
module makes available a <acronym>DBI</>-compliant database-handle
named <varname>$pg_dbh</varname>, and you can use that to perform
queries with normal <acronym>DBI</> syntax.
</para> </para>
</sect1> </sect1>
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/plpython.sgml,v 1.7 2001/11/21 05:53:41 thomas Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/plpython.sgml,v 1.8 2002/01/07 02:29:13 petere Exp $ -->
<chapter id="plpython"> <chapter id="plpython">
<title>PL/Python - Python Procedural Language</title> <title>PL/Python - Python Procedural Language</title>
...@@ -6,44 +6,74 @@ ...@@ -6,44 +6,74 @@
<indexterm zone="plpython"><primary>PL/Python</></> <indexterm zone="plpython"><primary>PL/Python</></>
<indexterm zone="plpython"><primary>Python</></> <indexterm zone="plpython"><primary>Python</></>
<note> <sect1 id="plpython-intro">
<title>Introduction</title>
<para> <para>
This chapter is not fully developed yet. The <application>PL/Python</application> procedural language allows
<productname>PostgreSQL</productname> functions to be written in
the <ulink url="http://www.python.org">Python</ulink> language.
</para> </para>
<para> <para>
The current version of PL/Python functions as a trusted language only; The current version of <application>PL/Python</application>
access to the filesystem and other local resources are disabled. functions as a trusted language only; access to the file system and
Specifically, PL/Python uses the Python restricted execution environment, other local resources is disabled. Specifically,
further restricts it to prevent the use of the file open call, and <application>PL/Python</application> uses the Python restricted
allows only modules from a specific list to be imported. Presently, execution environment, further restricts it to prevent the use of
that list includes: array, bisect, binascii, calendar, cmath, codecs, the file <function>open</> call, and allows only modules from a
errno, marshal, math, md5, mpz, operator, pcre, pickle, random, re, specific list to be imported. Presently, that list includes:
regex, sre, sha, string, StringIO, struct, time, whrandom, and zlib. array, bisect, binascii, calendar, cmath, codecs, errno, marshal,
math, md5, mpz, operator, pcre, pickle, random, re, regex, sre,
sha, string, StringIO, struct, time, whrandom, and zlib.
</para> </para>
<para> <para>
There is discussion on creating an untrusted language variant for a In the current version, any database error encountered while
running a <application>PL/Python</application> function will result
in the immediate termination of that function by the server. It is
not possible to trap error conditions using Python <literal>try
... catch</literal> constructs. For example, a syntax error in an
SQL statement passed to the <literal>plpy.execute()</literal> call
will terminate the function. This behavior may be changed in a
future release. future release.
</para> </para>
<para> </sect1>
In the current version, any postgresql error encountered while running
a PL/Python function will result in the immediate termination of that
function by the backend. It is not possible to trap error conditions
using Python try ... catch constructs. For example, a syntax error in
an SQL statement passed to the plpy.execute() call will terminate the
function. This behavior may be changed in a future release.
</para>
</note>
<sect1 id="plpython-install"> <sect1 id="plpython-install">
<title>Installation</title> <title>Installation</title>
<para> <para>
... needs to be worked out. To build PL/Python, the <option>--with-python</option> option needs
to be specified when running <filename>configure</filename>. If
after building and installing you have a file called
<filename>plpython.so</filename> (possibly a different extension),
then everything went well. Otherwise you should have seen a notice
like this flying by:
<screen>
*** Cannot build PL/Python because libpython is not a shared library.
*** You might have to rebuild your Python installation. Refer to
*** the documentation for details.
</screen>
That means you have to rebuild (part of) your Python installation
to supply this shared library.
</para>
<para>
The catch is that the Python distribution or the Python maintainers
do not provide any direct way to do this. The closest thing we can
offer you is the information in <ulink
url="http://www.python.org/doc/FAQ.html#3.30">Python FAQ
3.30</ulink>. On some operating systems you don't really have to
build a shared library, but then you will have to convince the
PostgreSQL build system of this. Consult the
<filename>Makefile</filename> in the
<filename>src/pl/plpython</filename> directory for details.
</para> </para>
</sect1> </sect1>
<sect1 id="plpython-using"> <sect1 id="plpython-using">
<title>Using</title> <title>Using PL/Python</title>
<para> <para>
There are sample functions in There are sample functions in
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.52 2002/01/02 00:41:26 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.53 2002/01/07 02:29:13 petere Exp $
--> -->
<chapter id="plpgsql"> <chapter id="plpgsql">
...@@ -1700,7 +1700,7 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id; ...@@ -1700,7 +1700,7 @@ RAISE EXCEPTION ''Inexistent ID --> %'',user_id;
<para> <para>
It is possible to hook into the error mechanism to notice that this It is possible to hook into the error mechanism to notice that this
happens. But currently it is impossible to tell what really happens. But currently it is impossible to tell what really
caused the abort (input/output conversion error, floating point caused the abort (input/output conversion error, floating-point
error, parse error). And it is possible that the database backend error, parse error). And it is possible that the database backend
is in an inconsistent state at this point so returning to the upper is in an inconsistent state at this point so returning to the upper
executor or issuing more commands might corrupt the whole database. executor or issuing more commands might corrupt the whole database.
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/problems.sgml,v 2.11 2001/11/21 05:53:41 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/problems.sgml,v 2.12 2002/01/07 02:29:13 petere Exp $
--> -->
<sect1 id="bug-reporting"> <sect1 id="bug-reporting">
...@@ -252,7 +252,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/problems.sgml,v 2.11 2001/11/21 05:53:41 th ...@@ -252,7 +252,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/problems.sgml,v 2.11 2001/11/21 05:53:41 th
Do not spend all your time to figure out which changes in the input make Do not spend all your time to figure out which changes in the input make
the problem go away. This will probably not help solving it. If it turns the problem go away. This will probably not help solving it. If it turns
out that the bug cannot be fixed right away, you will still have time to out that the bug cannot be fixed right away, you will still have time to
find and share your work around. Also, once again, do not waste your time find and share your work-around. Also, once again, do not waste your time
guessing why the bug exists. We will find that out soon enough. guessing why the bug exists. We will find that out soon enough.
</para> </para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/programmer.sgml,v 1.38 2001/05/12 22:51:35 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/programmer.sgml,v 1.39 2002/01/07 02:29:13 petere Exp $
PostgreSQL Programmer's Guide. PostgreSQL Programmer's Guide.
--> -->
...@@ -16,30 +16,17 @@ PostgreSQL Programmer's Guide. ...@@ -16,30 +16,17 @@ PostgreSQL Programmer's Guide.
&intro; &intro;
]]> ]]>
<preface id="organization">
<title>Organization</title>
<para>
The first part of this manual is the description of the client-side
programming interfaces and support libraries for various languages.
The second part explains the <productname>PostgreSQL</productname>
approach to extensibility and describe how users can extend
<productname>PostgreSQL</productname> by adding user-defined types,
operators, aggregates, and both query language and programming
language functions. After a discussion of the
<productname>PostgreSQL</productname> rule system, we discuss the
trigger and SPI interfaces. The third part documents the
procedural languages available in the
<productname>PostgreSQL</productname> distribution.
</para>
<para>
Proficiency with Unix and C programming is assumed.
</para>
</preface>
<part id="programmer-client"> <part id="programmer-client">
<title>Client Interfaces</title> <title>Client Interfaces</title>
<partintro>
<para>
This part of the manual is the description of the client-side
programming interfaces and support libraries for various
languages.
</para>
</partintro>
&libpq; &libpq;
&lobj; &lobj;
&libpqpp; &libpqpp;
...@@ -53,6 +40,20 @@ PostgreSQL Programmer's Guide. ...@@ -53,6 +40,20 @@ PostgreSQL Programmer's Guide.
<part id="programmer-server"> <part id="programmer-server">
<title>Server Programming</title> <title>Server Programming</title>
<partintro>
<para>
This second part of the manual explains the
<productname>PostgreSQL</productname> approach to extensibility
and describe how users can extend
<productname>PostgreSQL</productname> by adding user-defined
types, operators, aggregates, and both query language and
programming language functions. After a discussion of the
<productname>PostgreSQL</productname> rule system, we discuss the
trigger and SPI interfaces.
</para>
</partintro>
&arch-pg; &arch-pg;
&extend; &extend;
&xfunc; &xfunc;
...@@ -70,6 +71,14 @@ PostgreSQL Programmer's Guide. ...@@ -70,6 +71,14 @@ PostgreSQL Programmer's Guide.
<part id="programmer-pl"> <part id="programmer-pl">
<title>Procedural Languages</title> <title>Procedural Languages</title>
<partintro>
<para>
This part documents the procedural languages available in the
<productname>PostgreSQL</productname> distribution as well as
general issues concerning procedural languages.
</para>
</partintro>
&xplang; &xplang;
&plsql; &plsql;
&pltcl; &pltcl;
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/query.sgml,v 1.23 2001/11/28 20:49:10 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/query.sgml,v 1.24 2002/01/07 02:29:13 petere Exp $
--> -->
<chapter id="tutorial-sql"> <chapter id="tutorial-sql">
...@@ -137,7 +137,7 @@ CREATE TABLE weather ( ...@@ -137,7 +137,7 @@ CREATE TABLE weather (
<type>varchar(80)</type> specifies a data type that can store <type>varchar(80)</type> specifies a data type that can store
arbitrary character strings up to 80 characters in length. arbitrary character strings up to 80 characters in length.
<type>int</type> is the normal integer type. <type>real</type> is <type>int</type> is the normal integer type. <type>real</type> is
a type for storing single precision floating point numbers. a type for storing single precision floating-point numbers.
<type>date</type> should be self-explanatory. (Yes, the column of <type>date</type> should be self-explanatory. (Yes, the column of
type <type>date</type> is also named <literal>date</literal>. type <type>date</type> is also named <literal>date</literal>.
This may be convenient or confusing -- you choose.) This may be convenient or confusing -- you choose.)
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.22 2001/12/08 03:24:34 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_operator.sgml,v 1.23 2002/01/07 02:29:15 petere Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -343,7 +343,7 @@ MYBOXES.description &lt;&lt;&lt; box '((0,0), (1,1))' ...@@ -343,7 +343,7 @@ MYBOXES.description &lt;&lt;&lt; box '((0,0), (1,1))'
<replaceable class="parameter">res_proc</replaceable> <replaceable class="parameter">res_proc</replaceable>
must be a registered function (meaning it is already defined using must be a registered function (meaning it is already defined using
<command>CREATE FUNCTION</command>) which accepts arguments of the correct <command>CREATE FUNCTION</command>) which accepts arguments of the correct
data types and returns a floating point number. The data types and returns a floating-point number. The
query optimizer simply calls this function, passing the query optimizer simply calls this function, passing the
parameter <literal>((0,0), (1,1))</literal> and multiplies the result by the relation parameter <literal>((0,0), (1,1))</literal> and multiplies the result by the relation
size to get the expected number of instances. size to get the expected number of instances.
...@@ -352,7 +352,7 @@ MYBOXES.description &lt;&lt;&lt; box '((0,0), (1,1))' ...@@ -352,7 +352,7 @@ MYBOXES.description &lt;&lt;&lt; box '((0,0), (1,1))'
Similarly, when the operands of the operator both contain Similarly, when the operands of the operator both contain
instance variables, the query optimizer must estimate the instance variables, the query optimizer must estimate the
size of the resulting join. The function join_proc will size of the resulting join. The function join_proc will
return another floating point number which will be multiplied return another floating-point number which will be multiplied
by the cardinalities of the two tables involved to by the cardinalities of the two tables involved to
compute the expected result size. compute the expected result size.
</para> </para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.56 2001/12/29 20:29:49 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.57 2002/01/07 02:29:15 petere Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -195,8 +195,8 @@ SET TIME ZONE { '<replaceable class="PARAMETER">timezone</replaceable>' | LOCAL ...@@ -195,8 +195,8 @@ SET TIME ZONE { '<replaceable class="PARAMETER">timezone</replaceable>' | LOCAL
<para> <para>
The value for the seed to be used by the The value for the seed to be used by the
<function>random</function> function. Allowed <function>random</function> function. Allowed
values are floating point numbers between 0 and 1, which values are floating-point numbers between 0 and 1, which
are then multiplied by 2^31-1. This product will are then multiplied by 2<superscript>31</>-1. This product will
silently overflow if a number outside the range is used. silently overflow if a number outside the range is used.
</para> </para>
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/regress.sgml,v 1.23 2001/12/04 01:49:17 tgl Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/regress.sgml,v 1.24 2002/01/07 02:29:13 petere Exp $ -->
<chapter id="regress"> <chapter id="regress">
<title id="regress-title">Regression Tests</title> <title id="regress-title">Regression Tests</title>
...@@ -135,7 +135,7 @@ ...@@ -135,7 +135,7 @@
Some properly installed and fully functional Some properly installed and fully functional
<productname>PostgreSQL</productname> installations can <productname>PostgreSQL</productname> installations can
<quote>fail</quote> some of these regression tests due to <quote>fail</quote> some of these regression tests due to
platform-specific artifacts such as varying floating point representation platform-specific artifacts such as varying floating-point representation
and time zone support. The tests are currently evaluated using a simple and time zone support. The tests are currently evaluated using a simple
<application>diff</application> comparison against the outputs <application>diff</application> comparison against the outputs
generated on a reference system, so the results are sensitive to generated on a reference system, so the results are sensitive to
...@@ -248,7 +248,7 @@ PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ ...@@ -248,7 +248,7 @@ PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ
</sect2> </sect2>
<sect2> <sect2>
<title>Floating point differences</title> <title>Floating-point differences</title>
<para> <para>
Some of the tests involve computing 64-bit (<type>double Some of the tests involve computing 64-bit (<type>double
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.19 2001/11/21 06:09:45 thomas Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/rules.sgml,v 1.20 2002/01/07 02:29:13 petere Exp $ -->
<Chapter Id="rules"> <Chapter Id="rules">
<Title>The Rule System</Title> <Title>The Rule System</Title>
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
</para> </para>
</note> </note>
<sect1 id="rules-intro">
<title>Introduction</title>
<Para> <Para>
Production rule systems are conceptually simple, but Production rule systems are conceptually simple, but
there are many subtle points involved in actually using there are many subtle points involved in actually using
...@@ -42,6 +45,9 @@ ...@@ -42,6 +45,9 @@
as well as as well as
<XRef LinkEnd="STON90b">. <XRef LinkEnd="STON90b">.
</para> </para>
</sect1>
<Sect1 id="querytree"> <Sect1 id="querytree">
<Title>What is a Query Tree?</Title> <Title>What is a Query Tree?</Title>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.100 2001/12/27 21:37:34 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.101 2002/01/07 02:29:13 petere Exp $
--> -->
<Chapter Id="runtime"> <Chapter Id="runtime">
...@@ -128,9 +128,9 @@ postgres$ <userinput>initdb -D /usr/local/pgsql/data</userinput> ...@@ -128,9 +128,9 @@ postgres$ <userinput>initdb -D /usr/local/pgsql/data</userinput>
password to the database superuser. After <command>initdb</command>, password to the database superuser. After <command>initdb</command>,
modify <filename>pg_hba.conf</filename> to use <literal>md5</> or modify <filename>pg_hba.conf</filename> to use <literal>md5</> or
<literal>password</>, instead of <literal>trust</>, authentication <literal>password</>, instead of <literal>trust</>, authentication
<emphasis>before</> you first start the postmaster. (Other, possibly <emphasis>before</> you start the server for the first time. (Other, possibly
more convenient approaches include using <literal>ident</literal> more convenient approaches include using <literal>ident</literal>
authentication or filesystem permissions to restrict connections. See authentication or file system permissions to restrict connections. See
<xref linkend="client-authentication"> for more information.) <xref linkend="client-authentication"> for more information.)
</para> </para>
...@@ -493,7 +493,7 @@ log_connections = yes ...@@ -493,7 +493,7 @@ log_connections = yes
syslog = 2 syslog = 2
</programlisting> </programlisting>
As you see, options are one per line. The equal sign between name As you see, options are one per line. The equal sign between name
and value is optional. White space is insignificant, blank lines and value is optional. Whitespace is insignificant, blank lines
are ignored. Hash marks (<quote>#</quote>) introduce comments are ignored. Hash marks (<quote>#</quote>) introduce comments
anywhere. anywhere.
</para> </para>
...@@ -504,7 +504,7 @@ syslog = 2 ...@@ -504,7 +504,7 @@ syslog = 2
</indexterm> </indexterm>
The configuration file is reread whenever the postmaster receives The configuration file is reread whenever the postmaster receives
a <systemitem>SIGHUP</> signal (which is most easily sent by means a <systemitem>SIGHUP</> signal (which is most easily sent by means
of <application>pg_ctl reload</>). The postmaster also propagates of <literal>pg_ctl reload</>). The postmaster also propagates
this signal to all already-running backend processes, so that this signal to all already-running backend processes, so that
existing sessions also get the new default. existing sessions also get the new default.
Alternatively, you can send the signal to only one backend process Alternatively, you can send the signal to only one backend process
...@@ -886,7 +886,7 @@ env PGOPTIONS='-c geqo=off' psql ...@@ -886,7 +886,7 @@ env PGOPTIONS='-c geqo=off' psql
<term><varname>LOG_PID</varname> (<type>boolean</type>)</term> <term><varname>LOG_PID</varname> (<type>boolean</type>)</term>
<listitem> <listitem>
<para> <para>
Prefixes each server log message with the process id of the Prefixes each server log message with the process ID of the
backend process. This is useful to sort out which messages backend process. This is useful to sort out which messages
pertain to which connection. The default is off. pertain to which connection. The default is off.
</para> </para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.55 2001/12/08 03:24:23 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.56 2002/01/07 02:29:13 petere Exp $
--> -->
<chapter id="sql-syntax"> <chapter id="sql-syntax">
...@@ -102,7 +102,8 @@ INSERT INTO MY_TABLE VALUES (3, 'hi there'); ...@@ -102,7 +102,8 @@ INSERT INTO MY_TABLE VALUES (3, 'hi there');
<para> <para>
SQL identifiers and key words must begin with a letter SQL identifiers and key words must begin with a letter
(<literal>a</literal>-<literal>z</literal>) or underscore (<literal>a</literal>-<literal>z</literal>, but also letters with
diacritical marks and non-Latin letters) or an underscore
(<literal>_</literal>). Subsequent characters in an identifier or (<literal>_</literal>). Subsequent characters in an identifier or
key word can be letters, digits key word can be letters, digits
(<literal>0</literal>-<literal>9</literal>), or underscores, (<literal>0</literal>-<literal>9</literal>), or underscores,
...@@ -200,9 +201,9 @@ UPDATE "my_table" SET "a" = 5; ...@@ -200,9 +201,9 @@ UPDATE "my_table" SET "a" = 5;
</indexterm> </indexterm>
<para> <para>
There are four kinds of <firstterm>implicitly typed There are four kinds of <firstterm>implicitly-typed
constants</firstterm> in <productname>PostgreSQL</productname>: constants</firstterm> in <productname>PostgreSQL</productname>:
strings, bit strings, integers, and floating point numbers. strings, bit strings, integers, and floating-point numbers.
Constants can also be specified with explicit types, which can Constants can also be specified with explicit types, which can
enable more accurate representation and more efficient handling by enable more accurate representation and more efficient handling by
the system. The implicit constants are described below; explicit the system. The implicit constants are described below; explicit
...@@ -266,12 +267,12 @@ SELECT 'foobar'; ...@@ -266,12 +267,12 @@ SELECT 'foobar';
SELECT 'foo' 'bar'; SELECT 'foo' 'bar';
</programlisting> </programlisting>
is not valid syntax, and <productname>PostgreSQL</productname> is is not valid syntax, and <productname>PostgreSQL</productname> is
consistant with <acronym>SQL9x</acronym> in this regard. consistent with <acronym>SQL9x</acronym> in this regard.
</para> </para>
</sect3> </sect3>
<sect3 id="sql-syntax-bit-strings"> <sect3 id="sql-syntax-bit-strings">
<title>Bit String Constants</title> <title>Bit-String Constants</title>
<indexterm zone="sql-syntax-bit-strings"> <indexterm zone="sql-syntax-bit-strings">
<primary>bit strings</primary> <primary>bit strings</primary>
...@@ -279,12 +280,12 @@ SELECT 'foo' 'bar'; ...@@ -279,12 +280,12 @@ SELECT 'foo' 'bar';
</indexterm> </indexterm>
<para> <para>
Bit string constants look like string constants with a Bit-string constants look like string constants with a
<literal>B</literal> (upper or lower case) immediately before the <literal>B</literal> (upper or lower case) immediately before the
opening quote (no intervening whitespace), e.g., opening quote (no intervening whitespace), e.g.,
<literal>B'1001'</literal>. The only characters allowed within <literal>B'1001'</literal>. The only characters allowed within
bit string constants are <literal>0</literal> and bit-string constants are <literal>0</literal> and
<literal>1</literal>. Bit string constants can be continued <literal>1</literal>. Bit-string constants can be continued
across lines in the same way as regular string constants. across lines in the same way as regular string constants.
</para> </para>
</sect3> </sect3>
...@@ -303,7 +304,7 @@ SELECT 'foo' 'bar'; ...@@ -303,7 +304,7 @@ SELECT 'foo' 'bar';
</sect3> </sect3>
<sect3> <sect3>
<title>Floating Point Constants</title> <title>Floating-Point Constants</title>
<indexterm> <indexterm>
<primary>floating point</primary> <primary>floating point</primary>
...@@ -311,7 +312,7 @@ SELECT 'foo' 'bar'; ...@@ -311,7 +312,7 @@ SELECT 'foo' 'bar';
</indexterm> </indexterm>
<para> <para>
Floating point constants are accepted in these general forms: Floating-point constants are accepted in these general forms:
<synopsis> <synopsis>
<replaceable>digits</replaceable>.<optional><replaceable>digits</replaceable></optional><optional>e<optional>+-</optional><replaceable>digits</replaceable></optional> <replaceable>digits</replaceable>.<optional><replaceable>digits</replaceable></optional><optional>e<optional>+-</optional><replaceable>digits</replaceable></optional>
<optional><replaceable>digits</replaceable></optional>.<replaceable>digits</replaceable><optional>e<optional>+-</optional><replaceable>digits</replaceable></optional> <optional><replaceable>digits</replaceable></optional>.<replaceable>digits</replaceable><optional>e<optional>+-</optional><replaceable>digits</replaceable></optional>
...@@ -321,7 +322,7 @@ SELECT 'foo' 'bar'; ...@@ -321,7 +322,7 @@ SELECT 'foo' 'bar';
digits. At least one digit must be before or after the decimal digits. At least one digit must be before or after the decimal
point. At least one digit must follow the exponent delimiter point. At least one digit must follow the exponent delimiter
(<literal>e</literal>) if that field is present. (<literal>e</literal>) if that field is present.
Thus, a floating point constant is distinguished from an integer Thus, a floating-point constant is distinguished from an integer
constant by the presence of either the decimal point or the constant by the presence of either the decimal point or the
exponent clause (or both). There must not be a space or other exponent clause (or both). There must not be a space or other
characters embedded in the constant. characters embedded in the constant.
...@@ -329,7 +330,7 @@ SELECT 'foo' 'bar'; ...@@ -329,7 +330,7 @@ SELECT 'foo' 'bar';
<informalexample> <informalexample>
<para> <para>
These are some examples of valid floating point constants: These are some examples of valid floating-point constants:
<literallayout> <literallayout>
3.5 3.5
4. 4.
...@@ -341,7 +342,7 @@ SELECT 'foo' 'bar'; ...@@ -341,7 +342,7 @@ SELECT 'foo' 'bar';
</informalexample> </informalexample>
<para> <para>
Floating point constants are of type <type>DOUBLE Floating-point constants are of type <type>DOUBLE
PRECISION</type>. <type>REAL</type> can be specified explicitly PRECISION</type>. <type>REAL</type> can be specified explicitly
by using <acronym>SQL</acronym> string notation or by using <acronym>SQL</acronym> string notation or
<productname>PostgreSQL</productname> type notation: <productname>PostgreSQL</productname> type notation:
...@@ -385,9 +386,13 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -385,9 +386,13 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
<replaceable>typename</replaceable> ( <replaceable>value</replaceable> ) <replaceable>typename</replaceable> ( <replaceable>value</replaceable> )
</synopsis> </synopsis>
although this only works for types whose names are also valid as although this only works for types whose names are also valid as
function names. (For example, <literal>double precision</literal> function names. For example, <literal>double precision</literal>
can't be used this way --- but the equivalent <literal>float8</literal> can't be used this way, but the equivalent <literal>float8</literal>
can.) can. Also, the names <literal>interval</>, <literal>time</>, and
<literal>timestamp</> can only be used in this context if they are
double-quoted, because of parser conflicts. Therefore, the use of
the function-like cast syntax leads to inconsistencies and should
probably be avoided in new applications.
</para> </para>
<para> <para>
...@@ -429,8 +434,8 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -429,8 +434,8 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
<para> <para>
Individual array elements can be placed between double-quote Individual array elements can be placed between double-quote
marks (<literal>"</literal>) <!-- " --> to avoid ambiguity marks (<literal>"</literal>) <!-- " --> to avoid ambiguity
problems with respect to white space. Without quote marks, the problems with respect to whitespace. Without quote marks, the
array-value parser will skip leading white space. array-value parser will skip leading whitespace.
</para> </para>
<para> <para>
...@@ -495,7 +500,7 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -495,7 +500,7 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
<para> <para>
When working with non-SQL-standard operator names, you will usually When working with non-SQL-standard operator names, you will usually
need to separate adjacent operators with spaces to avoid ambiguity. need to separate adjacent operators with spaces to avoid ambiguity.
For example, if you have defined a left-unary operator named <literal>@</literal>, For example, if you have defined a left unary operator named <literal>@</literal>,
you cannot write <literal>X*@Y</literal>; you must write you cannot write <literal>X*@Y</literal>; you must write
<literal>X* @Y</literal> to ensure that <literal>X* @Y</literal> to ensure that
<productname>PostgreSQL</productname> reads it as two operator names <productname>PostgreSQL</productname> reads it as two operator names
...@@ -574,7 +579,7 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -574,7 +579,7 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
<listitem> <listitem>
<para> <para>
The period (<literal>.</literal>) is used in floating point The period (<literal>.</literal>) is used in floating-point
constants, and to separate table and column names. constants, and to separate table and column names.
</para> </para>
</listitem> </listitem>
...@@ -670,8 +675,8 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -670,8 +675,8 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
<listitem> <listitem>
<para> <para>
The identity (transaction ID) of the inserting transaction for The identity (transaction ID) of the inserting transaction for
this tuple. (Note: a tuple is an individual state of a row; this tuple. (Note: A tuple is an individual state of a row;
each UPDATE of a row creates a new tuple for the same logical row.) each update of a row creates a new tuple for the same logical row.)
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -733,7 +738,7 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -733,7 +738,7 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
counter to wrap around. Hence, it is bad practice to assume that OIDs counter to wrap around. Hence, it is bad practice to assume that OIDs
are unique, unless you take steps to ensure that they are unique. are unique, unless you take steps to ensure that they are unique.
Recommended practice when using OIDs for row identification is to create Recommended practice when using OIDs for row identification is to create
a unique index on the OID column of each table for which the OID will be a unique constraint on the OID column of each table for which the OID will be
used. Never assume that OIDs are unique across tables; use the used. Never assume that OIDs are unique across tables; use the
combination of <structfield>tableoid</> and row OID if you need a database-wide combination of <structfield>tableoid</> and row OID if you need a database-wide
identifier. (Future releases of <productname>PostgreSQL</productname> are likely to use a separate identifier. (Future releases of <productname>PostgreSQL</productname> are likely to use a separate
...@@ -756,12 +761,6 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -756,12 +761,6 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
In practice this limit is not a problem --- note that the limit is on In practice this limit is not a problem --- note that the limit is on
number of SQL queries, not number of tuples processed. number of SQL queries, not number of tuples processed.
</para> </para>
<para>
For further information on the system attributes consult
<xref linkend="STON87a">.
</para>
</sect1> </sect1>
...@@ -916,7 +915,7 @@ $<replaceable>number</replaceable> ...@@ -916,7 +915,7 @@ $<replaceable>number</replaceable>
<programlisting> <programlisting>
CREATE FUNCTION dept (text) RETURNS dept CREATE FUNCTION dept (text) RETURNS dept
AS 'SELECT * FROM dept WHERE name = $1' AS 'SELECT * FROM dept WHERE name = $1'
LANGUAGE 'sql'; LANGUAGE SQL;
</programlisting> </programlisting>
Here the <literal>$1</literal> will be replaced by the first Here the <literal>$1</literal> will be replaced by the first
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/xaggr.sgml,v 1.15 2001/11/21 06:09:45 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/xaggr.sgml,v 1.16 2002/01/07 02:29:14 petere Exp $
--> -->
<chapter id="xaggr"> <chapter id="xaggr">
...@@ -39,42 +39,42 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xaggr.sgml,v 1.15 2001/11/21 06:09:45 thoma ...@@ -39,42 +39,42 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xaggr.sgml,v 1.15 2001/11/21 06:09:45 thoma
the column values from each row. <function>Sum</> is an the column values from each row. <function>Sum</> is an
example of this kind of aggregate. <function>Sum</> starts at example of this kind of aggregate. <function>Sum</> starts at
zero and always adds the current row's value to zero and always adds the current row's value to
its running total. For example, if we want to make a Sum its running total. For example, if we want to make a <function>sum</>
aggregate to work on a data type for complex numbers, aggregate to work on a data type for complex numbers,
we only need the addition function for that data type. we only need the addition function for that data type.
The aggregate definition is: The aggregate definition is:
<programlisting> <programlisting>
CREATE AGGREGATE complex_sum ( CREATE AGGREGATE complex_sum (
sfunc = complex_add, sfunc = complex_add,
basetype = complex, basetype = complex,
stype = complex, stype = complex,
initcond = '(0,0)' initcond = '(0,0)'
); );
</programlisting>
<screen>
SELECT complex_sum(a) FROM test_complex; SELECT complex_sum(a) FROM test_complex;
+------------+ complex_sum
|complex_sum | -------------
+------------+ (34,53.9)
|(34,53.9) | </screen>
+------------+
</programlisting>
(In practice, we'd just name the aggregate <function>sum</function>, and rely on (In practice, we'd just name the aggregate <function>sum</function>, and rely on
<productname>PostgreSQL</productname> to figure out which kind <productname>PostgreSQL</productname> to figure out which kind
of sum to apply to a complex column.) of sum to apply to a column of type <type>complex</type>.)
</para> </para>
<para> <para>
The above definition of <function>Sum</function> will return zero (the initial The above definition of <function>sum</function> will return zero (the initial
state condition) if there are no non-null input values. state condition) if there are no non-null input values.
Perhaps we want to return NULL in that case instead --- SQL92 Perhaps we want to return NULL in that case instead --- the SQL standard
expects <function>Sum</function> to behave that way. We can do this simply by expects <function>sum</function> to behave that way. We can do this simply by
omitting the <literal>initcond</literal> phrase, so that the initial state omitting the <literal>initcond</literal> phrase, so that the initial state
condition is NULL. Ordinarily this would mean that the <literal>sfunc</literal> condition is NULL. Ordinarily this would mean that the <literal>sfunc</literal>
would need to check for a NULL state-condition input, but for would need to check for a NULL state-condition input, but for
<function>Sum</function> and some other simple aggregates like <function>Max</> and <function>Min</>, <function>sum</function> and some other simple aggregates like <function>max</> and <function>min</>,
it's sufficient to insert the first non-null input value into it's sufficient to insert the first non-null input value into
the state variable and then start applying the transition function the state variable and then start applying the transition function
at the second non-null input value. <productname>PostgreSQL</productname> at the second non-null input value. <productname>PostgreSQL</productname>
...@@ -93,7 +93,7 @@ SELECT complex_sum(a) FROM test_complex; ...@@ -93,7 +93,7 @@ SELECT complex_sum(a) FROM test_complex;
</para> </para>
<para> <para>
<function>Average</> is a more complex example of an aggregate. It requires <function>Avg</> (average) is a more complex example of an aggregate. It requires
two pieces of running state: the sum of the inputs and the count two pieces of running state: the sum of the inputs and the count
of the number of inputs. The final result is obtained by dividing of the number of inputs. The final result is obtained by dividing
these quantities. Average is typically implemented by using a these quantities. Average is typically implemented by using a
...@@ -101,7 +101,7 @@ SELECT complex_sum(a) FROM test_complex; ...@@ -101,7 +101,7 @@ SELECT complex_sum(a) FROM test_complex;
the built-in implementation of <function>avg(float8)</function> the built-in implementation of <function>avg(float8)</function>
looks like: looks like:
<programlisting> <programlisting>
CREATE AGGREGATE avg ( CREATE AGGREGATE avg (
sfunc = float8_accum, sfunc = float8_accum,
basetype = float8, basetype = float8,
...@@ -109,18 +109,13 @@ CREATE AGGREGATE avg ( ...@@ -109,18 +109,13 @@ CREATE AGGREGATE avg (
finalfunc = float8_avg, finalfunc = float8_avg,
initcond = '{0,0}' initcond = '{0,0}'
); );
</programlisting> </programlisting>
</para> </para>
<para> <para>
For further details see For further details see the description of the <command>CREATE
<!-- AGGREGATE</command> command in the <citetitle>Reference
Not available in the Programmer's Guide Manual</citetitle>.
<xref endterm="sql-createaggregate-title"
linkend="sql-createaggregate-title">.
-->
<command>CREATE AGGREGATE</command> in
<citetitle>The PostgreSQL User's Guide</citetitle>.
</para> </para>
</chapter> </chapter>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.45 2001/11/21 06:09:45 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.46 2002/01/07 02:29:14 petere Exp $
--> -->
<chapter id="xfunc"> <chapter id="xfunc">
...@@ -59,7 +59,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.45 2001/11/21 06:09:45 thoma ...@@ -59,7 +59,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.45 2001/11/21 06:09:45 thoma
<para> <para>
Every kind Every kind
of function can take a base type, a composite type or of function can take a base type, a composite type, or
some combination as arguments (parameters). In addition, some combination as arguments (parameters). In addition,
every kind of function can return a base type or every kind of function can return a base type or
a composite type. It's easiest to define <acronym>SQL</acronym> a composite type. It's easiest to define <acronym>SQL</acronym>
...@@ -67,6 +67,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.45 2001/11/21 06:09:45 thoma ...@@ -67,6 +67,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xfunc.sgml,v 1.45 2001/11/21 06:09:45 thoma
can also be found in <filename>funcs.sql</filename> can also be found in <filename>funcs.sql</filename>
and <filename>funcs.c</filename> in the tutorial directory. and <filename>funcs.c</filename> in the tutorial directory.
</para> </para>
<para>
Throughout this chapter, it can be useful to look at the reference
page of the <command>CREATE FUNCTION</command> command to
understand the examples better.
</para>
</sect1> </sect1>
<sect1 id="xfunc-sql"> <sect1 id="xfunc-sql">
...@@ -268,7 +274,7 @@ SELECT name, double_salary(EMP) AS dream ...@@ -268,7 +274,7 @@ SELECT name, double_salary(EMP) AS dream
<para> <para>
Notice the use of the syntax <literal>$1.salary</literal> Notice the use of the syntax <literal>$1.salary</literal>
to select one field of the argument row value. Also notice to select one field of the argument row value. Also notice
how the calling SELECT command uses a table name to denote how the calling <command>SELECT</> command uses a table name to denote
the entire current row of that table as a composite value. the entire current row of that table as a composite value.
</para> </para>
...@@ -376,7 +382,7 @@ ERROR: parser: parse error at or near "." ...@@ -376,7 +382,7 @@ ERROR: parser: parse error at or near "."
<para> <para>
Another way to use a function returning a row result is to declare a Another way to use a function returning a row result is to declare a
second function accepting a rowtype parameter, and pass the function second function accepting a row type parameter, and pass the function
result to it: result to it:
<programlisting> <programlisting>
...@@ -400,15 +406,15 @@ SELECT getname(new_emp()); ...@@ -400,15 +406,15 @@ SELECT getname(new_emp());
<para> <para>
As previously mentioned, an SQL function may be declared as As previously mentioned, an SQL function may be declared as
returning <literal>SETOF</literal> <replaceable>sometype</>. returning <literal>SETOF <replaceable>sometype</></literal>.
In this case the function's final SELECT query is executed to In this case the function's final <command>SELECT</> query is executed to
completion, and each row it outputs is returned as an element completion, and each row it outputs is returned as an element
of the set. of the set.
</para> </para>
<para> <para>
Functions returning sets may only be called in the target list Functions returning sets may only be called in the target list
of a SELECT query. For each row that the SELECT generates by itself, of a <command>SELECT</> query. For each row that the <command>SELECT</> generates by itself,
the function returning set is invoked, and an output row is generated the function returning set is invoked, and an output row is generated
for each element of the function's result set. An example: for each element of the function's result set. An example:
...@@ -449,9 +455,9 @@ SELECT name, listchildren(name) FROM nodes; ...@@ -449,9 +455,9 @@ SELECT name, listchildren(name) FROM nodes;
(5 rows) (5 rows)
</screen> </screen>
In the last SELECT, In the last <command>SELECT</command>,
notice that no output row appears for Child2, Child3, etc. notice that no output row appears for <literal>Child2</>, <literal>Child3</>, etc.
This happens because listchildren() returns an empty set This happens because <function>listchildren</function> returns an empty set
for those inputs, so no output rows are generated. for those inputs, so no output rows are generated.
</para> </para>
</sect2> </sect2>
...@@ -607,7 +613,7 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision ...@@ -607,7 +613,7 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision
<note> <note>
<para> <para>
The user id the <application>PostgreSQL</application> server runs The user ID the <application>PostgreSQL</application> server runs
as must be able to traverse the path to the file you intend to as must be able to traverse the path to the file you intend to
load. Making the file or a higher-level directory not readable load. Making the file or a higher-level directory not readable
and/or not executable by the <quote>postgres</quote> user is a and/or not executable by the <quote>postgres</quote> user is a
...@@ -671,7 +677,7 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision ...@@ -671,7 +677,7 @@ CREATE FUNCTION square_root(double precision) RETURNS double precision
<para> <para>
<xref linkend="xfunc-c-type-table"> gives the C type required for <xref linkend="xfunc-c-type-table"> gives the C type required for
parameters in the C functions that will be loaded into parameters in the C functions that will be loaded into
<productname>PostgreSQL</> <productname>PostgreSQL</>.
The <quote>Defined In</quote> column gives the header file that The <quote>Defined In</quote> column gives the header file that
needs to be included to get the type definition. (The actual needs to be included to get the type definition. (The actual
definition may be in a different file that is included by the definition may be in a different file that is included by the
...@@ -1262,9 +1268,9 @@ concat_text(PG_FUNCTION_ARGS) ...@@ -1262,9 +1268,9 @@ concat_text(PG_FUNCTION_ARGS)
At first glance, the version-1 coding conventions may appear to At first glance, the version-1 coding conventions may appear to
be just pointless obscurantism. However, they do offer a number be just pointless obscurantism. However, they do offer a number
of improvements, because the macros can hide unnecessary detail. of improvements, because the macros can hide unnecessary detail.
An example is that in coding add_one_float8, we no longer need to An example is that in coding <function>add_one_float8</>, we no longer need to
be aware that float8 is a pass-by-reference type. Another be aware that <type>float8</type> is a pass-by-reference type. Another
example is that the GETARG macros for variable-length types hide example is that the <literal>GETARG</> macros for variable-length types hide
the need to deal with fetching <quote>toasted</quote> (compressed or the need to deal with fetching <quote>toasted</quote> (compressed or
out-of-line) values. The old-style <function>copytext</function> out-of-line) values. The old-style <function>copytext</function>
and <function>concat_text</function> functions shown above are and <function>concat_text</function> functions shown above are
...@@ -1277,7 +1283,7 @@ concat_text(PG_FUNCTION_ARGS) ...@@ -1277,7 +1283,7 @@ concat_text(PG_FUNCTION_ARGS)
<para> <para>
One big improvement in version-1 functions is better handling of NULL One big improvement in version-1 functions is better handling of NULL
inputs and results. The macro <function>PG_ARGISNULL(n)</function> inputs and results. The macro <function>PG_ARGISNULL(<replaceable>n</>)</function>
allows a function to test whether each input is NULL (of course, doing allows a function to test whether each input is NULL (of course, doing
this is only necessary in functions not declared <quote>strict</>). this is only necessary in functions not declared <quote>strict</>).
As with the As with the
...@@ -1287,7 +1293,7 @@ concat_text(PG_FUNCTION_ARGS) ...@@ -1287,7 +1293,7 @@ concat_text(PG_FUNCTION_ARGS)
<function>PG_GETARG_<replaceable>xxx</replaceable>()</function> until <function>PG_GETARG_<replaceable>xxx</replaceable>()</function> until
one has verified that the argument isn't NULL. one has verified that the argument isn't NULL.
To return a NULL result, execute <function>PG_RETURN_NULL()</function>; To return a NULL result, execute <function>PG_RETURN_NULL()</function>;
this works in both strict and non-strict functions. this works in both strict and nonstrict functions.
</para> </para>
<para> <para>
...@@ -1323,7 +1329,7 @@ FROM emp ...@@ -1323,7 +1329,7 @@ FROM emp
WHERE name = 'Bill' OR name = 'Sam'; WHERE name = 'Bill' OR name = 'Sam';
</programlisting> </programlisting>
In the query above, we can define c_overpaid as: In the query above, we can define <function>c_overpaid</> as:
<programlisting> <programlisting>
#include "postgres.h" #include "postgres.h"
...@@ -1371,13 +1377,13 @@ c_overpaid(PG_FUNCTION_ARGS) ...@@ -1371,13 +1377,13 @@ c_overpaid(PG_FUNCTION_ARGS)
three arguments: the argument of type <type>TupleTableSlot*</type> passed into three arguments: the argument of type <type>TupleTableSlot*</type> passed into
the function, the name of the desired attribute, and a the function, the name of the desired attribute, and a
return parameter that tells whether the attribute return parameter that tells whether the attribute
is null. <function>GetAttributeByName</function> returns a Datum is null. <function>GetAttributeByName</function> returns a <type>Datum</type>
value that you can convert to the proper datatype by using the value that you can convert to the proper data type by using the
appropriate <function>DatumGet<replaceable>XXX</replaceable>()</function> macro. appropriate <function>DatumGet<replaceable>XXX</replaceable>()</function> macro.
</para> </para>
<para> <para>
The following query lets <productname>PostgreSQL</productname> The following command lets <productname>PostgreSQL</productname>
know about the <function>c_overpaid</function> function: know about the <function>c_overpaid</function> function:
<programlisting> <programlisting>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.21 2001/11/21 06:09:45 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/xindex.sgml,v 1.22 2002/01/07 02:29:14 petere Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
<chapter id="xindex"> <chapter id="xindex">
<title>Interfacing Extensions To Indexes</title> <title>Interfacing Extensions To Indexes</title>
<sect1 id="xindex-intro">
<title>Introduction</title>
<para> <para>
The procedures described thus far let you define a new type, new The procedures described thus far let you define new types, new
functions and new operators. However, we cannot yet define a secondary functions, and new operators. However, we cannot yet define a secondary
index (such as a <acronym>B-tree</acronym>, <acronym>R-tree</acronym> or index (such as a B-tree, R-tree, or
hash access method) over a new type or its operators. hash access method) over a new type or its operators.
</para> </para>
...@@ -25,14 +28,19 @@ PostgreSQL documentation ...@@ -25,14 +28,19 @@ PostgreSQL documentation
class for the <acronym>B-tree</acronym> access method that stores and class for the <acronym>B-tree</acronym> access method that stores and
sorts complex numbers in ascending absolute value order. sorts complex numbers in ascending absolute value order.
</para> </para>
</sect1>
<sect1 id="xindex-am">
<title>Access Methods</title>
<para> <para>
The <filename>pg_am</filename> table contains one row for every index The <filename>pg_am</filename> table contains one row for every
access method. Support for the heap access method is built into index access method. Support for the heap access method is built
<productname>PostgreSQL</productname>, but every other access method is into <productname>PostgreSQL</productname>, but all other access
described in <filename>pg_am</filename>. The schema is methods are described in <filename>pg_am</filename>. The schema is
shown in <xref linkend="xindex-pgam-table">.
<table tocentry="1"> <table tocentry="1" id="xindex-pgam-table">
<title>Index Access Method Schema</title> <title>Index Access Method Schema</title>
<tgroup cols="2"> <tgroup cols="2">
...@@ -49,7 +57,7 @@ PostgreSQL documentation ...@@ -49,7 +57,7 @@ PostgreSQL documentation
</row> </row>
<row> <row>
<entry>amowner</entry> <entry>amowner</entry>
<entry>user id of the owner</entry> <entry>user ID of the owner (currently not used)</entry>
</row> </row>
<row> <row>
<entry>amstrategies</entry> <entry>amstrategies</entry>
...@@ -66,7 +74,7 @@ PostgreSQL documentation ...@@ -66,7 +74,7 @@ PostgreSQL documentation
</row> </row>
<row> <row>
<entry>amcanunique</entry> <entry>amcanunique</entry>
<entry>does AM support UNIQUE indexes?</entry> <entry>does AM support unique indexes?</entry>
</row> </row>
<row> <row>
<entry>amcanmulticol</entry> <entry>amcanmulticol</entry>
...@@ -89,7 +97,7 @@ PostgreSQL documentation ...@@ -89,7 +97,7 @@ PostgreSQL documentation
<row> <row>
<entry>...</entry> <entry>...</entry>
<entry>procedure identifiers for interface routines to the access <entry>procedure identifiers for interface routines to the access
method. For example, regproc ids for opening, closing, and method. For example, regproc IDs for opening, closing, and
getting rows from the access method appear here.</entry> getting rows from the access method appear here.</entry>
</row> </row>
</tbody> </tbody>
...@@ -104,49 +112,55 @@ PostgreSQL documentation ...@@ -104,49 +112,55 @@ PostgreSQL documentation
you are interested in is the <acronym>object ID</acronym> of the access you are interested in is the <acronym>object ID</acronym> of the access
method you want to extend: method you want to extend:
<programlisting> <screen>
SELECT oid FROM pg_am WHERE amname = 'btree'; SELECT oid FROM pg_am WHERE amname = 'btree';
oid oid
----- -----
403 403
(1 row) (1 row)
</programlisting> </screen>
We will use that <command>SELECT</command> in a <command>WHERE</command> We will use that query in a <literal>WHERE</literal>
clause later. clause later.
</para> </para>
</sect1>
<sect1 id="xindex-strategies">
<title>Access Method Strategies</title>
<para> <para>
The <filename>amstrategies</filename> column exists to standardize The <structfield>amstrategies</structfield> column exists to standardize
comparisons across data types. For example, <acronym>B-tree</acronym>s comparisons across data types. For example, B-trees
impose a strict ordering on keys, lesser to greater. Since impose a strict ordering on keys, lesser to greater. Since
<productname>PostgreSQL</productname> allows the user to define operators, <productname>PostgreSQL</productname> allows the user to define operators,
<productname>PostgreSQL</productname> cannot look at the name of an operator <productname>PostgreSQL</productname> cannot look at the name of an operator
(e.g., <literal>&gt;</> or <literal>&lt;</>) and tell what kind of comparison it is. In fact, (e.g., <literal>&gt;</> or <literal>&lt;</>) and tell what kind of comparison it is. In fact,
some access methods don't impose any ordering at all. For example, some access methods don't impose any ordering at all. For example,
<acronym>R-tree</acronym>s express a rectangle-containment relationship, R-trees express a rectangle-containment relationship,
whereas a hashed data structure expresses only bitwise similarity based whereas a hashed data structure expresses only bitwise similarity based
on the value of a hash function. <productname>PostgreSQL</productname> on the value of a hash function. <productname>PostgreSQL</productname>
needs some consistent way of taking a qualification in your query, needs some consistent way of taking a qualification in your query,
looking at the operator and then deciding if a usable index exists. This looking at the operator, and then deciding if a usable index exists. This
implies that <productname>PostgreSQL</productname> needs to know, for implies that <productname>PostgreSQL</productname> needs to know, for
example, that the <literal>&lt;=</> and <literal>&gt;</> operators partition a example, that the <literal>&lt;=</> and <literal>&gt;</> operators partition a
<acronym>B-tree</acronym>. <productname>PostgreSQL</productname> B-tree. <productname>PostgreSQL</productname>
uses strategies to express these relationships between uses <firstterm>strategies</firstterm> to express these relationships between
operators and the way they can be used to scan indexes. operators and the way they can be used to scan indexes.
</para> </para>
<para> <para>
Defining a new set of strategies is beyond the scope of this discussion, Defining a new set of strategies is beyond the scope of this
but we'll explain how <acronym>B-tree</acronym> strategies work because discussion, but we'll explain how B-tree strategies work because
you'll need to know that to add a new B-tree operator class. In the you'll need to know that to add a new B-tree operator class. In the
<filename>pg_am</filename> table, the amstrategies column is the <classname>pg_am</classname> table, the
number of strategies defined for this access method. For <structfield>amstrategies</structfield> column sets the number of
<acronym>B-tree</acronym>s, this number is 5. These strategies strategies defined for this access method. For B-trees, this number
correspond to is 5. The meanings of these strategies are shown in <xref
linkend="xindex-btree-table">.
</para>
<table tocentry="1"> <table tocentry="1" id="xindex-btree-table">
<title>B-tree Strategies</title> <title>B-tree Strategies</title>
<titleabbrev>B-tree</titleabbrev> <titleabbrev>B-tree</titleabbrev>
<tgroup cols="2"> <tgroup cols="2">
...@@ -180,26 +194,29 @@ SELECT oid FROM pg_am WHERE amname = 'btree'; ...@@ -180,26 +194,29 @@ SELECT oid FROM pg_am WHERE amname = 'btree';
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
</para>
<para> <para>
The idea is that you'll need to add operators corresponding to the The idea is that you'll need to add operators corresponding to these strategies
comparisons above to the <filename>pg_amop</filename> relation (see below). to the <classname>pg_amop</classname> relation (see below).
The access method code can use these strategy numbers, regardless of data The access method code can use these strategy numbers, regardless of data
type, to figure out how to partition the <acronym>B-tree</acronym>, type, to figure out how to partition the B-tree,
compute selectivity, and so on. Don't worry about the details of adding compute selectivity, and so on. Don't worry about the details of adding
operators yet; just understand that there must be a set of these operators yet; just understand that there must be a set of these
operators for <filename>int2, int4, oid,</filename> and every other operators for <type>int2</>, <type>int4</>, <type>oid</>, and all other
data type on which a <acronym>B-tree</acronym> can operate. data types on which a B-tree can operate.
</para> </para>
</sect1>
<sect1 id="xindex-support">
<title>Access Method Support Routines</title>
<para> <para>
Sometimes, strategies aren't enough information for the system to figure Sometimes, strategies aren't enough information for the system to figure
out how to use an index. Some access methods require additional support out how to use an index. Some access methods require additional support
routines in order to work. For example, the <acronym>B-tree</acronym> routines in order to work. For example, the B-tree
access method must be able to compare two keys and determine whether one 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 is greater than, equal to, or less than the other. Similarly, the
<acronym>R-tree</acronym> access method must be able to compute R-tree access method must be able to compute
intersections, unions, and sizes of rectangles. These intersections, unions, and sizes of rectangles. These
operations do not correspond to operators used in qualifications in operations do not correspond to operators used in qualifications in
SQL queries; they are administrative routines used by SQL queries; they are administrative routines used by
...@@ -209,60 +226,60 @@ SELECT oid FROM pg_am WHERE amname = 'btree'; ...@@ -209,60 +226,60 @@ SELECT oid FROM pg_am WHERE amname = 'btree';
<para> <para>
In order to manage diverse support routines consistently across all In order to manage diverse support routines consistently across all
<productname>PostgreSQL</productname> access methods, <productname>PostgreSQL</productname> access methods,
<filename>pg_am</filename> includes a column called <classname>pg_am</classname> includes a column called
<filename>amsupport</filename>. This column records the number of <structfield>amsupport</structfield>. This column records the
support routines used by an access method. For <acronym>B-tree</acronym>s, number of support routines used by an access method. For B-trees,
this number is one -- the routine to take two keys and return -1, 0, or this number is one: the routine to take two keys and return -1, 0,
+1, depending on whether the first key is less than, equal or +1, depending on whether the first key is less than, equal to,
to, or greater than the second. or greater than the second. (Strictly speaking, this routine can
return a negative number (&lt; 0), zero, or a non-zero positive
<note> number (&gt; 0).)
<para>
Strictly speaking, this routine can return a negative
number (&lt; 0), zero, or a non-zero positive number (&gt; 0).
</para>
</note>
</para> </para>
<para> <para>
The <filename>amstrategies</filename> entry in <filename>pg_am</filename> The <structfield>amstrategies</structfield> entry in
is just the number <classname>pg_am</classname> is just the number of strategies
of strategies defined for the access method in question. The operators defined for the access method in question. The operators for less
for less than, less equal, and so on don't appear in than, less equal, and so on don't appear in
<filename>pg_am</filename>. Similarly, <filename>amsupport</filename> <classname>pg_am</classname>. Similarly,
is just the number of support routines required by the access <structfield>amsupport</structfield> is just the number of support
method. The actual routines are listed elsewhere. routines required by the access method. The actual routines are
listed elsewhere.
</para> </para>
<para> <para>
By the way, the <filename>amorderstrategy</filename> entry tells whether By the way, the <structfield>amorderstrategy</structfield> column tells whether
the access method supports ordered scan. Zero means it doesn't; if it the access method supports ordered scan. Zero means it doesn't; if it
does, <filename>amorderstrategy</filename> is the number of the strategy does, <structfield>amorderstrategy</structfield> is the number of the strategy
routine that corresponds to the ordering operator. For example, B-tree routine that corresponds to the ordering operator. For example, B-tree
has <filename>amorderstrategy</filename> = 1 which is its has <structfield>amorderstrategy</structfield> = 1, which is its
<quote>less than</quote> strategy number. <quote>less than</quote> strategy number.
</para> </para>
</sect1>
<sect1 id="xindex-opclass">
<title>Operator Classes</title>
<para> <para>
The next table of interest is <filename>pg_opclass</filename>. This table The next table of interest is <classname>pg_opclass</classname>. This table
defines operator class names and input data types for each of the operator defines operator class names and input data types for each of the operator
classes supported by a given index access method. The same class name classes supported by a given index access method. The same class name
can be used for several different access methods (for example, both B-tree can be used for several different access methods (for example, both B-tree
and hash access methods have operator classes named and hash access methods have operator classes named
<filename>oid_ops</filename>), but a separate <literal>oid_ops</literal>), but a separate
<filename>pg_opclass</filename> row must appear for each access method. <filename>pg_opclass</filename> row must appear for each access method.
The <filename>oid</filename> of the <filename>pg_opclass</filename> row is The OID of the <classname>pg_opclass</classname> row is
used as a foreign used as a foreign
key in other tables to associate specific operators and support routines key in other tables to associate specific operators and support routines
with the operator class. with the operator class.
</para> </para>
<para> <para>
You need to add a row with your opclass name (for example, You need to add a row with your operator class name (for example,
<filename>complex_abs_ops</filename>) to <literal>complex_abs_ops</literal>) to
<filename>pg_opclass</filename>: <classname>pg_opclass</classname>:
<programlisting> <programlisting>
INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype) INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
VALUES ( VALUES (
(SELECT oid FROM pg_am WHERE amname = 'btree'), (SELECT oid FROM pg_am WHERE amname = 'btree'),
...@@ -279,52 +296,50 @@ SELECT oid, * ...@@ -279,52 +296,50 @@ SELECT oid, *
--------+---------+-----------------+-----------+------------+------------ --------+---------+-----------------+-----------+------------+------------
277975 | 403 | complex_abs_ops | 277946 | t | 0 277975 | 403 | complex_abs_ops | 277946 | t | 0
(1 row) (1 row)
</programlisting> </programlisting>
Note that the oid for your <filename>pg_opclass</filename> row will Note that the OID for your <classname>pg_opclass</classname> row will
be different! Don't worry about this though. We'll get this number be different! Don't worry about this though. We'll get this number
from the system later just like we got the oid of the type here. from the system later just like we got the OID of the type here.
</para> </para>
<para> <para>
The above example assumes that you want to make this new opclass the The above example assumes that you want to make this new operator class the
default B-tree opclass for the <filename>complex</filename> data type. default B-tree operator class for the <type>complex</type> data type.
If you don't, just set <filename>opcdefault</filename> to false instead. If you don't, just set <structfield>opcdefault</structfield> to false instead.
<filename>opckeytype</filename> is not described here; it should always <structfield>opckeytype</structfield> is not described here; it should always
be zero for B-tree opclasses. be zero for B-tree operator classes.
</para> </para>
</sect1>
<sect1 id="xindex-operators">
<title>Creating the Operators and Support Routines</title>
<para> <para>
So now we have an access method and an operator class. So now we have an access method and an operator class.
We still need a set of operators. The procedure for We still need a set of operators. The procedure for
defining operators was discussed earlier in this manual. defining operators was discussed in <xref linkend="xoper">.
For the <filename>complex_abs_ops</filename> operator class on B-trees, For the <literal>complex_abs_ops</literal> operator class on B-trees,
the operators we require are: the operators we require are:
<programlisting> <itemizedlist spacing="compact">
absolute value less-than <listitem><simpara>absolute-value less-than (strategy 1)</></>
absolute value less-than-or-equal <listitem><simpara>absolute-value less-than-or-equal (strategy 2)</></>
absolute value equal <listitem><simpara>absolute-value equal (strategy 3)</></>
absolute value greater-than-or-equal <listitem><simpara>absolute-value greater-than-or-equal (strategy 4)</></>
absolute value greater-than <listitem><simpara>absolute-value greater-than (strategy 5)</></>
</programlisting> </itemizedlist>
</para> </para>
<para> <para>
Suppose the code that implements these functions Suppose the code that implements these functions
is stored in the file is stored in the file
<replaceable>PGROOT</replaceable><filename>/tutorial/complex.c</filename>, <filename><replaceable>PGROOT</replaceable>/src/tutorial/complex.c</filename>,
which we have compiled into which we have compiled into
<replaceable>PGROOT</replaceable><filename>/tutorial/complex.so</filename>. <filename><replaceable>PGROOT</replaceable>/src/tutorial/complex.so</filename>.
</para> Part of the C code looks like this:
<para> <programlisting>
Part of the C code looks 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.source</filename> for the details.)
<programlisting>
#define Mag(c) ((c)-&gt;x*(c)-&gt;x + (c)-&gt;y*(c)-&gt;y) #define Mag(c) ((c)-&gt;x*(c)-&gt;x + (c)-&gt;y*(c)-&gt;y)
bool bool
...@@ -333,23 +348,27 @@ SELECT oid, * ...@@ -333,23 +348,27 @@ SELECT oid, *
double amag = Mag(a), bmag = Mag(b); double amag = Mag(a), bmag = Mag(b);
return (amag==bmag); return (amag==bmag);
} }
</programlisting> </programlisting>
(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.source</filename> for the details.)
</para> </para>
<para> <para>
We make the function known to <productname>PostgreSQL</productname> like this: We make the function known to <productname>PostgreSQL</productname> like this:
<programlisting> <programlisting>
CREATE FUNCTION complex_abs_eq(complex, complex) CREATE FUNCTION complex_abs_eq(complex, complex) RETURNS boolean
RETURNS bool AS '<replaceable>PGROOT</replaceable>/src/tutorial/complex'
AS '<replaceable>PGROOT</replaceable>/tutorial/complex' LANGUAGE C;
LANGUAGE C; </programlisting>
</programlisting>
</para> </para>
<para> <para>
There are some important things that are happening here. There are some important things that are happening here:
</para>
<itemizedlist>
<listitem>
<para> <para>
First, note that operators for less-than, less-than-or-equal, equal, First, note that operators for less-than, less-than-or-equal, equal,
greater-than-or-equal, and greater-than for <filename>complex</filename> greater-than-or-equal, and greater-than for <filename>complex</filename>
...@@ -358,9 +377,11 @@ CREATE FUNCTION complex_abs_eq(complex, complex) ...@@ -358,9 +377,11 @@ CREATE FUNCTION complex_abs_eq(complex, complex)
we don't have any other operator = for <filename>complex</filename>, we don't have any other operator = for <filename>complex</filename>,
but if we were building a practical data type we'd probably want = to but if we were building a practical data type we'd probably want = to
be the ordinary equality operation for complex numbers. In that case, be the ordinary equality operation for complex numbers. In that case,
we'd need to use some other operator name for complex_abs_eq. we'd need to use some other operator name for <function>complex_abs_eq</>.
</para> </para>
</listitem>
<listitem>
<para> <para>
Second, although <productname>PostgreSQL</productname> can cope with operators having Second, although <productname>PostgreSQL</productname> can cope with operators having
the same name as long as they have different input data types, C can only the same name as long as they have different input data types, C can only
...@@ -369,7 +390,9 @@ CREATE FUNCTION complex_abs_eq(complex, complex) ...@@ -369,7 +390,9 @@ CREATE FUNCTION complex_abs_eq(complex, complex)
Usually it's a good practice to include the data type name in the C Usually it's a good practice to include the data type name in the C
function name, so as not to conflict with functions for other data types. function name, so as not to conflict with functions for other data types.
</para> </para>
</listitem>
<listitem>
<para> <para>
Third, we could have made the <productname>PostgreSQL</productname> name of the function Third, we could have made the <productname>PostgreSQL</productname> name of the function
<filename>abs_eq</filename>, relying on <productname>PostgreSQL</productname> to distinguish it <filename>abs_eq</filename>, relying on <productname>PostgreSQL</productname> to distinguish it
...@@ -377,58 +400,63 @@ CREATE FUNCTION complex_abs_eq(complex, complex) ...@@ -377,58 +400,63 @@ CREATE FUNCTION complex_abs_eq(complex, complex)
To keep the example simple, we make the function have the same names To keep the example simple, we make the function have the same names
at the C level and <productname>PostgreSQL</productname> level. at the C level and <productname>PostgreSQL</productname> level.
</para> </para>
</listitem>
<listitem>
<para> <para>
Finally, note that these operator functions return Boolean values. Finally, note that these operator functions return Boolean values.
In practice, all operators defined as index access method strategies In practice, all operators defined as index access method
must return Boolean, since they must appear at the top level of a WHERE strategies must return type <type>boolean</type>, since they must
clause to be used with an index. appear at the top level of a <literal>WHERE</> clause to be used with an index.
(On the other (On the other hand, the support function returns whatever the
hand, the support function returns whatever the particular access method particular access method expects -- in this case, a signed
expects -- in this case, a signed integer.) integer.)
</para>
</listitem>
</itemizedlist>
</para> </para>
<para> <para>
The final routine in the The final routine in the file is the <quote>support routine</quote>
file is the <quote>support routine</quote> mentioned when we discussed the amsupport mentioned when we discussed the <structfield>amsupport</> column of the
column of the <filename>pg_am</filename> table. We will use this <classname>pg_am</classname> table. We will use this later on. For
later on. For now, ignore it. now, ignore it.
</para> </para>
<para> <para>
Now we are ready to define the operators: Now we are ready to define the operators:
<programlisting> <programlisting>
CREATE OPERATOR = ( CREATE OPERATOR = (
leftarg = complex, rightarg = complex, leftarg = complex, rightarg = complex,
procedure = complex_abs_eq, procedure = complex_abs_eq,
restrict = eqsel, join = eqjoinsel restrict = eqsel, join = eqjoinsel
); );
</programlisting> </programlisting>
The important The important
things here are the procedure names (which are the <acronym>C</acronym> things here are the procedure names (which are the C
functions defined above) and the restriction and join selectivity functions defined above) and the restriction and join selectivity
functions. You should just use the selectivity functions used in functions. You should just use the selectivity functions used in
the example (see <filename>complex.source</filename>). the example (see <filename>complex.source</filename>).
Note that there Note that there
are different such functions for the less-than, equal, and greater-than are different such functions for the less-than, equal, and greater-than
cases. These must be supplied, or the optimizer will be unable to cases. These must be supplied or the optimizer will be unable to
make effective use of the index. make effective use of the index.
</para> </para>
<para> <para>
The next step is to add entries for these operators to The next step is to add entries for these operators to
the <filename>pg_amop</filename> relation. To do this, the <classname>pg_amop</classname> relation. To do this,
we'll need the <filename>oid</filename>s of the operators we just we'll need the OIDs of the operators we just
defined. We'll look up the names of all the operators that take defined. We'll look up the names of all the operators that take
two <filename>complex</filename>es, and pick ours out: two operands of type <type>complex</type>, and pick ours out:
<programlisting> <screen>
SELECT o.oid AS opoid, o.oprname SELECT o.oid AS opoid, o.oprname
INTO TEMP TABLE complex_ops_tmp INTO TEMP TABLE complex_ops_tmp
FROM pg_operator o, pg_type t FROM pg_operator o, pg_type t
WHERE o.oprleft = t.oid and o.oprright = t.oid WHERE o.oprleft = t.oid and o.oprright = t.oid
and t.typname = 'complex'; and t.typname = 'complex';
opoid | oprname opoid | oprname
...@@ -440,30 +468,30 @@ CREATE OPERATOR = ( ...@@ -440,30 +468,30 @@ CREATE OPERATOR = (
277973 | &gt;= 277973 | &gt;=
277974 | &gt; 277974 | &gt;
(6 rows) (6 rows)
</programlisting> </screen>
(Again, some of your <filename>oid</filename> numbers will almost (Again, some of your OID numbers will almost
certainly be different.) The operators we are interested in are those certainly be different.) The operators we are interested in are those
with <filename>oid</filename>s 277970 through 277974. The values you with OIDs 277970 through 277974. The values you
get will probably be different, and you should substitute them for the get will probably be different, and you should substitute them for the
values below. We will do this with a select statement. values below. We will do this with a select statement.
</para> </para>
<para> <para>
Now we are ready to insert entries into <filename>pg_amop</filename> for Now we are ready to insert entries into <classname>pg_amop</classname> for
our new operator class. These entries must associate the correct our new operator class. These entries must associate the correct
B-tree strategy numbers with each of the operators we need. B-tree strategy numbers with each of the operators we need.
The command to insert the less-than operator looks like: The command to insert the less-than operator looks like:
<programlisting> <programlisting>
INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr) INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
SELECT opcl.oid, 1, false, c.opoid SELECT opcl.oid, 1, false, c.opoid
FROM pg_opclass opcl, complex_ops_tmp c FROM pg_opclass opcl, complex_ops_tmp c
WHERE WHERE
opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
opcname = 'complex_abs_ops' AND opcname = 'complex_abs_ops' AND
c.oprname = '&lt;'; c.oprname = '&lt;';
</programlisting> </programlisting>
Now do this for the other operators substituting for the <literal>1</> in the Now do this for the other operators substituting for the <literal>1</> in the
second line above and the <literal>&lt;</> in the last line. Note the order: second line above and the <literal>&lt;</> in the last line. Note the order:
...@@ -478,51 +506,58 @@ CREATE OPERATOR = ( ...@@ -478,51 +506,58 @@ CREATE OPERATOR = (
</para> </para>
<para> <para>
The final step is registration of the <quote>support routine</quote> previously The final step is the registration of the <quote>support routine</quote> previously
described in our discussion of <filename>pg_am</filename>. The described in our discussion of <classname>pg_am</classname>. The
<filename>oid</filename> of this support routine is stored in the OID of this support routine is stored in the
<filename>pg_amproc</filename> table, keyed by the operator class <classname>pg_amproc</classname> table, keyed by the operator class
<filename>oid</filename> and the support routine number. OID and the support routine number.
</para>
<para>
First, we need to register the function in First, we need to register the function in
<productname>PostgreSQL</productname> (recall that we put the <productname>PostgreSQL</productname> (recall that we put the
<acronym>C</acronym> code that implements this routine in the bottom of C code that implements this routine in the bottom of
the file in which we implemented the operator routines): the file in which we implemented the operator routines):
<programlisting> <programlisting>
CREATE FUNCTION complex_abs_cmp(complex, complex) CREATE FUNCTION complex_abs_cmp(complex, complex)
RETURNS int4 RETURNS integer
AS '<replaceable>PGROOT</replaceable>/tutorial/complex' AS '<replaceable>PGROOT</replaceable>/src/tutorial/complex'
LANGUAGE C; LANGUAGE C;
SELECT oid, proname FROM pg_proc SELECT oid, proname FROM pg_proc
WHERE proname = 'complex_abs_cmp'; WHERE proname = 'complex_abs_cmp';
oid | proname oid | proname
--------+----------------- --------+-----------------
277997 | complex_abs_cmp 277997 | complex_abs_cmp
(1 row) (1 row)
</programlisting> </programlisting>
(Again, your OID number will probably be different.)
</para>
(Again, your <filename>oid</filename> number will probably be different.) <para>
We can add the new row as follows: We can add the new row as follows:
<programlisting> <programlisting>
INSERT INTO pg_amproc (amopclaid, amprocnum, amproc) INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
SELECT opcl.oid, 1, p.oid SELECT opcl.oid, 1, p.oid
FROM pg_opclass opcl, pg_proc p FROM pg_opclass opcl, pg_proc p
WHERE WHERE
opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND opcamid = (SELECT oid FROM pg_am WHERE amname = 'btree') AND
opcname = 'complex_abs_ops' AND opcname = 'complex_abs_ops' AND
p.proname = 'complex_abs_cmp'; p.proname = 'complex_abs_cmp';
</programlisting> </programlisting>
</para> </para>
<para> <para>
And we're done! (Whew.) It should now be possible to create And we're done! (Whew.) It should now be possible to create
and use B-tree indexes on <filename>complex</filename> columns. and use B-tree indexes on <type>complex</type> columns.
</para> </para>
</sect1>
</chapter> </chapter>
<!-- Keep this comment at the end of the file <!-- Keep this comment at the end of the file
Local variables: Local variables:
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/xoper.sgml,v 1.16 2001/11/21 06:09:45 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/xoper.sgml,v 1.17 2002/01/07 02:29:14 petere Exp $
--> -->
<Chapter Id="xoper"> <Chapter Id="xoper">
<Title>Extending <Acronym>SQL</Acronym>: Operators</Title> <Title>Extending <Acronym>SQL</Acronym>: Operators</Title>
<sect1 id="xoper-intro">
<title>Introduction</title>
<Para> <Para>
<ProductName>PostgreSQL</ProductName> supports left unary, <ProductName>PostgreSQL</ProductName> supports left unary,
right unary and binary right unary, and binary
operators. Operators can be overloaded; that is, operators. Operators can be overloaded; that is,
the same operator name can be used for different operators the same operator name can be used for different operators
that have different numbers and types of arguments. If that have different numbers and types of operands. If
there is an ambiguous situation and the system cannot there is an ambiguous situation and the system cannot
determine the correct operator to use, it will return determine the correct operator to use, it will return
an error. You may have to typecast the left and/or an error. You may have to type-cast the left and/or
right operands to help it understand which operator you right operands to help it understand which operator you
meant to use. meant to use.
</Para> </Para>
...@@ -22,20 +25,24 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xoper.sgml,v 1.16 2001/11/21 06:09:45 thoma ...@@ -22,20 +25,24 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xoper.sgml,v 1.16 2001/11/21 06:09:45 thoma
Every operator is <quote>syntactic sugar</quote> for a call to an Every operator is <quote>syntactic sugar</quote> for a call to an
underlying function that does the real work; so you must underlying function that does the real work; so you must
first create the underlying function before you can create first create the underlying function before you can create
the operator. However, an operator is <emphasis>not</emphasis> the operator. However, an operator is <emphasis>not merely</emphasis>
merely syntactic sugar, because it carries additional information syntactic sugar, because it carries additional information
that helps the query planner optimize queries that use the that helps the query planner optimize queries that use the
operator. Much of this chapter will be devoted to explaining operator. Much of this chapter will be devoted to explaining
that additional information. that additional information.
</Para> </Para>
</sect1>
<sect1 id="xoper-example">
<title>Example</title>
<Para> <Para>
Here is an example of creating an operator for adding two Here is an example of creating an operator for adding two complex
complex numbers. We assume we've already created the definition numbers. We assume we've already created the definition of type
of type complex. First we need a function that does the work; <type>complex</type> (see <xref linkend="xtypes">). First we need a
then we can define the operator: function that does the work, then we can define the operator:
<ProgramListing> <ProgramListing>
CREATE FUNCTION complex_add(complex, complex) CREATE FUNCTION complex_add(complex, complex)
RETURNS complex RETURNS complex
AS '<replaceable>PGROOT</replaceable>/tutorial/complex' AS '<replaceable>PGROOT</replaceable>/tutorial/complex'
...@@ -47,34 +54,33 @@ CREATE OPERATOR + ( ...@@ -47,34 +54,33 @@ CREATE OPERATOR + (
procedure = complex_add, procedure = complex_add,
commutator = + commutator = +
); );
</ProgramListing> </ProgramListing>
</Para> </Para>
<Para> <Para>
Now we can do: Now we can do:
<ProgramListing> <screen>
SELECT (a + b) AS c FROM test_complex; SELECT (a + b) AS c FROM test_complex;
+----------------+ c
|c | -----------------
+----------------+ (5.2,6.05)
|(5.2,6.05) | (133.42,144.95)
+----------------+ </screen>
|(133.42,144.95) |
+----------------+
</ProgramListing>
</Para> </Para>
<Para> <Para>
We've shown how to create a binary operator here. To We've shown how to create a binary operator here. To create unary
create unary operators, just omit one of leftarg (for operators, just omit one of <literal>leftarg</> (for left unary) or
left unary) or rightarg (for right unary). The procedure <literal>rightarg</> (for right unary). The <literal>procedure</>
clause and the argument clauses are the only required items clause and the argument clauses are the only required items in
in CREATE OPERATOR. The COMMUTATOR clause shown in the example <command>CREATE OPERATOR</command>. The <literal>commutator</>
is an optional hint to the query optimizer. Further details about clause shown in the example is an optional hint to the query
COMMUTATOR and other optimizer hints appear below. optimizer. Further details about <literal>commutator</> and other
optimizer hints appear below.
</Para> </Para>
</sect1>
<sect1 id="xoper-optimization"> <sect1 id="xoper-optimization">
<title>Operator Optimization Information</title> <title>Operator Optimization Information</title>
...@@ -102,28 +108,28 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -102,28 +108,28 @@ SELECT (a + b) AS c FROM test_complex;
<para> <para>
Additional optimization clauses might be added in future versions of Additional optimization clauses might be added in future versions of
<ProductName>PostgreSQL</ProductName>. The ones described here are all <ProductName>PostgreSQL</ProductName>. The ones described here are all
the ones that release 6.5 understands. the ones that release &version; understands.
</para> </para>
<sect2> <sect2>
<title>COMMUTATOR</title> <title>COMMUTATOR</title>
<para> <para>
The COMMUTATOR clause, if provided, names an operator that is the The <literal>COMMUTATOR</> clause, if provided, names an operator that is the
commutator of the operator being defined. We say that operator A is the commutator of the operator being defined. We say that operator A is the
commutator of operator B if (x A y) equals (y B x) for all possible input commutator of operator B if (x A y) equals (y B x) for all possible input
values x,y. Notice that B is also the commutator of A. For example, values x, y. Notice that B is also the commutator of A. For example,
operators <literal>&lt;</> and <literal>&gt;</> for a particular data type are usually each others' operators <literal>&lt;</> and <literal>&gt;</> for a particular data type are usually each others'
commutators, and operator <literal>+</> is usually commutative with itself. commutators, and operator <literal>+</> is usually commutative with itself.
But operator <literal>-</> is usually not commutative with anything. But operator <literal>-</> is usually not commutative with anything.
</para> </para>
<para> <para>
The left argument type of a commuted operator is the same as the The left operand type of a commuted operator is the same as the
right argument type of its commutator, and vice versa. So the name of right operand type of its commutator, and vice versa. So the name of
the commutator operator is all that <ProductName>PostgreSQL</ProductName> the commutator operator is all that <ProductName>PostgreSQL</ProductName>
needs to be given to look up the commutator, and that's all that need needs to be given to look up the commutator, and that's all that needs to
be provided in the COMMUTATOR clause. be provided in the <literal>COMMUTATOR</> clause.
</para> </para>
<para> <para>
...@@ -136,29 +142,29 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -136,29 +142,29 @@ SELECT (a + b) AS c FROM test_complex;
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
One way is to omit the COMMUTATOR clause in the first operator that One way is to omit the <literal>COMMUTATOR</> clause in the first operator that
you define, and then provide one in the second operator's definition. you define, and then provide one in the second operator's definition.
Since <ProductName>PostgreSQL</ProductName> knows that commutative Since <ProductName>PostgreSQL</ProductName> knows that commutative
operators come in pairs, when it sees the second definition it will operators come in pairs, when it sees the second definition it will
automatically go back and fill in the missing COMMUTATOR clause in automatically go back and fill in the missing <literal>COMMUTATOR</> clause in
the first definition. the first definition.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
The other, more straightforward way is just to include COMMUTATOR clauses The other, more straightforward way is just to include <literal>COMMUTATOR</> clauses
in both definitions. When <ProductName>PostgreSQL</ProductName> processes in both definitions. When <ProductName>PostgreSQL</ProductName> processes
the first definition and realizes that COMMUTATOR refers to a non-existent the first definition and realizes that <literal>COMMUTATOR</> refers to a non-existent
operator, the system will make a dummy entry for that operator in the operator, the system will make a dummy entry for that operator in the
system's pg_operator table. This dummy entry will have valid data only system catalog. This dummy entry will have valid data only
for the operator name, left and right argument types, and result type, for the operator name, left and right operand types, and result type,
since that's all that <ProductName>PostgreSQL</ProductName> can deduce since that's all that <ProductName>PostgreSQL</ProductName> can deduce
at this point. The first operator's catalog entry will link to this at this point. The first operator's catalog entry will link to this
dummy entry. Later, when you define the second operator, the system dummy entry. Later, when you define the second operator, the system
updates the dummy entry with the additional information from the second updates the dummy entry with the additional information from the second
definition. If you try to use the dummy operator before it's been filled definition. If you try to use the dummy operator before it's been filled
in, you'll just get an error message. (Note: this procedure did not work in, you'll just get an error message. (Note: This procedure did not work
reliably in <ProductName>PostgreSQL</ProductName> versions before 6.5, reliably in <ProductName>PostgreSQL</ProductName> versions before 6.5,
but it is now the recommended way to do things.) but it is now the recommended way to do things.)
</para> </para>
...@@ -171,29 +177,29 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -171,29 +177,29 @@ SELECT (a + b) AS c FROM test_complex;
<title>NEGATOR</title> <title>NEGATOR</title>
<para> <para>
The NEGATOR clause, if provided, names an operator that is the The <literal>NEGATOR</> clause, if provided, names an operator that is the
negator of the operator being defined. We say that operator A negator of the operator being defined. We say that operator A
is the negator of operator B if both return boolean results and is the negator of operator B if both return Boolean results and
(x A y) equals NOT (x B y) for all possible inputs x,y. (x A y) equals NOT (x B y) for all possible inputs x, y.
Notice that B is also the negator of A. Notice that B is also the negator of A.
For example, <literal>&lt;</> and <literal>&gt;=</> are a negator pair for most data types. For example, <literal>&lt;</> and <literal>&gt;=</> are a negator pair for most data types.
An operator can never be validly be its own negator. An operator can never validly be its own negator.
</para> </para>
<para> <para>
Unlike COMMUTATOR, a pair of unary operators could validly be marked Unlike commutators, a pair of unary operators could validly be marked
as each others' negators; that would mean (A x) equals NOT (B x) as each others' negators; that would mean (A x) equals NOT (B x)
for all x, or the equivalent for right-unary operators. for all x, or the equivalent for right unary operators.
</para> </para>
<para> <para>
An operator's negator must have the same left and/or right argument types An operator's negator must have the same left and/or right operand types
as the operator itself, so just as with COMMUTATOR, only the operator as the operator itself, so just as with <literal>COMMUTATOR</>, only the operator
name need be given in the NEGATOR clause. name need be given in the <literal>NEGATOR</> clause.
</para> </para>
<para> <para>
Providing NEGATOR is very helpful to the query optimizer since Providing a negator is very helpful to the query optimizer since
it allows expressions like NOT (x = y) to be simplified into it allows expressions like NOT (x = y) to be simplified into
x &lt;&gt; y. This comes up more often than you might think, because x &lt;&gt; y. This comes up more often than you might think, because
NOTs can be inserted as a consequence of other rearrangements. NOTs can be inserted as a consequence of other rearrangements.
...@@ -210,21 +216,21 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -210,21 +216,21 @@ SELECT (a + b) AS c FROM test_complex;
<title>RESTRICT</title> <title>RESTRICT</title>
<para> <para>
The RESTRICT clause, if provided, names a restriction selectivity The <literal>RESTRICT</> clause, if provided, names a restriction selectivity
estimation function for the operator (note that this is a function estimation function for the operator (note that this is a function
name, not an operator name). RESTRICT clauses only make sense for name, not an operator name). <literal>RESTRICT</> clauses only make sense for
binary operators that return boolean. The idea behind a restriction binary operators that return <type>boolean</>. The idea behind a restriction
selectivity estimator is to guess what fraction of the rows in a selectivity estimator is to guess what fraction of the rows in a
table will satisfy a WHERE-clause condition of the form table will satisfy a <literal>WHERE</literal>-clause condition of the form
<ProgramListing> <ProgramListing>
field OP constant column OP constant
</ProgramListing> </ProgramListing>
for the current operator and a particular constant value. for the current operator and a particular constant value.
This assists the optimizer by This assists the optimizer by
giving it some idea of how many rows will be eliminated by WHERE giving it some idea of how many rows will be eliminated by <literal>WHERE</>
clauses that have this form. (What happens if the constant is on clauses that have this form. (What happens if the constant is on
the left, you may be wondering? Well, that's one of the things that the left, you may be wondering? Well, that's one of the things that
COMMUTATOR is for...) <literal>COMMUTATOR</> is for...)
</para> </para>
<para> <para>
...@@ -232,12 +238,12 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -232,12 +238,12 @@ SELECT (a + b) AS c FROM test_complex;
the scope of this chapter, but fortunately you can usually just use the scope of this chapter, but fortunately you can usually just use
one of the system's standard estimators for many of your own operators. one of the system's standard estimators for many of your own operators.
These are the standard restriction estimators: These are the standard restriction estimators:
<ProgramListing> <simplelist>
eqsel for = <member><function>eqsel</> for <literal>=</></member>
neqsel for &lt;&gt; <member><function>neqsel</> for <literal>&lt;&gt;</></member>
scalarltsel for &lt; or &lt;= <member><function>scalarltsel</> for <literal>&lt;</> or <literal>&lt;=</></member>
scalargtsel for &gt; or &gt;= <member><function>scalargtsel</> for <literal>&gt;</> or <literal>&gt;=</></member>
</ProgramListing> </simplelist>
It might seem a little odd that these are the categories, but they It might seem a little odd that these are the categories, but they
make sense if you think about it. <literal>=</> will typically accept only make sense if you think about it. <literal>=</> will typically accept only
a small fraction of the rows in a table; <literal>&lt;&gt;</> will typically reject a small fraction of the rows in a table; <literal>&lt;&gt;</> will typically reject
...@@ -252,28 +258,28 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -252,28 +258,28 @@ SELECT (a + b) AS c FROM test_complex;
</para> </para>
<para> <para>
You can frequently get away with using either eqsel or neqsel for You can frequently get away with using either <function>eqsel</function> or <function>neqsel</function> for
operators that have very high or very low selectivity, even if they operators that have very high or very low selectivity, even if they
aren't really equality or inequality. For example, the aren't really equality or inequality. For example, the
approximate-equality geometric operators use eqsel on the assumption that approximate-equality geometric operators use <function>eqsel</function> on the assumption that
they'll usually only match a small fraction of the entries in a table. they'll usually only match a small fraction of the entries in a table.
</para> </para>
<para> <para>
You can use scalarltsel and scalargtsel for comparisons on data types that You can use <function>scalarltsel</> and <function>scalargtsel</> for comparisons on data types that
have some sensible means of being converted into numeric scalars for have some sensible means of being converted into numeric scalars for
range comparisons. If possible, add the data type to those understood range comparisons. If possible, add the data type to those understood
by the routine convert_to_scalar() in <filename>src/backend/utils/adt/selfuncs.c</filename>. by the routine <function>convert_to_scalar()</function> in <filename>src/backend/utils/adt/selfuncs.c</filename>.
(Eventually, this routine should be replaced by per-data-type functions (Eventually, this routine should be replaced by per-data-type functions
identified through a column of the pg_type table; but that hasn't happened identified through a column of the <classname>pg_type</> system catalog; but that hasn't happened
yet.) If you do not do this, things will still work, but the optimizer's yet.) If you do not do this, things will still work, but the optimizer's
estimates won't be as good as they could be. estimates won't be as good as they could be.
</para> </para>
<para> <para>
There are additional selectivity functions designed for geometric There are additional selectivity functions designed for geometric
operators in <filename>src/backend/utils/adt/geo_selfuncs.c</filename>: areasel, positionsel, operators in <filename>src/backend/utils/adt/geo_selfuncs.c</filename>: <function>areasel</function>, <function>positionsel</function>,
and contsel. At this writing these are just stubs, but you may want and <function>contsel</function>. At this writing these are just stubs, but you may want
to use them (or even better, improve them) anyway. to use them (or even better, improve them) anyway.
</para> </para>
</sect2> </sect2>
...@@ -282,16 +288,16 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -282,16 +288,16 @@ SELECT (a + b) AS c FROM test_complex;
<title>JOIN</title> <title>JOIN</title>
<para> <para>
The JOIN clause, if provided, names a join selectivity The <literal>JOIN</> clause, if provided, names a join selectivity
estimation function for the operator (note that this is a function estimation function for the operator (note that this is a function
name, not an operator name). JOIN clauses only make sense for name, not an operator name). <literal>JOIN</> clauses only make sense for
binary operators that return boolean. The idea behind a join binary operators that return <type>boolean</type>. The idea behind a join
selectivity estimator is to guess what fraction of the rows in a selectivity estimator is to guess what fraction of the rows in a
pair of tables will satisfy a WHERE-clause condition of the form pair of tables will satisfy a <literal>WHERE</>-clause condition of the form
<ProgramListing> <ProgramListing>
table1.field1 OP table2.field2 table1.column1 OP table2.column2
</ProgramListing> </ProgramListing>
for the current operator. As with the RESTRICT clause, this helps for the current operator. As with the <literal>RESTRICT</literal> clause, this helps
the optimizer very substantially by letting it figure out which the optimizer very substantially by letting it figure out which
of several possible join sequences is likely to take the least work. of several possible join sequences is likely to take the least work.
</para> </para>
...@@ -300,15 +306,15 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -300,15 +306,15 @@ SELECT (a + b) AS c FROM test_complex;
As before, this chapter will make no attempt to explain how to write As before, this chapter will make no attempt to explain how to write
a join selectivity estimator function, but will just suggest that a join selectivity estimator function, but will just suggest that
you use one of the standard estimators if one is applicable: you use one of the standard estimators if one is applicable:
<ProgramListing> <simplelist>
eqjoinsel for = <member><function>eqjoinsel</> for <literal>=</></member>
neqjoinsel for &lt;&gt; <member><function>neqjoinsel</> for <literal>&lt;&gt;</></member>
scalarltjoinsel for &lt; or &lt;= <member><function>scalarltjoinsel</> for <literal>&lt;</> or <literal>&lt;=</></member>
scalargtjoinsel for &gt; or &gt;= <member><function>scalargtjoinsel</> for <literal>&gt;</> or <literal>&gt;=</></member>
areajoinsel for 2D area-based comparisons <member><function>areajoinsel</> for 2D area-based comparisons</member>
positionjoinsel for 2D position-based comparisons <member><function>positionjoinsel</> for 2D position-based comparisons</member>
contjoinsel for 2D containment-based comparisons <member><function>contjoinsel</> for 2D containment-based comparisons</member>
</ProgramListing> </simplelist>
</para> </para>
</sect2> </sect2>
...@@ -316,19 +322,19 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -316,19 +322,19 @@ SELECT (a + b) AS c FROM test_complex;
<title>HASHES</title> <title>HASHES</title>
<para> <para>
The HASHES clause, if present, tells the system that it is OK to The <literal>HASHES</literal> clause, if present, tells the system that it is OK to
use the hash join method for a join based on this operator. HASHES use the hash join method for a join based on this operator. <literal>HASHES</>
only makes sense for binary operators that return boolean, and only makes sense for binary operators that return <literal>boolean</>, and
in practice the operator had better be equality for some data type. in practice the operator had better be equality for some data type.
</para> </para>
<para> <para>
The assumption underlying hash join is that the join operator can The assumption underlying hash join is that the join operator can
only return TRUE for pairs of left and right values that hash to the only return true for pairs of left and right values that hash to the
same hash code. If two values get put in different hash buckets, the same hash code. If two values get put in different hash buckets, the
join will never compare them at all, implicitly assuming that the join will never compare them at all, implicitly assuming that the
result of the join operator must be FALSE. So it never makes sense result of the join operator must be false. So it never makes sense
to specify HASHES for operators that do not represent equality. to specify <literal>HASHES</literal> for operators that do not represent equality.
</para> </para>
<para> <para>
...@@ -353,18 +359,18 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -353,18 +359,18 @@ SELECT (a + b) AS c FROM test_complex;
There are also machine-dependent ways in which a hash join might fail There are also machine-dependent ways in which a hash join might fail
to do the right thing. For example, if your data type to do the right thing. For example, if your data type
is a structure in which there may be uninteresting pad bits, it's unsafe is a structure in which there may be uninteresting pad bits, it's unsafe
to mark the equality operator HASHES. (Unless, perhaps, you write to mark the equality operator <literal>HASHES</>. (Unless, perhaps, you write
your other operators to ensure that the unused bits are always zero.) your other operators to ensure that the unused bits are always zero.)
Another example is that the FLOAT data types are unsafe for hash Another example is that the floating-point data types are unsafe for hash
joins. On machines that meet the <acronym>IEEE</> floating point standard, minus joins. On machines that meet the <acronym>IEEE</> floating-point standard, minus
zero and plus zero are different values (different bit patterns) but zero and plus zero are different values (different bit patterns) but
they are defined to compare equal. So, if float equality were marked they are defined to compare equal. So, if the equality operator on floating-point data types were marked
HASHES, a minus zero and a plus zero would probably not be matched up <literal>HASHES</>, a minus zero and a plus zero would probably not be matched up
by a hash join, but they would be matched up by any other join process. by a hash join, but they would be matched up by any other join process.
</para> </para>
<para> <para>
The bottom line is that you should probably only use HASHES for The bottom line is that you should probably only use <literal>HASHES</literal> for
equality operators that are (or could be) implemented by <function>memcmp()</function>. equality operators that are (or could be) implemented by <function>memcmp()</function>.
</para> </para>
...@@ -374,11 +380,11 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -374,11 +380,11 @@ SELECT (a + b) AS c FROM test_complex;
<title>SORT1 and SORT2</title> <title>SORT1 and SORT2</title>
<para> <para>
The SORT clauses, if present, tell the system that it is permissible to use The <literal>SORT</literal> clauses, if present, tell the system that it is permissible to use
the merge join method for a join based on the current operator. the merge join method for a join based on the current operator.
Both must be specified if either is. The current operator must be Both must be specified if either is. The current operator must be
equality for some pair of data types, and the SORT1 and SORT2 clauses equality for some pair of data types, and the <literal>SORT1</> and <literal>SORT2</> clauses
name the ordering operator ('<' operator) for the left and right-side name the ordering operator (<quote>&lt;</quote> operator) for the left and right-side
data types respectively. data types respectively.
</para> </para>
...@@ -388,29 +394,29 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -388,29 +394,29 @@ SELECT (a + b) AS c FROM test_complex;
be capable of being fully ordered, and the join operator must be one be capable of being fully ordered, and the join operator must be one
that can only succeed for pairs of values that fall at the <quote>same place</> that can only succeed for pairs of values that fall at the <quote>same place</>
in the sort order. In practice this means that the join operator must in the sort order. In practice this means that the join operator must
behave like equality. But unlike hashjoin, where the left and right behave like equality. But unlike hash join, where the left and right
data types had better be the same (or at least bitwise equivalent), data types had better be the same (or at least bitwise equivalent),
it is possible to mergejoin two it is possible to merge-join two
distinct data types so long as they are logically compatible. For distinct data types so long as they are logically compatible. For
example, the int2-versus-int4 equality operator is mergejoinable. example, the <type>int2</type>-versus-<type>int4</type> equality operator is merge-joinable.
We only need sorting operators that will bring both data types into a We only need sorting operators that will bring both data types into a
logically compatible sequence. logically compatible sequence.
</para> </para>
<para> <para>
When specifying merge sort operators, the current operator and both When specifying merge-sort operators, the current operator and both
referenced operators must return boolean; the SORT1 operator must have referenced operators must return <type>boolean</type>; the <literal>SORT1</> operator must have
both input data types equal to the current operator's left argument type, both input data types equal to the current operator's left operand type,
and the SORT2 operator must have and the <literal>SORT2</> operator must have
both input data types equal to the current operator's right argument type. both input data types equal to the current operator's right operand type.
(As with COMMUTATOR and NEGATOR, this means that the operator name is (As with <literal>COMMUTATOR</> and <literal>NEGATOR</>, this means that the operator name is
sufficient to specify the operator, and the system is able to make dummy sufficient to specify the operator, and the system is able to make dummy
operator entries if you happen to define the equality operator before operator entries if you happen to define the equality operator before
the other ones.) the other ones.)
</para> </para>
<para> <para>
In practice you should only write SORT clauses for an <literal>=</> operator, In practice you should only write <literal>SORT</> clauses for an <literal>=</> operator,
and the two referenced operators should always be named <literal>&lt;</>. Trying and the two referenced operators should always be named <literal>&lt;</>. Trying
to use merge join with operators named anything else will result in to use merge join with operators named anything else will result in
hopeless confusion, for reasons we'll see in a moment. hopeless confusion, for reasons we'll see in a moment.
...@@ -418,14 +424,14 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -418,14 +424,14 @@ SELECT (a + b) AS c FROM test_complex;
<para> <para>
There are additional restrictions on operators that you mark There are additional restrictions on operators that you mark
mergejoinable. These restrictions are not currently checked by merge-joinable. These restrictions are not currently checked by
CREATE OPERATOR, but a merge join may fail at runtime if any are <command>CREATE OPERATOR</command>, but a merge join may fail at run time if any are
not true: not true:
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
The mergejoinable equality operator must have a commutator The merge-joinable equality operator must have a commutator
(itself if the two data types are the same, or a related equality operator (itself if the two data types are the same, or a related equality operator
if they are different). if they are different).
</para> </para>
...@@ -434,13 +440,13 @@ SELECT (a + b) AS c FROM test_complex; ...@@ -434,13 +440,13 @@ SELECT (a + b) AS c FROM test_complex;
<listitem> <listitem>
<para> <para>
There must be <literal>&lt;</> and <literal>&gt;</> ordering operators having the same left and There must be <literal>&lt;</> and <literal>&gt;</> ordering operators having the same left and
right input data types as the mergejoinable operator itself. These right operand data types as the merge-joinable operator itself. These
operators <emphasis>must</emphasis> be named <literal>&lt;</> and <literal>&gt;</>; you do operators <emphasis>must</emphasis> be named <literal>&lt;</> and <literal>&gt;</>; you do
not have any choice in the matter, since there is no provision for not have any choice in the matter, since there is no provision for
specifying them explicitly. Note that if the left and right data types specifying them explicitly. Note that if the left and right data types
are different, neither of these operators is the same as either are different, neither of these operators is the same as either
SORT operator. But they had better order the data values compatibly <literal>SORT</literal> operator. But they had better order the data values compatibly
with the SORT operators, or mergejoin will fail to work. with the <literal>SORT</literal> operators, or the merge join will fail to work.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.16 2001/11/21 06:09:45 thomas Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.17 2002/01/07 02:29:14 petere Exp $
--> -->
<chapter id="xplang"> <chapter id="xplang">
<title id="xplang-title">Procedural Languages</title> <title id="xplang-title">Procedural Languages</title>
<sect1 id="xplang-intro">
<title>Introduction</title>
<para> <para>
<productname>PostgreSQL</productname> allows users to add new <productname>PostgreSQL</productname> allows users to add new
programming languages to be available for writing functions and programming languages to be available for writing functions and
...@@ -23,11 +26,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.16 2001/11/21 06:09:45 thom ...@@ -23,11 +26,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/xplang.sgml,v 1.16 2001/11/21 06:09:45 thom
</para> </para>
<para> <para>
Writing a handler for a new procedural language is outside the Writing a handler for a new procedural language is described in
scope of this manual, although some information is provided in <xref linkend="xfunc-plhandler">. Several procedural languages are
the CREATE LANGUAGE reference page. Several procedural languages are available in the standard <productname>PostgreSQL</productname>
available in the standard <productname>PostgreSQL</productname> distribution. distribution, which can serve as examples.
</para> </para>
</sect1>
<sect1 id="xplang-install"> <sect1 id="xplang-install">
<title>Installing Procedural Languages</title> <title>Installing Procedural Languages</title>
...@@ -73,7 +77,7 @@ createlang plpgsql template1 ...@@ -73,7 +77,7 @@ createlang plpgsql template1
</para> </para>
</step> </step>
<step performance="required"> <step performance="required" id="xplang-install-cr1">
<para> <para>
The handler must be declared with the command The handler must be declared with the command
<synopsis> <synopsis>
...@@ -88,43 +92,51 @@ CREATE FUNCTION <replaceable>handler_function_name</replaceable> () ...@@ -88,43 +92,51 @@ CREATE FUNCTION <replaceable>handler_function_name</replaceable> ()
</para> </para>
</step> </step>
<step performance="required"> <step performance="required" id="xplang-install-cr2">
<para> <para>
The PL must be declared with the command The PL must be declared with the command
<synopsis> <synopsis>
CREATE <optional>TRUSTED</optional> <optional>PROCEDURAL</optional> LANGUAGE <replaceable>language-name</replaceable> CREATE <optional>TRUSTED</optional> <optional>PROCEDURAL</optional> LANGUAGE <replaceable>language-name</replaceable>
HANDLER <replaceable>handler_function_name</replaceable>; HANDLER <replaceable>handler_function_name</replaceable>;
</synopsis> </synopsis>
The optional key word <token>TRUSTED</token> tells The optional key word <literal>TRUSTED</literal> tells whether
whether ordinary database users that have no superuser ordinary database users that have no superuser privileges should
privileges should be allowed to use this language to create functions be allowed to use this language to create functions and trigger
and trigger procedures. Since PL functions are procedures. Since PL functions are executed inside the database
executed inside the database backend, the <acronym>TRUSTED</acronym> server, the <literal>TRUSTED</literal> flag should only be given
flag should only be given for for languages that do not allow access to database server
languages that do not allow access to database backends internals or the file system. The languages
internals or the file system. The languages <application>PL/pgSQL</application>, <application>PL/pgSQL</application>,
<application>PL/Tcl</application>, and <application>PL/Perl</application> are known to be trusted; the language <application>PL/TclU</application> <application>PL/Tcl</application>,
should <emphasis>not</emphasis> be marked trusted. <application>PL/Perl</application>, and
<application>PL/Python</application> are known to be trusted;
the languages <application>PL/TclU</application> and
<application>PL/PerlU</application> are designed to provide
unlimited functionality should <emphasis>not</emphasis> be
marked trusted.
</para> </para>
</step> </step>
</procedure> </procedure>
<para> <para>
In a default <productname>PostgreSQL</productname> installation, the In a default <productname>PostgreSQL</productname> installation,
handler for the <application>PL/pgSQL</application> language is built and installed into the the handler for the <application>PL/pgSQL</application> language
<quote>library</quote> directory. If Tcl/Tk support is configured is built and installed into the <quote>library</quote>
in, the handlers for PL/Tcl and PL/TclU are also built and installed in directory. If Tcl/Tk support is configured in, the handlers for
the same location. Likewise, the PL/Perl handler is built and installed PL/Tcl and PL/TclU are also built and installed in the same
if Perl support is configured. The <filename>createlang</filename> location. Likewise, the PL/Perl and PL/PerlU handlers are built
script automates the two CREATE steps described above. and installed if Perl support is configured, and PL/Python is
installed if Python support is configured. The
<filename>createlang</filename> script automates <xref
linkend="xplang-install-cr1"> and <xref
linkend="xplang-install-cr2"> described above.
</para> </para>
<procedure> <example>
<title>Example</title> <title>Manual Installation of <application>PL/pgSQL</application></title>
<step performance="required">
<para> <para>
The following command tells the database where to find the The following command tells the database server where to find the
shared object for the <application>PL/pgSQL</application> language's call handler function. shared object for the <application>PL/pgSQL</application> language's call handler function.
<programlisting> <programlisting>
...@@ -132,9 +144,7 @@ CREATE FUNCTION plpgsql_call_handler () RETURNS OPAQUE AS ...@@ -132,9 +144,7 @@ CREATE FUNCTION plpgsql_call_handler () RETURNS OPAQUE AS
'$libdir/plpgsql' LANGUAGE C; '$libdir/plpgsql' LANGUAGE C;
</programlisting> </programlisting>
</para> </para>
</step>
<step performance="Required">
<para> <para>
The command The command
<programlisting> <programlisting>
...@@ -145,8 +155,7 @@ CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql ...@@ -145,8 +155,7 @@ CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql
should be invoked for functions and trigger procedures where the should be invoked for functions and trigger procedures where the
language attribute is <literal>plpgsql</literal>. language attribute is <literal>plpgsql</literal>.
</para> </para>
</step> </example>
</procedure>
</sect1> </sect1>
......
...@@ -6,55 +6,73 @@ ...@@ -6,55 +6,73 @@
<secondary>extending</secondary> <secondary>extending</secondary>
</indexterm> </indexterm>
<comment>
This chapter needs to be updated for the version-1 function manager
interface.
</comment>
<para> <para>
As previously mentioned, there are two kinds of types As previously mentioned, there are two kinds of types in
in <productname>PostgreSQL</productname>: base types (defined in a programming language) <productname>PostgreSQL</productname>: base types (defined in a
and composite types. programming language) and composite types. This chapter describes
Examples in this section up to interfacing indexes can how to define new base types.
be found in <filename>complex.sql</filename> and <filename>complex.c</filename>. Composite examples
are in <filename>funcs.sql</filename>.
</para> </para>
<sect1 id="xtypes-userdefined"> <para>
<title>User-Defined Types</title> The examples in this section can be found in
<filename>complex.sql</filename> and <filename>complex.c</filename>
in the tutorial directory. Composite examples are in
<filename>funcs.sql</filename>.
</para>
<sect2> <para>
<title>Functions Needed for a User-Defined Type</title> <indexterm>
<para> <primary>input function</primary>
A user-defined type must always have input and output </indexterm>
functions. These functions determine how the type <indexterm>
appears in strings (for input by the user and output to <primary>output function</primary>
the user) and how the type is organized in memory. The </indexterm>
input function takes a null-delimited character string A user-defined type must always have input and output functions.
as its input and returns the internal (in memory) These functions determine how the type appears in strings (for input
representation of the type. The output function takes the by the user and output to the user) and how the type is organized in
internal representation of the type and returns a null memory. The input function takes a null-terminated character string
delimited character string. as its input and returns the internal (in memory) representation of
Suppose we want to define a complex type which represents the type. The output function takes the internal representation of
complex numbers. Naturally, we choose to represent a the type and returns a null-terminated character string.
complex in memory as the following <acronym>C</acronym> structure: </para>
<programlisting> <para>
Suppose we want to define a complex type which represents complex
numbers. Naturally, we would choose to represent a complex in memory
as the following <acronym>C</acronym> structure:
<programlisting>
typedef struct Complex { typedef struct Complex {
double x; double x;
double y; double y;
} Complex; } Complex;
</programlisting> </programlisting>
and a string of the form (x,y) as the external string and a string of the form <literal>(x,y)</literal> as the external string
representation. representation.
These functions are usually not hard to write, especially </para>
the output function. However, there are a number of points
to remember: <para>
The functions are usually not hard to write, especially the output
<itemizedlist> function. However, there are a number of points to remember:
<listitem>
<para> When defining your external (string) representation, <itemizedlist>
remember that you must eventually write a <listitem>
complete and robust parser for that representation <para>
as your input function! When defining your external (string) representation, remember
that you must eventually write a complete and robust parser for
<programlisting> that representation as your input function!
</para>
<para>
For instance:
<programlisting>
Complex * Complex *
complex_in(char *str) complex_in(char *str)
{ {
...@@ -69,11 +87,13 @@ complex_in(char *str) ...@@ -69,11 +87,13 @@ complex_in(char *str)
result-&gt;y = y; result-&gt;y = y;
return (result); return (result);
} }
</programlisting> </programlisting>
</para>
The output function can simply be: <para>
The output function can simply be:
<programlisting> <programlisting>
char * char *
complex_out(Complex *complex) complex_out(Complex *complex)
{ {
...@@ -84,30 +104,30 @@ complex_out(Complex *complex) ...@@ -84,30 +104,30 @@ complex_out(Complex *complex)
sprintf(result, "(%g,%g)", complex-&gt;x, complex-&gt;y); sprintf(result, "(%g,%g)", complex-&gt;x, complex-&gt;y);
return(result); return(result);
} }
</programlisting> </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> </para>
</listitem>
<listitem>
<para> <para>
To define the <acronym>complex</acronym> type, we need to create the two You should try to make the input and output functions inverses of
user-defined functions complex_in and complex_out each other. If you do not, you will have severe problems when
before creating the type: 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>
<programlisting> <para>
To define the <type>complex</type> type, we need to create the two
user-defined functions <function>complex_in</function> and
<function>complex_out</function> before creating the type:
<programlisting>
CREATE FUNCTION complex_in(opaque) CREATE FUNCTION complex_in(opaque)
RETURNS complex RETURNS complex
AS '<replaceable>PGROOT</replaceable>/tutorial/complex' AS '<replaceable>PGROOT</replaceable>/tutorial/complex'
...@@ -117,47 +137,57 @@ CREATE FUNCTION complex_out(opaque) ...@@ -117,47 +137,57 @@ CREATE FUNCTION complex_out(opaque)
RETURNS opaque RETURNS opaque
AS '<replaceable>PGROOT</replaceable>/tutorial/complex' AS '<replaceable>PGROOT</replaceable>/tutorial/complex'
LANGUAGE C; LANGUAGE C;
</programlisting>
</para>
<para>
Finally, we can declare the data type:
<programlisting>
CREATE TYPE complex ( CREATE TYPE complex (
internallength = 16, internallength = 16,
input = complex_in, input = complex_in,
output = complex_out output = complex_out
); );
</programlisting> </programlisting>
</para> </para>
<para>
As discussed earlier, <productname>PostgreSQL</productname> fully supports arrays of
base types. Additionally, <productname>PostgreSQL</productname> supports arrays of
user-defined types as well. When you define a type,
<productname>PostgreSQL</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>
<sect2> <para>
<title>Large Objects</title> <indexterm>
<primary>arrays</primary>
<para> </indexterm>
If the values of your datatype might exceed a few hundred bytes in As discussed earlier, <productname>PostgreSQL</productname> fully
size (in internal form), you should be careful to mark them TOASTable. supports arrays of base types. Additionally,
To do this, the internal representation must follow the standard <productname>PostgreSQL</productname> supports arrays of
layout for variable-length data: the first four bytes must be an int32 user-defined types as well. When you define a type,
containing the total length in bytes of the datum (including itself). <productname>PostgreSQL</productname> automatically provides support
Then, all your functions that accept values of the type must be careful for arrays of that type. For historical reasons, the array type has
to call pg_detoast_datum() on the supplied values --- after checking the same name as the user-defined type with the underscore character
that the value is not NULL, if your function is not strict. Finally, <literal>_</> prepended.
select the appropriate storage option when giving the CREATE TYPE </para>
command.
</para> <para>
</sect2> Composite types do not need any function defined on them, since the
</sect1> system already understands what they look like inside.
</chapter> </para>
<para>
<indexterm>
<primary>TOAST</primary>
<secondary>and user-defined types</secondary>
</indexterm>
If the values of your datatype might exceed a few hundred bytes in
size (in internal form), you should be careful to mark them
TOAST-able. To do this, the internal representation must follow the
standard layout for variable-length data: the first four bytes must
be an <type>int32</type> containing the total length in bytes of the
datum (including itself). Then, all your functions that accept
values of the type must be careful to call
<function>pg_detoast_datum()</function> on the supplied values ---
after checking that the value is not NULL, if your function is not
strict. Finally, select the appropriate storage option when giving
the <command>CREATE TYPE</command> command.
</para>
</chapter>
<!-- Keep this comment at the end of the file <!-- Keep this comment at the end of the file
Local variables: Local variables:
......
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/error.c,v 1.14 2001/12/23 12:17:41 meskes Exp $ */ /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/lib/Attic/error.c,v 1.15 2002/01/07 02:29:15 petere Exp $ */
#include "postgres_fe.h" #include "postgres_fe.h"
...@@ -54,7 +54,7 @@ ECPGraise(int line, int code, const char *str) ...@@ -54,7 +54,7 @@ ECPGraise(int line, int code, const char *str)
case ECPG_FLOAT_FORMAT: case ECPG_FLOAT_FORMAT:
snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc), snprintf(sqlca.sqlerrm.sqlerrmc, sizeof(sqlca.sqlerrm.sqlerrmc),
"Not correctly formatted floating point type: %s in line %d.", str, line); "Not correctly formatted floating-point type: %s in line %d.", str, line);
break; break;
case ECPG_CONVERT_BOOL: case ECPG_CONVERT_BOOL:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment