Commit 706a32cd authored by Peter Eisentraut's avatar Peter Eisentraut

Big editing for consistent content and presentation.

parent 31e69ccb
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/advanced.sgml,v 1.32 2003/02/19 04:06:27 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/advanced.sgml,v 1.33 2003/03/13 01:30:24 petere Exp $
--> -->
<chapter id="tutorial-advanced"> <chapter id="tutorial-advanced">
...@@ -344,14 +344,14 @@ SELECT name, altitude ...@@ -344,14 +344,14 @@ SELECT name, altitude
which returns: which returns:
<screen> <screen>
name | altitude name | altitude
-----------+---------- -----------+----------
Las Vegas | 2174 Las Vegas | 2174
Mariposa | 1953 Mariposa | 1953
Madison | 845 Madison | 845
(3 rows) (3 rows)
</screen> </screen>
</para> </para>
<para> <para>
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.24 2002/11/11 20:14:02 petere Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/array.sgml,v 1.25 2003/03/13 01:30:26 petere Exp $ -->
<sect1 id="arrays"> <sect1 id="arrays">
<title>Arrays</title> <title>Arrays</title>
...@@ -10,8 +10,14 @@ ...@@ -10,8 +10,14 @@
<para> <para>
<productname>PostgreSQL</productname> allows columns of a table to be <productname>PostgreSQL</productname> allows columns of a table to be
defined as variable-length multidimensional arrays. Arrays of any defined as variable-length multidimensional arrays. Arrays of any
built-in type or user-defined type can be created. To illustrate built-in type or user-defined type can be created.
their use, we create this table: </para>
<sect2>
<title>Declaration of Array Types</title>
<para>
To illustrate the use of array types, we create this table:
<programlisting> <programlisting>
CREATE TABLE sal_emp ( CREATE TABLE sal_emp (
name text, name text,
...@@ -20,24 +26,27 @@ CREATE TABLE sal_emp ( ...@@ -20,24 +26,27 @@ CREATE TABLE sal_emp (
); );
</programlisting> </programlisting>
As shown, an array data type is named by appending square brackets As shown, an array data type is named by appending square brackets
(<literal>[]</>) to the data type name of the array elements. (<literal>[]</>) to the data type name of the array elements. The
The above command will create a table named above command will create a table named
<structname>sal_emp</structname> with columns including <structname>sal_emp</structname> with a column of type
a <type>text</type> string (<structfield>name</structfield>), <type>text</type> (<structfield>name</structfield>), a
a one-dimensional array of type one-dimensional array of type <type>integer</type>
<type>integer</type> (<structfield>pay_by_quarter</structfield>), (<structfield>pay_by_quarter</structfield>), which represents the
which represents the employee's salary by quarter, and a employee's salary by quarter, and a two-dimensional array of
two-dimensional array of <type>text</type> <type>text</type> (<structfield>schedule</structfield>), which
(<structfield>schedule</structfield>), which represents the represents the employee's weekly schedule.
employee's weekly schedule.
</para> </para>
</sect2>
<sect2>
<title>Array Value Input</title>
<para> <para>
Now we do some <command>INSERT</command>s. Observe that to write an array Now we can show some <command>INSERT</command> statements. To write an array
value, we enclose the element values within curly braces and separate them value, we enclose the element values within curly braces and separate them
by commas. If you know C, this is not unlike the syntax for by commas. If you know C, this is not unlike the syntax for
initializing structures. (More details appear below.) initializing structures. (More details appear below.)
<programlisting> <programlisting>
INSERT INTO sal_emp INSERT INTO sal_emp
VALUES ('Bill', VALUES ('Bill',
...@@ -51,8 +60,21 @@ INSERT INTO sal_emp ...@@ -51,8 +60,21 @@ INSERT INTO sal_emp
</programlisting> </programlisting>
</para> </para>
<note>
<para>
A limitation of the present array implementation is that individual
elements of an array cannot be SQL null values. The entire array can be set
to null, but you can't have an array with some elements null and some
not. Fixing this is on the to-do list.
</para>
</note>
</sect2>
<sect2>
<title>Array Value References</title>
<para> <para>
Now, we can run some queries on <structname>sal_emp</structname>. Now, we can run some queries on the table.
First, we show how to access a single element of an array at a time. First, we show how to access a single element of an array at a time.
This query retrieves the names of the employees whose pay changed in This query retrieves the names of the employees whose pay changed in
the second quarter: the second quarter:
...@@ -91,7 +113,7 @@ SELECT pay_by_quarter[3] FROM sal_emp; ...@@ -91,7 +113,7 @@ SELECT pay_by_quarter[3] FROM sal_emp;
We can also access arbitrary rectangular slices of an array, or We can also access arbitrary rectangular slices of an array, or
subarrays. An array slice is denoted by writing subarrays. An array slice is denoted by writing
<literal><replaceable>lower-bound</replaceable>:<replaceable>upper-bound</replaceable></literal> <literal><replaceable>lower-bound</replaceable>:<replaceable>upper-bound</replaceable></literal>
for one or more array dimensions. This query retrieves the first for one or more array dimensions. For example, this query retrieves the first
item on Bill's schedule for the first two days of the week: item on Bill's schedule for the first two days of the week:
<programlisting> <programlisting>
...@@ -109,7 +131,7 @@ SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = 'Bill'; ...@@ -109,7 +131,7 @@ SELECT schedule[1:2][1:1] FROM sal_emp WHERE name = 'Bill';
SELECT schedule[1:2][1] FROM sal_emp WHERE name = 'Bill'; SELECT schedule[1:2][1] FROM sal_emp WHERE name = 'Bill';
</programlisting> </programlisting>
with the same result. An array subscripting operation is taken to with the same result. An array subscripting operation is always taken to
represent an array slice if any of the subscripts are written in the represent an array slice if any of the subscripts are written in the
form form
<literal><replaceable>lower</replaceable>:<replaceable>upper</replaceable></literal>. <literal><replaceable>lower</replaceable>:<replaceable>upper</replaceable></literal>.
...@@ -199,10 +221,15 @@ SELECT array_dims(schedule) FROM sal_emp WHERE name = 'Carol'; ...@@ -199,10 +221,15 @@ SELECT array_dims(schedule) FROM sal_emp WHERE name = 'Carol';
array_lower</function> return the upper/lower bound of the array_lower</function> return the upper/lower bound of the
given array dimension, respectively. given array dimension, respectively.
</para> </para>
</sect2>
<sect2>
<title>Searching in Arrays</title>
<para> <para>
To search for a value in an array, you must check each value of the To search for a value in an array, you must check each value of the
array. This can be done by hand (if you know the size of the array): array. This can be done by hand (if you know the size of the array).
For example:
<programlisting> <programlisting>
SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR
...@@ -212,8 +239,8 @@ SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR ...@@ -212,8 +239,8 @@ SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR
</programlisting> </programlisting>
However, this quickly becomes tedious for large arrays, and is not However, this quickly becomes tedious for large arrays, and is not
helpful if the size of the array is unknown. Although it is not part helpful if the size of the array is unknown. Although it is not built
of the primary <productname>PostgreSQL</productname> distribution, into <productname>PostgreSQL</productname>,
there is an extension available that defines new functions and there is an extension available that defines new functions and
operators for iterating over array values. Using this, the above operators for iterating over array values. Using this, the above
query could be: query could be:
...@@ -222,7 +249,7 @@ SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR ...@@ -222,7 +249,7 @@ SELECT * FROM sal_emp WHERE pay_by_quarter[1] = 10000 OR
SELECT * FROM sal_emp WHERE pay_by_quarter[1:4] *= 10000; SELECT * FROM sal_emp WHERE pay_by_quarter[1:4] *= 10000;
</programlisting> </programlisting>
To search the entire array (not just specified columns), you could To search the entire array (not just specified slices), you could
use: use:
<programlisting> <programlisting>
...@@ -249,18 +276,11 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000; ...@@ -249,18 +276,11 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000;
Tables can obviously be searched easily. Tables can obviously be searched easily.
</para> </para>
</tip> </tip>
</sect2>
<note> <sect2>
<para> <title>Array Input and Output Syntax</title>
A limitation of the present array implementation is that individual
elements of an array cannot be SQL null values. The entire array can be set
to null, but you can't have an array with some elements null and some
not. Fixing this is on the to-do list.
</para>
</note>
<formalpara>
<title>Array input and output syntax.</title>
<para> <para>
The external representation of an array value consists of items that The external representation of an array value consists of items that
are interpreted according to the I/O conversion rules for the array's are interpreted according to the I/O conversion rules for the array's
...@@ -280,10 +300,11 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000; ...@@ -280,10 +300,11 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000;
is not ignored, however: after skipping leading whitespace, everything is not ignored, however: after skipping leading whitespace, everything
up to the next right brace or delimiter is taken as the item value. up to the next right brace or delimiter is taken as the item value.
</para> </para>
</formalpara> </sect2>
<sect2>
<title>Quoting Array Elements</title>
<formalpara>
<title>Quoting array elements.</title>
<para> <para>
As shown above, when writing an array value you may write double As shown above, when writing an array value you may write double
quotes around any individual array quotes around any individual array
...@@ -295,7 +316,6 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000; ...@@ -295,7 +316,6 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000;
Alternatively, you can use backslash-escaping to protect all data characters Alternatively, you can use backslash-escaping to protect all data characters
that would otherwise be taken as array syntax or ignorable white space. that would otherwise be taken as array syntax or ignorable white space.
</para> </para>
</formalpara>
<para> <para>
The array output routine will put double quotes around element values The array output routine will put double quotes around element values
...@@ -308,7 +328,7 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000; ...@@ -308,7 +328,7 @@ SELECT * FROM sal_emp WHERE pay_by_quarter **= 10000;
<productname>PostgreSQL</productname> releases.) <productname>PostgreSQL</productname> releases.)
</para> </para>
<tip> <note>
<para> <para>
Remember that what you write in an SQL command will first be interpreted Remember that what you write in an SQL command will first be interpreted
as a string literal, and then as an array. This doubles the number of as a string literal, and then as an array. This doubles the number of
...@@ -325,6 +345,7 @@ INSERT ... VALUES ('{"\\\\","\\""}'); ...@@ -325,6 +345,7 @@ INSERT ... VALUES ('{"\\\\","\\""}');
<type>bytea</> for example, we might need as many as eight backslashes <type>bytea</> for example, we might need as many as eight backslashes
in the command to get one backslash into the stored array element.) in the command to get one backslash into the stored array element.)
</para> </para>
</tip> </note>
</sect2>
</sect1> </sect1>
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/charset.sgml,v 2.31 2003/01/19 00:13:28 momjian Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/charset.sgml,v 2.32 2003/03/13 01:30:26 petere Exp $ -->
<chapter id="charset"> <chapter id="charset">
<title>Localization</> <title>Localization</>
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
<command>initdb</command> exactly which locale you want with the <command>initdb</command> exactly which locale you want with the
option <option>--locale</option>. For example: option <option>--locale</option>. For example:
<screen> <screen>
<prompt>$ </><userinput>initdb --locale=sv_SE</> initdb --locale=sv_SE
</screen> </screen>
</para> </para>
...@@ -517,7 +517,7 @@ perl: warning: Falling back to the standard locale ("C"). ...@@ -517,7 +517,7 @@ perl: warning: Falling back to the standard locale ("C").
for a <productname>PostgreSQL</productname> installation. For example: for a <productname>PostgreSQL</productname> installation. For example:
<screen> <screen>
$ <userinput>initdb -E EUC_JP</> initdb -E EUC_JP
</screen> </screen>
sets the default encoding to <literal>EUC_JP</literal> (Extended Unix Code for Japanese). sets the default encoding to <literal>EUC_JP</literal> (Extended Unix Code for Japanese).
...@@ -531,7 +531,7 @@ $ <userinput>initdb -E EUC_JP</> ...@@ -531,7 +531,7 @@ $ <userinput>initdb -E EUC_JP</>
You can create a database with a different encoding: You can create a database with a different encoding:
<screen> <screen>
$ <userinput>createdb -E EUC_KR korean</> createdb -E EUC_KR korean
</screen> </screen>
will create a database named <database>korean</database> with <literal>EUC_KR</literal> encoding. will create a database named <database>korean</database> with <literal>EUC_KR</literal> encoding.
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.45 2003/02/13 05:47:46 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.46 2003/03/13 01:30:26 petere Exp $
--> -->
<chapter id="client-authentication"> <chapter id="client-authentication">
...@@ -40,7 +40,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.45 2003/02/13 05:47:46 ...@@ -40,7 +40,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.45 2003/02/13 05:47:46
runs. If all the users of a particular server also have accounts on runs. If all the users of a particular server also have accounts on
the server's machine, it makes sense to assign database user names the server's machine, it makes sense to assign database user names
that match their operating system user names. However, a server that that match their operating system user names. However, a server that
accepts remote connections may have many users who have no local accepts remote connections may have many database users who have no local operating system
account, and in such cases there need be no connection between account, and in such cases there need be no connection between
database user names and OS user names. database user names and OS user names.
</para> </para>
...@@ -64,7 +64,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.45 2003/02/13 05:47:46 ...@@ -64,7 +64,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.45 2003/02/13 05:47:46
<para> <para>
The general format of the <filename>pg_hba.conf</filename> file is The general format of the <filename>pg_hba.conf</filename> file is
a set of records, one per line. Blank lines are ignored, as is any a set of records, one per line. Blank lines are ignored, as is any
text after the <quote>#</quote> comment character. A record is made text after the <literal>#</literal> comment character. A record is made
up of a number of fields which are separated by spaces and/or tabs. up of a number of fields which are separated by spaces and/or tabs.
Fields can contain white space if the field value is quoted. Records Fields can contain white space if the field value is quoted. Records
cannot be continued across lines. cannot be continued across lines.
...@@ -84,11 +84,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.45 2003/02/13 05:47:46 ...@@ -84,11 +84,11 @@ $Header: /cvsroot/pgsql/doc/src/sgml/client-auth.sgml,v 1.45 2003/02/13 05:47:46
<para> <para>
A record may have one of the three formats A record may have one of the three formats
<synopsis> <synopsis>
local <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional> local <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional> host <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional> hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <replaceable>IP-address</replaceable> <replaceable>IP-mask</replaceable> <replaceable>authentication-method</replaceable> <optional><replaceable>authentication-option</replaceable></optional>
</synopsis> </synopsis>
The meaning of the fields is as follows: The meaning of the fields is as follows:
<variablelist> <variablelist>
...@@ -96,7 +96,7 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> < ...@@ -96,7 +96,7 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <
<term><literal>local</literal></term> <term><literal>local</literal></term>
<listitem> <listitem>
<para> <para>
This record matches connection attempts using Unix domain This record matches connection attempts using Unix-domain
sockets. Without a record of this type, Unix-domain socket sockets. Without a record of this type, Unix-domain socket
connections are disallowed connections are disallowed
</para> </para>
...@@ -181,11 +181,9 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> < ...@@ -181,11 +181,9 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <
numerically, not as domain or host names.) Taken together they numerically, not as domain or host names.) Taken together they
specify the client machine IP addresses that this record specify the client machine IP addresses that this record
matches. The precise logic is that matches. The precise logic is that
<blockquote> <programlisting>
<informalfigure> (<replaceable>actual-IP-address</replaceable> xor <replaceable>IP-address-field</replaceable>) and <replaceable>IP-mask-field</replaceable>
<programlisting>(<replaceable>actual-IP-address</replaceable> xor <replaceable>IP-address-field</replaceable>) and <replaceable>IP-mask-field</replaceable></programlisting> </programlisting>
</informalfigure>
</blockquote>
must be zero for the record to match. (Of course IP addresses must be zero for the record to match. (Of course IP addresses
can be spoofed but this consideration is beyond the scope of can be spoofed but this consideration is beyond the scope of
<productname>PostgreSQL</productname>.) If you machine supports <productname>PostgreSQL</productname>.) If you machine supports
...@@ -217,7 +215,7 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> < ...@@ -217,7 +215,7 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <
<para> <para>
The connection is allowed unconditionally. This method The connection is allowed unconditionally. This method
allows anyone that can connect to the allows anyone that can connect to the
<productname>PostgreSQL</productname> database to login as <productname>PostgreSQL</productname> database server to login as
any <productname>PostgreSQL</productname> user they like, any <productname>PostgreSQL</productname> user they like,
without the need for a password. See <xref without the need for a password. See <xref
linkend="auth-trust"> for details. linkend="auth-trust"> for details.
...@@ -251,7 +249,7 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> < ...@@ -251,7 +249,7 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <
<term><literal>crypt</></term> <term><literal>crypt</></term>
<listitem> <listitem>
<para> <para>
Like <literal>md5</literal> method but uses older crypt Like the <literal>md5</literal> method but uses older <function>crypt()</>
encryption, which is needed for pre-7.2 clients. encryption, which is needed for pre-7.2 clients.
<literal>md5</literal> is preferred for 7.2 and later clients. <literal>md5</literal> is preferred for 7.2 and later clients.
See <xref linkend="auth-password"> for details. See <xref linkend="auth-password"> for details.
...@@ -263,7 +261,7 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> < ...@@ -263,7 +261,7 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <
<term><literal>password</></term> <term><literal>password</></term>
<listitem> <listitem>
<para> <para>
Same as "md5", but the password is sent in clear text over the Same as <literal>md5</>, but the password is sent in clear text over the
network. This should not be used on untrusted networks. network. This should not be used on untrusted networks.
See <xref linkend="auth-password"> for details. See <xref linkend="auth-password"> for details.
</para> </para>
...@@ -306,11 +304,11 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> < ...@@ -306,11 +304,11 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <
<para> <para>
If you use the map <literal>sameuser</literal>, the user If you use the map <literal>sameuser</literal>, the user
names are assumed to be identical. If not, the map name is names are required to be identical. If not, the map name is
looked up in the file <filename>pg_ident.conf</filename> looked up in the file <filename>pg_ident.conf</filename>
in the same directory as <filename>pg_hba.conf</filename>. in the same directory as <filename>pg_hba.conf</filename>.
The connection is accepted if that file contains an The connection is accepted if that file contains an
entry for this map name with the ident-supplied user name entry for this map name with the operating-system user name
and the requested <productname>PostgreSQL</productname> user and the requested <productname>PostgreSQL</productname> user
name. name.
</para> </para>
...@@ -365,8 +363,8 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> < ...@@ -365,8 +363,8 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <
match parameters and weaker authentication methods, while later match parameters and weaker authentication methods, while later
records will have looser match parameters and stronger authentication records will have looser match parameters and stronger authentication
methods. For example, one might wish to use <literal>trust</> methods. For example, one might wish to use <literal>trust</>
authentication for local TCP connections but require a password for authentication for local TCP/IP connections but require a password for
remote TCP connections. In this case a record specifying remote TCP/IP connections. In this case a record specifying
<literal>trust</> authentication for connections from 127.0.0.1 would <literal>trust</> authentication for connections from 127.0.0.1 would
appear before a record specifying password authentication for a wider appear before a record specifying password authentication for a wider
range of allowed client IP addresses. range of allowed client IP addresses.
...@@ -374,27 +372,26 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> < ...@@ -374,27 +372,26 @@ hostssl <replaceable>database</replaceable> <replaceable>user</replaceable> <
<important> <important>
<para> <para>
Do not prevent the superuser from accessing the template1 Do not prevent the superuser from accessing the <literal>template1</literal>
database. Various utility commands need access to template1. database. Various utility commands need access to <literal>template1</literal>.
</para> </para>
</important> </important>
<para> <para>
<indexterm>
<primary>SIGHUP</primary>
</indexterm>
The <filename>pg_hba.conf</filename> file is read on start-up and when The <filename>pg_hba.conf</filename> file is read on start-up and when
the <application>postmaster</> receives a the main server process (<command>postmaster</>) receives a
<systemitem>SIGHUP</systemitem> signal. If you edit the file on an <systemitem>SIGHUP</systemitem><indexterm><primary>SIGHUP</primary></indexterm>
active system, you will need to signal the <application>postmaster</> signal. If you edit the file on an
active system, you will need to signal the <command>postmaster</>
(using <literal>pg_ctl reload</> or <literal>kill -HUP</>) to make it (using <literal>pg_ctl reload</> or <literal>kill -HUP</>) to make it
re-read the file. re-read the file.
</para> </para>
<para> <para>
An example of a <filename>pg_hba.conf</filename> file is shown in An example of a <filename>pg_hba.conf</filename> file is shown in
<xref linkend="example-pg-hba.conf">. See below for details on the <xref linkend="example-pg-hba.conf">. See the next section for details on the
different authentication methods. different authentication methods.
</para>
<example id="example-pg-hba.conf"> <example id="example-pg-hba.conf">
<title>An example <filename>pg_hba.conf</filename> file</title> <title>An example <filename>pg_hba.conf</filename> file</title>
...@@ -462,7 +459,6 @@ local all @admins,+support md5 ...@@ -462,7 +459,6 @@ local all @admins,+support md5
local db1,db2,@demodbs all md5 local db1,db2,@demodbs all md5
</programlisting> </programlisting>
</example> </example>
</para>
</sect1> </sect1>
<sect1 id="auth-methods"> <sect1 id="auth-methods">
...@@ -479,8 +475,8 @@ local db1,db2,@demodbs all md5 ...@@ -479,8 +475,8 @@ local db1,db2,@demodbs all md5
<productname>PostgreSQL</productname> assumes that anyone who can <productname>PostgreSQL</productname> assumes that anyone who can
connect to the server is authorized to access the database as connect to the server is authorized to access the database as
whatever database user he specifies (including the database superuser). whatever database user he specifies (including the database superuser).
This method should only be used when there is adequate system-level This method should only be used when there is adequate operating system-level
protection on connections to the postmaster port. protection on connections to the server.
</para> </para>
<para> <para>
...@@ -488,8 +484,8 @@ local db1,db2,@demodbs all md5 ...@@ -488,8 +484,8 @@ local db1,db2,@demodbs all md5
convenient for local connections on a single-user workstation. It convenient for local connections on a single-user workstation. It
is usually <emphasis>not</> appropriate by itself on a multiuser is usually <emphasis>not</> appropriate by itself on a multiuser
machine. However, you may be able to use <literal>trust</> even machine. However, you may be able to use <literal>trust</> even
on a multiuser machine, if you restrict access to the postmaster's on a multiuser machine, if you restrict access to the server's
socket file using file-system permissions. To do this, set the Unix-domain socket file using file-system permissions. To do this, set the
<varname>unix_socket_permissions</varname> (and possibly <varname>unix_socket_permissions</varname> (and possibly
<varname>unix_socket_group</varname>) configuration parameters as <varname>unix_socket_group</varname>) configuration parameters as
described in <xref linkend="runtime-config-general">. Or you described in <xref linkend="runtime-config-general">. Or you
...@@ -500,18 +496,18 @@ local db1,db2,@demodbs all md5 ...@@ -500,18 +496,18 @@ local db1,db2,@demodbs all md5
<para> <para>
Setting file-system permissions only helps for Unix-socket connections. Setting file-system permissions only helps for Unix-socket connections.
Local TCP connections are not restricted by it; therefore, if you want Local TCP/IP connections are not restricted by it; therefore, if you want
to use permissions for local security, remove the <literal>host ... to use file-system permissions for local security, remove the <literal>host ...
127.0.0.1 ...</> line from <filename>pg_hba.conf</>, or change it to a 127.0.0.1 ...</> line from <filename>pg_hba.conf</>, or change it to a
non-<literal>trust</> authentication method. non-<literal>trust</> authentication method.
</para> </para>
<para> <para>
<literal>trust</> authentication is only suitable for TCP connections <literal>trust</> authentication is only suitable for TCP/IP connections
if you trust every user on every machine that is allowed to connect if you trust every user on every machine that is allowed to connect
to the server by the <filename>pg_hba.conf</> lines that specify to the server by the <filename>pg_hba.conf</> lines that specify
<literal>trust</>. It is seldom reasonable to use <literal>trust</> <literal>trust</>. It is seldom reasonable to use <literal>trust</>
for any TCP connections other than those from <systemitem>localhost</> (127.0.0.1). for any TCP/IP connections other than those from <systemitem>localhost</> (127.0.0.1).
</para> </para>
</sect2> </sect2>
...@@ -530,7 +526,7 @@ local db1,db2,@demodbs all md5 ...@@ -530,7 +526,7 @@ local db1,db2,@demodbs all md5
</indexterm> </indexterm>
<para> <para>
Password-based authentication methods include <literal>md5</>, The password-based authentication methods are <literal>md5</>,
<literal>crypt</>, and <literal>password</>. These methods operate <literal>crypt</>, and <literal>password</>. These methods operate
similarly except for the way that the password is sent across the similarly except for the way that the password is sent across the
connection. If you are at all concerned about password connection. If you are at all concerned about password
...@@ -545,7 +541,7 @@ local db1,db2,@demodbs all md5 ...@@ -545,7 +541,7 @@ local db1,db2,@demodbs all md5
<productname>PostgreSQL</productname> database passwords are <productname>PostgreSQL</productname> database passwords are
separate from operating system user passwords. The password for separate from operating system user passwords. The password for
each database user is stored in the <literal>pg_shadow</> system each database user is stored in the <literal>pg_shadow</> system
catalog table. Passwords can be managed with the query language catalog table. Passwords can be managed with the SQL
commands <command>CREATE USER</command> and <command>ALTER commands <command>CREATE USER</command> and <command>ALTER
USER</command>, e.g., <userinput>CREATE USER foo WITH PASSWORD USER</command>, e.g., <userinput>CREATE USER foo WITH PASSWORD
'secret';</userinput>. By default, that is, if no password has 'secret';</userinput>. By default, that is, if no password has
...@@ -554,15 +550,10 @@ local db1,db2,@demodbs all md5 ...@@ -554,15 +550,10 @@ local db1,db2,@demodbs all md5
</para> </para>
<para> <para>
To restrict the set of users that are allowed to connect to certain To restrict the set of users that are allowed to connect to
databases, list the users separated by commas, or in a separate certain databases, list the users in the <replaceable>user</>
file. The file should contain user names separated by commas or one column of <filename>pg_hba.conf</filename>, as explained in the
user name per line, and be in the same directory as previous section.
<filename>pg_hba.conf</>. Mention the (base) name of the file
preceded with <literal>@</> in the user column. The
database column can similarly accept a list of values or
a file name. You can also specify group names by preceding the group
name with <literal>+</>.
</para> </para>
</sect2> </sect2>
...@@ -598,11 +589,11 @@ local db1,db2,@demodbs all md5 ...@@ -598,11 +589,11 @@ local db1,db2,@demodbs all md5
<para> <para>
<productname>PostgreSQL</> operates like a normal Kerberos service. <productname>PostgreSQL</> operates like a normal Kerberos service.
The name of the service principal is The name of the service principal is
<replaceable>servicename/hostname@realm</>, where <literal><replaceable>servicename</>/<replaceable>hostname</>@<replaceable>realm</></literal>, where
<replaceable>servicename</> is <literal>postgres</literal> (unless a <replaceable>servicename</> is <literal>postgres</literal> (unless a
different service name was selected at configure time with different service name was selected at configure time with
<literal>./configure --with-krb-srvnam=whatever</>). <literal>./configure --with-krb-srvnam=whatever</>).
<replaceable>hostname</> is the fully qualified domain name of the <replaceable>hostname</> is the fully qualified host name of the
server machine. The service principal's realm is the preferred realm server machine. The service principal's realm is the preferred realm
of the server machine. of the server machine.
</para> </para>
...@@ -610,7 +601,7 @@ local db1,db2,@demodbs all md5 ...@@ -610,7 +601,7 @@ local db1,db2,@demodbs all md5
<para> <para>
Client principals must have their <productname>PostgreSQL</> user Client principals must have their <productname>PostgreSQL</> user
name as their first component, for example name as their first component, for example
<replaceable>pgusername/otherstuff@realm</>. At present the realm of <literal>pgusername/otherstuff@realm</>. At present the realm of
the client is not checked by <productname>PostgreSQL</>; so if you the client is not checked by <productname>PostgreSQL</>; so if you
have cross-realm authentication enabled, then any principal in any have cross-realm authentication enabled, then any principal in any
realm that can communicate with yours will be accepted. realm that can communicate with yours will be accepted.
...@@ -619,9 +610,9 @@ local db1,db2,@demodbs all md5 ...@@ -619,9 +610,9 @@ local db1,db2,@demodbs all md5
<para> <para>
Make sure that your server key file is readable (and preferably only Make sure that your server key file is readable (and preferably only
readable) by the <productname>PostgreSQL</productname> server readable) by the <productname>PostgreSQL</productname> server
account (see <xref linkend="postgres-user">). The location of the account. (See also <xref linkend="postgres-user">). The location of the
key file is specified with the <varname>krb_server_keyfile</> run key file is specified with the <varname>krb_server_keyfile</> run-time
time configuration parameter. (See also <xref configuration parameter. (See also <xref
linkend="runtime-config">.) The default is <filename>/etc/srvtab</> linkend="runtime-config">.) The default is <filename>/etc/srvtab</>
if you are using Kerberos 4 and if you are using Kerberos 4 and
<filename>FILE:/usr/local/pgsql/etc/krb5.keytab</> (or whichever <filename>FILE:/usr/local/pgsql/etc/krb5.keytab</> (or whichever
...@@ -745,7 +736,7 @@ local db1,db2,@demodbs all md5 ...@@ -745,7 +736,7 @@ local db1,db2,@demodbs all md5
<productname>PostgreSQL</productname> checks whether that user is <productname>PostgreSQL</productname> checks whether that user is
allowed to connect as the database user he is requesting to connect allowed to connect as the database user he is requesting to connect
as. This is controlled by the ident map argument that follows the as. This is controlled by the ident map argument that follows the
<literal>ident</> keyword in the <filename>pg_hba.conf</filename> <literal>ident</> key word in the <filename>pg_hba.conf</filename>
file. There is a predefined ident map <literal>sameuser</literal>, file. There is a predefined ident map <literal>sameuser</literal>,
which allows any operating system user to connect as the database which allows any operating system user to connect as the database
user of the same name (if the latter exists). Other maps must be user of the same name (if the latter exists). Other maps must be
...@@ -753,10 +744,10 @@ local db1,db2,@demodbs all md5 ...@@ -753,10 +744,10 @@ local db1,db2,@demodbs all md5
</para> </para>
<para> <para>
<indexterm><primary>pg_ident.conf</primary></indexterm> Ident maps Ident maps
other than <literal>sameuser</literal> are defined in the file other than <literal>sameuser</literal> are defined in the file
<filename>pg_ident.conf</filename> in the data directory, which <filename>pg_ident.conf</filename><indexterm><primary>pg_ident.conf</primary></indexterm>
contains lines of the general form: in the data directory, which contains lines of the general form:
<synopsis> <synopsis>
<replaceable>map-name</> <replaceable>ident-username</> <replaceable>database-username</> <replaceable>map-name</> <replaceable>ident-username</> <replaceable>database-username</>
</synopsis> </synopsis>
...@@ -771,13 +762,11 @@ local db1,db2,@demodbs all md5 ...@@ -771,13 +762,11 @@ local db1,db2,@demodbs all md5
</para> </para>
<para> <para>
<indexterm>
<primary>SIGHUP</primary>
</indexterm>
The <filename>pg_ident.conf</filename> file is read on start-up and The <filename>pg_ident.conf</filename> file is read on start-up and
when the <application>postmaster</> receives a when the main server process (<command>postmaster</>) receives a
<systemitem>SIGHUP</systemitem> signal. If you edit the file on an <systemitem>SIGHUP</systemitem><indexterm><primary>SIGHUP</primary></indexterm>
active system, you will need to signal the <application>postmaster</> signal. If you edit the file on an
active system, you will need to signal the <command>postmaster</>
(using <literal>pg_ctl reload</> or <literal>kill -HUP</>) to make it (using <literal>pg_ctl reload</> or <literal>kill -HUP</>) to make it
re-read the file. re-read the file.
</para> </para>
...@@ -788,14 +777,14 @@ local db1,db2,@demodbs all md5 ...@@ -788,14 +777,14 @@ local db1,db2,@demodbs all md5
linkend="example-pg-hba.conf"> is shown in <xref linkend="example-pg-hba.conf"> is shown in <xref
linkend="example-pg-ident.conf">. In this example setup, anyone linkend="example-pg-ident.conf">. In this example setup, anyone
logged in to a machine on the 192.168 network that does not have the logged in to a machine on the 192.168 network that does not have the
Unix user name <systemitem>bryanh</>, <systemitem>ann</>, or Unix user name <literal>bryanh</>, <literal>ann</>, or
<systemitem>robert</> would not be granted access. Unix user <literal>robert</> would not be granted access. Unix user
<systemitem>robert</> would only be allowed access when he tries to <literal>robert</> would only be allowed access when he tries to
connect as <productname>PostgreSQL</> user <systemitem>bob</>, not connect as <productname>PostgreSQL</> user <literal>bob</>, not
as <systemitem>robert</> or anyone else. <systemitem>ann</> would as <literal>robert</> or anyone else. <literal>ann</> would
only be allowed to connect as <systemitem>ann</>. User only be allowed to connect as <literal>ann</>. User
<systemitem>bryanh</> would be allowed to connect as either <literal>bryanh</> would be allowed to connect as either
<systemitem>bryanh</> himself or as <systemitem>guest1</>. <literal>bryanh</> himself or as <literal>guest1</>.
</para> </para>
<example id="example-pg-ident.conf"> <example id="example-pg-ident.conf">
...@@ -818,12 +807,12 @@ omicron bryanh guest1 ...@@ -818,12 +807,12 @@ omicron bryanh guest1
<title>PAM Authentication</title> <title>PAM Authentication</title>
<para> <para>
This authentication type operates similarly to This authentication method operates similarly to
<firstterm>password</firstterm> except that it uses PAM (Pluggable <literal>password</literal> except that it uses PAM (Pluggable
Authentication Modules) as the authentication mechanism. The Authentication Modules) as the authentication mechanism. The
default PAM service name is <literal>postgresql</literal>. You can default PAM service name is <literal>postgresql</literal>. You can
optionally supply you own service name after the <literal>pam</> optionally supply you own service name after the <literal>pam</>
keyword in the file. For more information about PAM, please read key word in the file <filename>pg_hba.conf</filename>. For more information about PAM, please read
the <ulink the <ulink
url="http://www.kernel.org/pub/linux/libs/pam/"><productname>Linux-PAM</> url="http://www.kernel.org/pub/linux/libs/pam/"><productname>Linux-PAM</>
Page</ulink> and the <ulink Page</ulink> and the <ulink
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.116 2003/03/13 01:30:27 petere Exp $
--> -->
<chapter id="datatype"> <chapter id="datatype">
...@@ -22,8 +22,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -22,8 +22,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
</para> </para>
<para> <para>
<xref linkend="datatype-table"> shows all general-purpose data types <xref linkend="datatype-table"> shows all built-in general-purpose data types.
included in the standard distribution. Most of the alternative names Most of the alternative names
listed in the listed in the
<quote>Aliases</quote> column are the names used internally by <quote>Aliases</quote> column are the names used internally by
<productname>PostgreSQL</productname> for historical reasons. In <productname>PostgreSQL</productname> for historical reasons. In
...@@ -31,13 +31,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -31,13 +31,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
but they are not listed here. but they are not listed here.
</para> </para>
<para>
<table id="datatype-table"> <table id="datatype-table">
<title>Data Types</title> <title>Data Types</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row> <row>
<entry>Type Name</entry> <entry>Name</entry>
<entry>Aliases</entry> <entry>Aliases</entry>
<entry>Description</entry> <entry>Description</entry>
</row> </row>
...@@ -77,7 +76,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -77,7 +76,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
<row> <row>
<entry><type>box</type></entry> <entry><type>box</type></entry>
<entry></entry> <entry></entry>
<entry>rectangular box in 2D plane</entry> <entry>rectangular box in the plane</entry>
</row> </row>
<row> <row>
...@@ -107,7 +106,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -107,7 +106,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
<row> <row>
<entry><type>circle</type></entry> <entry><type>circle</type></entry>
<entry></entry> <entry></entry>
<entry>circle in 2D plane</entry> <entry>circle in the plane</entry>
</row> </row>
<row> <row>
...@@ -137,19 +136,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -137,19 +136,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
<row> <row>
<entry><type>interval(<replaceable>p</replaceable>)</type></entry> <entry><type>interval(<replaceable>p</replaceable>)</type></entry>
<entry></entry> <entry></entry>
<entry>general-use time span</entry> <entry>time span</entry>
</row> </row>
<row> <row>
<entry><type>line</type></entry> <entry><type>line</type></entry>
<entry></entry> <entry></entry>
<entry>infinite line in 2D plane (not implemented)</entry> <entry>infinite line in the plane (not fully implemented)</entry>
</row> </row>
<row> <row>
<entry><type>lseg</type></entry> <entry><type>lseg</type></entry>
<entry></entry> <entry></entry>
<entry>line segment in 2D plane</entry> <entry>line segment in the plane</entry>
</row> </row>
<row> <row>
...@@ -175,19 +174,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -175,19 +174,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
<row> <row>
<entry><type>path</type></entry> <entry><type>path</type></entry>
<entry></entry> <entry></entry>
<entry>open and closed geometric path in 2D plane</entry> <entry>open and closed geometric path in the plane</entry>
</row> </row>
<row> <row>
<entry><type>point</type></entry> <entry><type>point</type></entry>
<entry></entry> <entry></entry>
<entry>geometric point in 2D plane</entry> <entry>geometric point in the plane</entry>
</row> </row>
<row> <row>
<entry><type>polygon</type></entry> <entry><type>polygon</type></entry>
<entry></entry> <entry></entry>
<entry>closed geometric path in 2D plane</entry> <entry>closed geometric path in the plane</entry>
</row> </row>
<row> <row>
...@@ -240,7 +239,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -240,7 +239,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
</para>
<note> <note>
<title>Compatibility</title> <title>Compatibility</title>
...@@ -264,11 +262,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -264,11 +262,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
to <productname>PostgreSQL</productname>, such as open and closed to <productname>PostgreSQL</productname>, such as open and closed
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
base types (e.g., integers and floating-point numbers) do some
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 accuracy when compared to
the original input. the original input.
</para> </para>
...@@ -277,7 +272,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -277,7 +272,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
addition and multiplication) do not perform run-time error-checking in the addition and multiplication) do not perform run-time error-checking in the
interests of improving execution speed. interests of improving execution speed.
On some systems, for example, the numeric operators for some data types may On some systems, for example, the numeric operators for some data types may
silently underflow or overflow. silently cause underflow or overflow.
</para> </para>
<sect1 id="datatype-numeric"> <sect1 id="datatype-numeric">
...@@ -358,8 +353,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -358,8 +353,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
<tgroup cols="4"> <tgroup cols="4">
<thead> <thead>
<row> <row>
<entry>Type name</entry> <entry>Name</entry>
<entry>Storage size</entry> <entry>Storage Size</entry>
<entry>Description</entry> <entry>Description</entry>
<entry>Range</entry> <entry>Range</entry>
</row> </row>
...@@ -369,19 +364,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -369,19 +364,19 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
<row> <row>
<entry><type>smallint</></entry> <entry><type>smallint</></entry>
<entry>2 bytes</entry> <entry>2 bytes</entry>
<entry>small range fixed-precision</entry> <entry>small-range integer</entry>
<entry>-32768 to +32767</entry> <entry>-32768 to +32767</entry>
</row> </row>
<row> <row>
<entry><type>integer</></entry> <entry><type>integer</></entry>
<entry>4 bytes</entry> <entry>4 bytes</entry>
<entry>usual choice for fixed-precision</entry> <entry>usual choice for integer</entry>
<entry>-2147483648 to +2147483647</entry> <entry>-2147483648 to +2147483647</entry>
</row> </row>
<row> <row>
<entry><type>bigint</></entry> <entry><type>bigint</></entry>
<entry>8 bytes</entry> <entry>8 bytes</entry>
<entry>large range fixed-precision</entry> <entry>large-range integer</entry>
<entry>-9223372036854775808 to 9223372036854775807</entry> <entry>-9223372036854775808 to 9223372036854775807</entry>
</row> </row>
...@@ -437,10 +432,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -437,10 +432,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
</para> </para>
<sect2 id="datatype-int"> <sect2 id="datatype-int">
<title>The Integer Types</title> <title>Integer Types</title>
<para> <para>
The types <type>smallint</type>, <type>integer</type>, The types <type>smallint</type>, <type>integer</type>, and
<type>bigint</type> store whole numbers, that is, numbers without <type>bigint</type> store whole numbers, that is, numbers without
fractional components, of various ranges. Attempts to store fractional components, of various ranges. Attempts to store
values outside of the allowed range will result in an error. values outside of the allowed range will result in an error.
...@@ -501,7 +496,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m ...@@ -501,7 +496,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.115 2003/02/19 04:06:27 m
<title>Arbitrary Precision Numbers</title> <title>Arbitrary Precision Numbers</title>
<para> <para>
The type <type>numeric</type> can store numbers with up to 1,000 The type <type>numeric</type> can store numbers with up to 1000
digits of precision and perform calculations exactly. It is digits of precision and perform calculations exactly. It is
especially recommended for storing monetary amounts and other especially recommended for storing monetary amounts and other
quantities where exactness is required. However, the quantities where exactness is required. However, the
...@@ -625,7 +620,7 @@ NUMERIC ...@@ -625,7 +620,7 @@ NUMERIC
</sect2> </sect2>
<sect2 id="datatype-serial"> <sect2 id="datatype-serial">
<title>The Serial Types</title> <title>Serial Types</title>
<indexterm zone="datatype-serial"> <indexterm zone="datatype-serial">
<primary>serial</primary> <primary>serial</primary>
...@@ -654,7 +649,8 @@ NUMERIC ...@@ -654,7 +649,8 @@ NUMERIC
</indexterm> </indexterm>
<para> <para>
The <type>serial</type> data type is not a true type, but merely The data types <type>serial</type> and <type>bigserial</type>
are not true types, but merely
a notational convenience for setting up identifier columns a notational convenience for setting up identifier columns
(similar to the <literal>AUTO_INCREMENT</literal> property (similar to the <literal>AUTO_INCREMENT</literal> property
supported by some other databases). In the current supported by some other databases). In the current
...@@ -684,6 +680,16 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( ...@@ -684,6 +680,16 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
not automatic. not automatic.
</para> </para>
<note>
<para>
Prior to <productname>PostgreSQL</productname> 7.3, <type>serial</type>
implied <literal>UNIQUE</literal>. This is no longer automatic. If
you wish a serial column to be in a unique constraint or a
primary key, it must now be specified, same as with
any other data type.
</para>
</note>
<para> <para>
To use a <type>serial</type> column to insert the next value of To use a <type>serial</type> column to insert the next value of
the sequence into the table, specify that the <type>serial</type> the sequence into the table, specify that the <type>serial</type>
...@@ -705,7 +711,7 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( ...@@ -705,7 +711,7 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
<para> <para>
The sequence created by a <type>serial</type> type is The sequence created by a <type>serial</type> type is
automatically dropped when the owning column is dropped, and automatically dropped when the owning column is dropped and
cannot be dropped otherwise. (This was not true in cannot be dropped otherwise. (This was not true in
<productname>PostgreSQL</productname> releases before 7.3. Note <productname>PostgreSQL</productname> releases before 7.3. Note
that this automatic drop linkage will not occur for a sequence that this automatic drop linkage will not occur for a sequence
...@@ -714,49 +720,32 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( ...@@ -714,49 +720,32 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
dependency link.) Furthermore, this dependency between sequence dependency link.) Furthermore, this dependency between sequence
and column is made only for the <type>serial</> column itself; if and column is made only for the <type>serial</> column itself; if
any other columns reference the sequence (perhaps by manually any other columns reference the sequence (perhaps by manually
calling the <function>nextval()</>) function), they may be broken calling the <function>nextval</>) function), they may be broken
if the sequence is removed. Using <type>serial</> columns in if the sequence is removed. Using <type>serial</> columns in
fashion is considered bad form. fashion is considered bad form.
</para> </para>
<note>
<para>
Prior to <productname>PostgreSQL</> 7.3, <type>serial</type>
implied <literal>UNIQUE</literal>. This is no longer automatic.
If you wish a serial column to be <literal>UNIQUE</literal> or a
<literal>PRIMARY KEY</literal> it must now be specified, just as
with any other data type.
</para>
</note>
</sect2> </sect2>
</sect1> </sect1>
<sect1 id="datatype-money"> <sect1 id="datatype-money">
<title>Monetary Type</title> <title>Monetary Types</title>
<note> <note>
<title>Note</title>
<para> <para>
The <type>money</type> type is deprecated. Use The <type>money</type> type is deprecated. Use
<type>numeric</type> or <type>decimal</type> instead, in <type>numeric</type> or <type>decimal</type> instead, in
combination with the <function>to_char</function> function. The combination with the <function>to_char</function> function.
money type may become a locale-aware layer over the
<type>numeric</type> type in a future release.
</para> </para>
</note> </note>
<para> <para>
The <type>money</type> type stores a currency amount with fixed The <type>money</type> type stores a currency amount with a fixed
decimal point representation; see <xref fractional precision; see <xref
linkend="datatype-money-table">. The output format is linkend="datatype-money-table">.
locale-specific.
</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 generally in the latter form but depends on the locale.
</para> </para>
<table id="datatype-money-table"> <table id="datatype-money-table">
...@@ -764,8 +753,8 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( ...@@ -764,8 +753,8 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
<tgroup cols="4"> <tgroup cols="4">
<thead> <thead>
<row> <row>
<entry>Type Name</entry> <entry>Name</entry>
<entry>Storage</entry> <entry>Storage Size</entry>
<entry>Description</entry> <entry>Description</entry>
<entry>Range</entry> <entry>Range</entry>
</row> </row>
...@@ -806,7 +795,7 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( ...@@ -806,7 +795,7 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
<tgroup cols="2"> <tgroup cols="2">
<thead> <thead>
<row> <row>
<entry>Type name</entry> <entry>Name</entry>
<entry>Description</entry> <entry>Description</entry>
</row> </row>
</thead> </thead>
...@@ -850,7 +839,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( ...@@ -850,7 +839,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
string. string.
</para> </para>
<note>
<para> <para>
If one explicitly casts a value to <type>character If one explicitly casts a value to <type>character
varying(<replaceable>n</>)</type> or varying(<replaceable>n</>)</type> or
...@@ -859,7 +847,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( ...@@ -859,7 +847,6 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
raising an error. (This too is required by the raising an error. (This too is required by the
<acronym>SQL</acronym> standard.) <acronym>SQL</acronym> standard.)
</para> </para>
</note>
<note> <note>
<para> <para>
...@@ -881,13 +868,11 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> ( ...@@ -881,13 +868,11 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
</para> </para>
<para> <para>
In addition, <productname>PostgreSQL</productname> supports the In addition, <productname>PostgreSQL</productname> provides the
more general <type>text</type> type, which stores strings of any <type>text</type> type, which stores strings of any
length. Unlike <type>character varying</type>, <type>text</type> length. Although the type <type>text</type> is not in the
does not require an explicit declared upper limit on the size of <acronym>SQL</acronym> standard, several other SQL database products
the string. Although the type <type>text</type> is not in the have it as well.
<acronym>SQL</acronym> standard, many other RDBMS packages have it
as well.
</para> </para>
<para> <para>
...@@ -963,8 +948,8 @@ SELECT b, char_length(b) FROM test2; ...@@ -963,8 +948,8 @@ SELECT b, char_length(b) FROM test2;
There are two other fixed-length character types in There are two other fixed-length character types in
<productname>PostgreSQL</productname>, shown in <xref <productname>PostgreSQL</productname>, shown in <xref
linkend="datatype-character-special-table">. The <type>name</type> linkend="datatype-character-special-table">. The <type>name</type>
type exists <emphasis>only</emphasis> for storage of internal type exists <emphasis>only</emphasis> for storage of identifiers
catalog names and is not intended for use by the general user. Its in the internal system catalogs and is not intended for use by the general user. Its
length is currently defined as 64 bytes (63 usable characters plus length is currently defined as 64 bytes (63 usable characters plus
terminator) but should be referenced using the constant terminator) but should be referenced using the constant
<symbol>NAMEDATALEN</symbol>. The length is set at compile time (and <symbol>NAMEDATALEN</symbol>. The length is set at compile time (and
...@@ -976,12 +961,12 @@ SELECT b, char_length(b) FROM test2; ...@@ -976,12 +961,12 @@ SELECT b, char_length(b) FROM test2;
</para> </para>
<table id="datatype-character-special-table"> <table id="datatype-character-special-table">
<title>Specialty Character Types</title> <title>Special Character Types</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row> <row>
<entry>Type Name</entry> <entry>Name</entry>
<entry>Storage</entry> <entry>Storage Size</entry>
<entry>Description</entry> <entry>Description</entry>
</row> </row>
</thead> </thead>
...@@ -989,12 +974,12 @@ SELECT b, char_length(b) FROM test2; ...@@ -989,12 +974,12 @@ SELECT b, char_length(b) FROM test2;
<row> <row>
<entry><type>"char"</type></entry> <entry><type>"char"</type></entry>
<entry>1 byte</entry> <entry>1 byte</entry>
<entry>single character internal type</entry> <entry>single-character internal type</entry>
</row> </row>
<row> <row>
<entry><type>name</type></entry> <entry><type>name</type></entry>
<entry>64 bytes</entry> <entry>64 bytes</entry>
<entry>sixty-three character internal type</entry> <entry>internal type for object names</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -1003,19 +988,19 @@ SELECT b, char_length(b) FROM test2; ...@@ -1003,19 +988,19 @@ SELECT b, char_length(b) FROM test2;
</sect1> </sect1>
<sect1 id="datatype-binary"> <sect1 id="datatype-binary">
<title>Binary Strings</title> <title>Binary Data Types</title>
<para> <para>
The <type>bytea</type> data type allows storage of binary strings; The <type>bytea</type> data type allows storage of binary strings;
see <xref linkend="datatype-binary-table">. see <xref linkend="datatype-binary-table">.
</para> </para>
<table id="datatype-binary-table"> <table id="datatype-binary-table">
<title>Binary String Types</title> <title>Binary Data Types</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row> <row>
<entry>Type Name</entry> <entry>Name</entry>
<entry>Storage</entry> <entry>Storage Size</entry>
<entry>Description</entry> <entry>Description</entry>
</row> </row>
</thead> </thead>
...@@ -1023,8 +1008,7 @@ SELECT b, char_length(b) FROM test2; ...@@ -1023,8 +1008,7 @@ SELECT b, char_length(b) FROM test2;
<row> <row>
<entry><type>bytea</type></entry> <entry><type>bytea</type></entry>
<entry>4 bytes plus the actual binary string</entry> <entry>4 bytes plus the actual binary string</entry>
<entry>Variable (not specifically limited) <entry>variable-length binary string</entry>
length binary string</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -1034,7 +1018,7 @@ SELECT b, char_length(b) FROM test2; ...@@ -1034,7 +1018,7 @@ SELECT b, char_length(b) FROM test2;
A binary string is a sequence of octets (or bytes). Binary A binary string is a sequence of octets (or bytes). Binary
strings are distinguished from characters strings by two strings are distinguished from characters strings by two
characteristics: First, binary strings specifically allow storing characteristics: First, binary strings specifically allow storing
octets of zero value and other <quote>non-printable</quote> octets of value zero and other <quote>non-printable</quote>
octets. Second, operations on binary strings process the actual octets. Second, operations on binary strings process the actual
bytes, whereas the encoding and processing of character strings bytes, whereas the encoding and processing of character strings
depends on locale settings. depends on locale settings.
...@@ -1058,9 +1042,9 @@ SELECT b, char_length(b) FROM test2; ...@@ -1058,9 +1042,9 @@ SELECT b, char_length(b) FROM test2;
<row> <row>
<entry>Decimal Octet Value</entry> <entry>Decimal Octet Value</entry>
<entry>Description</entry> <entry>Description</entry>
<entry>Input Escaped Representation</entry> <entry>Escaped Input Representation</entry>
<entry>Example</entry> <entry>Example</entry>
<entry>Printed Result</entry> <entry>Output Representation</entry>
</row> </row>
</thead> </thead>
...@@ -1096,13 +1080,37 @@ SELECT b, char_length(b) FROM test2; ...@@ -1096,13 +1080,37 @@ SELECT b, char_length(b) FROM test2;
<para> <para>
Note that the result in each of the examples in <xref linkend="datatype-binary-sqlesc"> was exactly one Note that the result in each of the examples in <xref linkend="datatype-binary-sqlesc"> was exactly one
octet in length, even though the output representation of the zero octet in length, even though the output representation of the zero
octet and backslash are more than one character. <type>Bytea</type> octet and backslash are more than one character.
output octets are also escaped. In general, each </para>
<quote>non-printable</quote> octet decimal value is converted into
its equivalent three digit octal value, and preceded by one backslash. <para>
The reason that you have to write so many backslashes, as shown in
<xref linkend="datatype-binary-sqlesc">, is that an input string
written as a string literal must pass through two parse phases in
the <productname>PostgreSQL</productname> server. The first
backslash of each pair is interpreted as an escape character by
the string-literal parser and is therefore consumed, leaving the
second backslash of the pair. The remaining backslash is then
recognized by the <type>bytea</type> input function as starting
either a three digit octal value or escaping another backslash.
For example, a string literal passed to the server as
<literal>'\\001'</literal> becomes <literal>\001</literal> after
passing through the string-literal parser. The
<literal>\001</literal> is then sent to the <type>bytea</type>
input function, where it is converted to a single octet with a
decimal value of 1. Note that the apostrophe character is not
treated specially by <type>bytea</type>, so it follows the normal
rules for string literals. (See also <xref
linkend="sql-syntax-strings">.)
</para>
<para>
<type>Bytea</type> octets are also escaped in the output. In general, each
<quote>non-printable</quote> octet is converted into
its equivalent three-digit octal value and preceded by one backslash.
Most <quote>printable</quote> octets are represented by their standard Most <quote>printable</quote> octets are represented by their standard
representation in the client character set. The octet with decimal representation in the client character set. The octet with decimal
value 92 (backslash) has a special alternate output representation. value 92 (backslash) has a special alternative output representation.
Details are in <xref linkend="datatype-binary-resesc">. Details are in <xref linkend="datatype-binary-resesc">.
</para> </para>
...@@ -1113,9 +1121,9 @@ SELECT b, char_length(b) FROM test2; ...@@ -1113,9 +1121,9 @@ SELECT b, char_length(b) FROM test2;
<row> <row>
<entry>Decimal Octet Value</entry> <entry>Decimal Octet Value</entry>
<entry>Description</entry> <entry>Description</entry>
<entry>Output Escaped Representation</entry> <entry>Escaped Output Representation</entry>
<entry>Example</entry> <entry>Example</entry>
<entry>Printed Result</entry> <entry>Output Result</entry>
</row> </row>
</thead> </thead>
...@@ -1132,7 +1140,7 @@ SELECT b, char_length(b) FROM test2; ...@@ -1132,7 +1140,7 @@ SELECT b, char_length(b) FROM test2;
<row> <row>
<entry>0 to 31 and 127 to 255</entry> <entry>0 to 31 and 127 to 255</entry>
<entry><quote>non-printable</quote> octets</entry> <entry><quote>non-printable</quote> octets</entry>
<entry><literal>\### (octal value)</literal></entry> <entry><literal>\<replaceable>xxx</></literal> (octal value)</entry>
<entry><literal>SELECT '\\001'::bytea;</literal></entry> <entry><literal>SELECT '\\001'::bytea;</literal></entry>
<entry><literal>\001</literal></entry> <entry><literal>\001</literal></entry>
</row> </row>
...@@ -1149,60 +1157,12 @@ SELECT b, char_length(b) FROM test2; ...@@ -1149,60 +1157,12 @@ SELECT b, char_length(b) FROM test2;
</tgroup> </tgroup>
</table> </table>
<para>
To use the <type>bytea</type> escaped octet notation, string
literals (input strings) must contain two backslashes because they
must pass through two parsers in the <productname>PostgreSQL</>
server. The first backslash is interpreted as an escape character
by the string-literal parser, and therefore is consumed, leaving
the characters that follow. The remaining backslash is recognized
by the <type>bytea</type> input function as the prefix of a three
digit octal value. For example, a string literal passed to the
backend as <literal>'\\001'</literal> becomes
<literal>'\001'</literal> after passing through the string-literal
parser. The <literal>'\001'</literal> is then sent to the
<type>bytea</type> input function, where it is converted to a
single octet with a decimal value of 1.
</para>
<para>
For a similar reason, a backslash must be input as
<literal>'\\\\'</literal> (or <literal>'\\134'</literal>). The first
and third backslashes are interpreted as escape characters by the
string-literal parser, and therefore are consumed, leaving two
backslashes in the string passed to the <type>bytea</type> input function,
which interprets them as representing a single backslash.
For example, a string literal passed to the
server as <literal>'\\\\'</literal> becomes <literal>'\\'</literal>
after passing through the string-literal parser. The
<literal>'\\'</literal> is then sent to the <type>bytea</type> input
function, where it is converted to a single octet with a decimal
value of 92.
</para>
<para>
A single quote is a bit different in that it must be input as
<literal>'\''</literal> (or <literal>'\\047'</literal>),
<emphasis>not</emphasis> as <literal>'\\''</literal>. This is because,
while the literal parser interprets the single quote as a special
character, and will consume the single backslash, the
<type>bytea</type> input function does <emphasis>not</emphasis>
recognize a single quote as a special octet. Therefore a string
literal passed to the backend as <literal>'\''</literal> becomes
<literal>'''</literal> after passing through the string-literal
parser. The <literal>'''</literal> is then sent to the
<type>bytea</type> input function, where it is retains its single
octet decimal value of 39.
</para>
<para> <para>
Depending on the front end to <productname>PostgreSQL</> you use, Depending on the front end to <productname>PostgreSQL</> you use,
you may have additional work to do in terms of escaping and you may have additional work to do in terms of escaping and
unescaping <type>bytea</type> strings. For example, you may also unescaping <type>bytea</type> strings. For example, you may also
have to escape line feeds and carriage returns if your interface have to escape line feeds and carriage returns if your interface
automatically translates these. Or you may have to double up on automatically translates these.
backslashes if the parser for your language or choice also treats
them as an escape character.
</para> </para>
<para> <para>
...@@ -1229,59 +1189,59 @@ SELECT b, char_length(b) FROM test2; ...@@ -1229,59 +1189,59 @@ SELECT b, char_length(b) FROM test2;
<tgroup cols="6"> <tgroup cols="6">
<thead> <thead>
<row> <row>
<entry>Type</entry> <entry>Name</entry>
<entry>Storage Size</entry>
<entry>Description</entry> <entry>Description</entry>
<entry>Storage</entry> <entry>Low Value</entry>
<entry>Earliest</entry> <entry>High Value</entry>
<entry>Latest</entry>
<entry>Resolution</entry> <entry>Resolution</entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry><type>timestamp [ (<replaceable>p</replaceable>) ] [ without time zone ]</type></entry> <entry><type>timestamp [ (<replaceable>p</replaceable>) ] [ without time zone ]</type></entry>
<entry>both date and time</entry>
<entry>8 bytes</entry> <entry>8 bytes</entry>
<entry>both date and time</entry>
<entry>4713 BC</entry> <entry>4713 BC</entry>
<entry>AD 5874897</entry> <entry>AD 5874897</entry>
<entry>1 microsecond / 14 digits</entry> <entry>1 microsecond / 14 digits</entry>
</row> </row>
<row> <row>
<entry><type>timestamp [ (<replaceable>p</replaceable>) ] with time zone</type></entry> <entry><type>timestamp [ (<replaceable>p</replaceable>) ] with time zone</type></entry>
<entry>both date and time</entry>
<entry>8 bytes</entry> <entry>8 bytes</entry>
<entry>both date and time, with time zone</entry>
<entry>4713 BC</entry> <entry>4713 BC</entry>
<entry>AD 5874897</entry> <entry>AD 5874897</entry>
<entry>1 microsecond / 14 digits</entry> <entry>1 microsecond / 14 digits</entry>
</row> </row>
<row> <row>
<entry><type>interval [ (<replaceable>p</replaceable>) ]</type></entry> <entry><type>interval [ (<replaceable>p</replaceable>) ]</type></entry>
<entry>time intervals</entry>
<entry>12 bytes</entry> <entry>12 bytes</entry>
<entry>time intervals</entry>
<entry>-178000000 years</entry> <entry>-178000000 years</entry>
<entry>178000000 years</entry> <entry>178000000 years</entry>
<entry>1 microsecond</entry> <entry>1 microsecond</entry>
</row> </row>
<row> <row>
<entry><type>date</type></entry> <entry><type>date</type></entry>
<entry>dates only</entry>
<entry>4 bytes</entry> <entry>4 bytes</entry>
<entry>dates only</entry>
<entry>4713 BC</entry> <entry>4713 BC</entry>
<entry>32767 AD</entry> <entry>32767 AD</entry>
<entry>1 day</entry> <entry>1 day</entry>
</row> </row>
<row> <row>
<entry><type>time [ (<replaceable>p</replaceable>) ] [ without time zone ]</type></entry> <entry><type>time [ (<replaceable>p</replaceable>) ] [ without time zone ]</type></entry>
<entry>times of day only</entry>
<entry>8 bytes</entry> <entry>8 bytes</entry>
<entry>times of day only</entry>
<entry>00:00:00.00</entry> <entry>00:00:00.00</entry>
<entry>23:59:59.99</entry> <entry>23:59:59.99</entry>
<entry>1 microsecond</entry> <entry>1 microsecond</entry>
</row> </row>
<row> <row>
<entry><type>time [ (<replaceable>p</replaceable>) ] with time zone</type></entry> <entry><type>time [ (<replaceable>p</replaceable>) ] with time zone</type></entry>
<entry>times of day only</entry>
<entry>12 bytes</entry> <entry>12 bytes</entry>
<entry>times of day only, with time zone</entry>
<entry>00:00:00.00+12</entry> <entry>00:00:00.00+12</entry>
<entry>23:59:59.99-12</entry> <entry>23:59:59.99-12</entry>
<entry>1 microsecond</entry> <entry>1 microsecond</entry>
...@@ -1304,8 +1264,8 @@ SELECT b, char_length(b) FROM test2; ...@@ -1304,8 +1264,8 @@ SELECT b, char_length(b) FROM test2;
<para> <para>
When <type>timestamp</> values are stored as double precision floating-point When <type>timestamp</> values are stored as double precision floating-point
numbers (currently the default), the effective limit of precision numbers (currently the default), the effective limit of precision
may be less than 6, since timestamp values are stored as seconds may be less than 6. Timestamp values are stored as seconds
since 2000-01-01. Microsecond precision is achieved for dates within since 2000-01-01, and microsecond precision is achieved for dates within
a few years of 2000-01-01, but the precision degrades for dates further a few years of 2000-01-01, but the precision degrades for dates further
away. When timestamps are stored as eight-byte integers (a compile-time away. When timestamps are stored as eight-byte integers (a compile-time
option), microsecond precision is available over the full range of option), microsecond precision is available over the full range of
...@@ -1314,34 +1274,26 @@ SELECT b, char_length(b) FROM test2; ...@@ -1314,34 +1274,26 @@ SELECT b, char_length(b) FROM test2;
</para> </para>
</note> </note>
<note>
<para>
Prior to <productname>PostgreSQL</productname> 7.3, writing just
<type>timestamp</type> was equivalent to <type>timestamp with
time zone</type>. This was changed for SQL compliance.
</para>
</note>
<para> <para>
For the <type>time</type> types, the allowed range of For the <type>time</type> types, the allowed range of
<replaceable>p</replaceable> is from 0 to 6 when eight-byte integer <replaceable>p</replaceable> is from 0 to 6 when eight-byte integer
storage is used, or from 0 to 10 when floating-point storage is used. storage is used, or from 0 to 10 when floating-point storage is used.
</para> </para>
<para>
Time zones, and time-zone conventions, are influenced by
political decisions, not just earth geometry. Time zones around the
world became somewhat standardized during the 1900's,
but continue to be prone to arbitrary changes.
<productname>PostgreSQL</productname> uses your operating
system's underlying features to provide output time-zone
support, and these systems usually contain information for only
the time period 1902 through 2038 (corresponding to the full
range of conventional Unix system time).
<type>timestamp with time zone</type> and <type>time with time
zone</type> will use time zone
information only within that year range, and assume that times
outside that range are in <acronym>UTC</acronym>.
</para>
<para> <para>
The type <type>time with time zone</type> is defined by the SQL The type <type>time with time zone</type> is defined by the SQL
standard, but the definition exhibits properties which lead to standard, but the definition exhibits properties which lead to
questionable usefulness. In most cases, a combination of questionable usefulness. In most cases, a combination of
<type>date</type>, <type>time</type>, <type>timestamp without time <type>date</type>, <type>time</type>, <type>timestamp without time
zone</type> and <type>timestamp with time zone</type> should zone</type>, and <type>timestamp with time zone</type> should
provide a complete range of date/time functionality required by provide a complete range of date/time functionality required by
any application. any application.
</para> </para>
...@@ -1360,22 +1312,22 @@ SELECT b, char_length(b) FROM test2; ...@@ -1360,22 +1312,22 @@ SELECT b, char_length(b) FROM test2;
<para> <para>
Date and time input is accepted in almost any reasonable format, including Date and time input is accepted in almost any reasonable format, including
<acronym>ISO 8601</acronym>, <acronym>SQL</acronym>-compatible, ISO 8601, <acronym>SQL</acronym>-compatible,
traditional <productname>PostgreSQL</productname>, and others. traditional <productname>POSTGRES</productname>, and others.
For some formats, ordering of month and day in date input can be For some formats, ordering of month and day in date input can be
ambiguous and there is support for specifying the expected ambiguous and there is support for specifying the expected
ordering of these fields. ordering of these fields.
The command The command
<literal>SET DateStyle TO 'US'</literal> <literal>SET datestyle TO 'US'</literal>
or <literal>SET DateStyle TO 'NonEuropean'</literal> or <literal>SET datestyle TO 'NonEuropean'</literal>
specifies the variant <quote>month before day</quote>, the command specifies the variant <quote>month before day</quote>, the command
<literal>SET DateStyle TO 'European'</literal> sets the variant <literal>SET datestyle TO 'European'</literal> sets the variant
<quote>day before month</quote>. <quote>day before month</quote>.
</para> </para>
<para> <para>
<productname>PostgreSQL</productname> is more flexible in <productname>PostgreSQL</productname> is more flexible in
handling date/time than the handling date/time input than the
<acronym>SQL</acronym> standard requires. <acronym>SQL</acronym> standard requires.
See <xref linkend="datetime-appendix"> See <xref linkend="datetime-appendix">
for the exact parsing rules of date/time input and for the for the exact parsing rules of date/time input and for the
...@@ -1393,11 +1345,12 @@ SELECT b, char_length(b) FROM test2; ...@@ -1393,11 +1345,12 @@ SELECT b, char_length(b) FROM test2;
<replaceable>type</replaceable> [ (<replaceable>p</replaceable>) ] '<replaceable>value</replaceable>' <replaceable>type</replaceable> [ (<replaceable>p</replaceable>) ] '<replaceable>value</replaceable>'
</synopsis> </synopsis>
where <replaceable>p</replaceable> in the optional precision where <replaceable>p</replaceable> in the optional precision
specification is an integer corresponding to the specification is an integer corresponding to the number of
number of fractional digits in the seconds field. Precision can fractional digits in the seconds field. Precision can be
be specified specified for <type>time</type>, <type>timestamp</type>, and
for <type>time</type>, <type>timestamp</type>, and <type>interval</type> types. The allowed values are mentioned
<type>interval</type> types. above. If no precision is specified in a constant specification,
it defaults to the precision of the literal value.
</para> </para>
<sect3> <sect3>
...@@ -1433,23 +1386,19 @@ SELECT b, char_length(b) FROM test2; ...@@ -1433,23 +1386,19 @@ SELECT b, char_length(b) FROM test2;
</row> </row>
<row> <row>
<entry>1/8/1999</entry> <entry>1/8/1999</entry>
<entry>U.S.; read as August 1 in European mode</entry> <entry>ambiguous (January 8 in U.S. mode; August 1 in European mode)</entry>
</row>
<row>
<entry>8/1/1999</entry>
<entry>European; read as August 1 in U.S. mode</entry>
</row> </row>
<row> <row>
<entry>1/18/1999</entry> <entry>1/18/1999</entry>
<entry>U.S.; read as January 18 in any mode</entry> <entry>U.S. notation; January 18 in any mode</entry>
</row> </row>
<row> <row>
<entry>19990108</entry> <entry>19990108</entry>
<entry>ISO-8601 year, month, day</entry> <entry>ISO-8601; year, month, day</entry>
</row> </row>
<row> <row>
<entry>990108</entry> <entry>990108</entry>
<entry>ISO-8601 year, month, day</entry> <entry>ISO-8601; year, month, day</entry>
</row> </row>
<row> <row>
<entry>1999.008</entry> <entry>1999.008</entry>
...@@ -1497,12 +1446,10 @@ SELECT b, char_length(b) FROM test2; ...@@ -1497,12 +1446,10 @@ SELECT b, char_length(b) FROM test2;
</para> </para>
<para> <para>
Valid input for these types consists of a time of day followed by an Valid input for these types consists of a time of day followed
optional time zone. (See <xref linkend="datatype-datetime-time-table">.) by an optional time zone. (See <xref
The optional precision linkend="datatype-datetime-time-table">.) If a time zone is
<replaceable>p</replaceable> should be between 0 and 6, and specified in the input for <type>time without time zone</type>,
defaults to the precision of the input time literal. If a time zone
is specified in the input for <type>time without time zone</type>,
it is silently ignored. it is silently ignored.
</para> </para>
...@@ -1571,7 +1518,7 @@ SELECT b, char_length(b) FROM test2; ...@@ -1571,7 +1518,7 @@ SELECT b, char_length(b) FROM test2;
</sect3> </sect3>
<sect3> <sect3>
<title>Time stamps</title> <title>Time Stamps</title>
<indexterm> <indexterm>
<primary>timestamp</primary> <primary>timestamp</primary>
...@@ -1588,22 +1535,6 @@ SELECT b, char_length(b) FROM test2; ...@@ -1588,22 +1535,6 @@ SELECT b, char_length(b) FROM test2;
<secondary>data type</secondary> <secondary>data type</secondary>
</indexterm> </indexterm>
<para>
The time stamp types are <type>timestamp [
(<replaceable>p</replaceable>) ] without time zone</type> and
<type>timestamp [ (<replaceable>p</replaceable>) ] with time
zone</type>. Writing just <type>timestamp</type> is equivalent to
<type>timestamp without time zone</type>.
</para>
<note>
<para>
Prior to <productname>PostgreSQL</productname> 7.3, writing just
<type>timestamp</type> was equivalent to <type>timestamp with time
zone</type>. This was changed for SQL spec compliance.
</para>
</note>
<para> <para>
Valid input for the time stamp types consists of a concatenation Valid input for the time stamp types consists of a concatenation
of a date and a time, followed by an optional of a date and a time, followed by an optional
...@@ -1629,13 +1560,7 @@ January 8 04:05:06 1999 PST ...@@ -1629,13 +1560,7 @@ January 8 04:05:06 1999 PST
</para> </para>
<para> <para>
The optional precision For <type>timestamp [without time zone]</type>, any explicit time
<replaceable>p</replaceable> should be between 0 and 6, and
defaults to the precision of the input <type>timestamp</type> literal.
</para>
<para>
For <type>timestamp without time zone</type>, any explicit time
zone specified in the input is silently ignored. That is, the zone specified in the input is silently ignored. That is, the
resulting date/time value is derived from the explicit date/time resulting date/time value is derived from the explicit date/time
fields in the input value, and is not adjusted for time zone. fields in the input value, and is not adjusted for time zone.
...@@ -1643,20 +1568,22 @@ January 8 04:05:06 1999 PST ...@@ -1643,20 +1568,22 @@ January 8 04:05:06 1999 PST
<para> <para>
For <type>timestamp with time zone</type>, the internally stored For <type>timestamp with time zone</type>, the internally stored
value is always in UTC (GMT). An input value that has an explicit value is always in UTC (Universal
Coordinated Time, traditionally known as Greenwich Mean Time,
<acronym>GMT</>). An input value that has an explicit
time zone specified is converted to UTC using the appropriate offset time zone specified is converted to UTC using the appropriate offset
for that time zone. If no time zone is stated in the input string, for that time zone. If no time zone is stated in the input string,
then it is assumed to be in the time zone indicated by the system's then it is assumed to be in the time zone indicated by the system's
<varname>TimeZone</> parameter, and is converted to UTC using the <varname>timezone</> parameter, and is converted to UTC using the
offset for the <varname>TimeZone</> zone. offset for the <varname>timezone</> zone.
</para> </para>
<para> <para>
When a <type>timestamp with time When a <type>timestamp with time
zone</type> value is output, it is always converted from UTC to the zone</type> value is output, it is always converted from UTC to the
current <varname>TimeZone</> zone, and displayed as local time in that current <varname>timezone</> zone, and displayed as local time in that
zone. To see the time in another time zone, either change zone. To see the time in another time zone, either change
<varname>TimeZone</> or use the <literal>AT TIME ZONE</> construct <varname>timezone</> or use the <literal>AT TIME ZONE</> construct
(see <xref linkend="functions-datetime-zoneconvert">). (see <xref linkend="functions-datetime-zoneconvert">).
</para> </para>
...@@ -1664,7 +1591,7 @@ January 8 04:05:06 1999 PST ...@@ -1664,7 +1591,7 @@ January 8 04:05:06 1999 PST
Conversions between <type>timestamp without time zone</type> and Conversions between <type>timestamp without time zone</type> and
<type>timestamp with time zone</type> normally assume that the <type>timestamp with time zone</type> normally assume that the
<type>timestamp without time zone</type> value should be taken or given <type>timestamp without time zone</type> value should be taken or given
as <varname>TimeZone</> local time. A different zone reference can as <varname>timezone</> local time. A different zone reference can
be specified for the conversion using <literal>AT TIME ZONE</>. be specified for the conversion using <literal>AT TIME ZONE</>.
</para> </para>
...@@ -1673,7 +1600,7 @@ January 8 04:05:06 1999 PST ...@@ -1673,7 +1600,7 @@ January 8 04:05:06 1999 PST
<tgroup cols="2"> <tgroup cols="2">
<thead> <thead>
<row> <row>
<entry>Time Zone</entry> <entry>Example</entry>
<entry>Description</entry> <entry>Description</entry>
</row> </row>
</thead> </thead>
...@@ -1710,17 +1637,16 @@ January 8 04:05:06 1999 PST ...@@ -1710,17 +1637,16 @@ January 8 04:05:06 1999 PST
<type>interval</type> values can be written with the following syntax: <type>interval</type> values can be written with the following syntax:
<programlisting> <programlisting>
Quantity Unit [Quantity Unit...] [Direction] <optional>@</> <replaceable>quantity</> <replaceable>unit</> <optional><replaceable>quantity</> <replaceable>unit</>...</> <optional><replaceable>direction</></optional>
@ Quantity Unit [Quantity Unit...] [Direction]
</programlisting> </programlisting>
where: <literal>Quantity</literal> is a number (possibly signed), Where: <replaceable>quantity</> is a number (possibly signed);
<literal>Unit</literal> is <literal>second</literal>, <replaceable>unit</> is <literal>second</literal>,
<literal>minute</literal>, <literal>hour</literal>, <literal>day</literal>, <literal>minute</literal>, <literal>hour</literal>, <literal>day</literal>,
<literal>week</literal>, <literal>month</literal>, <literal>year</literal>, <literal>week</literal>, <literal>month</literal>, <literal>year</literal>,
<literal>decade</literal>, <literal>century</literal>, <literal>millennium</literal>, <literal>decade</literal>, <literal>century</literal>, <literal>millennium</literal>,
or abbreviations or plurals of these units; or abbreviations or plurals of these units;
<literal>Direction</literal> can be <literal>ago</literal> or <replaceable>direction</> can be <literal>ago</literal> or
empty. The at sign (<literal>@</>) is optional noise. The amounts empty. The at sign (<literal>@</>) is optional noise. The amounts
of different units are implicitly added up with appropriate of different units are implicitly added up with appropriate
sign accounting. sign accounting.
...@@ -1740,7 +1666,7 @@ January 8 04:05:06 1999 PST ...@@ -1740,7 +1666,7 @@ January 8 04:05:06 1999 PST
</sect3> </sect3>
<sect3> <sect3>
<title>Special values</title> <title>Special Values</title>
<indexterm> <indexterm>
<primary>time</primary> <primary>time</primary>
...@@ -1769,6 +1695,8 @@ January 8 04:05:06 1999 PST ...@@ -1769,6 +1695,8 @@ January 8 04:05:06 1999 PST
are specially represented inside the system and will be displayed are specially represented inside the system and will be displayed
the same way; but the others are simply notational shorthands the same way; but the others are simply notational shorthands
that will be converted to ordinary date/time values when read. that will be converted to ordinary date/time values when read.
All of these values are treated as normal constants and need to be
written in single quotes.
</para> </para>
<table id="datatype-datetime-special-table"> <table id="datatype-datetime-special-table">
...@@ -1776,44 +1704,51 @@ January 8 04:05:06 1999 PST ...@@ -1776,44 +1704,51 @@ January 8 04:05:06 1999 PST
<tgroup cols="2"> <tgroup cols="2">
<thead> <thead>
<row> <row>
<entry>Input string</entry> <entry>Input String</entry>
<entry>Valid Types</entry>
<entry>Description</entry> <entry>Description</entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry><literal>epoch</literal></entry> <entry><literal>epoch</literal></entry>
<entry><type>date</type>, <type>timestamp</type></entry>
<entry>1970-01-01 00:00:00+00 (Unix system time zero)</entry> <entry>1970-01-01 00:00:00+00 (Unix system time zero)</entry>
</row> </row>
<row> <row>
<entry><literal>infinity</literal></entry> <entry><literal>infinity</literal></entry>
<entry>later than all other timestamps (not available for <entry><type>timestamp</type></entry>
type <type>date</>)</entry> <entry>later than all other time stamps</entry>
</row> </row>
<row> <row>
<entry><literal>-infinity</literal></entry> <entry><literal>-infinity</literal></entry>
<entry>earlier than all other timestamps (not available for <entry><type>timestamp</type></entry>
type <type>date</>)</entry> <entry>earlier than all other time stamps</entry>
</row> </row>
<row> <row>
<entry><literal>now</literal></entry> <entry><literal>now</literal></entry>
<entry><type>date</type>, <type>time</type>, <type>timestamp</type></entry>
<entry>current transaction time</entry> <entry>current transaction time</entry>
</row> </row>
<row> <row>
<entry><literal>today</literal></entry> <entry><literal>today</literal></entry>
<entry><type>date</type>, <type>timestamp</type></entry>
<entry>midnight today</entry> <entry>midnight today</entry>
</row> </row>
<row> <row>
<entry><literal>tomorrow</literal></entry> <entry><literal>tomorrow</literal></entry>
<entry><type>date</type>, <type>timestamp</type></entry>
<entry>midnight tomorrow</entry> <entry>midnight tomorrow</entry>
</row> </row>
<row> <row>
<entry><literal>yesterday</literal></entry> <entry><literal>yesterday</literal></entry>
<entry><type>date</type>, <type>timestamp</type></entry>
<entry>midnight yesterday</entry> <entry>midnight yesterday</entry>
</row> </row>
<row> <row>
<entry><literal>zulu</>, <literal>allballs</>, <literal>z</></entry> <entry><literal>zulu</>, <literal>allballs</>, <literal>z</></entry>
<entry>00:00:00.00 GMT</entry> <entry><type>time</type></entry>
<entry>00:00:00.00 UTC</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -1838,9 +1773,9 @@ January 8 04:05:06 1999 PST ...@@ -1838,9 +1773,9 @@ January 8 04:05:06 1999 PST
</indexterm> </indexterm>
<para> <para>
Output formats can be set to one of the four styles ISO 8601, The output format of the date/time types can be set to one of the four styles ISO 8601,
<acronym>SQL</acronym> (Ingres), traditional PostgreSQL, and <acronym>SQL</acronym> (Ingres), traditional POSTGRES, and
German, using the <command>SET DateStyle</command>. The default German, using the <literal>SET datestyle</literal>. The default
is the <acronym>ISO</acronym> format. (The is the <acronym>ISO</acronym> format. (The
<acronym>SQL</acronym> standard requires the use of the ISO 8601 <acronym>SQL</acronym> standard requires the use of the ISO 8601
format. The name of the <quote>SQL</quote> output format is a format. The name of the <quote>SQL</quote> output format is a
...@@ -1873,7 +1808,7 @@ January 8 04:05:06 1999 PST ...@@ -1873,7 +1808,7 @@ January 8 04:05:06 1999 PST
<entry>12/17/1997 07:37:16.00 PST</entry> <entry>12/17/1997 07:37:16.00 PST</entry>
</row> </row>
<row> <row>
<entry>PostgreSQL</entry> <entry>POSTGRES</entry>
<entry>original style</entry> <entry>original style</entry>
<entry>Wed Dec 17 07:37:16 1997 PST</entry> <entry>Wed Dec 17 07:37:16 1997 PST</entry>
</row> </row>
...@@ -1909,7 +1844,7 @@ January 8 04:05:06 1999 PST ...@@ -1909,7 +1844,7 @@ January 8 04:05:06 1999 PST
<row> <row>
<entry>European</entry> <entry>European</entry>
<entry><replaceable>day</replaceable>/<replaceable>month</replaceable>/<replaceable>year</replaceable></entry> <entry><replaceable>day</replaceable>/<replaceable>month</replaceable>/<replaceable>year</replaceable></entry>
<entry>17/12/1997 15:37:16.00 MET</entry> <entry>17/12/1997 15:37:16.00 CET</entry>
</row> </row>
<row> <row>
<entry>US</entry> <entry>US</entry>
...@@ -1921,18 +1856,20 @@ January 8 04:05:06 1999 PST ...@@ -1921,18 +1856,20 @@ January 8 04:05:06 1999 PST
</table> </table>
<para> <para>
<type>interval</type> output looks like the input format, except that units like <type>interval</type> output looks like the input format, except
<literal>week</literal> or <literal>century</literal> are converted to years and days. that units like <literal>century</literal> or
In ISO mode the output looks like <literal>wek</literal> are converted to years and days and that
<literal>ago</literal> is converted to an appropriate sign. In
ISO mode the output looks like
<programlisting> <programlisting>
[ Quantity Units [ ... ] ] [ Days ] Hours:Minutes [ ago ] <optional> <replaceable>quantity</> <replaceable>unit</> <optional> ... </> </> <optional> <replaceable>days</> </> <optional> <replaceable>hours</>:<replaceable>minutes</>:<replaceable>sekunden</> </optional>
</programlisting> </programlisting>
</para> </para>
<para> <para>
The date/time styles can be selected by the user using the The date/time styles can be selected by the user using the
<command>SET DATESTYLE</command> command, the <command>SET datestyle</command> command, the
<varname>datestyle</varname> parameter in the <varname>datestyle</varname> parameter in the
<filename>postgresql.conf</filename> configuration file, and the <filename>postgresql.conf</filename> configuration file, and the
<envar>PGDATESTYLE</envar> environment variable on the server or <envar>PGDATESTYLE</envar> environment variable on the server or
...@@ -1949,6 +1886,25 @@ January 8 04:05:06 1999 PST ...@@ -1949,6 +1886,25 @@ January 8 04:05:06 1999 PST
<primary>time zones</primary> <primary>time zones</primary>
</indexterm> </indexterm>
<para>
Time zones, and time-zone conventions, are influenced by
political decisions, not just earth geometry. Time zones around the
world became somewhat standardized during the 1900's,
but continue to be prone to arbitrary changes.
<productname>PostgreSQL</productname> uses your operating
system's underlying features to provide output time-zone
support, and these systems usually contain information for only
the time period 1902 through 2038 (corresponding to the full
range of conventional Unix system time).
<type>timestamp with time zone</type> and <type>time with time
zone</type> will use time zone
information only within that year range, and assume that times
outside that range are in <acronym>UTC</acronym>.
But since time zone support is derived from the underlying operating
system time-zone capabilities, it can handle daylight-saving time
and other special behavior.
</para>
<para> <para>
<productname>PostgreSQL</productname> endeavors to be compatible with <productname>PostgreSQL</productname> endeavors to be compatible with
the <acronym>SQL</acronym> standard definitions for typical usage. the <acronym>SQL</acronym> standard definitions for typical usage.
...@@ -1970,8 +1926,8 @@ January 8 04:05:06 1999 PST ...@@ -1970,8 +1926,8 @@ January 8 04:05:06 1999 PST
<listitem> <listitem>
<para> <para>
The default time zone is specified as a constant integer offset The default time zone is specified as a constant numeric offset
from <acronym>GMT</>/<acronym>UTC</>. It is not possible to adapt to daylight-saving from <acronym>UTC</>. It is not possible to adapt to daylight-saving
time when doing date/time arithmetic across time when doing date/time arithmetic across
<acronym>DST</acronym> boundaries. <acronym>DST</acronym> boundaries.
</para> </para>
...@@ -1988,26 +1944,13 @@ January 8 04:05:06 1999 PST ...@@ -1988,26 +1944,13 @@ January 8 04:05:06 1999 PST
<productname>PostgreSQL</productname> for legacy applications and <productname>PostgreSQL</productname> for legacy applications and
for compatibility with other <acronym>SQL</acronym> for compatibility with other <acronym>SQL</acronym>
implementations). <productname>PostgreSQL</productname> assumes implementations). <productname>PostgreSQL</productname> assumes
your local time zone for any type containing only date or your local time zone for any type containing only date or time.
time. Further, time zone support is derived from the underlying
operating system time-zone capabilities, and hence can handle
daylight-saving time and other expected behavior.
</para>
<para>
<productname>PostgreSQL</productname> obtains time-zone support
from the underlying operating system for dates between 1902 and
2038 (near the typical date limits for Unix-style
systems). Outside of this range, all dates are assumed to be
specified and used in Universal Coordinated Time
(<acronym>UTC</acronym>).
</para> </para>
<para> <para>
All dates and times are stored internally in All dates and times are stored internally in
<acronym>UTC</acronym>, traditionally known as Greenwich Mean <acronym>UTC</acronym>. Times are converted to local time
Time (<acronym>GMT</acronym>). Times are converted to local time on the database server before being sent to the client,
on the database server before being sent to the client frontend,
hence by default are in the server time zone. hence by default are in the server time zone.
</para> </para>
...@@ -2026,7 +1969,7 @@ January 8 04:05:06 1999 PST ...@@ -2026,7 +1969,7 @@ January 8 04:05:06 1999 PST
<listitem> <listitem>
<para> <para>
The <varname>timezone</varname> configuration parameter can be The <varname>timezone</varname> configuration parameter can be
set in <filename>postgresql.conf</>. set in the file <filename>postgresql.conf</>.
</para> </para>
</listitem> </listitem>
...@@ -2191,8 +2134,8 @@ SELECT * FROM test1 WHERE a; ...@@ -2191,8 +2134,8 @@ SELECT * FROM test1 WHERE a;
<tgroup cols="4"> <tgroup cols="4">
<thead> <thead>
<row> <row>
<entry>Geometric Type</entry> <entry>Name</entry>
<entry>Storage</entry> <entry>Storage Size</entry>
<entry>Representation</entry> <entry>Representation</entry>
<entry>Description</entry> <entry>Description</entry>
</row> </row>
...@@ -2201,50 +2144,50 @@ SELECT * FROM test1 WHERE a; ...@@ -2201,50 +2144,50 @@ SELECT * FROM test1 WHERE a;
<row> <row>
<entry><type>point</type></entry> <entry><type>point</type></entry>
<entry>16 bytes</entry> <entry>16 bytes</entry>
<entry>Point on the plane</entry>
<entry>(x,y)</entry> <entry>(x,y)</entry>
<entry>Point in space</entry>
</row> </row>
<row> <row>
<entry><type>line</type></entry> <entry><type>line</type></entry>
<entry>32 bytes</entry> <entry>32 bytes</entry>
<entry>((x1,y1),(x2,y2))</entry>
<entry>Infinite line (not fully implemented)</entry> <entry>Infinite line (not fully implemented)</entry>
<entry>((x1,y1),(x2,y2))</entry>
</row> </row>
<row> <row>
<entry><type>lseg</type></entry> <entry><type>lseg</type></entry>
<entry>32 bytes</entry> <entry>32 bytes</entry>
<entry>((x1,y1),(x2,y2))</entry>
<entry>Finite line segment</entry> <entry>Finite line segment</entry>
<entry>((x1,y1),(x2,y2))</entry>
</row> </row>
<row> <row>
<entry><type>box</type></entry> <entry><type>box</type></entry>
<entry>32 bytes</entry> <entry>32 bytes</entry>
<entry>((x1,y1),(x2,y2))</entry>
<entry>Rectangular box</entry> <entry>Rectangular box</entry>
<entry>((x1,y1),(x2,y2))</entry>
</row> </row>
<row> <row>
<entry><type>path</type></entry> <entry><type>path</type></entry>
<entry>16+16n bytes</entry> <entry>16+16n bytes</entry>
<entry>((x1,y1),...)</entry>
<entry>Closed path (similar to polygon)</entry> <entry>Closed path (similar to polygon)</entry>
<entry>((x1,y1),...)</entry>
</row> </row>
<row> <row>
<entry><type>path</type></entry> <entry><type>path</type></entry>
<entry>16+16n bytes</entry> <entry>16+16n bytes</entry>
<entry>[(x1,y1),...]</entry>
<entry>Open path</entry> <entry>Open path</entry>
<entry>[(x1,y1),...]</entry>
</row> </row>
<row> <row>
<entry><type>polygon</type></entry> <entry><type>polygon</type></entry>
<entry>40+16n bytes</entry> <entry>40+16n bytes</entry>
<entry>((x1,y1),...)</entry>
<entry>Polygon (similar to closed path)</entry> <entry>Polygon (similar to closed path)</entry>
<entry>((x1,y1),...)</entry>
</row> </row>
<row> <row>
<entry><type>circle</type></entry> <entry><type>circle</type></entry>
<entry>24 bytes</entry> <entry>24 bytes</entry>
<entry><(x,y),r></entry> <entry>Circle</entry>
<entry>Circle (center and radius)</entry> <entry><(x,y),r> (center and radius)</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -2257,7 +2200,7 @@ SELECT * FROM test1 WHERE a; ...@@ -2257,7 +2200,7 @@ SELECT * FROM test1 WHERE a;
</para> </para>
<sect2> <sect2>
<title>Point</title> <title>Points</title>
<indexterm> <indexterm>
<primary>point</primary> <primary>point</primary>
...@@ -2265,39 +2208,20 @@ SELECT * FROM test1 WHERE a; ...@@ -2265,39 +2208,20 @@ SELECT * FROM test1 WHERE a;
<para> <para>
Points are the fundamental two-dimensional building block for geometric types. Points are the fundamental two-dimensional building block for geometric types.
<type>point</type> is specified using the following syntax: Values of type <type>point</type> are specified using the following syntax:
<synopsis> <synopsis>
( <replaceable>x</replaceable> , <replaceable>y</replaceable> ) ( <replaceable>x</replaceable> , <replaceable>y</replaceable> )
<replaceable>x</replaceable> , <replaceable>y</replaceable> <replaceable>x</replaceable> , <replaceable>y</replaceable>
</synopsis> </synopsis>
where the arguments are where <replaceable>x</> and <replaceable>y</> are the respective
coordinates as floating-point numbers.
<variablelist>
<varlistentry>
<term><replaceable>x</replaceable></term>
<listitem>
<para>
the x-axis coordinate as a floating-point number
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable>y</replaceable></term>
<listitem>
<para>
the y-axis coordinate as a floating-point number
</para>
</listitem>
</varlistentry>
</variablelist>
</para> </para>
</sect2> </sect2>
<sect2> <sect2>
<title>Line Segment</title> <title>Line Segments</title>
<indexterm> <indexterm>
<primary>line</primary> <primary>line</primary>
...@@ -2305,7 +2229,7 @@ SELECT * FROM test1 WHERE a; ...@@ -2305,7 +2229,7 @@ SELECT * FROM test1 WHERE a;
<para> <para>
Line segments (<type>lseg</type>) are represented by pairs of points. Line segments (<type>lseg</type>) are represented by pairs of points.
<type>lseg</type> is specified using the following syntax: Values of type <type>lseg</type> are specified using the following syntax:
<synopsis> <synopsis>
( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) ) ( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) )
...@@ -2313,24 +2237,16 @@ SELECT * FROM test1 WHERE a; ...@@ -2313,24 +2237,16 @@ SELECT * FROM test1 WHERE a;
<replaceable>x1</replaceable> , <replaceable>y1</replaceable> , <replaceable>x2</replaceable> , <replaceable>y2</replaceable> <replaceable>x1</replaceable> , <replaceable>y1</replaceable> , <replaceable>x2</replaceable> , <replaceable>y2</replaceable>
</synopsis> </synopsis>
where the arguments are where
<literal>(<replaceable>x1</replaceable>,<replaceable>y1</replaceable>)</literal>
<variablelist> and
<varlistentry> <literal>(<replaceable>x2</replaceable>,<replaceable>y2</replaceable>)</literal>
<term>(<replaceable>x1</replaceable>,<replaceable>y1</replaceable>)</term> are the end points of the line segment.
<term>(<replaceable>x2</replaceable>,<replaceable>y2</replaceable>)</term>
<listitem>
<para>
the end points of the line segment
</para>
</listitem>
</varlistentry>
</variablelist>
</para> </para>
</sect2> </sect2>
<sect2> <sect2>
<title>Box</title> <title>Boxes</title>
<indexterm> <indexterm>
<primary>box (data type)</primary> <primary>box (data type)</primary>
...@@ -2339,7 +2255,7 @@ SELECT * FROM test1 WHERE a; ...@@ -2339,7 +2255,7 @@ SELECT * FROM test1 WHERE a;
<para> <para>
Boxes are represented by pairs of points that are opposite Boxes are represented by pairs of points that are opposite
corners of the box. corners of the box.
<type>box</type> is specified using the following syntax: Values of type <type>box</type> is specified using the following syntax:
<synopsis> <synopsis>
( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) ) ( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ( <replaceable>x2</replaceable> , <replaceable>y2</replaceable> ) )
...@@ -2347,19 +2263,11 @@ SELECT * FROM test1 WHERE a; ...@@ -2347,19 +2263,11 @@ SELECT * FROM test1 WHERE a;
<replaceable>x1</replaceable> , <replaceable>y1</replaceable> , <replaceable>x2</replaceable> , <replaceable>y2</replaceable> <replaceable>x1</replaceable> , <replaceable>y1</replaceable> , <replaceable>x2</replaceable> , <replaceable>y2</replaceable>
</synopsis> </synopsis>
where the arguments are where
<literal>(<replaceable>x1</replaceable>,<replaceable>y1</replaceable>)</literal>
<variablelist> and
<varlistentry> <literal>(<replaceable>x2</replaceable>,<replaceable>y2</replaceable>)</literal>
<term>(<replaceable>x1</replaceable>,<replaceable>y1</replaceable>)</term> are the opposite corners of the box.
<term>(<replaceable>x2</replaceable>,<replaceable>y2</replaceable>)</term>
<listitem>
<para>
opposite corners of the box
</para>
</listitem>
</varlistentry>
</variablelist>
</para> </para>
<para> <para>
...@@ -2372,7 +2280,7 @@ SELECT * FROM test1 WHERE a; ...@@ -2372,7 +2280,7 @@ SELECT * FROM test1 WHERE a;
</sect2> </sect2>
<sect2> <sect2>
<title>Path</title> <title>Paths</title>
<indexterm> <indexterm>
<primary>path (data type)</primary> <primary>path (data type)</primary>
...@@ -2382,19 +2290,19 @@ SELECT * FROM test1 WHERE a; ...@@ -2382,19 +2290,19 @@ SELECT * FROM test1 WHERE a;
Paths are represented by connected sets of points. Paths can be Paths are represented by connected sets of points. Paths can be
<firstterm>open</firstterm>, where <firstterm>open</firstterm>, where
the first and last points in the set are not connected, and <firstterm>closed</firstterm>, the first and last points in the set are not connected, and <firstterm>closed</firstterm>,
where the first and last point are connected. Functions where the first and last point are connected. The functions
<function>popen(p)</function> <function>popen(<replaceable>p</>)</function>
and and
<function>pclose(p)</function> <function>pclose(<replaceable>p</>)</function>
are supplied to force a path to be open or closed, and functions are supplied to force a path to be open or closed, and the functions
<function>isopen(p)</function> <function>isopen(<replaceable>p</>)</function>
and and
<function>isclosed(p)</function> <function>isclosed(<replaceable>p</>)</function>
are supplied to test for either type in a query. are supplied to test for either type in an expression.
</para> </para>
<para> <para>
<type>path</type> is specified using the following syntax: Values of type <type>path</type> are specified using the following syntax:
<synopsis> <synopsis>
( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ... , ( <replaceable>xn</replaceable> , <replaceable>yn</replaceable> ) ) ( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ... , ( <replaceable>xn</replaceable> , <replaceable>yn</replaceable> ) )
...@@ -2404,20 +2312,10 @@ SELECT * FROM test1 WHERE a; ...@@ -2404,20 +2312,10 @@ SELECT * FROM test1 WHERE a;
<replaceable>x1</replaceable> , <replaceable>y1</replaceable> , ... , <replaceable>xn</replaceable> , <replaceable>yn</replaceable> <replaceable>x1</replaceable> , <replaceable>y1</replaceable> , ... , <replaceable>xn</replaceable> , <replaceable>yn</replaceable>
</synopsis> </synopsis>
where the arguments are where the points are the end points of the line segments
comprising the path. Square brackets (<literal>[]</>) indicate
<variablelist> an open path, while parentheses (<literal>()</>) indicate a
<varlistentry> closed path.
<term>(<replaceable>x</replaceable>,<replaceable>y</replaceable>)</term>
<listitem>
<para>
End points of the line segments comprising the path.
A leading square bracket (<literal>[</>) indicates an open path, while
a leading parenthesis (<literal>(</>) indicates a closed path.
</para>
</listitem>
</varlistentry>
</variablelist>
</para> </para>
<para> <para>
...@@ -2426,7 +2324,7 @@ SELECT * FROM test1 WHERE a; ...@@ -2426,7 +2324,7 @@ SELECT * FROM test1 WHERE a;
</sect2> </sect2>
<sect2> <sect2>
<title>Polygon</title> <title>Polygons</title>
<indexterm> <indexterm>
<primary>polygon</primary> <primary>polygon</primary>
...@@ -2439,7 +2337,7 @@ SELECT * FROM test1 WHERE a; ...@@ -2439,7 +2337,7 @@ SELECT * FROM test1 WHERE a;
</para> </para>
<para> <para>
<type>polygon</type> is specified using the following syntax: Values of type <type>polygon</type> are specified using the following syntax:
<synopsis> <synopsis>
( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ... , ( <replaceable>xn</replaceable> , <replaceable>yn</replaceable> ) ) ( ( <replaceable>x1</replaceable> , <replaceable>y1</replaceable> ) , ... , ( <replaceable>xn</replaceable> , <replaceable>yn</replaceable> ) )
...@@ -2448,19 +2346,8 @@ SELECT * FROM test1 WHERE a; ...@@ -2448,19 +2346,8 @@ SELECT * FROM test1 WHERE a;
<replaceable>x1</replaceable> , <replaceable>y1</replaceable> , ... , <replaceable>xn</replaceable> , <replaceable>yn</replaceable> <replaceable>x1</replaceable> , <replaceable>y1</replaceable> , ... , <replaceable>xn</replaceable> , <replaceable>yn</replaceable>
</synopsis> </synopsis>
where the arguments are where the points are the end points of the line segments
comprising the boundary of the polygon.
<variablelist>
<varlistentry>
<term>(<replaceable>x</replaceable>,<replaceable>y</replaceable>)</term>
<listitem>
<para>
End points of the line segments comprising the boundary of the
polygon
</para>
</listitem>
</varlistentry>
</variablelist>
</para> </para>
<para> <para>
...@@ -2469,7 +2356,7 @@ SELECT * FROM test1 WHERE a; ...@@ -2469,7 +2356,7 @@ SELECT * FROM test1 WHERE a;
</sect2> </sect2>
<sect2> <sect2>
<title>Circle</title> <title>Circles</title>
<indexterm> <indexterm>
<primary>circle</primary> <primary>circle</primary>
...@@ -2477,7 +2364,7 @@ SELECT * FROM test1 WHERE a; ...@@ -2477,7 +2364,7 @@ SELECT * FROM test1 WHERE a;
<para> <para>
Circles are represented by a center point and a radius. Circles are represented by a center point and a radius.
<type>circle</type> is specified using the following syntax: Values of type <type>circle</type> are specified using the following syntax:
<synopsis> <synopsis>
&lt; ( <replaceable>x</replaceable> , <replaceable>y</replaceable> ) , <replaceable>r</replaceable> &gt; &lt; ( <replaceable>x</replaceable> , <replaceable>y</replaceable> ) , <replaceable>r</replaceable> &gt;
...@@ -2486,27 +2373,9 @@ SELECT * FROM test1 WHERE a; ...@@ -2486,27 +2373,9 @@ SELECT * FROM test1 WHERE a;
<replaceable>x</replaceable> , <replaceable>y</replaceable> , <replaceable>r</replaceable> <replaceable>x</replaceable> , <replaceable>y</replaceable> , <replaceable>r</replaceable>
</synopsis> </synopsis>
where the arguments are where
<literal>(<replaceable>x</replaceable>,<replaceable>y</replaceable>)</literal>
<variablelist> is the center and <replaceable>r</replaceable> is the radius of the circle.
<varlistentry>
<term>(<replaceable>x</replaceable>,<replaceable>y</replaceable>)</term>
<listitem>
<para>
center of the circle
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable>r</replaceable></term>
<listitem>
<para>
radius of the circle
</para>
</listitem>
</varlistentry>
</variablelist>
</para> </para>
<para> <para>
...@@ -2517,7 +2386,7 @@ SELECT * FROM test1 WHERE a; ...@@ -2517,7 +2386,7 @@ SELECT * FROM test1 WHERE a;
</sect1> </sect1>
<sect1 id="datatype-net-types"> <sect1 id="datatype-net-types">
<title>Network Address Data Types</title> <title>Network Address Types</title>
<indexterm zone="datatype-net-types"> <indexterm zone="datatype-net-types">
<primary>network</primary> <primary>network</primary>
...@@ -2533,14 +2402,13 @@ SELECT * FROM test1 WHERE a; ...@@ -2533,14 +2402,13 @@ SELECT * FROM test1 WHERE a;
</para> </para>
<table tocentry="1" id="datatype-net-types-table"> <table tocentry="1" id="datatype-net-types-table">
<title>Network Address Data Types</title> <title>Network Address Types</title>
<tgroup cols="4"> <tgroup cols="3">
<thead> <thead>
<row> <row>
<entry>Name</entry> <entry>Name</entry>
<entry>Storage</entry> <entry>Storage Size</entry>
<entry>Description</entry> <entry>Description</entry>
<entry>Range</entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>
...@@ -2548,22 +2416,19 @@ SELECT * FROM test1 WHERE a; ...@@ -2548,22 +2416,19 @@ SELECT * FROM test1 WHERE a;
<row> <row>
<entry><type>cidr</type></entry> <entry><type>cidr</type></entry>
<entry>12 bytes</entry> <entry>12 bytes</entry>
<entry>IP networks</entry> <entry>IPv4 networks</entry>
<entry>valid IPv4 networks</entry>
</row> </row>
<row> <row>
<entry><type>inet</type></entry> <entry><type>inet</type></entry>
<entry>12 bytes</entry> <entry>12 bytes</entry>
<entry>IP hosts and networks</entry> <entry>IPv4 hosts and networks</entry>
<entry>valid IPv4 hosts or networks</entry>
</row> </row>
<row> <row>
<entry><type>macaddr</type></entry> <entry><type>macaddr</type></entry>
<entry>6 bytes</entry> <entry>6 bytes</entry>
<entry>MAC addresses</entry> <entry>MAC addresses</entry>
<entry>customary formats</entry>
</row> </row>
</tbody> </tbody>
...@@ -2585,11 +2450,11 @@ SELECT * FROM test1 WHERE a; ...@@ -2585,11 +2450,11 @@ SELECT * FROM test1 WHERE a;
<para> <para>
The <type>inet</type> type holds an IP host address, and The <type>inet</type> type holds an IP host address, and
optionally the identity of the subnet it is in, all in one field. optionally the identity of the subnet it is in, all in one field.
The subnet identity is represented by the number of bits in the The subnet identity is represented by stating how many bits of
network part of the address (the <quote>netmask</quote>). If the the host address represent the network address (the
netmask is 32, <quote>netmask</quote>). If the netmask is 32, then the value
then the value does not indicate a subnet, only a single host. does not indicate a subnet, only a single host. Note that if you
Note that if you want to accept networks only, you should use the want to accept networks only, you should use the
<type>cidr</type> type rather than <type>inet</type>. <type>cidr</type> type rather than <type>inet</type>.
</para> </para>
...@@ -2617,15 +2482,15 @@ SELECT * FROM test1 WHERE a; ...@@ -2617,15 +2482,15 @@ SELECT * FROM test1 WHERE a;
The <type>cidr</type> type holds an IP network specification. The <type>cidr</type> type holds an IP network specification.
Input and output formats follow Classless Internet Domain Routing Input and output formats follow Classless Internet Domain Routing
conventions. conventions.
The format for The format for specifying networks is <replaceable
specifying classless networks is <replaceable
class="parameter">x.x.x.x/y</> where <replaceable class="parameter">x.x.x.x/y</> where <replaceable
class="parameter">x.x.x.x</> is the network and <replaceable class="parameter">x.x.x.x</> is the network and <replaceable
class="parameter">y</> is the number of bits in the netmask. If class="parameter">y</> is the number of bits in the netmask. If
<replaceable class="parameter">y</> is omitted, it is calculated <replaceable class="parameter">y</> is omitted, it is calculated
using assumptions from the older classful numbering system, except using assumptions from the older classful network numbering system, except
that it will be at least large enough to include all of the octets that it will be at least large enough to include all of the octets
written in the input. written in the input. It is an error to specify a network address
that has bits set to the right of the specified netmask.
</para> </para>
<para> <para>
...@@ -2637,9 +2502,9 @@ SELECT * FROM test1 WHERE a; ...@@ -2637,9 +2502,9 @@ SELECT * FROM test1 WHERE a;
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row> <row>
<entry><type>CIDR</type> Input</entry> <entry><type>cidr</type> Input</entry>
<entry><type>CIDR</type> Displayed</entry> <entry><type>cidr</type> Output</entry>
<entry><function>abbrev</function>(<type>CIDR</type>)</entry> <entry><literal><function>abbrev</function>(<type>cidr</type>)</literal></entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>
...@@ -2704,21 +2569,21 @@ SELECT * FROM test1 WHERE a; ...@@ -2704,21 +2569,21 @@ SELECT * FROM test1 WHERE a;
</sect2> </sect2>
<sect2 id="datatype-inet-vs-cidr"> <sect2 id="datatype-inet-vs-cidr">
<title><type>inet</type> vs <type>cidr</type></title> <title><type>inet</type> vs. <type>cidr</type></title>
<para> <para>
The essential difference between <type>inet</type> and <type>cidr</type> The essential difference between <type>inet</type> and <type>cidr</type>
data types is that <type>inet</type> accepts values with nonzero bits to data types is that <type>inet</type> accepts values with nonzero bits to
the right of the netmask, whereas <type>cidr</type> does not. the right of the netmask, whereas <type>cidr</type> does not.
</para>
<tip> <tip>
<para> <para>
If you do not like the output format for <type>inet</type> or If you do not like the output format for <type>inet</type> or
<type>cidr</type> values, try the <function>host</>(), <type>cidr</type> values, try the functions <function>host</>,
<function>text</>(), and <function>abbrev</>() functions. <function>text</>, and <function>abbrev</>.
</para> </para>
</tip> </tip>
</para>
</sect2> </sect2>
<sect2 id="datatype-macaddr"> <sect2 id="datatype-macaddr">
...@@ -2774,37 +2639,37 @@ SELECT * FROM test1 WHERE a; ...@@ -2774,37 +2639,37 @@ SELECT * FROM test1 WHERE a;
<para> <para>
Bit strings are strings of 1's and 0's. They can be used to store Bit strings are strings of 1's and 0's. They can be used to store
or visualize bit masks. There are two SQL bit types: or visualize bit masks. There are two SQL bit types:
<type>BIT(<replaceable>n</replaceable>)</type> and <type>BIT <type>bit(<replaceable>n</replaceable>)</type> and <type>bit
VARYING(<replaceable>n</replaceable>)</type>, where varying(<replaceable>n</replaceable>)</type>, where
<replaceable>n</replaceable> is a positive integer. <replaceable>n</replaceable> is a positive integer.
</para> </para>
<para> <para>
<type>BIT</type> type data must match the length <type>bit</type> type data must match the length
<replaceable>n</replaceable> exactly; it is an error to attempt to <replaceable>n</replaceable> exactly; it is an error to attempt to
store shorter or longer bit strings. <type>BIT VARYING</type> data is store shorter or longer bit strings. <type>bit varying</type> data is
of variable length up to the maximum length of variable length up to the maximum length
<replaceable>n</replaceable>; longer strings will be rejected. <replaceable>n</replaceable>; longer strings will be rejected.
Writing <type>BIT</type> without a length is equivalent to Writing <type>bit</type> without a length is equivalent to
<literal>BIT(1)</literal>, while <type>BIT VARYING</type> without a length <literal>bit(1)</literal>, while <type>bit varying</type> without a length
specification means unlimited length. specification means unlimited length.
</para> </para>
<note> <note>
<para> <para>
If one explicitly casts a bit-string value to If one explicitly casts a bit-string value to
<type>BIT(<replaceable>n</>)</type>, it will be truncated or <type>bit(<replaceable>n</>)</type>, it will be truncated or
zero-padded on the right to be exactly <replaceable>n</> bits, zero-padded on the right to be exactly <replaceable>n</> bits,
without raising an error. Similarly, without raising an error. Similarly,
if one explicitly casts a bit-string value to if one explicitly casts a bit-string value to
<type>BIT VARYING(<replaceable>n</>)</type>, it will be truncated <type>bit varying(<replaceable>n</>)</type>, it will be truncated
on the right if it is more than <replaceable>n</> bits. on the right if it is more than <replaceable>n</> bits.
</para> </para>
</note> </note>
<note> <note>
<para> <para>
Prior to <productname>PostgreSQL</> 7.2, <type>BIT</type> data Prior to <productname>PostgreSQL</> 7.2, <type>bit</type> data
was always silently truncated or zero-padded on the right, with was always silently truncated or zero-padded on the right, with
or without an explicit cast. This was changed to comply with the or without an explicit cast. This was changed to comply with the
<acronym>SQL</acronym> standard. <acronym>SQL</acronym> standard.
...@@ -2842,6 +2707,8 @@ SELECT * FROM test; ...@@ -2842,6 +2707,8 @@ SELECT * FROM test;
</sect1> </sect1>
&array;
<sect1 id="datatype-oid"> <sect1 id="datatype-oid">
<title>Object Identifier Types</title> <title>Object Identifier Types</title>
...@@ -2896,7 +2763,7 @@ SELECT * FROM test; ...@@ -2896,7 +2763,7 @@ SELECT * FROM test;
tables. Also, an OID system column is added to user-created tables tables. Also, an OID system column is added to user-created tables
(unless <literal>WITHOUT OIDS</> is specified at table creation time). (unless <literal>WITHOUT OIDS</> is specified at table creation time).
Type <type>oid</> represents an object identifier. There are also Type <type>oid</> represents an object identifier. There are also
several aliases for <type>oid</>: <type>regproc</>, <type>regprocedure</>, several alias types for <type>oid</>: <type>regproc</>, <type>regprocedure</>,
<type>regoper</>, <type>regoperator</>, <type>regclass</>, <type>regoper</>, <type>regoperator</>, <type>regclass</>,
and <type>regtype</>. <xref linkend="datatype-oid-table"> shows an overview. and <type>regtype</>. <xref linkend="datatype-oid-table"> shows an overview.
</para> </para>
...@@ -2911,15 +2778,15 @@ SELECT * FROM test; ...@@ -2911,15 +2778,15 @@ SELECT * FROM test;
</para> </para>
<para> <para>
The <type>oid</> type itself has few operations beyond comparison The <type>oid</> type itself has few operations beyond comparison.
(which is implemented as unsigned comparison). It can be cast to It can be cast to
integer, however, and then manipulated using the standard integer integer, however, and then manipulated using the standard integer
operators. (Beware of possible signed-versus-unsigned confusion operators. (Beware of possible signed-versus-unsigned confusion
if you do this.) if you do this.)
</para> </para>
<para> <para>
The <type>oid</> alias types have no operations of their own except The OID alias types have no operations of their own except
for specialized input and output routines. These routines are able for specialized input and output routines. These routines are able
to accept and display symbolic names for system objects, rather than to accept and display symbolic names for system objects, rather than
the raw numeric value that type <type>oid</> would use. The alias the raw numeric value that type <type>oid</> would use. The alias
...@@ -2936,10 +2803,10 @@ SELECT * FROM test; ...@@ -2936,10 +2803,10 @@ SELECT * FROM test;
<tgroup cols="4"> <tgroup cols="4">
<thead> <thead>
<row> <row>
<entry>Type name</entry> <entry>Name</entry>
<entry>References</entry> <entry>References</entry>
<entry>Description</entry> <entry>Description</entry>
<entry>Value example</entry> <entry>Value Example</entry>
</row> </row>
</thead> </thead>
...@@ -2990,7 +2857,7 @@ SELECT * FROM test; ...@@ -2990,7 +2857,7 @@ SELECT * FROM test;
<row> <row>
<entry><type>regtype</></entry> <entry><type>regtype</></entry>
<entry><structname>pg_type</></entry> <entry><structname>pg_type</></entry>
<entry>type name</entry> <entry>data type name</entry>
<entry><literal>integer</></entry> <entry><literal>integer</></entry>
</row> </row>
</tbody> </tbody>
...@@ -3009,42 +2876,16 @@ SELECT * FROM test; ...@@ -3009,42 +2876,16 @@ SELECT * FROM test;
operand. operand.
</para> </para>
<para>
OIDs are 32-bit quantities and are assigned from a single cluster-wide
counter. In a large or long-lived database, it is possible for the
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.
Recommended practice when using OIDs for row identification is to create
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
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
OID counter for each table, so that <structfield>tableoid</>
<emphasis>must</> be included to arrive at a globally unique identifier.)
</para>
<para> <para>
Another identifier type used by the system is <type>xid</>, or transaction Another identifier type used by the system is <type>xid</>, or transaction
(abbreviated <abbrev>xact</>) identifier. This is the data type of the system columns (abbreviated <abbrev>xact</>) identifier. This is the data type of the system columns
<structfield>xmin</> and <structfield>xmax</>. <structfield>xmin</> and <structfield>xmax</>. Transaction identifiers are 32-bit quantities.
Transaction identifiers are 32-bit quantities. In a long-lived
database it is possible for transaction IDs to wrap around. This
is not a fatal problem given appropriate maintenance procedures;
see the &cite-admin; for details. However, it is
unwise to depend on uniqueness of transaction IDs over the long term
(more than one billion transactions).
</para> </para>
<para> <para>
A third identifier type used by the system is <type>cid</>, or A third identifier type used by the system is <type>cid</>, or
command identifier. This is the data type of the system columns command identifier. This is the data type of the system columns
<structfield>cmin</> and <structfield>cmax</>. Command <structfield>cmin</> and <structfield>cmax</>. Command identifiers are also 32-bit quantities.
identifiers are also 32-bit quantities. This creates a hard limit
of 2<superscript>32</> (4 billion) <acronym>SQL</acronym> commands
within a single transaction. In practice this limit is not a
problem --- note that the limit is on number of
<acronym>SQL</acronym> commands, not number of tuples processed.
</para> </para>
<para> <para>
...@@ -3055,6 +2896,10 @@ SELECT * FROM test; ...@@ -3055,6 +2896,10 @@ SELECT * FROM test;
physical location of the tuple within its table. physical location of the tuple within its table.
</para> </para>
<para>
(The system columns are further explained in <xref
linkend="ddl-system-columns">.)
</para>
</sect1> </sect1>
<sect1 id="datatype-pseudo"> <sect1 id="datatype-pseudo">
...@@ -3114,57 +2959,56 @@ SELECT * FROM test; ...@@ -3114,57 +2959,56 @@ SELECT * FROM test;
<tgroup cols="2"> <tgroup cols="2">
<thead> <thead>
<row> <row>
<entry>Type name</entry> <entry>Name</entry>
<entry>Description</entry> <entry>Description</entry>
</row> </row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry><type>record</></entry> <entry><type>record</></entry>
<entry>Identifies a function returning an unspecified row type</entry> <entry>Identifies a function returning an unspecified row type.</entry>
</row> </row>
<row> <row>
<entry><type>any</></entry> <entry><type>any</></entry>
<entry>Indicates that a function accepts any input data type whatever</entry> <entry>Indicates that a function accepts any input data type whatever.</entry>
</row> </row>
<row> <row>
<entry><type>anyarray</></entry> <entry><type>anyarray</></entry>
<entry>Indicates that a function accepts any array data type</entry> <entry>Indicates that a function accepts any array data type.</entry>
</row> </row>
<row> <row>
<entry><type>void</></entry> <entry><type>void</></entry>
<entry>Indicates that a function returns no value</entry> <entry>Indicates that a function returns no value.</entry>
</row> </row>
<row> <row>
<entry><type>trigger</></entry> <entry><type>trigger</></entry>
<entry>A trigger function is declared to return <type>trigger</></entry> <entry>A trigger function is declared to return <type>trigger.</></entry>
</row> </row>
<row> <row>
<entry><type>language_handler</></entry> <entry><type>language_handler</></entry>
<entry>A procedural language call handler is declared to return <type>language_handler</></entry> <entry>A procedural language call handler is declared to return <type>language_handler</>.</entry>
</row> </row>
<row> <row>
<entry><type>cstring</></entry> <entry><type>cstring</></entry>
<entry>Indicates that a function accepts or returns a null-terminated C string</entry> <entry>Indicates that a function accepts or returns a null-terminated C string.</entry>
</row> </row>
<row> <row>
<entry><type>internal</></entry> <entry><type>internal</></entry>
<entry>Indicates that a function accepts or returns a server-internal <entry>Indicates that a function accepts or returns a server-internal
data type</entry> data type.</entry>
</row> </row>
<row> <row>
<entry><type>opaque</></entry> <entry><type>opaque</></entry>
<entry>An obsolete type name that formerly served all the above purposes</entry> <entry>An obsolete type name that formerly served all the above purposes.</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -3199,8 +3043,6 @@ SELECT * FROM test; ...@@ -3199,8 +3043,6 @@ SELECT * FROM test;
</sect1> </sect1>
&array;
</chapter> </chapter>
<!-- Keep this comment at the end of the file <!-- Keep this comment at the end of the file
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.29 2002/11/11 20:14:02 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/datetime.sgml,v 2.30 2003/03/13 01:30:27 petere Exp $
Date/time details
--> -->
<appendix id="datetime-appendix"> <appendix id="datetime-appendix">
<title id="datetime-appendix-title">Date/Time Support</title> <title>Date/Time Support</title>
<para> <para>
<productname>PostgreSQL</productname> uses an internal heuristic <productname>PostgreSQL</productname> uses an internal heuristic
...@@ -28,12 +27,10 @@ Date/time details ...@@ -28,12 +27,10 @@ Date/time details
<title>Date/Time Input Interpretation</title> <title>Date/Time Input Interpretation</title>
<para> <para>
The date/time types are all decoded using a common set of routines. The date/time type inputs are all decoded using the following routine.
</para> </para>
<procedure> <procedure>
<title>Date/Time Input Interpretation</title>
<step> <step>
<para> <para>
Break the input string into tokens and categorize each token as Break the input string into tokens and categorize each token as
...@@ -61,7 +58,7 @@ Date/time details ...@@ -61,7 +58,7 @@ Date/time details
If the token is numeric only, then it is either a single field If the token is numeric only, then it is either a single field
or an ISO 8601 concatenated date (e.g., or an ISO 8601 concatenated date (e.g.,
<literal>19990113</literal> for January 13, 1999) or time <literal>19990113</literal> for January 13, 1999) or time
(e.g. <literal>141516</literal> for 14:15:16). (e.g., <literal>141516</literal> for 14:15:16).
</para> </para>
</step> </step>
...@@ -187,7 +184,7 @@ Date/time details ...@@ -187,7 +184,7 @@ Date/time details
<para> <para>
If BC has been specified, negate the year and add one for If BC has been specified, negate the year and add one for
internal storage. (There is no year zero in the Gregorian internal storage. (There is no year zero in the Gregorian
calendar, so numerically <literal>1BC</literal> becomes year calendar, so numerically 1 BC becomes year
zero.) zero.)
</para> </para>
</step> </step>
...@@ -195,8 +192,8 @@ Date/time details ...@@ -195,8 +192,8 @@ Date/time details
<step> <step>
<para> <para>
If BC was not specified, and if the year field was two digits in length, then If BC was not specified, and if the year field was two digits in length, then
adjust the year to 4 digits. If the field was less than 70, then add 2000; adjust the year to four digits. If the field is less than 70, then add 2000,
otherwise, add 1900. otherwise add 1900.
<tip> <tip>
<para> <para>
...@@ -382,8 +379,8 @@ Date/time details ...@@ -382,8 +379,8 @@ Date/time details
<para> <para>
The key word <literal>ABSTIME</literal> is ignored for historical The key word <literal>ABSTIME</literal> is ignored for historical
reasons; in very old releases of reasons: In very old releases of
<productname>PostgreSQL</productname> invalid fields of type <type>abstime</type> <productname>PostgreSQL</productname>, invalid values of type <type>abstime</type>
were emitted as <literal>Invalid Abstime</literal>. This is no were emitted as <literal>Invalid Abstime</literal>. This is no
longer the case however and this key word will likely be dropped in longer the case however and this key word will likely be dropped in
a future release. a future release.
...@@ -406,7 +403,7 @@ Date/time details ...@@ -406,7 +403,7 @@ Date/time details
<para> <para>
The table is organized by time zone offset from <acronym>UTC</>, The table is organized by time zone offset from <acronym>UTC</>,
rather than alphabetically; this is intended to facilitate rather than alphabetically. This is intended to facilitate
matching local usage with recognized abbreviations for cases where matching local usage with recognized abbreviations for cases where
these might differ. these might differ.
</para> </para>
...@@ -425,7 +422,7 @@ Date/time details ...@@ -425,7 +422,7 @@ Date/time details
<row> <row>
<entry>NZDT</entry> <entry>NZDT</entry>
<entry>+13:00</entry> <entry>+13:00</entry>
<entry>New Zealand Daylight Time</entry> <entry>New Zealand Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>IDLE</entry> <entry>IDLE</entry>
...@@ -455,12 +452,12 @@ Date/time details ...@@ -455,12 +452,12 @@ Date/time details
<row> <row>
<entry>CADT</entry> <entry>CADT</entry>
<entry>+10:30</entry> <entry>+10:30</entry>
<entry>Central Australia Daylight Savings Time</entry> <entry>Central Australia Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>SADT</entry> <entry>SADT</entry>
<entry>+10:30</entry> <entry>+10:30</entry>
<entry>South Australian Daylight Time</entry> <entry>South Australian Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>AEST</entry> <entry>AEST</entry>
...@@ -475,7 +472,7 @@ Date/time details ...@@ -475,7 +472,7 @@ Date/time details
<row> <row>
<entry>GST</entry> <entry>GST</entry>
<entry>+10:00</entry> <entry>+10:00</entry>
<entry>Guam Standard Time, USSR Zone 9</entry> <entry>Guam Standard Time, Russia zone 9</entry>
</row> </row>
<row> <row>
<entry>LIGT</entry> <entry>LIGT</entry>
...@@ -500,7 +497,7 @@ Date/time details ...@@ -500,7 +497,7 @@ Date/time details
<row> <row>
<entry>JST</entry> <entry>JST</entry>
<entry>+09:00</entry> <entry>+09:00</entry>
<entry>Japan Standard Time,USSR Zone 8</entry> <entry>Japan Standard Time, Russia zone 8</entry>
</row> </row>
<row> <row>
<entry>KST</entry> <entry>KST</entry>
...@@ -515,7 +512,7 @@ Date/time details ...@@ -515,7 +512,7 @@ Date/time details
<row> <row>
<entry>WDT</entry> <entry>WDT</entry>
<entry>+09:00</entry> <entry>+09:00</entry>
<entry>West Australian Daylight Time</entry> <entry>West Australian Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>MT</entry> <entry>MT</entry>
...@@ -535,7 +532,7 @@ Date/time details ...@@ -535,7 +532,7 @@ Date/time details
<row> <row>
<entry>WADT</entry> <entry>WADT</entry>
<entry>+08:00</entry> <entry>+08:00</entry>
<entry>West Australian Daylight Time</entry> <entry>West Australian Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>WST</entry> <entry>WST</entry>
...@@ -608,7 +605,7 @@ Date/time details ...@@ -608,7 +605,7 @@ Date/time details
<row> <row>
<entry>EAST</entry> <entry>EAST</entry>
<entry>+04:00</entry> <entry>+04:00</entry>
<entry>Antananarivo Savings Time</entry> <entry>Antananarivo Summer Time</entry>
</row> </row>
<row> <row>
<entry>MUT</entry> <entry>MUT</entry>
...@@ -643,7 +640,7 @@ Date/time details ...@@ -643,7 +640,7 @@ Date/time details
<row> <row>
<entry>EETDST</entry> <entry>EETDST</entry>
<entry>+03:00</entry> <entry>+03:00</entry>
<entry>Eastern Europe Daylight Savings Time</entry> <entry>Eastern Europe Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>HMT</entry> <entry>HMT</entry>
...@@ -658,17 +655,17 @@ Date/time details ...@@ -658,17 +655,17 @@ Date/time details
<row> <row>
<entry>CEST</entry> <entry>CEST</entry>
<entry>+02:00</entry> <entry>+02:00</entry>
<entry>Central European Savings Time</entry> <entry>Central European Summer Time</entry>
</row> </row>
<row> <row>
<entry>CETDST</entry> <entry>CETDST</entry>
<entry>+02:00</entry> <entry>+02:00</entry>
<entry>Central European Daylight Savings Time</entry> <entry>Central European Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>EET</entry> <entry>EET</entry>
<entry>+02:00</entry> <entry>+02:00</entry>
<entry>Eastern Europe, USSR Zone 1</entry> <entry>Eastern European Time, Russia zone 1</entry>
</row> </row>
<row> <row>
<entry>FWT</entry> <entry>FWT</entry>
...@@ -683,12 +680,12 @@ Date/time details ...@@ -683,12 +680,12 @@ Date/time details
<row> <row>
<entry>MEST</entry> <entry>MEST</entry>
<entry>+02:00</entry> <entry>+02:00</entry>
<entry>Middle Europe Summer Time</entry> <entry>Middle European Summer Time</entry>
</row> </row>
<row> <row>
<entry>METDST</entry> <entry>METDST</entry>
<entry>+02:00</entry> <entry>+02:00</entry>
<entry>Middle Europe Daylight Time</entry> <entry>Middle Europe Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>SST</entry> <entry>SST</entry>
...@@ -718,17 +715,17 @@ Date/time details ...@@ -718,17 +715,17 @@ Date/time details
<row> <row>
<entry>MET</entry> <entry>MET</entry>
<entry>+01:00</entry> <entry>+01:00</entry>
<entry>Middle Europe Time</entry> <entry>Middle European Time</entry>
</row> </row>
<row> <row>
<entry>MEWT</entry> <entry>MEWT</entry>
<entry>+01:00</entry> <entry>+01:00</entry>
<entry>Middle Europe Winter Time</entry> <entry>Middle European Winter Time</entry>
</row> </row>
<row> <row>
<entry>MEZ</entry> <entry>MEZ</entry>
<entry>+01:00</entry> <entry>+01:00</entry>
<entry>Middle Europe Zone</entry> <entry><foreignphrase>Mitteleuropäische Zeit</></entry>
</row> </row>
<row> <row>
<entry>NOR</entry> <entry>NOR</entry>
...@@ -748,37 +745,37 @@ Date/time details ...@@ -748,37 +745,37 @@ Date/time details
<row> <row>
<entry>WETDST</entry> <entry>WETDST</entry>
<entry>+01:00</entry> <entry>+01:00</entry>
<entry>Western Europe Daylight Savings Time</entry> <entry>Western European Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>GMT</entry> <entry>GMT</entry>
<entry>+00:00</entry> <entry>00:00</entry>
<entry>Greenwich Mean Time</entry> <entry>Greenwich Mean Time</entry>
</row> </row>
<row> <row>
<entry>UT</entry> <entry>UT</entry>
<entry>+00:00</entry> <entry>00:00</entry>
<entry>Universal Time</entry> <entry>Universal Time</entry>
</row> </row>
<row> <row>
<entry>UTC</entry> <entry>UTC</entry>
<entry>+00:00</entry> <entry>00:00</entry>
<entry>Universal Time, Coordinated</entry> <entry>Universal Coordinated Time</entry>
</row> </row>
<row> <row>
<entry>Z</entry> <entry>Z</entry>
<entry>+00:00</entry> <entry>00:00</entry>
<entry>Same as UTC</entry> <entry>Same as UTC</entry>
</row> </row>
<row> <row>
<entry>ZULU</entry> <entry>ZULU</entry>
<entry>+00:00</entry> <entry>00:00</entry>
<entry>Same as UTC</entry> <entry>Same as UTC</entry>
</row> </row>
<row> <row>
<entry>WET</entry> <entry>WET</entry>
<entry>+00:00</entry> <entry>00:00</entry>
<entry>Western Europe</entry> <entry>Western European Time</entry>
</row> </row>
<row> <row>
<entry>WAT</entry> <entry>WAT</entry>
...@@ -788,12 +785,12 @@ Date/time details ...@@ -788,12 +785,12 @@ Date/time details
<row> <row>
<entry>NDT</entry> <entry>NDT</entry>
<entry>-02:30</entry> <entry>-02:30</entry>
<entry>Newfoundland Daylight Time</entry> <entry>Newfoundland Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>ADT</entry> <entry>ADT</entry>
<entry>-03:00</entry> <entry>-03:00</entry>
<entry>Atlantic Daylight Time</entry> <entry>Atlantic Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>AWT</entry> <entry>AWT</entry>
...@@ -828,7 +825,7 @@ Date/time details ...@@ -828,7 +825,7 @@ Date/time details
<row> <row>
<entry>EDT</entry> <entry>EDT</entry>
<entry>-04:00</entry> <entry>-04:00</entry>
<entry>Eastern Daylight Time</entry> <entry>Eastern Daylight-Saving Time</entry>
</row> </row>
<!-- <!--
<row> <row>
...@@ -840,7 +837,7 @@ Date/time details ...@@ -840,7 +837,7 @@ Date/time details
<row> <row>
<entry>CDT</entry> <entry>CDT</entry>
<entry>-05:00</entry> <entry>-05:00</entry>
<entry>Central Daylight Time</entry> <entry>Central Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>EST</entry> <entry>EST</entry>
...@@ -862,7 +859,7 @@ Date/time details ...@@ -862,7 +859,7 @@ Date/time details
<row> <row>
<entry>MDT</entry> <entry>MDT</entry>
<entry>-06:00</entry> <entry>-06:00</entry>
<entry>Mountain Daylight Time</entry> <entry>Mountain Daylight-Saving Time</entry>
</row> </row>
<!-- <!--
<row> <row>
...@@ -879,12 +876,12 @@ Date/time details ...@@ -879,12 +876,12 @@ Date/time details
<row> <row>
<entry>PDT</entry> <entry>PDT</entry>
<entry>-07:00</entry> <entry>-07:00</entry>
<entry>Pacific Daylight Time</entry> <entry>Pacific Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>AKDT</entry> <entry>AKDT</entry>
<entry>-08:00</entry> <entry>-08:00</entry>
<entry>Alaska Daylight Time</entry> <entry>Alaska Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>PST</entry> <entry>PST</entry>
...@@ -894,7 +891,7 @@ Date/time details ...@@ -894,7 +891,7 @@ Date/time details
<row> <row>
<entry>YDT</entry> <entry>YDT</entry>
<entry>-08:00</entry> <entry>-08:00</entry>
<entry>Yukon Daylight Time</entry> <entry>Yukon Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>AKST</entry> <entry>AKST</entry>
...@@ -904,7 +901,7 @@ Date/time details ...@@ -904,7 +901,7 @@ Date/time details
<row> <row>
<entry>HDT</entry> <entry>HDT</entry>
<entry>-09:00</entry> <entry>-09:00</entry>
<entry>Hawaii/Alaska Daylight Time</entry> <entry>Hawaii/Alaska Daylight-Saving Time</entry>
</row> </row>
<row> <row>
<entry>YST</entry> <entry>YST</entry>
...@@ -919,7 +916,7 @@ Date/time details ...@@ -919,7 +916,7 @@ Date/time details
<row> <row>
<entry>AHST</entry> <entry>AHST</entry>
<entry>-10:00</entry> <entry>-10:00</entry>
<entry>Alaska-Hawaii Standard Time</entry> <entry>Alaska/Hawaii Standard Time</entry>
</row> </row>
<row> <row>
<entry>HST</entry> <entry>HST</entry>
...@@ -950,10 +947,10 @@ Date/time details ...@@ -950,10 +947,10 @@ Date/time details
<para> <para>
There are three naming conflicts between Australian time zone There are three naming conflicts between Australian time zone
names with time zones commonly used in North and South America: names and time zone names commonly used in North and South America:
<literal>ACST</literal>, <literal>CST</literal>, and <literal>ACST</literal>, <literal>CST</literal>, and
<literal>EST</literal>. If the run-time option <literal>EST</literal>. If the run-time option
<varname>AUSTRALIAN_TIMEZONES</varname> is set to true then <varname>australian_timezones</varname> is set to true then
<literal>ACST</literal>, <literal>CST</literal>, <literal>ACST</literal>, <literal>CST</literal>,
<literal>EST</literal>, and <literal>SAT</literal> are interpreted <literal>EST</literal>, and <literal>SAT</literal> are interpreted
as Australian time zone names, as shown in <xref as Australian time zone names, as shown in <xref
...@@ -1002,29 +999,23 @@ Date/time details ...@@ -1002,29 +999,23 @@ Date/time details
</sect1> </sect1>
<sect1 id="units-history"> <sect1 id="datetime-units-history">
<title>History of Units</title> <title>History of Units</title>
<note>
<para>
Contributed by José Soares (<email>jose@sferacarta.com</email>)
</para>
</note>
<para> <para>
The Julian Day was invented by the French scholar The Julian Date was invented by the French scholar
Joseph Justus Scaliger (1540-1609) Joseph Justus Scaliger (1540-1609)
and probably takes its name from the Scaliger's father, and probably takes its name from the Scaliger's father,
the Italian scholar Julius Caesar Scaliger (1484-1558). the Italian scholar Julius Caesar Scaliger (1484-1558).
Astronomers have used the Julian period to assign a unique number to Astronomers have used the Julian period to assign a unique number to
every day since 1 January 4713 BC. This is the so-called Julian Day every day since 1 January 4713 BC. This is the so-called Julian Date
(JD). JD 0 designates the 24 hours from noon UTC on 1 January 4713 BC (JD). JD 0 designates the 24 hours from noon UTC on 1 January 4713 BC
to noon UTC on 2 January 4713 BC. to noon UTC on 2 January 4713 BC.
</para> </para>
<para> <para>
The <quote>Julian Day</quote> is different from the <quote>Julian The <quote>Julian Date</quote> is different from the <quote>Julian
Date</quote>. The Julian date refers to the Julian calendar, which Calendar</quote>. The Julian calendar
was introduced by Julius Caesar in 45 BC. It was in common use was introduced by Julius Caesar in 45 BC. It was in common use
until the 1582, when countries started changing to the Gregorian until the 1582, when countries started changing to the Gregorian
calendar. In the Julian calendar, the tropical year is calendar. In the Julian calendar, the tropical year is
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.12 2003/02/19 04:06:27 momjian Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/ddl.sgml,v 1.13 2003/03/13 01:30:28 petere Exp $ -->
<chapter id="ddl"> <chapter id="ddl">
<title>Data Definition</title> <title>Data Definition</title>
...@@ -171,9 +171,9 @@ DROP TABLE products; ...@@ -171,9 +171,9 @@ DROP TABLE products;
The object identifier (object ID) of a row. This is a serial The object identifier (object ID) of a row. This is a serial
number that is automatically added by number that is automatically added by
<productname>PostgreSQL</productname> to all table rows (unless <productname>PostgreSQL</productname> to all table rows (unless
the table was created <literal>WITHOUT OIDS</literal>, in which the table was created using <literal>WITHOUT OIDS</literal>, in which
case this column is not present). This column is of type case this column is not present). This column is of type
<literal>oid</literal> (same name as the column); see <xref <type>oid</type> (same name as the column); see <xref
linkend="datatype-oid"> for more information about the type. linkend="datatype-oid"> for more information about the type.
</para> </para>
</listitem> </listitem>
...@@ -183,7 +183,7 @@ DROP TABLE products; ...@@ -183,7 +183,7 @@ DROP TABLE products;
<term><structfield>tableoid</></term> <term><structfield>tableoid</></term>
<listitem> <listitem>
<para> <para>
The OID of the table containing this row. This attribute is The OID of the table containing this row. This column is
particularly handy for queries that select from inheritance particularly handy for queries that select from inheritance
hierarchies, since without it, it's difficult to tell which hierarchies, since without it, it's difficult to tell which
individual table a row came from. The individual table a row came from. The
...@@ -221,7 +221,7 @@ DROP TABLE products; ...@@ -221,7 +221,7 @@ DROP TABLE products;
<listitem> <listitem>
<para> <para>
The identity (transaction ID) of the deleting transaction, or The identity (transaction ID) of the deleting transaction, or
zero for an undeleted tuple. It is possible for this field to zero for an undeleted tuple. It is possible for this column to
be nonzero in a visible tuple: That usually indicates that the be nonzero in a visible tuple: That usually indicates that the
deleting transaction hasn't committed yet, or that an attempted deleting transaction hasn't committed yet, or that an attempted
deletion was rolled back. deletion was rolled back.
...@@ -254,9 +254,42 @@ DROP TABLE products; ...@@ -254,9 +254,42 @@ DROP TABLE products;
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
<para>
OIDs are 32-bit quantities and are assigned from a single cluster-wide
counter. In a large or long-lived database, it is possible for the
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.
Recommended practice when using OIDs for row identification is to create
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
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
OID counter for each table, so that <structfield>tableoid</>
<emphasis>must</> be included to arrive at a globally unique identifier.)
</para>
<para>
Transaction identifiers are also 32-bit quantities. In a long-lived
database it is possible for transaction IDs to wrap around. This
is not a fatal problem given appropriate maintenance procedures;
see the &cite-admin; for details. However, it is
unwise to depend on uniqueness of transaction IDs over the long term
(more than one billion transactions).
</para>
<para>
Command
identifiers are also 32-bit quantities. This creates a hard limit
of 2<superscript>32</> (4 billion) <acronym>SQL</acronym> commands
within a single transaction. In practice this limit is not a
problem --- note that the limit is on number of
<acronym>SQL</acronym> commands, not number of tuples processed.
</para>
</sect1> </sect1>
<sect1> <sect1 id="ddl-default">
<title>Default Values</title> <title>Default Values</title>
<para> <para>
...@@ -279,7 +312,7 @@ DROP TABLE products; ...@@ -279,7 +312,7 @@ DROP TABLE products;
data type. For example: data type. For example:
<programlisting> <programlisting>
CREATE TABLE products ( CREATE TABLE products (
product_no integer PRIMARY KEY, product_no integer,
name text, name text,
price numeric <emphasis>DEFAULT 9.99</emphasis> price numeric <emphasis>DEFAULT 9.99</emphasis>
); );
...@@ -1194,7 +1227,7 @@ GRANT SELECT ON accounts TO GROUP staff; ...@@ -1194,7 +1227,7 @@ GRANT SELECT ON accounts TO GROUP staff;
REVOKE ALL ON accounts FROM PUBLIC; REVOKE ALL ON accounts FROM PUBLIC;
</programlisting> </programlisting>
The special privileges of the table owner (i.e., the right to do The special privileges of the table owner (i.e., the right to do
<command>DROP</>, <command>GRANT</>, <command>REVOKE</>, etc) <command>DROP</>, <command>GRANT</>, <command>REVOKE</>, etc.)
are always implicit in being the owner, are always implicit in being the owner,
and cannot be granted or revoked. But the table owner can choose and cannot be granted or revoked. But the table owner can choose
to revoke his own ordinary privileges, for example to make a to revoke his own ordinary privileges, for example to make a
...@@ -1214,7 +1247,7 @@ REVOKE ALL ON accounts FROM PUBLIC; ...@@ -1214,7 +1247,7 @@ REVOKE ALL ON accounts FROM PUBLIC;
</indexterm> </indexterm>
<para> <para>
A <productname>PostgreSQL</productname> database cluster (installation) A <productname>PostgreSQL</productname> database cluster
contains one or more named databases. Users and groups of users are contains one or more named databases. Users and groups of users are
shared across the entire cluster, but no other data is shared across shared across the entire cluster, but no other data is shared across
databases. Any given client connection to the server can access databases. Any given client connection to the server can access
...@@ -1536,10 +1569,10 @@ REVOKE CREATE ON public FROM PUBLIC; ...@@ -1536,10 +1569,10 @@ REVOKE CREATE ON public FROM PUBLIC;
no longer true: you may create such a table name if you wish, in no longer true: you may create such a table name if you wish, in
any non-system schema. However, it's best to continue to avoid any non-system schema. However, it's best to continue to avoid
such names, to ensure that you won't suffer a conflict if some such names, to ensure that you won't suffer a conflict if some
future version defines a system catalog named the same as your future version defines a system table named the same as your
table. (With the default search path, an unqualified reference to table. (With the default search path, an unqualified reference to
your table name would be resolved as the system catalog instead.) your table name would be resolved as the system table instead.)
System catalogs will continue to follow the convention of having System tables will continue to follow the convention of having
names beginning with <literal>pg_</>, so that they will not names beginning with <literal>pg_</>, so that they will not
conflict with unqualified user-table names so long as users avoid conflict with unqualified user-table names so long as users avoid
the <literal>pg_</> prefix. the <literal>pg_</> prefix.
...@@ -1681,7 +1714,8 @@ REVOKE CREATE ON public FROM PUBLIC; ...@@ -1681,7 +1714,8 @@ REVOKE CREATE ON public FROM PUBLIC;
linkend="ddl-constraints-fk">, with the orders table depending on linkend="ddl-constraints-fk">, with the orders table depending on
it, would result in an error message such as this: it, would result in an error message such as this:
<screen> <screen>
<userinput>DROP TABLE products;</userinput> DROP TABLE products;
NOTICE: constraint $1 on table orders depends on table products NOTICE: constraint $1 on table orders depends on table products
ERROR: Cannot drop table products because other objects depend on it ERROR: Cannot drop table products because other objects depend on it
Use DROP ... CASCADE to drop the dependent objects too Use DROP ... CASCADE to drop the dependent objects too
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.41 2003/01/19 00:13:28 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.42 2003/03/13 01:30:28 petere Exp $
--> -->
<chapter id="ecpg"> <chapter id="ecpg">
...@@ -44,7 +44,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.41 2003/01/19 00:13:28 momjia ...@@ -44,7 +44,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/ecpg.sgml,v 1.41 2003/01/19 00:13:28 momjia
implementation is designed to match this standard as much as implementation is designed to match this standard as much as
possible, and it is usually possible to port embedded possible, and it is usually possible to port embedded
<acronym>SQL</acronym> programs written for other <acronym>SQL</acronym> programs written for other
<acronym>RDBMS</acronym> to <productname>PostgreSQL</productname> SQL databases to <productname>PostgreSQL</productname>
with relative ease. with relative ease.
</para> </para>
...@@ -124,30 +124,30 @@ EXEC SQL CONNECT TO <replaceable>target</replaceable> <optional>AS <replaceable> ...@@ -124,30 +124,30 @@ EXEC SQL CONNECT TO <replaceable>target</replaceable> <optional>AS <replaceable>
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<simpara> <simpara>
<literal><replaceable>userid</replaceable></literal> <literal><replaceable>username</replaceable></literal>
</simpara> </simpara>
</listitem> </listitem>
<listitem> <listitem>
<simpara> <simpara>
<literal><replaceable>userid</replaceable>/<replaceable>password</replaceable></literal> <literal><replaceable>username</replaceable>/<replaceable>password</replaceable></literal>
</simpara> </simpara>
</listitem> </listitem>
<listitem> <listitem>
<simpara> <simpara>
<literal><replaceable>userid</replaceable> IDENTIFIED BY <replaceable>password</replaceable></literal> <literal><replaceable>username</replaceable> IDENTIFIED BY <replaceable>password</replaceable></literal>
</simpara> </simpara>
</listitem> </listitem>
<listitem> <listitem>
<simpara> <simpara>
<literal><replaceable>userid</replaceable> USING <replaceable>password</replaceable></literal> <literal><replaceable>username</replaceable> USING <replaceable>password</replaceable></literal>
</simpara> </simpara>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
The <replaceable>userid</replaceable> and The <replaceable>username</replaceable> and
<replaceable>password</replaceable> may be a constant text, a <replaceable>password</replaceable> may be an SQL name, a
character variable, or a character string. character variable, or a character string.
</para> </para>
...@@ -164,7 +164,7 @@ EXEC SQL CONNECT TO <replaceable>target</replaceable> <optional>AS <replaceable> ...@@ -164,7 +164,7 @@ EXEC SQL CONNECT TO <replaceable>target</replaceable> <optional>AS <replaceable>
<para> <para>
To close a connection, use the following statement: To close a connection, use the following statement:
<programlisting> <programlisting>
EXEC SQL DISCONNECT [<replaceable>connection</replaceable>]; EXEC SQL DISCONNECT <optional><replaceable>connection</replaceable></optional>;
</programlisting> </programlisting>
The <replaceable>connection</replaceable> can be specified The <replaceable>connection</replaceable> can be specified
in the following ways: in the following ways:
...@@ -275,7 +275,7 @@ EXEC SQL COMMIT; ...@@ -275,7 +275,7 @@ EXEC SQL COMMIT;
other interfaces) via the <option>-t</option> command-line option other interfaces) via the <option>-t</option> command-line option
to <command>ecpg</command> (see below) or via the <literal>EXEC SQL to <command>ecpg</command> (see below) or via the <literal>EXEC SQL
SET AUTOCOMMIT TO ON</literal> statement. In autocommit mode, each SET AUTOCOMMIT TO ON</literal> statement. In autocommit mode, each
query is automatically committed unless it is inside an explicit command is automatically committed unless it is inside an explicit
transaction block. This mode can be explicitly turned off using transaction block. This mode can be explicitly turned off using
<literal>EXEC SQL SET AUTOCOMMIT TO OFF</literal>. <literal>EXEC SQL SET AUTOCOMMIT TO OFF</literal>.
</para> </para>
...@@ -324,16 +324,16 @@ char foo[16], bar[16]; ...@@ -324,16 +324,16 @@ char foo[16], bar[16];
<para> <para>
The special types <type>VARCHAR</type> and <type>VARCHAR2</type> The special types <type>VARCHAR</type> and <type>VARCHAR2</type>
are converted into a named <type>struct</> for every variable. A are converted into a named <type>struct</> for every variable. A
declaration like: declaration like
<programlisting> <programlisting>
VARCHAR var[180]; VARCHAR var[180];
</programlisting> </programlisting>
is converted into: is converted into
<programlisting> <programlisting>
struct varchar_var { int len; char arr[180]; } var; struct varchar_var { int len; char arr[180]; } var;
</programlisting> </programlisting>
This structure is suitable for interfacing with SQL datums of type This structure is suitable for interfacing with SQL datums of type
<type>VARCHAR</type>. <type>varchar</type>.
</para> </para>
<para> <para>
...@@ -389,7 +389,7 @@ struct sqlca ...@@ -389,7 +389,7 @@ struct sqlca
long sqlerrd[6]; long sqlerrd[6];
/* 0: empty */ /* 0: empty */
/* 1: OID of processed tuple if applicable */ /* 1: OID of processed row if applicable */
/* 2: number of rows processed in an INSERT, UPDATE */ /* 2: number of rows processed in an INSERT, UPDATE */
/* or DELETE statement */ /* or DELETE statement */
/* 3: empty */ /* 3: empty */
...@@ -400,7 +400,7 @@ struct sqlca ...@@ -400,7 +400,7 @@ struct sqlca
/* 0: set to 'W' if at least one other is 'W' */ /* 0: set to 'W' if at least one other is 'W' */
/* 1: if 'W' at least one character string */ /* 1: if 'W' at least one character string */
/* value was truncated when it was */ /* value was truncated when it was */
/* stored into a host variable. */ /* stored into a host variable */
/* 2: empty */ /* 2: empty */
/* 3: empty */ /* 3: empty */
/* 4: empty */ /* 4: empty */
...@@ -418,7 +418,7 @@ struct sqlca ...@@ -418,7 +418,7 @@ struct sqlca
If no error occurred in the last <acronym>SQL</acronym> statement, If no error occurred in the last <acronym>SQL</acronym> statement,
<literal>sqlca.sqlcode</literal> will be 0 <literal>sqlca.sqlcode</literal> will be 0
(<symbol>ECPG_NO_ERROR</>). If <literal>sqlca.sqlcode</literal> is (<symbol>ECPG_NO_ERROR</>). If <literal>sqlca.sqlcode</literal> is
less that zero, this is a serious error, like the database less than zero, this is a serious error, like the database
definition does not match the query. If it is greater than zero, it definition does not match the query. If it is greater than zero, it
is a normal error like the table did not contain the requested row. is a normal error like the table did not contain the requested row.
</para> </para>
...@@ -434,7 +434,7 @@ struct sqlca ...@@ -434,7 +434,7 @@ struct sqlca
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><computeroutput>-12, Out of memory in line %d.</computeroutput></term> <term><computeroutput>-12: Out of memory in line %d.</computeroutput></term>
<listitem> <listitem>
<para> <para>
Should not normally occur. This indicates your virtual memory Should not normally occur. This indicates your virtual memory
...@@ -462,7 +462,7 @@ struct sqlca ...@@ -462,7 +462,7 @@ struct sqlca
This means that the server has returned more arguments than we This means that the server has returned more arguments than we
have matching variables. Perhaps you have forgotten a couple have matching variables. Perhaps you have forgotten a couple
of the host variables in the <command>INTO of the host variables in the <command>INTO
:var1,:var2</command> list. :var1, :var2</command> list.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -481,7 +481,7 @@ struct sqlca ...@@ -481,7 +481,7 @@ struct sqlca
<term><computeroutput>-203 (ECPG_TOO_MANY_MATCHES): Too many matches line %d.</computeroutput></term> <term><computeroutput>-203 (ECPG_TOO_MANY_MATCHES): Too many matches line %d.</computeroutput></term>
<listitem> <listitem>
<para> <para>
This means the query has returned several rows but the This means the query has returned multiple rows but the
variables specified are not arrays. The variables specified are not arrays. The
<command>SELECT</command> command was not unique. <command>SELECT</command> command was not unique.
</para> </para>
...@@ -627,7 +627,7 @@ struct sqlca ...@@ -627,7 +627,7 @@ struct sqlca
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><computeroutput>-242 (ECPG_UNKNOWN_DESCRIPTOR_ITEM): Descriptor %s not found in line %d.</computeroutput></term> <term><computeroutput>-242 (ECPG_UNKNOWN_DESCRIPTOR_ITEM): Unknown descriptor item %s in line %d.</computeroutput></term>
<listitem> <listitem>
<para> <para>
The descriptor specified was not found. The statement you are trying to use has not been prepared. The descriptor specified was not found. The statement you are trying to use has not been prepared.
...@@ -656,12 +656,12 @@ struct sqlca ...@@ -656,12 +656,12 @@ struct sqlca
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><computeroutput>-400 (ECPG_PGSQL): Postgres error: %s line %d.</computeroutput></term> <term><computeroutput>-400 (ECPG_PGSQL): '%s' in line %d.</computeroutput></term>
<listitem> <listitem>
<para> <para>
Some <productname>PostgreSQL</productname> error. The message Some <productname>PostgreSQL</productname> error. The message
contains the error message from the contains the error message from the
<productname>PostgreSQL</productname> backend. <productname>PostgreSQL</productname> server.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -670,7 +670,7 @@ struct sqlca ...@@ -670,7 +670,7 @@ struct sqlca
<term><computeroutput>-401 (ECPG_TRANS): Error in transaction processing line %d.</computeroutput></term> <term><computeroutput>-401 (ECPG_TRANS): Error in transaction processing line %d.</computeroutput></term>
<listitem> <listitem>
<para> <para>
<productname>PostgreSQL</productname> signaled that we cannot The <productname>PostgreSQL</productname> server signaled that we cannot
start, commit, or rollback the transaction. start, commit, or rollback the transaction.
</para> </para>
</listitem> </listitem>
...@@ -680,7 +680,7 @@ struct sqlca ...@@ -680,7 +680,7 @@ struct sqlca
<term><computeroutput>-402 (ECPG_CONNECT): Could not connect to database %s in line %d.</computeroutput></term> <term><computeroutput>-402 (ECPG_CONNECT): Could not connect to database %s in line %d.</computeroutput></term>
<listitem> <listitem>
<para> <para>
The connect to the database did not work. The connection attempt to the database did not work.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -718,7 +718,7 @@ EXEC SQL INCLUDE <replaceable>filename</replaceable>; ...@@ -718,7 +718,7 @@ EXEC SQL INCLUDE <replaceable>filename</replaceable>;
<programlisting> <programlisting>
#include &lt;<replaceable>filename</replaceable>.h&gt; #include &lt;<replaceable>filename</replaceable>.h&gt;
</programlisting> </programlisting>
because the file would not be subject to SQL command preprocessing. because this file would not be subject to SQL command preprocessing.
Naturally, you can continue to use the C Naturally, you can continue to use the C
<literal>#include</literal> directive to include other header <literal>#include</literal> directive to include other header
files. files.
...@@ -744,7 +744,7 @@ EXEC SQL INCLUDE <replaceable>filename</replaceable>; ...@@ -744,7 +744,7 @@ EXEC SQL INCLUDE <replaceable>filename</replaceable>;
<acronym>SQL</acronym> statements you used to special function <acronym>SQL</acronym> statements you used to special function
calls. After compiling, you must link with a special library that calls. After compiling, you must link with a special library that
contains the needed functions. These functions fetch information contains the needed functions. These functions fetch information
from the arguments, perform the <acronym>SQL</acronym> query using from the arguments, perform the <acronym>SQL</acronym> command using
the <application>libpq</application> interface, and put the result the <application>libpq</application> interface, and put the result
in the arguments specified for output. in the arguments specified for output.
</para> </para>
...@@ -766,7 +766,7 @@ ecpg prog1.pgc ...@@ -766,7 +766,7 @@ ecpg prog1.pgc
</para> </para>
<para> <para>
The preprocessed file can be compiled normally, for example The preprocessed file can be compiled normally, for example:
<programlisting> <programlisting>
cc -c prog1.c cc -c prog1.c
</programlisting> </programlisting>
...@@ -823,83 +823,33 @@ ECPG = ecpg ...@@ -823,83 +823,33 @@ ECPG = ecpg
<function>ECPGdebug(int <replaceable>on</replaceable>, FILE <function>ECPGdebug(int <replaceable>on</replaceable>, FILE
*<replaceable>stream</replaceable>)</function> turns on debug *<replaceable>stream</replaceable>)</function> turns on debug
logging if called with the first argument non-zero. Debug logging logging if called with the first argument non-zero. Debug logging
is done on <replaceable>stream</replaceable>. Most is done on <replaceable>stream</replaceable>. The log contains
<acronym>SQL</acronym> statement log their arguments and results. all <acronym>SQL</acronym> statements with all the input
</para> variables inserted, and the results from the
<productname>PostgreSQL</productname> server. This can be very
<para> useful when searching for errors in your <acronym>SQL</acronym>
The most important function, <function>ECPGdo</function>, logs statements.
all <acronym>SQL</acronym> statements with both the expanded
string, i.e. the string with all the input variables inserted,
and the result from the <productname>PostgreSQL</productname>
server. This can be very useful when searching for errors in your
<acronym>SQL</acronym> statements.
</para> </para>
</listitem> </listitem>
<listitem> <listitem>
<para> <para>
<function>ECPGstatus()</function> This method returns true if we <function>ECPGstatus()</function> returns true if you
are connected to a database and false if not. are connected to a database and false if not.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
</sect1> </sect1>
<sect1 id="ecpg-porting">
<title>Porting From Other <acronym>RDBMS</acronym> Packages</title>
<para>
The design of <application>ecpg</application> follows the SQL
standard. Porting from a standard RDBMS should not be a problem.
Unfortunately there is no such thing as a standard RDBMS. Therefore
<application>ecpg</application> tries to understand syntax
extensions as long as they do not create conflicts with the
standard.
</para>
<para>
The following list shows all the known incompatibilities. If you
find one not listed please notify the developers. Note, however,
that we list only incompatibilities from a preprocessor of another
RDBMS to <application>ecpg</application> and not
<application>ecpg</application> features that these RDBMS do not
support.
</para>
<variablelist>
<varlistentry>
<term>Syntax of <command>FETCH</command></term>
<indexterm><primary>FETCH</><secondary>embedded SQL</></indexterm>
<listitem>
<para>
The standard syntax for <command>FETCH</command> is:
<synopsis>
FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></> IN|FROM <replaceable>cursor</replaceable>
</synopsis>
<indexterm><primary>Oracle</></>
<productname>Oracle</productname>, however, does not use the
keywords <literal>IN</literal> or <literal>FROM</literal>. This
feature cannot be added since it would create parsing conflicts.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect1>
<sect1 id="ecpg-develop"> <sect1 id="ecpg-develop">
<title>For the Developer</title> <title>Internals</title>
<para> <para>
This section explain how <application>ecpg</application> works This section explain how <application>ECPG</application> works
internally. This information can occasionally be useful to help internally. This information can occasionally be useful to help
users understand how to use <application>ecpg</application>. users understand how to use <application>ECPG</application>.
</para> </para>
<sect2>
<title>The Preprocessor</title>
<para> <para>
The first four lines written by <command>ecpg</command> to the The first four lines written by <command>ecpg</command> to the
output are fixed lines. Two are comments and two are include output are fixed lines. Two are comments and two are include
...@@ -910,8 +860,8 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></> ...@@ -910,8 +860,8 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></>
<para> <para>
When it sees an <command>EXEC SQL</command> statement, it When it sees an <command>EXEC SQL</command> statement, it
intervenes and changes it. The command starts with <command>exec intervenes and changes it. The command starts with <command>EXEC
sql</command> and ends with <command>;</command>. Everything in SQL</command> and ends with <command>;</command>. Everything in
between is treated as an <acronym>SQL</acronym> statement and between is treated as an <acronym>SQL</acronym> statement and
parsed for variable substitution. parsed for variable substitution.
</para> </para>
...@@ -920,16 +870,89 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></> ...@@ -920,16 +870,89 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></>
Variable substitution occurs when a symbol starts with a colon Variable substitution occurs when a symbol starts with a colon
(<literal>:</literal>). The variable with that name is looked up (<literal>:</literal>). The variable with that name is looked up
among the variables that were previously declared within a among the variables that were previously declared within a
<literal>EXEC SQL DECLARE</> section. Depending on whether the <literal>EXEC SQL DECLARE</> section.
variable is being use for input or output, a pointer to the </para>
variable is output to allow access by the function.
<para>
The most important function in the library is
<function>ECPGdo</function>, which takes care of executing most
commands. It takes a variable number of arguments. This can easily
add up to 50 or so arguments, and we hope this will not be a
problem on any platform.
</para>
<para>
The arguments are:
<variablelist>
<varlistentry>
<term>A line number</term>
<listitem>
<para>
This is the line number of the original line; used in error
messages only.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>A string</term>
<listitem>
<para>
This is the <acronym>SQL</acronym> command that is to be issued.
It is modified by the input variables, i.e., the variables that
where not known at compile time but are to be entered in the
command. Where the variables should go the string contains
<literal>?</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Input variables</term>
<listitem>
<para>
Every input variable causes ten arguments to be created. (See below.)
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>ECPGt_EOIT</></term>
<listitem>
<para>
An <type>enum</> telling that there are no more input
variables.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Output variables</term>
<listitem>
<para>
Every output variable causes ten arguments to be created.
(See below.) These variables are filled by the function.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>ECPGt_EORT</></term>
<listitem>
<para>
An <type>enum</> telling that there are no more variables.
</para>
</listitem>
</varlistentry>
</variablelist>
</para> </para>
<para> <para>
For every variable that is part of the <acronym>SQL</acronym> For every variable that is part of the <acronym>SQL</acronym>
query, the function gets other arguments: command, the function gets ten arguments:
<itemizedlist> <orderedlist>
<listitem> <listitem>
<para> <para>
The type as a special symbol. The type as a special symbol.
...@@ -968,8 +991,7 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></> ...@@ -968,8 +991,7 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></>
<listitem> <listitem>
<para> <para>
A pointer to the value of the indicator variable or a pointer A pointer to the indicator variable.
to the pointer of the indicator variable.
</para> </para>
</listitem> </listitem>
...@@ -981,7 +1003,7 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></> ...@@ -981,7 +1003,7 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></>
<listitem> <listitem>
<para> <para>
Number of elements in the indicator array (for array fetches). The number of elements in the indicator array (for array fetches).
</para> </para>
</listitem> </listitem>
...@@ -991,7 +1013,7 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></> ...@@ -991,7 +1013,7 @@ FETCH <optional><replaceable>direction</></> <optional><replaceable>amount</></>
array fetches). array fetches).
</para> </para>
</listitem> </listitem>
</itemizedlist> </orderedlist>
</para> </para>
<para> <para>
...@@ -1039,92 +1061,9 @@ ECPGdo(__LINE__, NULL, "SELECT res FROM mytable WHERE index = ? ", ...@@ -1039,92 +1061,9 @@ ECPGdo(__LINE__, NULL, "SELECT res FROM mytable WHERE index = ? ",
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 147 "foo.pgc" #line 147 "foo.pgc"
</programlisting> </programlisting>
(The indentation in this manual is added for readability and not (The indentation here is added for readability and not
something the preprocessor does.) something the preprocessor does.)
</para> </para>
</sect2>
<sect2>
<title>The Library</title>
<para>
The most important function in the library is
<function>ECPGdo</function>. It takes a variable number of
arguments. Hopefully there are no computers that limit the number
of variables that can be accepted by a
<function>varargs()</function> function. This can easily add up to
50 or so arguments.
</para>
<para>
The arguments are:
<variablelist>
<varlistentry>
<term>A line number</term>
<listitem>
<para>
This is a line number of the original line; used in error
messages only.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>A string</term>
<listitem>
<para>
This is the <acronym>SQL</acronym> query that is to be issued.
It is modified by the input variables, i.e. the variables that
where not known at compile time but are to be entered in the
query. Where the variables should go the string contains
<literal>?</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Input variables</term>
<listitem>
<para>
As described in the section about the preprocessor, every
input variable gets ten arguments.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>ECPGt_EOIT</></term>
<listitem>
<para>
An <type>enum</> telling that there are no more input
variables.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Output variables</term>
<listitem>
<para>
As described in the section about the preprocessor, every
input variable gets ten arguments. These variables are filled
by the function.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>ECPGt_EORT</></term>
<listitem>
<para>
An <type>enum</> telling that there are no more variables.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</sect2>
</sect1> </sect1>
</chapter> </chapter>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/features.sgml,v 2.17 2003/01/15 21:55:52 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/features.sgml,v 2.18 2003/03/13 01:30:28 petere Exp $
--> -->
<appendix id="features"> <appendix id="features">
...@@ -105,7 +105,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/features.sgml,v 2.17 2003/01/15 21:55:52 mo ...@@ -105,7 +105,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/features.sgml,v 2.17 2003/01/15 21:55:52 mo
<para> <para>
The following features defined in <acronym>SQL99</acronym> are not The following features defined in <acronym>SQL99</acronym> are not
implemented in the current release of implemented in this release of
<productname>PostgreSQL</productname>. In a few cases, equivalent <productname>PostgreSQL</productname>. In a few cases, equivalent
functionality is available. functionality is available.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.38 2002/11/11 20:14:03 petere Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/indices.sgml,v 1.39 2003/03/13 01:30:28 petere Exp $ -->
<chapter id="indexes"> <chapter id="indexes">
<title id="indexes-title">Indexes</title> <title id="indexes-title">Indexes</title>
...@@ -83,8 +83,8 @@ CREATE INDEX test1_id_index ON test1 (id); ...@@ -83,8 +83,8 @@ CREATE INDEX test1_id_index ON test1 (id);
</para> </para>
<para> <para>
Indexes can benefit <command>UPDATE</command>s and Indexes can also benefit <command>UPDATE</command> and
<command>DELETE</command>s with search conditions. Indexes can also be <command>DELETE</command> commands with search conditions. Indexes can moreover be
used in join queries. Thus, used in join queries. Thus,
an index defined on a column that is part of a join condition can an index defined on a column that is part of a join condition can
significantly speed up queries with joins. significantly speed up queries with joins.
...@@ -119,7 +119,7 @@ CREATE INDEX test1_id_index ON test1 (id); ...@@ -119,7 +119,7 @@ CREATE INDEX test1_id_index ON test1 (id);
By By
default, the <command>CREATE INDEX</command> command will create a default, the <command>CREATE INDEX</command> command will create a
B-tree index, which fits the most common situations. In B-tree index, which fits the most common situations. In
particular, the <productname>PostgreSQL</productname> query optimizer particular, the <productname>PostgreSQL</productname> query planner
will consider using a B-tree index whenever an indexed column is will consider using a B-tree index whenever an indexed column is
involved in a comparison using one of these operators: involved in a comparison using one of these operators:
...@@ -146,7 +146,7 @@ CREATE INDEX test1_id_index ON test1 (id); ...@@ -146,7 +146,7 @@ CREATE INDEX test1_id_index ON test1 (id);
<synopsis> <synopsis>
CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> USING RTREE (<replaceable>column</replaceable>); CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> USING RTREE (<replaceable>column</replaceable>);
</synopsis> </synopsis>
The <productname>PostgreSQL</productname> query optimizer will The <productname>PostgreSQL</productname> query planner will
consider using an R-tree index whenever an indexed column is consider using an R-tree index whenever an indexed column is
involved in a comparison using one of these operators: involved in a comparison using one of these operators:
...@@ -172,7 +172,7 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> ...@@ -172,7 +172,7 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable>
<primary>hash</primary> <primary>hash</primary>
<see>indexes</see> <see>indexes</see>
</indexterm> </indexterm>
The query optimizer will consider using a hash index whenever an The query planner will consider using a hash index whenever an
indexed column is involved in a comparison using the indexed column is involved in a comparison using the
<literal>=</literal> operator. The following command is used to <literal>=</literal> operator. The following command is used to
create a hash index: create a hash index:
...@@ -196,9 +196,8 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> ...@@ -196,9 +196,8 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable>
standard R-trees using Guttman's quadratic split algorithm. The standard R-trees using Guttman's quadratic split algorithm. The
hash index is an implementation of Litwin's linear hashing. We hash index is an implementation of Litwin's linear hashing. We
mention the algorithms used solely to indicate that all of these mention the algorithms used solely to indicate that all of these
access methods are fully dynamic and do not have to be optimized index methods are fully dynamic and do not have to be optimized
periodically (as is the case with, for example, static hash access periodically (as is the case with, for example, static hash methods).
methods).
</para> </para>
</sect1> </sect1>
...@@ -242,17 +241,17 @@ CREATE INDEX test2_mm_idx ON test2 (major, minor); ...@@ -242,17 +241,17 @@ CREATE INDEX test2_mm_idx ON test2 (major, minor);
</para> </para>
<para> <para>
The query optimizer can use a multicolumn index for queries that The query planner can use a multicolumn index for queries that
involve the first <parameter>n</parameter> consecutive columns in involve the leftmost column in the index definition and any number
the index (when used with appropriate operators), up to the total of columns listed to the right of it without a gap (when
number of columns specified in the index definition. For example, used with appropriate operators). For example,
an index on <literal>(a, b, c)</literal> can be used in queries an index on <literal>(a, b, c)</literal> can be used in queries
involving all of <literal>a</literal>, <literal>b</literal>, and involving all of <literal>a</literal>, <literal>b</literal>, and
<literal>c</literal>, or in queries involving both <literal>c</literal>, or in queries involving both
<literal>a</literal> and <literal>b</literal>, or in queries <literal>a</literal> and <literal>b</literal>, or in queries
involving only <literal>a</literal>, but not in other combinations. involving only <literal>a</literal>, but not in other combinations.
(In a query involving <literal>a</literal> and <literal>c</literal> (In a query involving <literal>a</literal> and <literal>c</literal>
the optimizer might choose to use the index for the planner might choose to use the index for
<literal>a</literal> only and treat <literal>c</literal> like an <literal>a</literal> only and treat <literal>c</literal> like an
ordinary unindexed column.) ordinary unindexed column.)
</para> </para>
...@@ -296,7 +295,7 @@ CREATE UNIQUE INDEX <replaceable>name</replaceable> ON <replaceable>table</repla ...@@ -296,7 +295,7 @@ CREATE UNIQUE INDEX <replaceable>name</replaceable> ON <replaceable>table</repla
<para> <para>
When an index is declared unique, multiple table rows with equal When an index is declared unique, multiple table rows with equal
indexed values will not be allowed. NULL values are not considered indexed values will not be allowed. Null values are not considered
equal. equal.
</para> </para>
...@@ -342,7 +341,7 @@ CREATE UNIQUE INDEX <replaceable>name</replaceable> ON <replaceable>table</repla ...@@ -342,7 +341,7 @@ CREATE UNIQUE INDEX <replaceable>name</replaceable> ON <replaceable>table</repla
SELECT * FROM test1 WHERE lower(col1) = 'value'; SELECT * FROM test1 WHERE lower(col1) = 'value';
</programlisting> </programlisting>
This query can use an index, if one has been This query can use an index, if one has been
defined on the result of the <literal>lower(column)</literal> defined on the result of the <literal>lower(col1)</literal>
operation: operation:
<programlisting> <programlisting>
CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1)); CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));
...@@ -353,7 +352,7 @@ CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1)); ...@@ -353,7 +352,7 @@ CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));
The function in the index definition can take more than one The function in the index definition can take more than one
argument, but they must be table columns, not constants. argument, but they must be table columns, not constants.
Functional indexes are always single-column (namely, the function Functional indexes are always single-column (namely, the function
result) even if the function uses more than one input field; there result) even if the function uses more than one input column; there
cannot be multicolumn indexes that contain function calls. cannot be multicolumn indexes that contain function calls.
</para> </para>
...@@ -377,29 +376,32 @@ CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1)); ...@@ -377,29 +376,32 @@ CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1));
CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> (<replaceable>column</replaceable> <replaceable>opclass</replaceable> <optional>, ...</optional>); CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> (<replaceable>column</replaceable> <replaceable>opclass</replaceable> <optional>, ...</optional>);
</synopsis> </synopsis>
The operator class identifies the operators to be used by the index The operator class identifies the operators to be used by the index
for that column. For example, a B-tree index on four-byte integers for that column. For example, a B-tree index on the type <type>int4</type>
would use the <literal>int4_ops</literal> class; this operator would use the <literal>int4_ops</literal> class; this operator
class includes comparison functions for four-byte integers. In class includes comparison functions for values of type <type>int4</type>. In
practice the default operator class for the column's data type is practice the default operator class for the column's data type is
usually sufficient. The main point of having operator classes is usually sufficient. The main point of having operator classes is
that for some data types, there could be more than one meaningful that for some data types, there could be more than one meaningful
ordering. For example, we might want to sort a complex-number data ordering. For example, we might want to sort a complex-number data
type either by absolute value or by real part. We could do this by type either by absolute value or by real part. We could do this by
defining two operator classes for the data type and then selecting defining two operator classes for the data type and then selecting
the proper class when making an index. There are also some the proper class when making an index.
operator classes with special purposes: </para>
<para>
There are also some built-in operator classes besides the default ones:
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
The operator classes <literal>box_ops</literal> and The operator classes <literal>box_ops</literal> and
<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 <type>box</type> 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 square units or larger, you should use
<literal>bigbox_ops</literal>. <literal>bigbox_ops</literal>.
</para> </para>
</listitem> </listitem>
...@@ -409,25 +411,25 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> ...@@ -409,25 +411,25 @@ CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable>
<para> <para>
The following query shows all defined operator classes: The following query shows all defined operator classes:
<programlisting> <programlisting>
SELECT am.amname AS acc_method, SELECT am.amname AS index_method,
opc.opcname AS ops_name opc.opcname AS opclass_name
FROM pg_am am, pg_opclass opc FROM pg_am am, pg_opclass opc
WHERE opc.opcamid = am.oid WHERE opc.opcamid = am.oid
ORDER BY acc_method, ops_name; ORDER BY index_method, opclass_name;
</programlisting> </programlisting>
It can be extended to show all the operators included in each class: It can be extended to show all the operators included in each class:
<programlisting> <programlisting>
SELECT am.amname AS acc_method, SELECT am.amname AS index_method,
opc.opcname AS ops_name, opc.opcname AS opclass_name,
opr.oprname AS ops_comp opr.oprname AS opclass_operator
FROM pg_am am, pg_opclass opc, pg_amop amop, pg_operator opr FROM pg_am am, pg_opclass opc, pg_amop amop, pg_operator opr
WHERE opc.opcamid = am.oid AND WHERE opc.opcamid = am.oid AND
amop.amopclaid = opc.oid AND amop.amopclaid = opc.oid AND
amop.amopopr = opr.oid amop.amopopr = opr.oid
ORDER BY acc_method, ops_name, ops_comp; ORDER BY index_method, opclass_name, opclass_operator;
</programlisting> </programlisting>
</para> </para>
</sect1> </sect1>
...@@ -465,7 +467,7 @@ SELECT am.amname AS acc_method, ...@@ -465,7 +467,7 @@ SELECT am.amname AS acc_method,
<para> <para>
Suppose you are storing web server access logs in a database. Suppose you are storing web server access logs in a database.
Most accesses originate from the IP range of your organization but Most accesses originate from the IP address range of your organization but
some are from elsewhere (say, employees on dial-up connections). some are from elsewhere (say, employees on dial-up connections).
If your searches by IP are primarily for outside accesses, If your searches by IP are primarily for outside accesses,
you probably do not need to index the IP range that corresponds to your you probably do not need to index the IP range that corresponds to your
...@@ -575,16 +577,16 @@ SELECT * FROM orders WHERE order_nr = 3501; ...@@ -575,16 +577,16 @@ SELECT * FROM orders WHERE order_nr = 3501;
predicate must match the conditions used in the queries that predicate must match the conditions used in the queries that
are supposed to benefit from the index. To be precise, a partial are supposed to benefit from the index. To be precise, a partial
index can be used in a query only if the system can recognize that index can be used in a query only if the system can recognize that
the query's WHERE condition mathematically <firstterm>implies</> the <literal>WHERE</> condition of the query mathematically implies
the index's predicate. the predicate of the index.
<productname>PostgreSQL</productname> does not have a sophisticated <productname>PostgreSQL</productname> does not have a sophisticated
theorem prover that can recognize mathematically equivalent theorem prover that can recognize mathematically equivalent
predicates that are written in different forms. (Not expressions that are written in different forms. (Not
only is such a general theorem prover extremely difficult to only is such a general theorem prover extremely difficult to
create, it would probably be too slow to be of any real use.) create, it would probably be too slow to be of any real use.)
The system can recognize simple inequality implications, for example The system can recognize simple inequality implications, for example
<quote>x &lt; 1</quote> implies <quote>x &lt; 2</quote>; otherwise <quote>x &lt; 1</quote> implies <quote>x &lt; 2</quote>; otherwise
the predicate condition must exactly match the query's WHERE condition the predicate condition must exactly match the query's <literal>WHERE</> condition
or the index will not be recognized to be usable. or the index will not be recognized to be usable.
</para> </para>
...@@ -606,15 +608,18 @@ SELECT * FROM orders WHERE order_nr = 3501; ...@@ -606,15 +608,18 @@ SELECT * FROM orders WHERE order_nr = 3501;
a given subject and target combination, but there might be any number of a given subject and target combination, but there might be any number of
<quote>unsuccessful</> entries. Here is one way to do it: <quote>unsuccessful</> entries. Here is one way to do it:
<programlisting> <programlisting>
CREATE TABLE tests (subject text, CREATE TABLE tests (
target text, subject text,
success bool, target text,
...); success boolean,
...
);
CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target) CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target)
WHERE success; WHERE success;
</programlisting> </programlisting>
This is a particularly efficient way of doing it when there are few This is a particularly efficient way of doing it when there are few
successful trials and many unsuccessful ones. successful tests and many unsuccessful ones.
</para> </para>
</example> </example>
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.128 2003/01/19 00:13:28 momjian Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/installation.sgml,v 1.129 2003/03/13 01:30:28 petere Exp $ -->
<chapter id="installation"> <chapter id="installation">
<title><![%standalone-include[<productname>PostgreSQL</>]]> <title><![%standalone-include[<productname>PostgreSQL</>]]>
...@@ -69,7 +69,7 @@ su - postgres ...@@ -69,7 +69,7 @@ su - postgres
<acronym>GNU</> <application>make</> is often installed under <acronym>GNU</> <application>make</> is often installed under
the name <filename>gmake</filename>; this document will always the name <filename>gmake</filename>; this document will always
refer to it by that name. (On some systems refer to it by that name. (On some systems
<acronym>GNU</acronym> make is the default tool with the name <acronym>GNU</acronym> <application>make</> is the default tool with the name
<filename>make</>.) To test for <acronym>GNU</acronym> <filename>make</>.) To test for <acronym>GNU</acronym>
<application>make</application> enter <application>make</application> enter
<screen> <screen>
...@@ -91,8 +91,8 @@ su - postgres ...@@ -91,8 +91,8 @@ su - postgres
<listitem> <listitem>
<para> <para>
<application>gzip</> is needed to unpack the distribution in the <application>gzip</> is needed to unpack the distribution in the
first place. If you are reading this, you probably already got first place.<![%standalone-include;[ If you are reading this, you probably already got
past that hurdle. past that hurdle.]]>
</para> </para>
</listitem> </listitem>
...@@ -108,7 +108,7 @@ su - postgres ...@@ -108,7 +108,7 @@ su - postgres
specify the <option>--without-readline</option> option for specify the <option>--without-readline</option> option for
<filename>configure</>. (On <productname>NetBSD</productname>, <filename>configure</>. (On <productname>NetBSD</productname>,
the <filename>libedit</filename> library is the <filename>libedit</filename> library is
<productname>readline</productname>-compatible and is used if <productname>Readline</productname>-compatible and is used if
<filename>libreadline</filename> is not found.) <filename>libreadline</filename> is not found.)
</para> </para>
</listitem> </listitem>
...@@ -259,7 +259,7 @@ JAVACMD=$JAVA_HOME/bin/java ...@@ -259,7 +259,7 @@ JAVACMD=$JAVA_HOME/bin/java
<systemitem class="osname">Solaris</>), for other systems you <systemitem class="osname">Solaris</>), for other systems you
can download an add-on package from here: <ulink can download an add-on package from here: <ulink
url="http://www.postgresql.org/~petere/gettext.html" ></ulink>. url="http://www.postgresql.org/~petere/gettext.html" ></ulink>.
If you are using the <application>gettext</> implementation in If you are using the <application>Gettext</> implementation in
the <acronym>GNU</acronym> C library then you will additionally the <acronym>GNU</acronym> C library then you will additionally
need the <productname>GNU Gettext</productname> package for some need the <productname>GNU Gettext</productname> package for some
utility programs. For any of the other implementations you will utility programs. For any of the other implementations you will
...@@ -278,7 +278,7 @@ JAVACMD=$JAVA_HOME/bin/java ...@@ -278,7 +278,7 @@ JAVACMD=$JAVA_HOME/bin/java
</para> </para>
<para> <para>
If you are build from a <acronym>CVS</acronym> tree instead of If you are building from a <acronym>CVS</acronym> tree instead of
using a released source package, or if you want to do development, using a released source package, or if you want to do development,
you also need the following packages: you also need the following packages:
...@@ -427,7 +427,7 @@ JAVACMD=$JAVA_HOME/bin/java ...@@ -427,7 +427,7 @@ JAVACMD=$JAVA_HOME/bin/java
</screen> </screen>
Versions prior to 7.0 do not have this Versions prior to 7.0 do not have this
<filename>postmaster.pid</> file. If you are using such a version <filename>postmaster.pid</> file. If you are using such a version
you must find out the process id of the server yourself, for you must find out the process ID of the server yourself, for
example by typing <userinput>ps ax | grep postmaster</>, and example by typing <userinput>ps ax | grep postmaster</>, and
supply it to the <command>kill</> command. supply it to the <command>kill</> command.
</para> </para>
...@@ -732,7 +732,7 @@ JAVACMD=$JAVA_HOME/bin/java ...@@ -732,7 +732,7 @@ JAVACMD=$JAVA_HOME/bin/java
<para> <para>
To use this option, you will need an implementation of the To use this option, you will need an implementation of the
<application>gettext</> API; see above. <application>Gettext</> API; see above.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -1082,7 +1082,7 @@ All of PostgreSQL is successfully made. Ready to install. ...@@ -1082,7 +1082,7 @@ All of PostgreSQL is successfully made. Ready to install.
<screen> <screen>
<userinput>gmake -C src/interfaces/python install</userinput> <userinput>gmake -C src/interfaces/python install</userinput>
</screen> </screen>
If you do not have superuser access you are on your own: If you do not have root access you are on your own:
you can still take the required files and place them in you can still take the required files and place them in
other directories where Python can find them, but how to other directories where Python can find them, but how to
do that is left as an exercise. do that is left as an exercise.
...@@ -1133,7 +1133,7 @@ All of PostgreSQL is successfully made. Ready to install. ...@@ -1133,7 +1133,7 @@ All of PostgreSQL is successfully made. Ready to install.
<para> <para>
After the installation you can make room by removing the built After the installation you can make room by removing the built
files from the source tree with the command <command>gmake files from the source tree with the command <command>gmake
clean</>. This will preserve the files made by the configure clean</>. This will preserve the files made by the <command>configure</command>
program, so that you can rebuild everything with <command>gmake</> program, so that you can rebuild everything with <command>gmake</>
later on. To reset the source tree to the state in which it was later on. To reset the source tree to the state in which it was
distributed, use <command>gmake distclean</>. If you are going to distributed, use <command>gmake distclean</>. If you are going to
...@@ -1143,8 +1143,8 @@ All of PostgreSQL is successfully made. Ready to install. ...@@ -1143,8 +1143,8 @@ All of PostgreSQL is successfully made. Ready to install.
</formalpara> </formalpara>
<para> <para>
If you perform a build and then discover that your configure If you perform a build and then discover that your <command>configure</>
options were wrong, or if you change anything that configure options were wrong, or if you change anything that <command>configure</>
investigates (for example, software upgrades), then it's a good investigates (for example, software upgrades), then it's a good
idea to do <command>gmake distclean</> before reconfiguring and idea to do <command>gmake distclean</> before reconfiguring and
rebuilding. Without this, your changes in configuration choices rebuilding. Without this, your changes in configuration choices
...@@ -1207,7 +1207,7 @@ setenv LD_LIBRARY_PATH /usr/local/pgsql/lib ...@@ -1207,7 +1207,7 @@ setenv LD_LIBRARY_PATH /usr/local/pgsql/lib
<para> <para>
On <systemitem class="osname">Cygwin</systemitem>, put the library On <systemitem class="osname">Cygwin</systemitem>, put the library
directory in the <envar>PATH</envar> or move the directory in the <envar>PATH</envar> or move the
<filename>.dll</filename> files into the <filename>bin/</filename> <filename>.dll</filename> files into the <filename>bin</filename>
directory. directory.
</para> </para>
...@@ -1283,7 +1283,7 @@ set path = ( /usr/local/pgsql/bin $path ) ...@@ -1283,7 +1283,7 @@ set path = ( /usr/local/pgsql/bin $path )
<seealso>man pages</seealso> <seealso>man pages</seealso>
</indexterm> </indexterm>
To enable your system to find the <application>man</> To enable your system to find the <application>man</>
documentation, you need to add a line like the following to a documentation, you need to add lines like the following to a
shell start-up file unless you installed into a location that is shell start-up file unless you installed into a location that is
searched by default. searched by default.
<programlisting> <programlisting>
...@@ -1544,8 +1544,8 @@ gunzip -c user.ps.gz \ ...@@ -1544,8 +1544,8 @@ gunzip -c user.ps.gz \
<entry>7.3</entry> <entry>7.3</entry>
<entry>2002-10-28, <entry>2002-10-28,
10.20 Tom Lane (<email>tgl@sss.pgh.pa.us</email>), 10.20 Tom Lane (<email>tgl@sss.pgh.pa.us</email>),
11.00, 11.11, 32 &amp; 64 bit, Giles Lean (<email>giles@nemeton.com.au</email>)</entry> 11.00, 11.11, 32 and 64 bit, Giles Lean (<email>giles@nemeton.com.au</email>)</entry>
<entry>gcc and cc; see also <filename>doc/FAQ_HPUX</filename></entry> <entry><command>gcc</> and <command>cc</>; see also <filename>doc/FAQ_HPUX</filename></entry>
</row> </row>
<row> <row>
<entry><systemitem class="osname">IRIX</></entry> <entry><systemitem class="osname">IRIX</></entry>
...@@ -1585,7 +1585,7 @@ gunzip -c user.ps.gz \ ...@@ -1585,7 +1585,7 @@ gunzip -c user.ps.gz \
<entry>7.3</entry> <entry>7.3</entry>
<entry>2002-11-19, <entry>2002-11-19,
Permaine Cheung <email>pcheung@redhat.com</email>)</entry> Permaine Cheung <email>pcheung@redhat.com</email>)</entry>
<entry>#undef HAS_TEST_AND_SET, remove slock_t typedef</entry> <entry><literal>#undef HAS_TEST_AND_SET</>, remove <type>slock_t</> <literal>typedef</></entry>
</row> </row>
<row> <row>
<entry><systemitem class="osname">Linux</></entry> <entry><systemitem class="osname">Linux</></entry>
...@@ -1715,7 +1715,7 @@ gunzip -c user.ps.gz \ ...@@ -1715,7 +1715,7 @@ gunzip -c user.ps.gz \
<entry><systemitem>x86</></entry> <entry><systemitem>x86</></entry>
<entry>7.3.1</entry> <entry>7.3.1</entry>
<entry>2002-12-11, Shibashish Satpathy (<email>shib@postmark.net</>)</entry> <entry>2002-12-11, Shibashish Satpathy (<email>shib@postmark.net</>)</entry>
<entry>5.0.4, gcc; see also <filename>doc/FAQ_SCO</filename></entry> <entry>5.0.4, <command>gcc</>; see also <filename>doc/FAQ_SCO</filename></entry>
</row> </row>
<row> <row>
<entry><systemitem class="osname">Solaris</></entry> <entry><systemitem class="osname">Solaris</></entry>
...@@ -1723,7 +1723,7 @@ gunzip -c user.ps.gz \ ...@@ -1723,7 +1723,7 @@ gunzip -c user.ps.gz \
<entry>7.3</entry> <entry>7.3</entry>
<entry>2002-10-28, <entry>2002-10-28,
Andrew Sullivan (<email>andrew@libertyrms.info</email>)</entry> Andrew Sullivan (<email>andrew@libertyrms.info</email>)</entry>
<entry>Solaris 7 &amp; 8; see also <filename>doc/FAQ_Solaris</filename></entry> <entry>Solaris 7 and 8; see also <filename>doc/FAQ_Solaris</filename></entry>
</row> </row>
<row> <row>
<entry><systemitem class="osname">Solaris</></entry> <entry><systemitem class="osname">Solaris</></entry>
...@@ -1813,7 +1813,7 @@ gunzip -c user.ps.gz \ ...@@ -1813,7 +1813,7 @@ gunzip -c user.ps.gz \
<entry>7.2</entry> <entry>7.2</entry>
<entry>2001-11-29, <entry>2001-11-29,
Cyril Velter (<email>cyril.velter@libertysurf.fr</email>)</entry> Cyril Velter (<email>cyril.velter@libertysurf.fr</email>)</entry>
<entry>needs updates to semaphore code</entry> <entry>needs updates to semaphore code</entry>
</row> </row>
<row> <row>
<entry><systemitem class="osname">DG/UX 5.4R4.11</></entry> <entry><systemitem class="osname">DG/UX 5.4R4.11</></entry>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.27 2002/04/18 14:28:14 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.28 2003/03/13 01:30:28 petere Exp $
--> -->
<chapter id="largeObjects"> <chapter id="largeObjects">
...@@ -8,9 +8,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.27 2002/04/18 14:28:14 momjia ...@@ -8,9 +8,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.27 2002/04/18 14:28:14 momjia
<indexterm zone="largeobjects"><primary>large object</></> <indexterm zone="largeobjects"><primary>large object</></>
<indexterm><primary>BLOB</><see>large object</></> <indexterm><primary>BLOB</><see>large object</></>
<sect1 id="lo-intro">
<title>Introduction</title>
<para> <para>
In <productname>PostgreSQL</productname> releases prior to 7.1, In <productname>PostgreSQL</productname> releases prior to 7.1,
the size of any row in the database could not exceed the size of a the size of any row in the database could not exceed the size of a
...@@ -19,10 +16,24 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.27 2002/04/18 14:28:14 momjia ...@@ -19,10 +16,24 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.27 2002/04/18 14:28:14 momjia
size of a data value was relatively low. To support the storage of size of a data value was relatively low. To support the storage of
larger atomic values, <productname>PostgreSQL</productname> larger atomic values, <productname>PostgreSQL</productname>
provided and continues to provide a large object interface. This provided and continues to provide a large object interface. This
interface provides file-oriented access to user data that has been interface provides file-oriented access to user data that is stored in
declared to be a large object. a special large-object structure.
</para> </para>
<para>
This chapter describes the implementation and the programming and
query language interfaces to <productname>PostgreSQL</productname>
large object data. We use the <application>libpq</application> C
library for the examples in this chapter, but most programming
interfaces native to <productname>PostgreSQL</productname> support
equivalent functionality. Other interfaces may use the large
object interface internally to provide generic support for large
values. This is not described here.
</para>
<sect1 id="lo-history">
<title>History</title>
<para> <para>
<productname>POSTGRES 4.2</productname>, the indirect predecessor <productname>POSTGRES 4.2</productname>, the indirect predecessor
of <productname>PostgreSQL</productname>, supported three standard of <productname>PostgreSQL</productname>, supported three standard
...@@ -50,21 +61,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.27 2002/04/18 14:28:14 momjia ...@@ -50,21 +61,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.27 2002/04/18 14:28:14 momjia
(nicknamed <quote><acronym>TOAST</acronym></quote>) that allows (nicknamed <quote><acronym>TOAST</acronym></quote>) that allows
data rows to be much larger than individual data pages. This data rows to be much larger than individual data pages. This
makes the large object interface partially obsolete. One makes the large object interface partially obsolete. One
remaining advantage of the large object interface is that it remaining advantage of the large object interface is that it allows values up
allows random access to the data, i.e., the ability to read or to 2 GB in size, whereas <acronym>TOAST</acronym> can only handle 1 GB.
write small chunks of a large value. It is planned to equip
<acronym>TOAST</acronym> with such functionality in the future.
</para>
<para>
This section describes the implementation and the programming and
query language interfaces to <productname>PostgreSQL</productname>
large object data. We use the <application>libpq</application> C
library for the examples in this section, but most programming
interfaces native to <productname>PostgreSQL</productname> support
equivalent functionality. Other interfaces may use the large
object interface internally to provide generic support for large
values. This is not described here.
</para> </para>
</sect1> </sect1>
...@@ -75,64 +73,45 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.27 2002/04/18 14:28:14 momjia ...@@ -75,64 +73,45 @@ $Header: /cvsroot/pgsql/doc/src/sgml/lobj.sgml,v 1.27 2002/04/18 14:28:14 momjia
<para> <para>
The large object implementation breaks large The large object implementation breaks large
objects up into <quote>chunks</quote> and stores the chunks in objects up into <quote>chunks</quote> and stores the chunks in
tuples in the database. A B-tree index guarantees fast rows in the database. A B-tree index guarantees fast
searches for the correct chunk number when doing random searches for the correct chunk number when doing random
access reads and writes. access reads and writes.
</para> </para>
</sect1> </sect1>
<sect1 id="lo-interfaces"> <sect1 id="lo-interfaces">
<title>Interfaces</title> <title>Client Interfaces</title>
<para> <para>
The facilities <productname>PostgreSQL</productname> provides to This section describes the facilities that
access large objects, both in the backend as part of user-defined <productname>PostgreSQL</productname> client interface libraries
functions or the front end as part of an application provide for accessing large objects. All large object
using the interface, are described below. For users manipulation using these functions <emphasis>must</emphasis> take
familiar with <productname>POSTGRES 4.2</productname>, place within an SQL transaction block. (This requirement is
<productname>PostgreSQL</productname> has a new set of strictly enforced as of <productname>PostgreSQL 6.5</>, though it
functions providing a more coherent interface. has been an implicit requirement in previous versions, resulting
in misbehavior if ignored.)
<note> The <productname>PostgreSQL</productname> large object interface is modeled after
<para> the <acronym>Unix</acronym> file-system interface, with analogues of
All large object manipulation <emphasis>must</emphasis> take <function>open</function>, <function>read</function>,
place within an SQL transaction. This requirement is strictly <function>write</function>,
enforced as of <productname>PostgreSQL 6.5</>, though it has been an <function>lseek</function>, etc.
implicit requirement in previous versions, resulting in
misbehavior if ignored.
</para>
</note>
</para> </para>
<para> <para>
The <productname>PostgreSQL</productname> large object interface is modeled after Client applications which use the large object interface in
the <acronym>Unix</acronym> file-system interface, with analogues of <application>libpq</application> should include the header file
<function>open(2)</function>, <function>read(2)</function>, <filename>libpq/libpq-fs.h</filename> and link with the
<function>write(2)</function>, <application>libpq</application> library.
<function>lseek(2)</function>, etc. User
functions call these routines to retrieve only the data of
interest from a large object. For example, if a large
object type called <type>mugshot</type> existed that stored
photographs of faces, then a function called <function>beard</function> could
be declared on <type>mugshot</type> data. <function>beard</> could look at the
lower third of a photograph, and determine the color of
the beard that appeared there, if any. The entire
large-object value need not be buffered, or even
examined, by the <function>beard</function> function.
Large objects may be accessed from dynamically-loaded <acronym>C</acronym>
functions or database client programs that link the
library. <productname>PostgreSQL</productname> provides a set of routines that
support opening, reading, writing, closing, and seeking on
large objects.
</para> </para>
<sect2> <sect2>
<title>Creating a Large Object</title> <title>Creating a Large Object</title>
<para> <para>
The routine The function
<synopsis> <synopsis>
Oid lo_creat(PGconn *<replaceable class="parameter">conn</replaceable>, int <replaceable class="parameter">mode</replaceable>) Oid lo_creat(PGconn *conn, int mode);
</synopsis> </synopsis>
creates a new large object. creates a new large object.
<replaceable class="parameter">mode</replaceable> is a bit mask <replaceable class="parameter">mode</replaceable> is a bit mask
...@@ -145,7 +124,11 @@ Oid lo_creat(PGconn *<replaceable class="parameter">conn</replaceable>, int <rep ...@@ -145,7 +124,11 @@ Oid lo_creat(PGconn *<replaceable class="parameter">conn</replaceable>, int <rep
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
bits should always be zero now. bits should always be zero now.
The commands below create a large object: The return value is the OID that was assigned to the new large object.
</para>
<para>
An example:
<programlisting> <programlisting>
inv_oid = lo_creat(INV_READ|INV_WRITE); inv_oid = lo_creat(INV_READ|INV_WRITE);
</programlisting> </programlisting>
...@@ -158,11 +141,12 @@ inv_oid = lo_creat(INV_READ|INV_WRITE); ...@@ -158,11 +141,12 @@ inv_oid = lo_creat(INV_READ|INV_WRITE);
<para> <para>
To import an operating system 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 *conn, const char *filename);
</synopsis> </synopsis>
<replaceable class="parameter">filename</replaceable> <replaceable class="parameter">filename</replaceable>
specifies the operating system 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.
The return value is the OID that was assigned to the new large object.
</para> </para>
</sect2> </sect2>
...@@ -173,7 +157,7 @@ Oid lo_import(PGconn *<replaceable class="parameter">conn</replaceable>, const c ...@@ -173,7 +157,7 @@ Oid lo_import(PGconn *<replaceable class="parameter">conn</replaceable>, const c
To export a large object To export a large object
into an operating system 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 *conn, Oid lobjId, const char *filename);
</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
...@@ -187,7 +171,7 @@ int lo_export(PGconn *<replaceable class="parameter">conn</replaceable>, Oid <re ...@@ -187,7 +171,7 @@ int lo_export(PGconn *<replaceable class="parameter">conn</replaceable>, Oid <re
<para> <para>
To open an existing large object, call To open an existing large object, call
<synopsis> <synopsis>
int lo_open(PGconn *conn, Oid lobjId, int mode) 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
...@@ -205,10 +189,10 @@ int lo_open(PGconn *conn, Oid lobjId, int mode) ...@@ -205,10 +189,10 @@ int lo_open(PGconn *conn, Oid lobjId, int mode)
<title>Writing Data to a Large Object</title> <title>Writing Data to a Large Object</title>
<para> <para>
The routine The function
<programlisting> <synopsis>
int lo_write(PGconn *conn, int fd, const char *buf, size_t len) int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
</programlisting> </synopsis>
writes <parameter>len</parameter> bytes from <parameter>buf</parameter> to large object <parameter>fd</>. The <parameter>fd</parameter> writes <parameter>len</parameter> bytes from <parameter>buf</parameter> to large object <parameter>fd</>. The <parameter>fd</parameter>
argument must have been returned by a previous <function>lo_open</function>. argument must have been returned by a previous <function>lo_open</function>.
The number of bytes actually written is returned. In The number of bytes actually written is returned. In
...@@ -220,10 +204,10 @@ int lo_write(PGconn *conn, int fd, const char *buf, size_t len) ...@@ -220,10 +204,10 @@ int lo_write(PGconn *conn, int fd, const char *buf, size_t len)
<title>Reading Data from a Large Object</title> <title>Reading Data from a Large Object</title>
<para> <para>
The routine The function
<programlisting> <synopsis>
int lo_read(PGconn *conn, int fd, char *buf, size_t len) int lo_read(PGconn *conn, int fd, char *buf, size_t len);
</programlisting> </synopsis>
reads <parameter>len</parameter> bytes from large object <parameter>fd</parameter> into <parameter>buf</parameter>. The <parameter>fd</parameter> reads <parameter>len</parameter> bytes from large object <parameter>fd</parameter> into <parameter>buf</parameter>. The <parameter>fd</parameter>
argument must have been returned by a previous <function>lo_open</function>. argument must have been returned by a previous <function>lo_open</function>.
The number of bytes actually read is returned. In The number of bytes actually read is returned. In
...@@ -237,13 +221,26 @@ int lo_read(PGconn *conn, int fd, char *buf, size_t len) ...@@ -237,13 +221,26 @@ int lo_read(PGconn *conn, int fd, char *buf, size_t len)
<para> <para>
To change the current read or write location on a large To change the current read or write location on a large
object, call object, call
<programlisting> <synopsis>
int lo_lseek(PGconn *conn, int fd, int offset, int whence) int lo_lseek(PGconn *conn, int fd, int offset, int whence);
</programlisting> </synopsis>
This routine moves the current location pointer for the This function moves the current location pointer for the
large object described by <parameter>fd</> to the new location specified large object described by <parameter>fd</> to the new location specified
by <parameter>offset</>. The valid values for <parameter>whence</> are by <parameter>offset</>. The valid values for <parameter>whence</> are
<symbol>SEEK_SET</>, <symbol>SEEK_CUR</>, and <symbol>SEEK_END</>. <symbol>SEEK_SET</> (seek from object start), <symbol>SEEK_CUR</> (seek from current position), and <symbol>SEEK_END</> (seek from object end). The return value is the new location pointer.
</para>
</sect2>
<sect2>
<title>Obtaining the Seek Position of a Large Object</title>
<para>
To obtain the current read or write location of a large object,
call
<synopsis>
int lo_tell(PGconn *conn, int fd);
</synopsis>
If there is an error, the return value is negative.
</para> </para>
</sect2> </sect2>
...@@ -252,9 +249,9 @@ int lo_lseek(PGconn *conn, int fd, int offset, int whence) ...@@ -252,9 +249,9 @@ int lo_lseek(PGconn *conn, int fd, int offset, int whence)
<para> <para>
A large object may be closed by calling A large object may be closed by calling
<programlisting> <synopsis>
int lo_close(PGconn *conn, int fd) int lo_close(PGconn *conn, int fd);
</programlisting> </synopsis>
where <parameter>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.
...@@ -267,7 +264,7 @@ int lo_close(PGconn *conn, int fd) ...@@ -267,7 +264,7 @@ int lo_close(PGconn *conn, int fd)
<para> <para>
To remove a large object from the database, call To remove a large object from the database, call
<synopsis> <synopsis>
int lo_unlink(PGconn *<replaceable class="parameter">conn</replaceable>, Oid lobjId) int lo_unlink(PGconn *conn, Oid lobjId);
</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 remove. In the event of an error, the return value is negative. object to remove. In the event of an error, the return value is negative.
...@@ -278,14 +275,14 @@ int lo_unlink(PGconn *<replaceable class="parameter">conn</replaceable>, Oid lob ...@@ -278,14 +275,14 @@ int lo_unlink(PGconn *<replaceable class="parameter">conn</replaceable>, Oid lob
</sect1> </sect1>
<sect1 id="lo-funcs"> <sect1 id="lo-funcs">
<title>Server-side Built-in Functions</title> <title>Server-side Functions</title>
<para> <para>
There are two built-in registered functions, <function>lo_import</function> There are two built-in server-side functions, <function>lo_import</function>
and <function>lo_export</function> which are convenient for use and <function>lo_export</function>, for large object access, which are available for use
in <acronym>SQL</acronym> in <acronym>SQL</acronym>
queries. commands.
Here is an example of their use Here is an example of their use:
<programlisting> <programlisting>
CREATE TABLE image ( CREATE TABLE image (
name text, name text,
...@@ -301,23 +298,20 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image ...@@ -301,23 +298,20 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image
</para> </para>
</sect1> </sect1>
<sect1 id="lo-libpq"> <sect1 id="lo-examplesect">
<title>Accessing Large Objects from <application>Libpq</application></title> <title>Example Program</title>
<para> <para>
<xref linkend="lo-example"> 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 reader's commented out but are left in the source for the reader's
benefit. This program can be found in benefit. This program can also be found in
<filename>src/test/examples/testlo.c</filename> in the source distribution. <filename>src/test/examples/testlo.c</filename> in the source distribution.
Frontend applications which use the large object interface
in <application>libpq</application> should include the header file
<filename>libpq/libpq-fs.h</filename> and link with the <application>libpq</application> library.
</para> </para>
<example id="lo-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/manage-ag.sgml,v 2.24 2002/11/15 03:11:17 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.25 2003/03/13 01:30:29 petere Exp $
--> -->
<chapter id="managing-databases"> <chapter id="managing-databases">
...@@ -16,7 +16,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.24 2002/11/15 03:11:17 m ...@@ -16,7 +16,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.24 2002/11/15 03:11:17 m
them. them.
</para> </para>
<sect1> <sect1 id="manage-ag-overview">
<title>Overview</title> <title>Overview</title>
<para> <para>
...@@ -24,8 +24,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.24 2002/11/15 03:11:17 m ...@@ -24,8 +24,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.24 2002/11/15 03:11:17 m
(<quote>database objects</quote>). Generally, every database (<quote>database objects</quote>). Generally, every database
object (tables, functions, etc.) belongs to one and only one object (tables, functions, etc.) belongs to one and only one
database. (But there are a few system catalogs, for example database. (But there are a few system catalogs, for example
<literal>pg_database</>, that belong to a whole installation and <literal>pg_database</>, that belong to a whole cluster and
are accessible from each database within the installation.) More are accessible from each database within the cluster.) More
accurately, a database is a collection of schemas and the schemas accurately, a database is a collection of schemas and the schemas
contain the tables, functions, etc. So the full hierarchy is: contain the tables, functions, etc. So the full hierarchy is:
server, database, schema, table (or something else instead of a server, database, schema, table (or something else instead of a
...@@ -70,10 +70,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.24 2002/11/15 03:11:17 m ...@@ -70,10 +70,10 @@ $Header: /cvsroot/pgsql/doc/src/sgml/manage-ag.sgml,v 2.24 2002/11/15 03:11:17 m
</para> </para>
<para> <para>
Databases are created with the query language command Databases are created with the SQL command
<command>CREATE DATABASE</command>: <command>CREATE DATABASE</command>:
<synopsis> <synopsis>
CREATE DATABASE <replaceable>name</> CREATE DATABASE <replaceable>name</>;
</synopsis> </synopsis>
where <replaceable>name</> follows the usual rules for where <replaceable>name</> follows the usual rules for
<acronym>SQL</acronym> identifiers. The current user automatically <acronym>SQL</acronym> identifiers. The current user automatically
...@@ -93,14 +93,14 @@ CREATE DATABASE <replaceable>name</> ...@@ -93,14 +93,14 @@ CREATE DATABASE <replaceable>name</>
question remains how the <emphasis>first</> database at any given question remains how the <emphasis>first</> database at any given
site can be created. The first database is always created by the site can be created. The first database is always created by the
<command>initdb</> command when the data storage area is <command>initdb</> command when the data storage area is
initialized. (See <xref linkend="creating-cluster">.) By convention initialized. (See <xref linkend="creating-cluster">.)
this database is called <literal>template1</>. So to create the This database is called <literal>template1</>. So to create the
first <quote>real</> database you can connect to first <quote>real</> database you can connect to
<literal>template1</>. <literal>template1</>.
</para> </para>
<para> <para>
The name <quote>template1</quote> is no accident: When a new The name <literal>template1</literal> is no accident: When a new
database is created, the template database is essentially cloned. database is created, the template database is essentially cloned.
This means that any changes you make in <literal>template1</> are This means that any changes you make in <literal>template1</> are
propagated to all subsequently created databases. This implies that propagated to all subsequently created databases. This implies that
...@@ -118,9 +118,9 @@ CREATE DATABASE <replaceable>name</> ...@@ -118,9 +118,9 @@ CREATE DATABASE <replaceable>name</>
createdb <replaceable class="parameter">dbname</replaceable> createdb <replaceable class="parameter">dbname</replaceable>
</synopsis> </synopsis>
<command>createdb</> does no magic. It connects to the template1 <command>createdb</> does no magic. It connects to the <literal>template1</>
database and issues the <command>CREATE DATABASE</> command, database and issues the <command>CREATE DATABASE</> command,
exactly as described above. It uses the <application>psql</> program exactly as described above. It uses the <command>psql</> program
internally. The reference page on <command>createdb</> contains the invocation internally. The reference page on <command>createdb</> contains the invocation
details. Note that <command>createdb</> without any arguments will create details. Note that <command>createdb</> without any arguments will create
a database with the current user name, which may or may not be what a database with the current user name, which may or may not be what
...@@ -174,7 +174,7 @@ createdb -O <replaceable>username</> <replaceable>dbname</> ...@@ -174,7 +174,7 @@ createdb -O <replaceable>username</> <replaceable>dbname</>
<literal>template1</>, that is, only the standard objects predefined by <literal>template1</>, that is, only the standard objects predefined by
your version of <productname>PostgreSQL</productname>. your version of <productname>PostgreSQL</productname>.
<literal>template0</> should never be changed <literal>template0</> should never be changed
after <literal>initdb</>. By instructing <command>CREATE DATABASE</> to after <command>initdb</>. By instructing <command>CREATE DATABASE</> to
copy <literal>template0</> instead of <literal>template1</>, you can copy <literal>template0</> instead of <literal>template1</>, you can
create a <quote>virgin</> user database that contains none of the create a <quote>virgin</> user database that contains none of the
site-local additions in <literal>template1</>. This is particularly site-local additions in <literal>template1</>. This is particularly
...@@ -198,7 +198,7 @@ createdb -T template0 <replaceable>dbname</> ...@@ -198,7 +198,7 @@ createdb -T template0 <replaceable>dbname</>
<para> <para>
It is possible to create additional template databases, and indeed It is possible to create additional template databases, and indeed
one might copy any database in an installation by specifying its name one might copy any database in a cluster by specifying its name
as the template for <command>CREATE DATABASE</>. It is important to as the template for <command>CREATE DATABASE</>. It is important to
understand, however, that this is not (yet) intended as understand, however, that this is not (yet) intended as
a general-purpose <quote><command>COPY DATABASE</command></quote> facility. In particular, it is a general-purpose <quote><command>COPY DATABASE</command></quote> facility. In particular, it is
...@@ -206,7 +206,7 @@ createdb -T template0 <replaceable>dbname</> ...@@ -206,7 +206,7 @@ createdb -T template0 <replaceable>dbname</>
in progress) in progress)
for the duration of the copying operation. <command>CREATE DATABASE</> for the duration of the copying operation. <command>CREATE DATABASE</>
will check will check
that no backend processes (other than itself) are connected to that no session (other than itself) is connected to
the source database at the start of the operation, but this does not the source database at the start of the operation, but this does not
guarantee that changes cannot be made while the copy proceeds, which guarantee that changes cannot be made while the copy proceeds, which
would result in an inconsistent copied database. Therefore, would result in an inconsistent copied database. Therefore,
...@@ -225,11 +225,9 @@ createdb -T template0 <replaceable>dbname</> ...@@ -225,11 +225,9 @@ createdb -T template0 <replaceable>dbname</>
If <literal>datallowconn</literal> is false, then no new connections If <literal>datallowconn</literal> is false, then no new connections
to that database will be allowed (but existing sessions are not killed to that database will be allowed (but existing sessions are not killed
simply by setting the flag false). The <literal>template0</literal> simply by setting the flag false). The <literal>template0</literal>
database is normally marked <literal>datallowconn</literal> = database is normally marked <literal>datallowconn = false</> to prevent modification of it.
<literal>false</> to prevent modification of it.
Both <literal>template0</literal> and <literal>template1</literal> Both <literal>template0</literal> and <literal>template1</literal>
should always be marked with <literal>datistemplate</literal> = should always be marked with <literal>datistemplate = true</>.
<literal>true</>.
</para> </para>
<para> <para>
...@@ -237,11 +235,11 @@ createdb -T template0 <replaceable>dbname</> ...@@ -237,11 +235,11 @@ createdb -T template0 <replaceable>dbname</>
it is a good idea to perform it is a good idea to perform
<command>VACUUM FREEZE</> or <command>VACUUM FULL FREEZE</> in that <command>VACUUM FREEZE</> or <command>VACUUM FULL FREEZE</> in that
database. If this is done when there are no other open transactions database. If this is done when there are no other open transactions
in the same database, then it is guaranteed that all tuples in the in the same database, then it is guaranteed that all rows in the
database are <quote>frozen</> and will not be subject to transaction database are <quote>frozen</> and will not be subject to transaction
ID wraparound problems. This is particularly important for a database ID wraparound problems. This is particularly important for a database
that will have <literal>datallowconn</literal> set to false, since it that will have <literal>datallowconn</literal> set to false, since it
will be impossible to do routine maintenance <command>VACUUM</>s on will be impossible to do routine maintenance <command>VACUUM</> in
such a database. such a database.
See <xref linkend="vacuum-for-wraparound"> for more information. See <xref linkend="vacuum-for-wraparound"> for more information.
</para> </para>
...@@ -295,7 +293,7 @@ ALTER DATABASE mydb SET geqo TO off; ...@@ -295,7 +293,7 @@ ALTER DATABASE mydb SET geqo TO off;
<para> <para>
It is possible to create a database in a location other than the It is possible to create a database in a location other than the
default location for the installation. Remember that all database access default location for the installation. But remember that all database access
occurs through the occurs through the
database server, so any location specified must be database server, so any location specified must be
accessible by the server. accessible by the server.
...@@ -317,7 +315,7 @@ ALTER DATABASE mydb SET geqo TO off; ...@@ -317,7 +315,7 @@ ALTER DATABASE mydb SET geqo TO off;
<para> <para>
To create the variable in the environment of the server process To create the variable in the environment of the server process
you must first shut down the server, define the variable, you must first shut down the server, define the variable,
initialize the data area, and finally restart the server. (See initialize the data area, and finally restart the server. (See also
<xref linkend="postmaster-shutdown"> and <xref <xref linkend="postmaster-shutdown"> and <xref
linkend="postmaster-start">.) To set an environment variable, type linkend="postmaster-start">.) To set an environment variable, type
<programlisting> <programlisting>
...@@ -328,7 +326,7 @@ export PGDATA2 ...@@ -328,7 +326,7 @@ export PGDATA2
<programlisting> <programlisting>
setenv PGDATA2 /home/postgres/data setenv PGDATA2 /home/postgres/data
</programlisting> </programlisting>
in <application>csh</> or <application>tcsh</>. You have to make sure that this environment in <command>csh</> or <command>tcsh</>. You have to make sure that this environment
variable is always defined in the server environment, otherwise variable is always defined in the server environment, otherwise
you won't be able to access that database. Therefore you probably you won't be able to access that database. Therefore you probably
want to set it in some sort of shell start-up file or server want to set it in some sort of shell start-up file or server
...@@ -352,7 +350,7 @@ initlocation PGDATA2 ...@@ -352,7 +350,7 @@ initlocation PGDATA2
<para> <para>
To create a database within the new location, use the command To create a database within the new location, use the command
<synopsis> <synopsis>
CREATE DATABASE <replaceable>name</> WITH LOCATION = '<replaceable>location</>' CREATE DATABASE <replaceable>name</> WITH LOCATION '<replaceable>location</>';
</synopsis> </synopsis>
where <replaceable>location</> is the environment variable you where <replaceable>location</> is the environment variable you
used, <envar>PGDATA2</> in this example. The <command>createdb</> used, <envar>PGDATA2</> in this example. The <command>createdb</>
...@@ -386,9 +384,9 @@ gmake CPPFLAGS=-DALLOW_ABSOLUTE_DBPATHS all ...@@ -386,9 +384,9 @@ gmake CPPFLAGS=-DALLOW_ABSOLUTE_DBPATHS all
<para> <para>
Databases are destroyed with the command <command>DROP DATABASE</command>: Databases are destroyed with the command <command>DROP DATABASE</command>:
<synopsis> <synopsis>
DROP DATABASE <replaceable>name</> DROP DATABASE <replaceable>name</>;
</synopsis> </synopsis>
Only the owner of the database (i.e., the user that created it), or Only the owner of the database (i.e., the user that created it) or
a superuser, can drop a database. Dropping a database removes all objects a superuser, can drop a database. Dropping a database removes all objects
that were that were
contained within the database. The destruction of a database cannot contained within the database. The destruction of a database cannot
...@@ -399,8 +397,8 @@ DROP DATABASE <replaceable>name</> ...@@ -399,8 +397,8 @@ DROP DATABASE <replaceable>name</>
You cannot execute the <command>DROP DATABASE</command> command You cannot execute the <command>DROP DATABASE</command> command
while connected to the victim database. You can, however, be while connected to the victim database. You can, however, be
connected to any other database, including the <literal>template1</> connected to any other database, including the <literal>template1</>
database, database.
which would be the only option for dropping the last user database of a <literal>template1</> would be the only option for dropping the last user database of a
given cluster. given cluster.
</para> </para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.33 2003/02/19 04:06:28 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.34 2003/03/13 01:30:29 petere Exp $
--> -->
<chapter id="mvcc"> <chapter id="mvcc">
...@@ -116,7 +116,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.33 2003/02/19 04:06:28 momjia ...@@ -116,7 +116,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.33 2003/02/19 04:06:28 momjia
<table tocentry="1" id="mvcc-isolevel-table"> <table tocentry="1" id="mvcc-isolevel-table">
<title><acronym>SQL</acronym> Transaction Isolation Levels</title> <title><acronym>SQL</acronym> Transaction Isolation Levels</title>
<titleabbrev>Isolation Levels</titleabbrev>
<tgroup cols="4"> <tgroup cols="4">
<thead> <thead>
<row> <row>
...@@ -222,7 +221,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.33 2003/02/19 04:06:28 momjia ...@@ -222,7 +221,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.33 2003/02/19 04:06:28 momjia
executed within its own transaction, even though they are not yet executed within its own transaction, even though they are not yet
committed.) In effect, a <command>SELECT</command> query committed.) In effect, a <command>SELECT</command> query
sees a snapshot of the database as of the instant that that query sees a snapshot of the database as of the instant that that query
begins to run. Notice that two successive <command>SELECT</command>s can begins to run. Notice that two successive <command>SELECT</command> commands can
see different data, even though they are within a single transaction, if see different data, even though they are within a single transaction, if
other transactions other transactions
commit changes during execution of the first <command>SELECT</command>. commit changes during execution of the first <command>SELECT</command>.
...@@ -232,7 +231,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.33 2003/02/19 04:06:28 momjia ...@@ -232,7 +231,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.33 2003/02/19 04:06:28 momjia
<command>UPDATE</command>, <command>DELETE</command>, and <command>SELECT <command>UPDATE</command>, <command>DELETE</command>, and <command>SELECT
FOR UPDATE</command> commands behave the same as <command>SELECT</command> FOR UPDATE</command> commands behave the same as <command>SELECT</command>
in terms of searching for target rows: they will only find target rows in terms of searching for target rows: they will only find target rows
that were committed as of the query start time. However, such a target that were committed as of the command start time. However, such a target
row may have already been updated (or deleted or marked for update) by row may have already been updated (or deleted or marked for update) by
another concurrent transaction by the time it is found. In this case, the another concurrent transaction by the time it is found. In this case, the
would-be updater will wait for the first updating transaction to commit or would-be updater will wait for the first updating transaction to commit or
...@@ -241,18 +240,18 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.33 2003/02/19 04:06:28 momjia ...@@ -241,18 +240,18 @@ $Header: /cvsroot/pgsql/doc/src/sgml/mvcc.sgml,v 2.33 2003/02/19 04:06:28 momjia
updating the originally found row. If the first updater commits, the updating the originally found row. If the first updater commits, the
second updater will ignore the row if the first updater deleted it, second updater will ignore the row if the first updater deleted it,
otherwise it will attempt to apply its operation to the updated version of otherwise it will attempt to apply its operation to the updated version of
the row. The query search condition (<literal>WHERE</> clause) is the row. The search condition of the command (the <literal>WHERE</> clause) is
re-evaluated to see if the updated version of the row still matches the re-evaluated to see if the updated version of the row still matches the
search condition. If so, the second updater proceeds with its operation, search condition. If so, the second updater proceeds with its operation,
starting from the updated version of the row. starting from the updated version of the row.
</para> </para>
<para> <para>
Because of the above rule, it is possible for updating queries to see Because of the above rule, it is possible for an updating command to see an
inconsistent snapshots --- they can see the effects of concurrent updating inconsistent snapshot: it can see the effects of concurrent updating
queries that affected the same rows they are trying to update, but they commands that affected the same rows it is trying to update, but it
do not see effects of those queries on other rows in the database. does not see effects of those commands on other rows in the database.
This behavior makes Read Committed mode unsuitable for queries that This behavior makes Read Committed mode unsuitable for commands that
involve complex search conditions. However, it is just right for simpler involve complex search conditions. However, it is just right for simpler
cases. For example, consider updating bank balances with transactions cases. For example, consider updating bank balances with transactions
like like
...@@ -266,17 +265,17 @@ COMMIT; ...@@ -266,17 +265,17 @@ COMMIT;
If two such transactions concurrently try to change the balance of account If two such transactions concurrently try to change the balance of account
12345, we clearly want the second transaction to start from the updated 12345, we clearly want the second transaction to start from the updated
version of the account's row. Because each query is affecting only a version of the account's row. Because each command is affecting only a
predetermined row, letting it see the updated version of the row does predetermined row, letting it see the updated version of the row does
not create any troublesome inconsistency. not create any troublesome inconsistency.
</para> </para>
<para> <para>
Since in Read Committed mode each new query starts with a new snapshot Since in Read Committed mode each new command starts with a new snapshot
that includes all transactions committed up to that instant, subsequent that includes all transactions committed up to that instant, subsequent
queries in the same transaction will see the effects of the committed commands in the same transaction will see the effects of the committed
concurrent transaction in any case. The point at issue here is whether concurrent transaction in any case. The point at issue here is whether
or not within a <emphasis>single</> query we see an absolutely consistent or not within a <emphasis>single</> command we see an absolutely consistent
view of the database. view of the database.
</para> </para>
...@@ -294,11 +293,11 @@ COMMIT; ...@@ -294,11 +293,11 @@ COMMIT;
<indexterm> <indexterm>
<primary>isolation levels</primary> <primary>isolation levels</primary>
<secondary>read serializable</secondary> <secondary>serializable</secondary>
</indexterm> </indexterm>
<para> <para>
<firstterm>Serializable</firstterm> provides the strictest transaction The level <firstterm>Serializable</firstterm> provides the strictest transaction
isolation. This level emulates serial transaction execution, isolation. This level emulates serial transaction execution,
as if transactions had been executed one after another, serially, as if transactions had been executed one after another, serially,
rather than concurrently. However, applications using this level must rather than concurrently. However, applications using this level must
...@@ -317,7 +316,7 @@ COMMIT; ...@@ -317,7 +316,7 @@ COMMIT;
<command>SELECT</command> <command>SELECT</command>
sees a snapshot as of the start of the transaction, not as of the start sees a snapshot as of the start of the transaction, not as of the start
of the current query within the transaction. Thus, successive of the current query within the transaction. Thus, successive
<command>SELECT</command>s within a single transaction always see the same <command>SELECT</command> commands within a single transaction always see the same
data. data.
</para> </para>
...@@ -354,7 +353,7 @@ ERROR: Can't serialize access due to concurrent update ...@@ -354,7 +353,7 @@ ERROR: Can't serialize access due to concurrent update
</para> </para>
<para> <para>
Note that only updating transactions may need to be retried --- read-only Note that only updating transactions may need to be retried; read-only
transactions will never have serialization conflicts. transactions will never have serialization conflicts.
</para> </para>
...@@ -367,7 +366,7 @@ ERROR: Can't serialize access due to concurrent update ...@@ -367,7 +366,7 @@ ERROR: Can't serialize access due to concurrent update
this mode is recommended only when updating transactions contain logic this mode is recommended only when updating transactions contain logic
sufficiently complex that they may give wrong answers in Read sufficiently complex that they may give wrong answers in Read
Committed mode. Most commonly, Serializable mode is necessary when Committed mode. Most commonly, Serializable mode is necessary when
a transaction performs several successive queries that must see a transaction executes several successive commands that must see
identical views of the database. identical views of the database.
</para> </para>
</sect2> </sect2>
...@@ -401,29 +400,29 @@ ERROR: Can't serialize access due to concurrent update ...@@ -401,29 +400,29 @@ ERROR: Can't serialize access due to concurrent update
<productname>PostgreSQL</productname>. <productname>PostgreSQL</productname>.
Remember that all of these lock modes are table-level locks, Remember that all of these lock modes are table-level locks,
even if the name contains the word even if the name contains the word
<quote>row</quote>. The names of the lock modes are historical. <quote>row</quote>; the names of the lock modes are historical.
To some extent the names reflect the typical usage of each lock To some extent the names reflect the typical usage of each lock
mode --- but the semantics are all the same. The only real difference mode --- but the semantics are all the same. The only real difference
between one lock mode and another is the set of lock modes with between one lock mode and another is the set of lock modes with
which each conflicts. Two transactions cannot hold locks of conflicting which each conflicts. Two transactions cannot hold locks of conflicting
modes on the same table at the same time. (However, a transaction modes on the same table at the same time. (However, a transaction
never conflicts with itself --- for example, it may acquire never conflicts with itself. For example, it may acquire
<literal>ACCESS EXCLUSIVE</literal> lock and later acquire <literal>ACCESS EXCLUSIVE</literal> lock and later acquire
<literal>ACCESS SHARE</literal> lock on the same table.) Non-conflicting <literal>ACCESS SHARE</literal> lock on the same table.) Non-conflicting
lock modes may be held concurrently by many transactions. Notice in lock modes may be held concurrently by many transactions. Notice in
particular that some lock modes are self-conflicting (for example, particular that some lock modes are self-conflicting (for example,
<literal>ACCESS EXCLUSIVE</literal> cannot be held by more than one an <literal>ACCESS EXCLUSIVE</literal> lock cannot be held by more than one
transaction at a time) while others are not self-conflicting (for example, transaction at a time) while others are not self-conflicting (for example,
<literal>ACCESS SHARE</literal> can be held by multiple transactions). an <literal>ACCESS SHARE</literal> lock can be held by multiple transactions).
Once acquired, a lock mode is held till end of transaction. Once acquired, a lock is held till end of transaction.
</para> </para>
<para> <para>
To examine a list of the currently outstanding locks in a To examine a list of the currently outstanding locks in a database
database server, use the <literal>pg_locks</literal> system server, use the <literal>pg_locks</literal> system view. For more
view. For more information on monitoring the status of the lock information on monitoring the status of the lock manager
manager subsystem, refer to the &cite-admin;. subsystem, refer to the &cite-admin;.
</para> </para>
<variablelist> <variablelist>
<title>Table-level lock modes</title> <title>Table-level lock modes</title>
...@@ -482,7 +481,7 @@ ERROR: Can't serialize access due to concurrent update ...@@ -482,7 +481,7 @@ ERROR: Can't serialize access due to concurrent update
acquire this lock mode on the target table (in addition to acquire this lock mode on the target table (in addition to
<literal>ACCESS SHARE</literal> locks on any other referenced <literal>ACCESS SHARE</literal> locks on any other referenced
tables). In general, this lock mode will be acquired by any tables). In general, this lock mode will be acquired by any
query that modifies the data in a table. command that modifies the data in a table.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -557,7 +556,7 @@ ERROR: Can't serialize access due to concurrent update ...@@ -557,7 +556,7 @@ ERROR: Can't serialize access due to concurrent update
EXCLUSIVE</literal>, <literal>SHARE</literal>, <literal>SHARE EXCLUSIVE</literal>, <literal>SHARE</literal>, <literal>SHARE
ROW EXCLUSIVE</literal>, <literal>EXCLUSIVE</literal>, and ROW EXCLUSIVE</literal>, <literal>EXCLUSIVE</literal>, and
<literal>ACCESS EXCLUSIVE</literal> lock modes. <literal>ACCESS EXCLUSIVE</literal> lock modes.
This mode allows only concurrent <literal>ACCESS SHARE</literal>, This mode allows only concurrent <literal>ACCESS SHARE</literal> locks,
i.e., only reads from the table can proceed in parallel with a i.e., only reads from the table can proceed in parallel with a
transaction holding this lock mode. transaction holding this lock mode.
</para> </para>
...@@ -596,13 +595,13 @@ ERROR: Can't serialize access due to concurrent update ...@@ -596,13 +595,13 @@ ERROR: Can't serialize access due to concurrent update
</varlistentry> </varlistentry>
</variablelist> </variablelist>
<note> <tip>
<para> <para>
Only an <literal>ACCESS EXCLUSIVE</literal> lock blocks a Only an <literal>ACCESS EXCLUSIVE</literal> lock blocks a
<command>SELECT</command> (without <option>FOR UPDATE</option>) <command>SELECT</command> (without <option>FOR UPDATE</option>)
statement. statement.
</para> </para>
</note> </tip>
</sect2> </sect2>
...@@ -635,7 +634,7 @@ ERROR: Can't serialize access due to concurrent update ...@@ -635,7 +634,7 @@ ERROR: Can't serialize access due to concurrent update
<para> <para>
In addition to table and row locks, page-level share/exclusive locks are In addition to table and row locks, page-level share/exclusive locks are
used to control read/write access to table pages in the shared buffer used to control read/write access to table pages in the shared buffer
pool. These locks are released immediately after a tuple is fetched or pool. These locks are released immediately after a row is fetched or
updated. Application developers normally need not be concerned with updated. Application developers normally need not be concerned with
page-level locks, but we mention them for completeness. page-level locks, but we mention them for completeness.
</para> </para>
...@@ -777,7 +776,7 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222; ...@@ -777,7 +776,7 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
example, a banking application might wish to check that the sum of example, a banking application might wish to check that the sum of
all credits in one table equals the sum of debits in another table, all credits in one table equals the sum of debits in another table,
when both tables are being actively updated. Comparing the results of two when both tables are being actively updated. Comparing the results of two
successive <literal>SELECT SUM(...)</literal> commands will not work reliably under successive <literal>SELECT sum(...)</literal> commands will not work reliably under
Read Committed mode, since the second query will likely include the results Read Committed mode, since the second query will likely include the results
of transactions not counted by the first. Doing the two sums in a of transactions not counted by the first. Doing the two sums in a
single serializable transaction will give an accurate picture of the single serializable transaction will give an accurate picture of the
...@@ -800,10 +799,11 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222; ...@@ -800,10 +799,11 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
Read Committed mode, or in Serializable mode be careful to obtain the Read Committed mode, or in Serializable mode be careful to obtain the
lock(s) before performing queries. An explicit lock obtained in a lock(s) before performing queries. An explicit lock obtained in a
serializable transaction guarantees that no other transactions modifying serializable transaction guarantees that no other transactions modifying
the table are still running --- but if the snapshot seen by the the table are still running, but if the snapshot seen by the
transaction predates obtaining the lock, it may predate some now-committed transaction predates obtaining the lock, it may predate some now-committed
changes in the table. A serializable transaction's snapshot is actually changes in the table. A serializable transaction's snapshot is actually
frozen at the start of its first query (<literal>SELECT</>, <literal>INSERT</>, frozen at the start of its first query or data-modification command
(<literal>SELECT</>, <literal>INSERT</>,
<literal>UPDATE</>, or <literal>DELETE</>), so <literal>UPDATE</>, or <literal>DELETE</>), so
it's possible to obtain explicit locks before the snapshot is it's possible to obtain explicit locks before the snapshot is
frozen. frozen.
...@@ -819,9 +819,6 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222; ...@@ -819,9 +819,6 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
data, nonblocking read/write access is not currently offered for every data, nonblocking read/write access is not currently offered for every
index access method implemented index access method implemented
in <productname>PostgreSQL</productname>. in <productname>PostgreSQL</productname>.
</para>
<para>
The various index types are handled as follows: The various index types are handled as follows:
<variablelist> <variablelist>
...@@ -833,7 +830,7 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222; ...@@ -833,7 +830,7 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
<para> <para>
Short-term share/exclusive page-level locks are used for Short-term share/exclusive page-level locks are used for
read/write access. Locks are released immediately after each read/write access. Locks are released immediately after each
index tuple is fetched or inserted. B-tree indexes provide index row is fetched or inserted. B-tree indexes provide
the highest concurrency without deadlock conditions. the highest concurrency without deadlock conditions.
</para> </para>
</listitem> </listitem>
...@@ -846,7 +843,7 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222; ...@@ -846,7 +843,7 @@ UPDATE accounts SET balance = balance - 100.00 WHERE acctnum = 22222;
<listitem> <listitem>
<para> <para>
Share/exclusive index-level locks are used for read/write access. Share/exclusive index-level locks are used for read/write access.
Locks are released after the statement (command) is done. Locks are released after the command is done.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.26 2003/01/28 03:34:29 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.27 2003/03/13 01:30:29 petere Exp $
--> -->
<chapter id="performance-tips"> <chapter id="performance-tips">
...@@ -39,8 +39,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.26 2003/01/28 03:34:29 mom ...@@ -39,8 +39,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.26 2003/01/28 03:34:29 mom
<listitem> <listitem>
<para> <para>
Estimated total cost (If all rows are retrieved, which they may not Estimated total cost (If all rows were to be retrieved, which they may not
be --- a query with a <literal>LIMIT</> clause will stop short of paying the total cost, be: a query with a <literal>LIMIT</> clause will stop short of paying the total cost,
for example.) for example.)
</para> </para>
</listitem> </listitem>
...@@ -48,7 +48,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.26 2003/01/28 03:34:29 mom ...@@ -48,7 +48,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.26 2003/01/28 03:34:29 mom
<listitem> <listitem>
<para> <para>
Estimated number of rows output by this plan node (Again, only if Estimated number of rows output by this plan node (Again, only if
executed to completion.) executed to completion)
</para> </para>
</listitem> </listitem>
...@@ -74,8 +74,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.26 2003/01/28 03:34:29 mom ...@@ -74,8 +74,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.26 2003/01/28 03:34:29 mom
the cost of all its child nodes. It's also important to realize that the cost of all its child nodes. It's also important to realize that
the cost only reflects things that the planner/optimizer cares about. the cost only reflects things that the planner/optimizer cares about.
In particular, the cost does not consider the time spent transmitting In particular, the cost does not consider the time spent transmitting
result rows to the frontend --- which could be a pretty dominant result rows to the frontend, which could be a pretty dominant
factor in the true elapsed time, but the planner ignores it because factor in the true elapsed time; but the planner ignores it because
it cannot change it by altering the plan. (Every correct plan will it cannot change it by altering the plan. (Every correct plan will
output the same row set, we trust.) output the same row set, we trust.)
</para> </para>
...@@ -83,19 +83,20 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.26 2003/01/28 03:34:29 mom ...@@ -83,19 +83,20 @@ $Header: /cvsroot/pgsql/doc/src/sgml/perform.sgml,v 1.26 2003/01/28 03:34:29 mom
<para> <para>
Rows output is a little tricky because it is <emphasis>not</emphasis> the Rows output is a little tricky because it is <emphasis>not</emphasis> the
number of rows number of rows
processed/scanned by the query --- it is usually less, reflecting the processed/scanned by the query, it is usually less, reflecting the
estimated selectivity of any <literal>WHERE</>-clause constraints that are being estimated selectivity of any <literal>WHERE</>-clause conditions that are being
applied at this node. Ideally the top-level rows estimate will applied at this node. Ideally the top-level rows estimate will
approximate the number of rows actually returned, updated, or deleted approximate the number of rows actually returned, updated, or deleted
by the query. by the query.
</para> </para>
<para> <para>
Here are some examples (using the regress test database after a Here are some examples (using the regression test database after a
<literal>VACUUM ANALYZE</>, and 7.3 development sources): <literal>VACUUM ANALYZE</>, and 7.3 development sources):
<programlisting> <programlisting>
regression=# EXPLAIN SELECT * FROM tenk1; EXPLAIN SELECT * FROM tenk1;
QUERY PLAN QUERY PLAN
------------------------------------------------------------- -------------------------------------------------------------
Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148) Seq Scan on tenk1 (cost=0.00..333.00 rows=10000 width=148)
...@@ -119,7 +120,8 @@ SELECT * FROM pg_class WHERE relname = 'tenk1'; ...@@ -119,7 +120,8 @@ SELECT * FROM pg_class WHERE relname = 'tenk1';
Now let's modify the query to add a <literal>WHERE</> condition: Now let's modify the query to add a <literal>WHERE</> condition:
<programlisting> <programlisting>
regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 1000; EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 1000;
QUERY PLAN QUERY PLAN
------------------------------------------------------------ ------------------------------------------------------------
Seq Scan on tenk1 (cost=0.00..358.00 rows=1033 width=148) Seq Scan on tenk1 (cost=0.00..358.00 rows=1033 width=148)
...@@ -145,7 +147,8 @@ regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 1000; ...@@ -145,7 +147,8 @@ regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 1000;
Modify the query to restrict the condition even more: Modify the query to restrict the condition even more:
<programlisting> <programlisting>
regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 50; EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 50;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Index Scan using tenk1_unique1 on tenk1 (cost=0.00..179.33 rows=49 width=148) Index Scan using tenk1_unique1 on tenk1 (cost=0.00..179.33 rows=49 width=148)
...@@ -161,11 +164,11 @@ regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 50; ...@@ -161,11 +164,11 @@ regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 50;
</para> </para>
<para> <para>
Add another clause to the <literal>WHERE</> condition: Add another condition to the <literal>WHERE</> clause:
<programlisting> <programlisting>
regression=# EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 50 AND EXPLAIN SELECT * FROM tenk1 WHERE unique1 &lt; 50 AND stringu1 = 'xxx';
regression-# stringu1 = 'xxx';
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Index Scan using tenk1_unique1 on tenk1 (cost=0.00..179.45 rows=1 width=148) Index Scan using tenk1_unique1 on tenk1 (cost=0.00..179.45 rows=1 width=148)
...@@ -173,7 +176,7 @@ regression-# stringu1 = 'xxx'; ...@@ -173,7 +176,7 @@ regression-# stringu1 = 'xxx';
Filter: (stringu1 = 'xxx'::name) Filter: (stringu1 = 'xxx'::name)
</programlisting> </programlisting>
The added clause <literal>stringu1 = 'xxx'</literal> reduces the The added condition <literal>stringu1 = 'xxx'</literal> reduces the
output-rows estimate, but not the cost because we still have to visit the output-rows estimate, but not the cost because we still have to visit the
same set of rows. Notice that the <literal>stringu1</> clause same set of rows. Notice that the <literal>stringu1</> clause
cannot be applied as an index condition (since this index is only on cannot be applied as an index condition (since this index is only on
...@@ -183,11 +186,11 @@ regression-# stringu1 = 'xxx'; ...@@ -183,11 +186,11 @@ regression-# stringu1 = 'xxx';
</para> </para>
<para> <para>
Let's try joining two tables, using the fields we have been discussing: Let's try joining two tables, using the columns we have been discussing:
<programlisting> <programlisting>
regression=# EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 &lt; 50 EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 &lt; 50 AND t1.unique2 = t2.unique2;
regression-# AND t1.unique2 = t2.unique2;
QUERY PLAN QUERY PLAN
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
Nested Loop (cost=0.00..327.02 rows=49 width=296) Nested Loop (cost=0.00..327.02 rows=49 width=296)
...@@ -203,7 +206,7 @@ regression-# AND t1.unique2 = t2.unique2; ...@@ -203,7 +206,7 @@ regression-# AND t1.unique2 = t2.unique2;
<para> <para>
In this nested-loop join, the outer scan is the same index scan we had In this nested-loop join, the outer scan is the same index scan we had
in the example before last, and so its cost and row count are the same in the example before last, and so its cost and row count are the same
because we are applying the <literal>unique1 &lt; 50</literal> <literal>WHERE</> clause at that node. because we are applying the <literal>WHERE</> clause <literal>unique1 &lt; 50</literal> at that node.
The <literal>t1.unique2 = t2.unique2</literal> clause is not relevant yet, so it doesn't The <literal>t1.unique2 = t2.unique2</literal> clause is not relevant yet, so it doesn't
affect row count of the outer scan. For the inner scan, the <literal>unique2</> value of the affect row count of the outer scan. For the inner scan, the <literal>unique2</> value of the
current current
...@@ -218,9 +221,9 @@ regression-# AND t1.unique2 = t2.unique2; ...@@ -218,9 +221,9 @@ regression-# AND t1.unique2 = t2.unique2;
</para> </para>
<para> <para>
In this example the loop's output row count is the same as the product In this example the join's output row count is the same as the product
of the two scans' row counts, but that's not true in general, because of the two scans' row counts, but that's not true in general, because
in general you can have <literal>WHERE</> clauses that mention both relations and in general you can have <literal>WHERE</> clauses that mention both tables and
so can only be applied at the join point, not to either input scan. so can only be applied at the join point, not to either input scan.
For example, if we added <literal>WHERE ... AND t1.hundred &lt; t2.hundred</literal>, For example, if we added <literal>WHERE ... AND t1.hundred &lt; t2.hundred</literal>,
that would decrease the output row count of the join node, but not change that would decrease the output row count of the join node, but not change
...@@ -234,10 +237,9 @@ regression-# AND t1.unique2 = t2.unique2; ...@@ -234,10 +237,9 @@ regression-# AND t1.unique2 = t2.unique2;
also <xref linkend="explicit-joins">.) also <xref linkend="explicit-joins">.)
<programlisting> <programlisting>
regression=# SET enable_nestloop = off; SET enable_nestloop = off;
SET EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 &lt; 50 AND t1.unique2 = t2.unique2;
regression=# EXPLAIN SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 &lt; 50
regression-# AND t1.unique2 = t2.unique2;
QUERY PLAN QUERY PLAN
-------------------------------------------------------------------------- --------------------------------------------------------------------------
Hash Join (cost=179.45..563.06 rows=49 width=296) Hash Join (cost=179.45..563.06 rows=49 width=296)
...@@ -269,9 +271,8 @@ regression-# AND t1.unique2 = t2.unique2; ...@@ -269,9 +271,8 @@ regression-# AND t1.unique2 = t2.unique2;
For example, we might get a result like this: For example, we might get a result like this:
<screen> <screen>
regression=# EXPLAIN ANALYZE EXPLAIN ANALYZE SELECT * FROM tenk1 t1, tenk2 t2 WHERE t1.unique1 &lt; 50 AND t1.unique2 = t2.unique2;
regression-# SELECT * FROM tenk1 t1, tenk2 t2
regression-# WHERE t1.unique1 &lt; 50 AND t1.unique2 = t2.unique2;
QUERY PLAN QUERY PLAN
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Nested Loop (cost=0.00..327.02 rows=49 width=296) Nested Loop (cost=0.00..327.02 rows=49 width=296)
...@@ -345,14 +346,14 @@ regression-# WHERE t1.unique1 &lt; 50 AND t1.unique2 = t2.unique2; ...@@ -345,14 +346,14 @@ regression-# WHERE t1.unique1 &lt; 50 AND t1.unique2 = t2.unique2;
<para> <para>
One component of the statistics is the total number of entries in each One component of the statistics is the total number of entries in each
table and index, as well as the number of disk blocks occupied by each table and index, as well as the number of disk blocks occupied by each
table and index. This information is kept in table and index. This information is kept in the table
<structname>pg_class</structname>'s <structfield>reltuples</structfield> <structname>pg_class</structname> in the columns <structfield>reltuples</structfield>
and <structfield>relpages</structfield> columns. We can look at it and <structfield>relpages</structfield>. We can look at it
with queries similar to this one: with queries similar to this one:
<screen> <screen>
regression=# SELECT relname, relkind, reltuples, relpages FROM pg_class SELECT relname, relkind, reltuples, relpages FROM pg_class WHERE relname LIKE 'tenk1%';
regression-# WHERE relname LIKE 'tenk1%';
relname | relkind | reltuples | relpages relname | relkind | reltuples | relpages
---------------+---------+-----------+---------- ---------------+---------+-----------+----------
tenk1 | r | 10000 | 233 tenk1 | r | 10000 | 233
...@@ -385,10 +386,10 @@ regression-# WHERE relname LIKE 'tenk1%'; ...@@ -385,10 +386,10 @@ regression-# WHERE relname LIKE 'tenk1%';
to having <literal>WHERE</> clauses that restrict the rows to be examined. to having <literal>WHERE</> clauses that restrict the rows to be examined.
The planner thus needs to make an estimate of the The planner thus needs to make an estimate of the
<firstterm>selectivity</> of <literal>WHERE</> clauses, that is, the fraction of <firstterm>selectivity</> of <literal>WHERE</> clauses, that is, the fraction of
rows that match each clause of the <literal>WHERE</> condition. The information rows that match each condition in the <literal>WHERE</> clause. The information
used for this task is stored in the <structname>pg_statistic</structname> used for this task is stored in the <structname>pg_statistic</structname>
system catalog. Entries in <structname>pg_statistic</structname> are system catalog. Entries in <structname>pg_statistic</structname> are
updated by <command>ANALYZE</> and <command>VACUUM ANALYZE</> commands, updated by <command>ANALYZE</> and <command>VACUUM ANALYZE</> commands
and are always approximate even when freshly updated. and are always approximate even when freshly updated.
</para> </para>
...@@ -398,7 +399,7 @@ regression-# WHERE relname LIKE 'tenk1%'; ...@@ -398,7 +399,7 @@ regression-# WHERE relname LIKE 'tenk1%';
when examining the statistics manually. <structname>pg_stats</structname> when examining the statistics manually. <structname>pg_stats</structname>
is designed to be more easily readable. Furthermore, is designed to be more easily readable. Furthermore,
<structname>pg_stats</structname> is readable by all, whereas <structname>pg_stats</structname> is readable by all, whereas
<structname>pg_statistic</structname> is only readable by the superuser. <structname>pg_statistic</structname> is only readable by a superuser.
(This prevents unprivileged users from learning something about (This prevents unprivileged users from learning something about
the contents of other people's tables from the statistics. The the contents of other people's tables from the statistics. The
<structname>pg_stats</structname> view is restricted to show only <structname>pg_stats</structname> view is restricted to show only
...@@ -406,13 +407,13 @@ regression-# WHERE relname LIKE 'tenk1%'; ...@@ -406,13 +407,13 @@ regression-# WHERE relname LIKE 'tenk1%';
For example, we might do: For example, we might do:
<screen> <screen>
regression=# SELECT attname, n_distinct, most_common_vals FROM pg_stats WHERE tablename = 'road'; SELECT attname, n_distinct, most_common_vals FROM pg_stats WHERE tablename = 'road';
attname | n_distinct | most_common_vals attname | n_distinct | most_common_vals
---------+------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------+------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | -0.467008 | {"I- 580 Ramp","I- 880 Ramp","Sp Railroad ","I- 580 ","I- 680 Ramp","I- 80 Ramp","14th St ","5th St ","Mission Blvd","I- 880 "} name | -0.467008 | {"I- 580 Ramp","I- 880 Ramp","Sp Railroad ","I- 580 ","I- 680 Ramp","I- 80 Ramp","14th St ","5th St ","Mission Blvd","I- 880 "}
thepath | 20 | {"[(-122.089,37.71),(-122.0886,37.711)]"} thepath | 20 | {"[(-122.089,37.71),(-122.0886,37.711)]"}
(2 rows) (2 rows)
regression=#
</screen> </screen>
</para> </para>
...@@ -428,7 +429,7 @@ regression=# ...@@ -428,7 +429,7 @@ regression=#
<thead> <thead>
<row> <row>
<entry>Name</entry> <entry>Name</entry>
<entry>Type</entry> <entry>Data Type</entry>
<entry>Description</entry> <entry>Description</entry>
</row> </row>
</thead> </thead>
...@@ -437,25 +438,25 @@ regression=# ...@@ -437,25 +438,25 @@ regression=#
<row> <row>
<entry><literal>tablename</literal></entry> <entry><literal>tablename</literal></entry>
<entry><type>name</type></entry> <entry><type>name</type></entry>
<entry>Name of the table containing the column</entry> <entry>Name of the table containing the column.</entry>
</row> </row>
<row> <row>
<entry><literal>attname</literal></entry> <entry><literal>attname</literal></entry>
<entry><type>name</type></entry> <entry><type>name</type></entry>
<entry>Column described by this row</entry> <entry>Name of the column described by this row.</entry>
</row> </row>
<row> <row>
<entry><literal>null_frac</literal></entry> <entry><literal>null_frac</literal></entry>
<entry><type>real</type></entry> <entry><type>real</type></entry>
<entry>Fraction of column's entries that are null</entry> <entry>Fraction of column entries that are null.</entry>
</row> </row>
<row> <row>
<entry><literal>avg_width</literal></entry> <entry><literal>avg_width</literal></entry>
<entry><type>integer</type></entry> <entry><type>integer</type></entry>
<entry>Average width in bytes of the column's entries</entry> <entry>Average width in bytes of the column entries.</entry>
</row> </row>
<row> <row>
...@@ -488,25 +489,25 @@ regression=# ...@@ -488,25 +489,25 @@ regression=#
</row> </row>
<row> <row>
<entry>histogram_bounds</entry> <entry><literal>histogram_bounds</literal></entry>
<entry><type>text[]</type></entry> <entry><type>text[]</type></entry>
<entry>A list of values that divide the column's values into <entry>A list of values that divide the column's values into
groups of approximately equal population. The groups of approximately equal population. The values in
<structfield>most_common_vals</>, if present, are omitted from the <structfield>most_common_vals</>, if present, are omitted from this
histogram calculation. (Omitted if column data type does not have a histogram calculation. (This columns is not filled if the column data type does not have a
<literal>&lt;</> operator, or if the <structfield>most_common_vals</> <literal>&lt;</> operator or if the <structfield>most_common_vals</>
list accounts for the entire population.) list accounts for the entire population.)
</entry> </entry>
</row> </row>
<row> <row>
<entry>correlation</entry> <entry><literal>correlation</literal></entry>
<entry><type>real</type></entry> <entry><type>real</type></entry>
<entry>Statistical correlation between physical row ordering and <entry>Statistical correlation between physical row ordering and
logical ordering of the column values. This ranges from -1 to +1. logical ordering of the column values. This ranges from -1 to +1.
When the value is near -1 or +1, an index scan on the column will When the value is near -1 or +1, an index scan on the column will
be estimated to be cheaper than when it is near zero, due to reduction be estimated to be cheaper than when it is near zero, due to reduction
of random access to the disk. (Omitted if column data type does of random access to the disk. (This column is not filled if the column data type does
not have a <literal>&lt;</> operator.) not have a <literal>&lt;</> operator.)
</entry> </entry>
</row> </row>
...@@ -532,7 +533,7 @@ regression=# ...@@ -532,7 +533,7 @@ regression=#
<title>Controlling the Planner with Explicit <literal>JOIN</> Clauses</title> <title>Controlling the Planner with Explicit <literal>JOIN</> Clauses</title>
<para> <para>
Beginning with <productname>PostgreSQL</productname> 7.1 it has been possible It is possible
to control the query planner to some extent by using the explicit <literal>JOIN</> to control the query planner to some extent by using the explicit <literal>JOIN</>
syntax. To see why this matters, we first need some background. syntax. To see why this matters, we first need some background.
</para> </para>
...@@ -547,7 +548,7 @@ SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id; ...@@ -547,7 +548,7 @@ SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id;
the <literal>WHERE</> condition <literal>a.id = b.id</>, and then the <literal>WHERE</> condition <literal>a.id = b.id</>, and then
joins C to this joined table, using the other <literal>WHERE</> joins C to this joined table, using the other <literal>WHERE</>
condition. Or it could join B to C and then join A to that result. condition. Or it could join B to C and then join A to that result.
Or it could join A to C and then join them with B --- but that Or it could join A to C and then join them with B, but that
would be inefficient, since the full Cartesian product of A and C would be inefficient, since the full Cartesian product of A and C
would have to be formed, there being no applicable condition in the would have to be formed, there being no applicable condition in the
<literal>WHERE</> clause to allow optimization of the join. (All <literal>WHERE</> clause to allow optimization of the join. (All
...@@ -570,7 +571,7 @@ SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id; ...@@ -570,7 +571,7 @@ SELECT * FROM a, b, c WHERE a.id = b.id AND b.ref = c.id;
<productname>PostgreSQL</productname> planner will switch from exhaustive <productname>PostgreSQL</productname> planner will switch from exhaustive
search to a <firstterm>genetic</firstterm> probabilistic search search to a <firstterm>genetic</firstterm> probabilistic search
through a limited number of possibilities. (The switch-over threshold is through a limited number of possibilities. (The switch-over threshold is
set by the <varname>GEQO_THRESHOLD</varname> run-time set by the <varname>geqo_threshold</varname> run-time
parameter described in the &cite-admin;.) parameter described in the &cite-admin;.)
The genetic search takes less time, but it won't The genetic search takes less time, but it won't
necessarily find the best possible plan. necessarily find the best possible plan.
...@@ -611,7 +612,7 @@ SELECT * FROM a JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id); ...@@ -611,7 +612,7 @@ SELECT * FROM a JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);
<para> <para>
To force the planner to follow the <literal>JOIN</> order for inner joins, To force the planner to follow the <literal>JOIN</> order for inner joins,
set the <varname>JOIN_COLLAPSE_LIMIT</> run-time parameter to 1. set the <varname>join_collapse_limit</> run-time parameter to 1.
(Other possible values are discussed below.) (Other possible values are discussed below.)
</para> </para>
...@@ -622,7 +623,7 @@ SELECT * FROM a JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id); ...@@ -622,7 +623,7 @@ SELECT * FROM a JOIN (b JOIN c ON (b.ref = c.id)) ON (a.id = b.id);
<programlisting> <programlisting>
SELECT * FROM a CROSS JOIN b, c, d, e WHERE ...; SELECT * FROM a CROSS JOIN b, c, d, e WHERE ...;
</programlisting> </programlisting>
With <varname>JOIN_COLLAPSE_LIMIT</> = 1, this With <varname>join_collapse_limit</> = 1, this
forces the planner to join A to B before joining them to other tables, forces the planner to join A to B before joining them to other tables,
but doesn't constrain its choices otherwise. In this example, the but doesn't constrain its choices otherwise. In this example, the
number of possible join orders is reduced by a factor of 5. number of possible join orders is reduced by a factor of 5.
...@@ -639,43 +640,43 @@ SELECT * FROM a CROSS JOIN b, c, d, e WHERE ...; ...@@ -639,43 +640,43 @@ SELECT * FROM a CROSS JOIN b, c, d, e WHERE ...;
<para> <para>
A closely related issue that affects planning time is collapsing of A closely related issue that affects planning time is collapsing of
sub-SELECTs into their parent query. For example, consider subqueries into their parent query. For example, consider
<programlisting> <programlisting>
SELECT * SELECT *
FROM x, y, FROM x, y,
(SELECT * FROM a, b, c WHERE something) AS ss (SELECT * FROM a, b, c WHERE something) AS ss
WHERE somethingelse WHERE somethingelse;
</programlisting> </programlisting>
This situation might arise from use of a view that contains a join; This situation might arise from use of a view that contains a join;
the view's SELECT rule will be inserted in place of the view reference, the view's <literal>SELECT</> rule will be inserted in place of the view reference,
yielding a query much like the above. Normally, the planner will try yielding a query much like the above. Normally, the planner will try
to collapse the sub-query into the parent, yielding to collapse the subquery into the parent, yielding
<programlisting> <programlisting>
SELECT * FROM x, y, a, b, c WHERE something AND somethingelse SELECT * FROM x, y, a, b, c WHERE something AND somethingelse;
</programlisting> </programlisting>
This usually results in a better plan than planning the sub-query This usually results in a better plan than planning the subquery
separately. (For example, the outer WHERE conditions might be such that separately. (For example, the outer <literal>WHERE</> conditions might be such that
joining X to A first eliminates many rows of A, thus avoiding the need to joining X to A first eliminates many rows of A, thus avoiding the need to
form the full logical output of the sub-select.) But at the same time, form the full logical output of the subquery.) But at the same time,
we have increased the planning time; here, we have a five-way join we have increased the planning time; here, we have a five-way join
problem replacing two separate three-way join problems. Because of the problem replacing two separate three-way join problems. Because of the
exponential growth of the number of possibilities, this makes a big exponential growth of the number of possibilities, this makes a big
difference. The planner tries to avoid getting stuck in huge join search difference. The planner tries to avoid getting stuck in huge join search
problems by not collapsing a sub-query if more than problems by not collapsing a subquery if more than
<varname>FROM_COLLAPSE_LIMIT</> FROM-items would result in the parent <varname>from_collapse_limit</> <literal>FROM</> items would result in the parent
query. You can trade off planning time against quality of plan by query. You can trade off planning time against quality of plan by
adjusting this run-time parameter up or down. adjusting this run-time parameter up or down.
</para> </para>
<para> <para>
<varname>FROM_COLLAPSE_LIMIT</> and <varname>JOIN_COLLAPSE_LIMIT</> <varname>from_collapse_limit</> and <varname>join_collapse_limit</>
are similarly named because they do almost the same thing: one controls are similarly named because they do almost the same thing: one controls
when the planner will <quote>flatten out</> sub-SELECTs, and the when the planner will <quote>flatten out</> subselects, and the
other controls when it will flatten out explicit inner JOINs. Typically other controls when it will flatten out explicit inner joins. Typically
you would either set <varname>JOIN_COLLAPSE_LIMIT</> equal to you would either set <varname>join_collapse_limit</> equal to
<varname>FROM_COLLAPSE_LIMIT</> (so that explicit JOINs and sub-SELECTs <varname>from_collapse_limit</> (so that explicit joins and subselects
act similarly) or set <varname>JOIN_COLLAPSE_LIMIT</> to 1 (if you want act similarly) or set <varname>join_collapse_limit</> to 1 (if you want
to control join order with explicit JOINs). But you might set them to control join order with explicit joins). But you might set them
differently if you are trying to fine-tune the tradeoff between planning differently if you are trying to fine-tune the tradeoff between planning
time and run time. time and run time.
</para> </para>
...@@ -701,19 +702,19 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse ...@@ -701,19 +702,19 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse
make sure the library does it when you want it done.) make sure the library does it when you want it done.)
If you allow each insertion to be committed separately, If you allow each insertion to be committed separately,
<productname>PostgreSQL</productname> is doing a lot of work for each <productname>PostgreSQL</productname> is doing a lot of work for each
record added. row added.
An additional benefit of doing all insertions in one transaction An additional benefit of doing all insertions in one transaction
is that if the insertion of one record were to fail then the is that if the insertion of one row were to fail then the
insertion of all records inserted up to that point would be rolled insertion of all rows inserted up to that point would be rolled
back, so you won't be stuck with partially loaded data. back, so you won't be stuck with partially loaded data.
</para> </para>
</sect2> </sect2>
<sect2 id="populate-copy-from"> <sect2 id="populate-copy-from">
<title>Use COPY FROM</title> <title>Use <command>COPY FROM</command></title>
<para> <para>
Use <command>COPY FROM STDIN</command> to load all the records in one Use <command>COPY FROM STDIN</command> to load all the rows in one
command, instead of using command, instead of using
a series of <command>INSERT</command> commands. This reduces parsing, a series of <command>INSERT</command> commands. This reduces parsing,
planning, etc. planning, etc.
...@@ -730,12 +731,12 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse ...@@ -730,12 +731,12 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse
create the table, bulk-load with <command>COPY</command>, then create any create the table, bulk-load with <command>COPY</command>, then create any
indexes needed indexes needed
for the table. Creating an index on pre-existing data is quicker than for the table. Creating an index on pre-existing data is quicker than
updating it incrementally as each record is loaded. updating it incrementally as each row is loaded.
</para> </para>
<para> <para>
If you are augmenting an existing table, you can <command>DROP If you are augmenting an existing table, you can drop the index,
INDEX</command>, load the table, then recreate the index. Of load the table, then recreate the index. Of
course, the database performance for other users may be adversely course, the database performance for other users may be adversely
affected during the time that the index is missing. One should also affected during the time that the index is missing. One should also
think twice before dropping unique indexes, since the error checking think twice before dropping unique indexes, since the error checking
...@@ -744,7 +745,7 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse ...@@ -744,7 +745,7 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse
</sect2> </sect2>
<sect2 id="populate-analyze"> <sect2 id="populate-analyze">
<title>Run ANALYZE Afterwards</title> <title>Run <command>ANALYZE</command> Afterwards</title>
<para> <para>
It's a good idea to run <command>ANALYZE</command> or <command>VACUUM It's a good idea to run <command>ANALYZE</command> or <command>VACUUM
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/queries.sgml,v 1.19 2002/11/11 20:14:03 petere Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/queries.sgml,v 1.20 2003/03/13 01:30:29 petere Exp $ -->
<chapter id="queries"> <chapter id="queries">
<title>Queries</title> <title>Queries</title>
...@@ -157,18 +157,17 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r ...@@ -157,18 +157,17 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r
row consisting of all columns in <replaceable>T1</replaceable> row consisting of all columns in <replaceable>T1</replaceable>
followed by all columns in <replaceable>T2</replaceable>. If followed by all columns in <replaceable>T2</replaceable>. If
the tables have N and M rows respectively, the joined the tables have N and M rows respectively, the joined
table will have N * M rows. A cross join is equivalent to an table will have N * M rows.
<literal>INNER JOIN ON TRUE</literal>.
</para> </para>
<tip> <para>
<para> <literal>FROM <replaceable>T1</replaceable> CROSS JOIN
<literal>FROM <replaceable>T1</replaceable> CROSS JOIN <replaceable>T2</replaceable></literal> is equivalent to
<replaceable>T2</replaceable></literal> is equivalent to <literal>FROM <replaceable>T1</replaceable>,
<literal>FROM <replaceable>T1</replaceable>, <replaceable>T2</replaceable></literal>. It is also equivalent to
<replaceable>T2</replaceable></literal>. <literal>FROM <replaceable>T1</replaceable> INNER JOIN
</para> <replaceable>T2</replaceable> ON TRUE</literal> (see below).
</tip> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -240,7 +239,6 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r ...@@ -240,7 +239,6 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r
<para> <para>
The possible types of qualified join are: The possible types of qualified join are:
</para>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
...@@ -302,6 +300,7 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r ...@@ -302,6 +300,7 @@ FROM <replaceable>table_reference</replaceable> <optional>, <replaceable>table_r
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
...@@ -630,12 +629,12 @@ SELECT ... FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt.c1) ...@@ -630,12 +629,12 @@ SELECT ... FROM fdt WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > fdt.c1)
condition of the <literal>WHERE</> clause are eliminated from condition of the <literal>WHERE</> clause are eliminated from
<literal>fdt</literal>. Notice the use of scalar subqueries as <literal>fdt</literal>. Notice the use of scalar subqueries as
value expressions. Just like any other query, the subqueries can value expressions. Just like any other query, the subqueries can
employ complex table expressions. Notice how employ complex table expressions. Notice also how
<literal>fdt</literal> is referenced in the subqueries. <literal>fdt</literal> is referenced in the subqueries.
Qualifying <literal>c1</> as <literal>fdt.c1</> is only necessary Qualifying <literal>c1</> as <literal>fdt.c1</> is only necessary
if <literal>c1</> is also the name of a column in the derived if <literal>c1</> is also the name of a column in the derived
input table of the subquery. Qualifying the column name adds input table of the subquery. But qualifying the column name adds
clarity even when it is not needed. This shows how the column clarity even when it is not needed. This example shows how the column
naming scope of an outer query extends into its inner queries. naming scope of an outer query extends into its inner queries.
</para> </para>
</sect2> </sect2>
...@@ -663,7 +662,7 @@ SELECT <replaceable>select_list</replaceable> ...@@ -663,7 +662,7 @@ SELECT <replaceable>select_list</replaceable>
</synopsis> </synopsis>
<para> <para>
The <literal>GROUP BY</> clause is used to group together rows in The <literal>GROUP BY</> clause is used to group together those rows in
a table that share the same values in all the columns listed. The a table that share the same values in all the columns listed. The
order in which the columns are listed does not matter. The order in which the columns are listed does not matter. The
purpose is to reduce each group of rows sharing common values into purpose is to reduce each group of rows sharing common values into
...@@ -711,7 +710,7 @@ SELECT <replaceable>select_list</replaceable> ...@@ -711,7 +710,7 @@ SELECT <replaceable>select_list</replaceable>
c | 2 c | 2
(3 rows) (3 rows)
</screen> </screen>
Here <literal>sum()</literal> is an aggregate function that Here <literal>sum</literal> is an aggregate function that
computes a single value over the entire group. More information computes a single value over the entire group. More information
about the available aggregate functions can be found in <xref about the available aggregate functions can be found in <xref
linkend="functions-aggregate">. linkend="functions-aggregate">.
...@@ -727,9 +726,8 @@ SELECT <replaceable>select_list</replaceable> ...@@ -727,9 +726,8 @@ SELECT <replaceable>select_list</replaceable>
</tip> </tip>
<para> <para>
Here is another example: <function>sum(sales)</function> on a Here is another example: it calculates the total sales for each
table grouped by product code gives the total sales for each product (rather than the total sales on all products).
product, not the total sales on all products.
<programlisting> <programlisting>
SELECT product_id, p.name, (sum(s.units) * p.price) AS sales SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
FROM products p LEFT JOIN sales s USING (product_id) FROM products p LEFT JOIN sales s USING (product_id)
...@@ -744,8 +742,8 @@ SELECT product_id, p.name, (sum(s.units) * p.price) AS sales ...@@ -744,8 +742,8 @@ SELECT product_id, p.name, (sum(s.units) * p.price) AS sales
unnecessary, but this is not implemented yet.) The column unnecessary, but this is not implemented yet.) The column
<literal>s.units</> does not have to be in the <literal>GROUP <literal>s.units</> does not have to be in the <literal>GROUP
BY</> list since it is only used in an aggregate expression BY</> list since it is only used in an aggregate expression
(<function>sum()</function>), which represents the group of sales (<literal>sum(...)</literal>), which represents the sales
of a product. For each product, a summary row is returned about of a product. For each product, the query returns a summary row about
all sales of the product. all sales of the product.
</para> </para>
...@@ -800,10 +798,11 @@ SELECT product_id, p.name, (sum(s.units) * (p.price - p.cost)) AS profit ...@@ -800,10 +798,11 @@ SELECT product_id, p.name, (sum(s.units) * (p.price - p.cost)) AS profit
HAVING sum(p.price * s.units) > 5000; HAVING sum(p.price * s.units) > 5000;
</programlisting> </programlisting>
In the example above, the <literal>WHERE</> clause is selecting In the example above, the <literal>WHERE</> clause is selecting
rows by a column that is not grouped, while the <literal>HAVING</> rows by a column that is not grouped (the expression is only true for
sales during the last four weeks), while the <literal>HAVING</>
clause restricts the output to groups with total gross sales over clause restricts the output to groups with total gross sales over
5000. Note that the aggregate expressions do not necessarily need 5000. Note that the aggregate expressions do not necessarily need
to be the same everywhere. to be the same in all parts of the query.
</para> </para>
</sect2> </sect2>
</sect1> </sect1>
...@@ -852,7 +851,7 @@ SELECT a, b, c FROM ... ...@@ -852,7 +851,7 @@ SELECT a, b, c FROM ...
If more than one table has a column of the same name, the table If more than one table has a column of the same name, the table
name must also be given, as in name must also be given, as in
<programlisting> <programlisting>
SELECT tbl1.a, tbl2.b, tbl1.c FROM ... SELECT tbl1.a, tbl2.a, tbl1.b FROM ...
</programlisting> </programlisting>
(See also <xref linkend="queries-where">.) (See also <xref linkend="queries-where">.)
</para> </para>
...@@ -860,7 +859,7 @@ SELECT tbl1.a, tbl2.b, tbl1.c FROM ... ...@@ -860,7 +859,7 @@ SELECT tbl1.a, tbl2.b, tbl1.c FROM ...
<para> <para>
If an arbitrary value expression is used in the select list, it If an arbitrary value expression is used in the select list, it
conceptually adds a new virtual column to the returned table. The conceptually adds a new virtual column to the returned table. The
value expression is evaluated once for each retrieved row, with value expression is evaluated once for each result row, with
the row's values substituted for any column references. But the the row's values substituted for any column references. But the
expressions in the select list do not have to reference any expressions in the select list do not have to reference any
columns in the table expression of the <literal>FROM</> clause; columns in the table expression of the <literal>FROM</> clause;
...@@ -888,7 +887,7 @@ SELECT a AS value, b + c AS sum FROM ... ...@@ -888,7 +887,7 @@ SELECT a AS value, b + c AS sum FROM ...
</para> </para>
<para> <para>
If no output column name is specified via AS, the system assigns a If no output column name is specified using <literal>AS</>, the system assigns a
default name. For simple column references, this is the name of the default name. For simple column references, this is the name of the
referenced column. For function referenced column. For function
calls, this is the name of the function. For complex expressions, calls, this is the name of the function. For complex expressions,
...@@ -1129,7 +1128,7 @@ SELECT <replaceable>select_list</replaceable> ...@@ -1129,7 +1128,7 @@ SELECT <replaceable>select_list</replaceable>
<para> <para>
<literal>OFFSET</> says to skip that many rows before beginning to <literal>OFFSET</> says to skip that many rows before beginning to
return rows to the client. <literal>OFFSET 0</> is the same as return rows. <literal>OFFSET 0</> is the same as
omitting the <literal>OFFSET</> clause. If both <literal>OFFSET</> omitting the <literal>OFFSET</> clause. If both <literal>OFFSET</>
and <literal>LIMIT</> appear, then <literal>OFFSET</> rows are and <literal>LIMIT</> appear, then <literal>OFFSET</> rows are
skipped before starting to count the <literal>LIMIT</> rows that skipped before starting to count the <literal>LIMIT</> rows that
...@@ -1140,7 +1139,7 @@ SELECT <replaceable>select_list</replaceable> ...@@ -1140,7 +1139,7 @@ SELECT <replaceable>select_list</replaceable>
When using <literal>LIMIT</>, it is a good idea to use an When using <literal>LIMIT</>, it is a good idea to use an
<literal>ORDER BY</> clause that constrains the result rows into a <literal>ORDER BY</> clause that constrains the result rows into a
unique order. Otherwise you will get an unpredictable subset of unique order. Otherwise you will get an unpredictable subset of
the query's rows---you may be asking for the tenth through the query's rows. --- You may be asking for the tenth through
twentieth rows, but tenth through twentieth in what ordering? The twentieth rows, but tenth through twentieth in what ordering? The
ordering is unknown, unless you specified <literal>ORDER BY</>. ordering is unknown, unless you specified <literal>ORDER BY</>.
</para> </para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/query.sgml,v 1.28 2002/11/11 20:14:03 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/query.sgml,v 1.29 2003/03/13 01:30:29 petere Exp $
--> -->
<chapter id="tutorial-sql"> <chapter id="tutorial-sql">
...@@ -214,7 +214,7 @@ INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27'); ...@@ -214,7 +214,7 @@ INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27');
The <type>point</type> type requires a coordinate pair as input, The <type>point</type> type requires a coordinate pair as input,
as shown here: as shown here:
<programlisting> <programlisting>
INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)'); INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)');
</programlisting> </programlisting>
</para> </para>
...@@ -296,7 +296,7 @@ SELECT * FROM weather; ...@@ -296,7 +296,7 @@ SELECT * FROM weather;
</para> </para>
<para> <para>
You may specify any arbitrary expressions in the target list. For You may specify any arbitrary expressions in the select list. For
example, you can do: example, you can do:
<programlisting> <programlisting>
SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather; SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather;
...@@ -339,7 +339,7 @@ SELECT * FROM weather ...@@ -339,7 +339,7 @@ SELECT * FROM weather
<indexterm><primary>DISTINCT</primary></indexterm> <indexterm><primary>DISTINCT</primary></indexterm>
<indexterm><primary>duplicate</primary></indexterm> <indexterm><primary>duplicate</primary></indexterm>
As a final note, you can request that the results of a select can As a final note, you can request that the results of a query can
be returned in sorted order or with duplicate rows removed: be returned in sorted order or with duplicate rows removed:
<programlisting> <programlisting>
...@@ -710,7 +710,7 @@ SELECT city, max(temp_lo) ...@@ -710,7 +710,7 @@ SELECT city, max(temp_lo)
<literal>WHERE</literal> clause must not contain aggregate functions; <literal>WHERE</literal> clause must not contain aggregate functions;
it makes no sense to try to use an aggregate to determine which rows it makes no sense to try to use an aggregate to determine which rows
will be inputs to the aggregates. On the other hand, will be inputs to the aggregates. On the other hand,
<literal>HAVING</literal> clauses always contain aggregate functions. <literal>HAVING</literal> clause always contains aggregate functions.
(Strictly speaking, you are allowed to write a <literal>HAVING</literal> (Strictly speaking, you are allowed to write a <literal>HAVING</literal>
clause that doesn't use aggregates, but it's wasteful: The same condition clause that doesn't use aggregates, but it's wasteful: The same condition
could be used more efficiently at the <literal>WHERE</literal> stage.) could be used more efficiently at the <literal>WHERE</literal> stage.)
......
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/regress.sgml,v 1.30 2002/11/08 20:26:12 tgl Exp $ --> <!-- $Header: /cvsroot/pgsql/doc/src/sgml/regress.sgml,v 1.31 2003/03/13 01:30:29 petere Exp $ -->
<chapter id="regress"> <chapter id="regress">
<title id="regress-title">Regression Tests</title> <title id="regress-title">Regression Tests</title>
<sect1 id="regress-intro">
<title>Introduction</title>
<para> <para>
The regression tests are a comprehensive set of tests for the SQL The regression tests are a comprehensive set of tests for the SQL
implementation in <productname>PostgreSQL</productname>. They test implementation in <productname>PostgreSQL</productname>. They test
standard SQL operations as well as the extended capabilities of standard SQL operations as well as the extended capabilities of
<productname>PostgreSQL</productname>. The test suite was <productname>PostgreSQL</productname>. From
originally developed by Jolly Chen and Andrew Yu, and was <productname>PostgreSQL</productname> 6.1 onward, the regression
extensively revised and repackaged by Marc Fournier and Thomas tests are current for every official release.
Lockhart. From <productname>PostgreSQL</productname> 6.1 onward
the regression tests are current for every official release.
</para> </para>
</sect1>
<sect1 id="regress-run"> <sect1 id="regress-run">
<title>Running the Tests</title> <title>Running the Tests</title>
...@@ -40,12 +33,12 @@ ...@@ -40,12 +33,12 @@
To run the regression tests after building but before installation, To run the regression tests after building but before installation,
type type
<screen> <screen>
<prompt>$ </prompt><userinput>gmake check</userinput> gmake check
</screen> </screen>
in the top-level directory. (Or you can change to in the top-level directory. (Or you can change to
<filename>src/test/regress</filename> and run the command there.) <filename>src/test/regress</filename> and run the command there.)
This will first build several auxiliary files, such as This will first build several auxiliary files, such as
platform-dependent <quote>expected</quote> files and some sample some sample
user-defined trigger functions, and then run the test driver user-defined trigger functions, and then run the test driver
script. At the end you should see something like script. At the end you should see something like
<screen> <screen>
...@@ -66,7 +59,7 @@ ...@@ -66,7 +59,7 @@
If you already did the build as root, you do not have to start all If you already did the build as root, you do not have to start all
over. Instead, make the regression test directory writable by over. Instead, make the regression test directory writable by
some other user, log in as that user, and restart the tests. some other user, log in as that user, and restart the tests.
For example, For example
<screen> <screen>
<prompt>root# </prompt><userinput>chmod -R a+w src/test/regress</userinput> <prompt>root# </prompt><userinput>chmod -R a+w src/test/regress</userinput>
<prompt>root# </prompt><userinput>chmod -R a+w contrib/spi</userinput> <prompt>root# </prompt><userinput>chmod -R a+w contrib/spi</userinput>
...@@ -87,7 +80,7 @@ ...@@ -87,7 +80,7 @@
<para> <para>
The parallel regression test starts quite a few processes under your The parallel regression test starts quite a few processes under your
user ID. Presently, the maximum concurrency is twenty parallel test user ID. Presently, the maximum concurrency is twenty parallel test
scripts, which means sixty processes --- there's a backend, a <application>psql</>, scripts, which means sixty processes: there's a server process, a <application>psql</>,
and usually a shell parent process for the <application>psql</> for each test script. and usually a shell parent process for the <application>psql</> for each test script.
So if your system enforces a per-user limit on the number of processes, So if your system enforces a per-user limit on the number of processes,
make sure this limit is at least seventy-five or so, else you may get make sure this limit is at least seventy-five or so, else you may get
...@@ -105,11 +98,9 @@ ...@@ -105,11 +98,9 @@
too many child processes in parallel. This may cause the parallel too many child processes in parallel. This may cause the parallel
test run to lock up or fail. In such cases, specify a different test run to lock up or fail. In such cases, specify a different
Bourne-compatible shell on the command line, for example: Bourne-compatible shell on the command line, for example:
<informalexample>
<screen> <screen>
<prompt>$ </prompt><userinput>gmake SHELL=/bin/ksh check</userinput> gmake SHELL=/bin/ksh check
</screen> </screen>
</informalexample>
If no non-broken shell is available, you can alter the parallel test If no non-broken shell is available, you can alter the parallel test
schedule as suggested above. schedule as suggested above.
</para> </para>
...@@ -120,7 +111,7 @@ ...@@ -120,7 +111,7 @@
initialize a data area and start the initialize a data area and start the
server, <![%standalone-ignore;[as explained in <xref linkend="runtime">, ]]> then type server, <![%standalone-ignore;[as explained in <xref linkend="runtime">, ]]> then type
<screen> <screen>
<prompt>$ </prompt><userinput>gmake installcheck</userinput> gmake installcheck
</screen> </screen>
The tests will expect to contact the server at the local host and the The tests will expect to contact the server at the local host and the
default port number, unless directed otherwise by <envar>PGHOST</envar> and <envar>PGPORT</envar> default port number, unless directed otherwise by <envar>PGHOST</envar> and <envar>PGPORT</envar>
...@@ -137,7 +128,7 @@ ...@@ -137,7 +128,7 @@
<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 <command>diff</command> 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
small system differences. When a test is reported as small system differences. When a test is reported as
<quote>failed</quote>, always examine the differences between <quote>failed</quote>, always examine the differences between
...@@ -150,12 +141,12 @@ ...@@ -150,12 +141,12 @@
<para> <para>
The actual outputs of the regression tests are in files in the The actual outputs of the regression tests are in files in the
<filename>src/test/regress/results</filename> directory. The test <filename>src/test/regress/results</filename> directory. The test
script uses <application>diff</application> to compare each output script uses <command>diff</command> to compare each output
file against the reference outputs stored in the file against the reference outputs stored in the
<filename>src/test/regress/expected</filename> directory. Any <filename>src/test/regress/expected</filename> directory. Any
differences are saved for your inspection in differences are saved for your inspection in
<filename>src/test/regress/regression.diffs</filename>. (Or you <filename>src/test/regress/regression.diffs</filename>. (Or you
can run <application>diff</application> yourself, if you prefer.) can run <command>diff</command> yourself, if you prefer.)
</para> </para>
<sect2> <sect2>
...@@ -183,7 +174,7 @@ ...@@ -183,7 +174,7 @@
failures. The regression test suite is set up to handle this failures. The regression test suite is set up to handle this
problem by providing alternative result files that together are problem by providing alternative result files that together are
known to handle a large number of locales. For example, for the known to handle a large number of locales. For example, for the
<quote>char</quote> test, the expected file <literal>char</literal> test, the expected file
<filename>char.out</filename> handles the <literal>C</> and <literal>POSIX</> locales, <filename>char.out</filename> handles the <literal>C</> and <literal>POSIX</> locales,
and the file <filename>char_1.out</filename> handles many other and the file <filename>char_1.out</filename> handles many other
locales. The regression test driver will automatically pick the locales. The regression test driver will automatically pick the
...@@ -214,28 +205,28 @@ ...@@ -214,28 +205,28 @@
fail if you run the test on the day of a daylight-saving time fail if you run the test on the day of a daylight-saving time
changeover, or the day before or after one. These queries assume changeover, or the day before or after one. These queries assume
that the intervals between midnight yesterday, midnight today and that the intervals between midnight yesterday, midnight today and
midnight tomorrow are exactly twenty-four hours -- which is wrong midnight tomorrow are exactly twenty-four hours --- which is wrong
if daylight-saving time went into or out of effect meanwhile. if daylight-saving time went into or out of effect meanwhile.
</para> </para>
<para> <para>
Most of the date and time results are dependent on the time zone Most of the date and time results are dependent on the time zone
environment. The reference files are generated for time zone environment. The reference files are generated for time zone
<literal>PST8PDT</literal> (Berkeley, California) and there will be apparent <literal>PST8PDT</literal> (Berkeley, California), and there will be apparent
failures if the tests are not run with that time zone setting. failures if the tests are not run with that time zone setting.
The regression test driver sets environment variable The regression test driver sets environment variable
<envar>PGTZ</envar> to <literal>PST8PDT</literal>, which normally <envar>PGTZ</envar> to <literal>PST8PDT</literal>, which normally
ensures proper results. However, your system must provide library ensures proper results. However, your operating system must provide
support for the <literal>PST8PDT</literal> time zone, or the time zone-dependent support for the <literal>PST8PDT</literal> time zone, or the time zone-dependent
tests will fail. To verify that your machine does have this tests will fail. To verify that your machine does have this
support, type the following: support, type the following:
<screen> <screen>
<prompt>$ </prompt><userinput>env TZ=PST8PDT date</userinput> env TZ=PST8PDT date
</screen> </screen>
The command above should have returned the current system time in The command above should have returned the current system time in
the <literal>PST8PDT</literal> time zone. If the <literal>PST8PDT</literal> database is not available, the <literal>PST8PDT</literal> time zone. If the <literal>PST8PDT</literal> time zone is not available,
then your system may have returned the time in GMT. If the then your system may have returned the time in GMT. If the
<literal>PST8PDT</literal> time zone is not available, you can set the time zone <literal>PST8PDT</literal> time zone is missing, you can set the time zone
rules explicitly: rules explicitly:
<programlisting> <programlisting>
PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ
...@@ -250,7 +241,7 @@ PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ ...@@ -250,7 +241,7 @@ PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ
</para> </para>
<para> <para>
Some systems using older time zone libraries fail to apply Some systems using older time-zone libraries fail to apply
daylight-saving corrections to dates before 1970, causing daylight-saving corrections to dates before 1970, causing
pre-1970 <acronym>PDT</acronym> times to be displayed in <acronym>PST</acronym> instead. This will pre-1970 <acronym>PDT</acronym> times to be displayed in <acronym>PST</acronym> instead. This will
result in localized differences in the test results. result in localized differences in the test results.
...@@ -261,8 +252,8 @@ PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ ...@@ -261,8 +252,8 @@ PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ
<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 floating-point numbers (<type>double
precision</type>) numbers from table columns. Differences in precision</type>) from table columns. Differences in
results involving mathematical functions of <type>double results involving mathematical functions of <type>double
precision</type> columns have been observed. The <literal>float8</> and precision</type> columns have been observed. The <literal>float8</> and
<literal>geometry</> tests are particularly prone to small differences <literal>geometry</> tests are particularly prone to small differences
...@@ -292,26 +283,26 @@ PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ ...@@ -292,26 +283,26 @@ PGTZ='PST8PDT7,M04.01.0,M10.05.03'; export PGTZ
You might see differences in which the same rows are output in a You might see differences in which the same rows are output in a
different order than what appears in the expected file. In most cases different order than what appears in the expected file. In most cases
this is not, strictly speaking, a bug. Most of the regression test this is not, strictly speaking, a bug. Most of the regression test
scripts are not so pedantic as to use an ORDER BY for every single scripts are not so pedantic as to use an <literal>ORDER BY</> for every single
SELECT, and so their result row orderings are not well-defined <literal>SELECT</>, and so their result row orderings are not well-defined
according to the letter of the SQL specification. In practice, since we are according to the letter of the SQL specification. In practice, since we are
looking at the same queries being executed on the same data by the same looking at the same queries being executed on the same data by the same
software, we usually get the same result ordering on all platforms, and software, we usually get the same result ordering on all platforms, and
so the lack of ORDER BY isn't a problem. Some queries do exhibit so the lack of <literal>ORDER BY</> isn't a problem. Some queries do exhibit
cross-platform ordering differences, however. (Ordering differences cross-platform ordering differences, however. (Ordering differences
can also be triggered by non-C locale settings.) can also be triggered by non-C locale settings.)
</para> </para>
<para> <para>
Therefore, if you see an ordering difference, it's not something to Therefore, if you see an ordering difference, it's not something to
worry about, unless the query does have an ORDER BY that your result worry about, unless the query does have an <literal>ORDER BY</> that your result
is violating. But please report it anyway, so that we can add an is violating. But please report it anyway, so that we can add an
ORDER BY to that particular query and thereby eliminate the bogus <literal>ORDER BY</> to that particular query and thereby eliminate the bogus
<quote>failure</quote> in future releases. <quote>failure</quote> in future releases.
</para> </para>
<para> <para>
You might wonder why we don't order all the regress test queries explicitly to You might wonder why we don't order all the regression test queries explicitly to
get rid of this issue once and for all. The reason is that that would get rid of this issue once and for all. The reason is that that would
make the regression tests less useful, not more, since they'd tend make the regression tests less useful, not more, since they'd tend
to exercise query plan types that produce ordered results to the to exercise query plan types that produce ordered results to the
...@@ -323,7 +314,7 @@ exclusion of those that don't. ...@@ -323,7 +314,7 @@ exclusion of those that don't.
<title>The <quote>random</quote> test</title> <title>The <quote>random</quote> test</title>
<para> <para>
There is at least one case in the <quote>random</quote> test There is at least one case in the <literal>random</literal> test
script that is intended to produce random results. This causes script that is intended to produce random results. This causes
random to fail the regression test once in a while (perhaps once random to fail the regression test once in a while (perhaps once
in every five to ten trials). Typing in every five to ten trials). Typing
...@@ -362,11 +353,11 @@ diff results/random.out expected/random.out ...@@ -362,11 +353,11 @@ diff results/random.out expected/random.out
testname/platformpattern=comparisonfilename testname/platformpattern=comparisonfilename
</synopsis> </synopsis>
The test name is just the name of the particular regression test The test name is just the name of the particular regression test
module. The platform pattern is a pattern in the style of module. The platform pattern is a pattern in the style of the Unix
<citerefentry><refentrytitle>expr</><manvolnum>1</></citerefentry> (that is, a regular expression with an implicit tool <command>expr</> (that is, a regular expression with an implicit
<literal>^</literal> anchor <literal>^</literal> anchor
at the start). It is matched against the platform name as printed at the start). It is matched against the platform name as printed
by <filename>config.guess</filename> followed by by <command>config.guess</command> followed by
<literal>:gcc</literal> or <literal>:cc</literal>, depending on <literal>:gcc</literal> or <literal>:cc</literal>, depending on
whether you use the GNU compiler or the system's native compiler whether you use the GNU compiler or the system's native compiler
(on systems where there is a difference). The comparison file (on systems where there is a difference). The comparison file
...@@ -387,7 +378,7 @@ testname/platformpattern=comparisonfilename ...@@ -387,7 +378,7 @@ testname/platformpattern=comparisonfilename
horology/hppa=horology-no-DST-before-1970 horology/hppa=horology-no-DST-before-1970
</programlisting> </programlisting>
which will trigger on any machine for which the output of <command>config.guess</command> which will trigger on any machine for which the output of <command>config.guess</command>
begins with <quote><literal>hppa</literal></quote>. Other lines begins with <literal>hppa</literal>. Other lines
in <filename>resultmap</> select the variant comparison file for other in <filename>resultmap</> select the variant comparison file for other
platforms where it's appropriate. platforms where it's appropriate.
</para> </para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.75 2003/02/19 03:13:24 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/syntax.sgml,v 1.76 2003/03/13 01:30:29 petere Exp $
--> -->
<chapter id="sql-syntax"> <chapter id="sql-syntax">
...@@ -179,7 +179,7 @@ UPDATE "my_table" SET "a" = 5; ...@@ -179,7 +179,7 @@ UPDATE "my_table" SET "a" = 5;
<para> <para>
Quoting an identifier also makes it case-sensitive, whereas Quoting an identifier also makes it case-sensitive, whereas
unquoted names are always folded to lower case. For example, the unquoted names are always folded to lower case. For example, the
identifiers <literal>FOO</literal>, <literal>foo</literal> and identifiers <literal>FOO</literal>, <literal>foo</literal>, and
<literal>"foo"</literal> are considered the same by <literal>"foo"</literal> are considered the same by
<productname>PostgreSQL</productname>, but <literal>"Foo"</literal> <productname>PostgreSQL</productname>, but <literal>"Foo"</literal>
and <literal>"FOO"</literal> are different from these three and and <literal>"FOO"</literal> are different from these three and
...@@ -414,10 +414,10 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -414,10 +414,10 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> )
function-call syntaxes can also be used to specify run-time type function-call syntaxes can also be used to specify run-time type
conversions of arbitrary expressions, as discussed in <xref conversions of arbitrary expressions, as discussed in <xref
linkend="sql-syntax-type-casts">. But the form linkend="sql-syntax-type-casts">. But the form
<replaceable>type</replaceable> '<replaceable>string</replaceable>' <literal><replaceable>type</replaceable> '<replaceable>string</replaceable>'</literal>
can only be used to specify the type of a literal constant. can only be used to specify the type of a literal constant.
Another restriction on Another restriction on
<replaceable>type</replaceable> '<replaceable>string</replaceable>' <literal><replaceable>type</replaceable> '<replaceable>string</replaceable>'</literal>
is that it does not work for array types; use <literal>::</literal> is that it does not work for array types; use <literal>::</literal>
or <literal>CAST()</literal> to specify the type of an array constant. or <literal>CAST()</literal> to specify the type of an array constant.
</para> </para>
...@@ -597,7 +597,7 @@ CAST ( '<replaceable>string</replaceable>' AS <replaceable>type</replaceable> ) ...@@ -597,7 +597,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 numeric
constants, and to separate schema, table, and column names. constants, and to separate schema, table, and column names.
</para> </para>
</listitem> </listitem>
...@@ -870,7 +870,7 @@ SELECT 3 OPERATOR(pg_catalog.+) 4; ...@@ -870,7 +870,7 @@ SELECT 3 OPERATOR(pg_catalog.+) 4;
<listitem> <listitem>
<para> <para>
A positional parameter reference, in the body of a function declaration. A positional parameter reference, in the body of a function definition.
</para> </para>
</listitem> </listitem>
......
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/typeconv.sgml,v 1.27 2003/03/13 01:30:29 petere Exp $
-->
<chapter Id="typeconv"> <chapter Id="typeconv">
<title>Type Conversion</title> <title>Type Conversion</title>
<para> <para>
<acronym>SQL</acronym> queries can, intentionally or not, require <acronym>SQL</acronym> statements can, intentionally or not, require
mixing of different data types in the same expression. mixing of different data types in the same expression.
<productname>PostgreSQL</productname> has extensive facilities for <productname>PostgreSQL</productname> has extensive facilities for
evaluating mixed-type expressions. evaluating mixed-type expressions.
...@@ -14,7 +18,7 @@ to understand the details of the type conversion mechanism. ...@@ -14,7 +18,7 @@ to understand the details of the type conversion mechanism.
However, the implicit conversions done by <productname>PostgreSQL</productname> However, the implicit conversions done by <productname>PostgreSQL</productname>
can affect the results of a query. When necessary, these results can affect the results of a query. When necessary, these results
can be tailored by a user or programmer can be tailored by a user or programmer
using <emphasis>explicit</emphasis> type coercion. using <emphasis>explicit</emphasis> type conversion.
</para> </para>
<para> <para>
...@@ -27,7 +31,7 @@ operators. ...@@ -27,7 +31,7 @@ operators.
<para> <para>
The &cite-programmer; has more details on the exact algorithms used for The &cite-programmer; has more details on the exact algorithms used for
implicit type conversion and coercion. implicit type conversion and conversion.
</para> </para>
<sect1 id="typeconv-overview"> <sect1 id="typeconv-overview">
...@@ -46,15 +50,16 @@ mixed-type expressions to be meaningful even with user-defined types. ...@@ -46,15 +50,16 @@ mixed-type expressions to be meaningful even with user-defined types.
<para> <para>
The <productname>PostgreSQL</productname> scanner/parser decodes lexical The <productname>PostgreSQL</productname> scanner/parser decodes lexical
elements into only five fundamental categories: integers, floating-point numbers, strings, elements into only five fundamental categories: integers, floating-point numbers, strings,
names, and key words. Most extended types are first tokenized into names, and key words. Most extended types are first classified as
strings. The <acronym>SQL</acronym> language definition allows specifying type strings. The <acronym>SQL</acronym> language definition allows specifying type
names with strings, and this mechanism can be used in names with strings, and this mechanism can be used in
<productname>PostgreSQL</productname> to start the parser down the correct <productname>PostgreSQL</productname> to start the parser down the correct
path. For example, the query path. For example, the query
<screen> <screen>
tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value"; SELECT text 'Origin' AS "label", point '(0,0)' AS "value";
Label | Value
label | value
--------+------- --------+-------
Origin | (0,0) Origin | (0,0)
(1 row) (1 row)
...@@ -62,7 +67,7 @@ tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value"; ...@@ -62,7 +67,7 @@ tgl=> SELECT text 'Origin' AS "Label", point '(0,0)' AS "Value";
has two literal constants, of type <type>text</type> and <type>point</type>. has two literal constants, of type <type>text</type> and <type>point</type>.
If a type is not specified for a string literal, then the placeholder type If a type is not specified for a string literal, then the placeholder type
<firstterm>unknown</firstterm> is assigned initially, to be resolved in later <type>unknown</type> is assigned initially, to be resolved in later
stages as described below. stages as described below.
</para> </para>
...@@ -70,7 +75,6 @@ stages as described below. ...@@ -70,7 +75,6 @@ stages as described below.
There are four fundamental <acronym>SQL</acronym> constructs requiring There are four fundamental <acronym>SQL</acronym> constructs requiring
distinct type conversion rules in the <productname>PostgreSQL</productname> distinct type conversion rules in the <productname>PostgreSQL</productname>
parser: parser:
</para>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
...@@ -92,9 +96,8 @@ Function calls ...@@ -92,9 +96,8 @@ Function calls
<listitem> <listitem>
<para> <para>
Much of the <productname>PostgreSQL</productname> type system is built around a Much of the <productname>PostgreSQL</productname> type system is built around a
rich set of functions. Function calls have one or more arguments which, for rich set of functions. Function calls can have one or more arguments.
any specific query, must be matched to the functions available in the system Since <productname>PostgreSQL</productname> permits function
catalog. Since <productname>PostgreSQL</productname> permits function
overloading, the function name alone does not uniquely identify the function overloading, the function name alone does not uniquely identify the function
to be called; the parser must select the right function based on the data to be called; the parser must select the right function based on the data
types of the supplied arguments. types of the supplied arguments.
...@@ -103,12 +106,12 @@ types of the supplied arguments. ...@@ -103,12 +106,12 @@ types of the supplied arguments.
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term> <term>
Query targets Value Storage
</term> </term>
<listitem> <listitem>
<para> <para>
<acronym>SQL</acronym> <command>INSERT</command> and <command>UPDATE</command> statements place the results of <acronym>SQL</acronym> <command>INSERT</command> and <command>UPDATE</command> statements place the results of
expressions into a table. The expressions in the query must be matched up expressions into a table. The expressions in the statement must be matched up
with, and perhaps converted to, the types of the target columns. with, and perhaps converted to, the types of the target columns.
</para> </para>
</listitem> </listitem>
...@@ -119,22 +122,15 @@ with, and perhaps converted to, the types of the target columns. ...@@ -119,22 +122,15 @@ with, and perhaps converted to, the types of the target columns.
</term> </term>
<listitem> <listitem>
<para> <para>
Since all select results from a unionized <literal>SELECT</literal> statement must appear in a single Since all query results from a unionized <literal>SELECT</literal> statement must appear in a single
set of columns, the types of the results set of columns, the types of the results
of each <literal>SELECT</> clause must be matched up and converted to a uniform set. of each <literal>SELECT</> clause must be matched up and converted to a uniform set.
Similarly, the result expressions of a <literal>CASE</> construct must be coerced to Similarly, the branch expressions of a <literal>CASE</> construct must be converted to
a common type so that the <literal>CASE</> expression as a whole has a known output type. a common type so that the <literal>CASE</> expression as a whole has a known output type.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>
<para>
Many of the general type conversion rules use simple conventions built on
the <productname>PostgreSQL</productname> function and operator system tables.
There are some heuristics included in the conversion rules to better support
conventions for the <acronym>SQL</acronym> standard native types such as
<type>smallint</type>, <type>integer</type>, and <type>real</type>.
</para> </para>
<para> <para>
...@@ -157,7 +153,7 @@ a <firstterm>preferred type</firstterm> which is preferentially selected ...@@ -157,7 +153,7 @@ a <firstterm>preferred type</firstterm> which is preferentially selected
when there is ambiguity. when there is ambiguity.
In the user-defined category, each type is its own preferred type. In the user-defined category, each type is its own preferred type.
Ambiguous expressions (those with multiple candidate parsing solutions) Ambiguous expressions (those with multiple candidate parsing solutions)
can often be resolved when there are multiple possible built-in types, but can therefore often be resolved when there are multiple possible built-in types, but
they will raise an error when there are multiple choices for user-defined they will raise an error when there are multiple choices for user-defined
types. types.
</para> </para>
...@@ -184,8 +180,7 @@ be converted to a user-defined type (of course, only if conversion is necessary) ...@@ -184,8 +180,7 @@ be converted to a user-defined type (of course, only if conversion is necessary)
<para> <para>
User-defined types are not related. Currently, <productname>PostgreSQL</productname> User-defined types are not related. Currently, <productname>PostgreSQL</productname>
does not have information available to it on relationships between types, other than does not have information available to it on relationships between types, other than
hardcoded heuristics for built-in types and implicit relationships based on available functions hardcoded heuristics for built-in types and implicit relationships based on available functions.
in the catalog.
</para> </para>
</listitem> </listitem>
...@@ -195,12 +190,12 @@ There should be no extra overhead from the parser or executor ...@@ -195,12 +190,12 @@ There should be no extra overhead from the parser or executor
if a query does not need implicit type conversion. if a query does not need implicit type conversion.
That is, if a query is well formulated and the types already match up, then the query should proceed That is, if a query is well formulated and the types already match up, then the query should proceed
without spending extra time in the parser and without introducing unnecessary implicit conversion without spending extra time in the parser and without introducing unnecessary implicit conversion
functions into the query. calls into the query.
</para> </para>
<para> <para>
Additionally, if a query usually requires an implicit conversion for a function, and Additionally, if a query usually requires an implicit conversion for a function, and
if then the user defines an explicit function with the correct argument types, the parser if then the user defines a new function with the correct argument types, the parser
should use this new function and will no longer do the implicit conversion using the old function. should use this new function and will no longer do the implicit conversion using the old function.
</para> </para>
</listitem> </listitem>
...@@ -226,7 +221,7 @@ should use this new function and will no longer do the implicit conversion using ...@@ -226,7 +221,7 @@ should use this new function and will no longer do the implicit conversion using
<para> <para>
Select the operators to be considered from the Select the operators to be considered from the
<classname>pg_operator</classname> system catalog. If an unqualified <classname>pg_operator</classname> system catalog. If an unqualified
operator name is used (the usual case), the operators operator name was used (the usual case), the operators
considered are those of the right name and argument count that are considered are those of the right name and argument count that are
visible in the current search path (see <xref linkend="ddl-schemas-path">). visible in the current search path (see <xref linkend="ddl-schemas-path">).
If a qualified operator name was given, only operators in the specified If a qualified operator name was given, only operators in the specified
...@@ -255,7 +250,7 @@ operators considered), use it. ...@@ -255,7 +250,7 @@ operators considered), use it.
<substeps> <substeps>
<step performance="optional"> <step performance="optional">
<para> <para>
If one argument of a binary operator is <type>unknown</type> type, If one argument of a binary operator invocation is of the <type>unknown</type> type,
then assume it is the same type as the other argument for this check. then assume it is the same type as the other argument for this check.
Other cases involving <type>unknown</type> will never find a match at Other cases involving <type>unknown</type> will never find a match at
this step. this step.
...@@ -272,9 +267,9 @@ Look for the best match. ...@@ -272,9 +267,9 @@ Look for the best match.
<step performance="required"> <step performance="required">
<para> <para>
Discard candidate operators for which the input types do not match Discard candidate operators for which the input types do not match
and cannot be coerced (using an implicit coercion function) to match. and cannot be converted (using an implicit conversion) to match.
<type>unknown</type> literals are <type>unknown</type> literals are
assumed to be coercible to anything for this purpose. If only one assumed to be convertible to anything for this purpose. If only one
candidate remains, use it; else continue to the next step. candidate remains, use it; else continue to the next step.
</para> </para>
</step> </step>
...@@ -296,23 +291,22 @@ If only one candidate remains, use it; else continue to the next step. ...@@ -296,23 +291,22 @@ If only one candidate remains, use it; else continue to the next step.
<step performance="required"> <step performance="required">
<para> <para>
Run through all candidates and keep those that accept preferred types at Run through all candidates and keep those that accept preferred types at
the most positions where type coercion will be required. the most positions where type conversion will be required.
Keep all candidates if none accept preferred types. Keep all candidates if none accept preferred types.
If only one candidate remains, use it; else continue to the next step. If only one candidate remains, use it; else continue to the next step.
</para> </para>
</step> </step>
<step performance="required"> <step performance="required">
<para> <para>
If any input arguments are <quote>unknown</quote>, check the type If any input arguments are <type>unknown</type>, check the type
categories accepted at those argument positions by the remaining categories accepted at those argument positions by the remaining
candidates. At each position, select the <quote>string</quote> category if any candidates. At each position, select the <literal>string</literal> category if any
candidate accepts that category (this bias towards string is appropriate candidate accepts that category. (This bias towards string is appropriate
since an unknown-type literal does look like a string). Otherwise, if since an unknown-type literal does look like a string.) Otherwise, if
all the remaining candidates accept the same type category, select that all the remaining candidates accept the same type category, select that
category; otherwise fail because the correct choice cannot be deduced category; otherwise fail because the correct choice cannot be deduced
without more clues. Also note whether any of the candidates accept a without more clues. Now discard operator
preferred data type within the selected category. Now discard operator candidates that do not accept the selected type category. Furthermore,
candidates that do not accept the selected type category; furthermore,
if any candidate accepts a preferred type at a given argument position, if any candidate accepts a preferred type at a given argument position,
discard candidates that accept non-preferred types for that argument. discard candidates that accept non-preferred types for that argument.
</para> </para>
...@@ -328,7 +322,9 @@ then fail. ...@@ -328,7 +322,9 @@ then fail.
</step> </step>
</procedure> </procedure>
<bridgehead renderas="sect2">Examples</bridgehead> <para>
Some examples follow.
</para>
<example> <example>
<title>Exponentiation Operator Type Resolution</title> <title>Exponentiation Operator Type Resolution</title>
...@@ -340,8 +336,9 @@ operator defined in the catalog, and it takes arguments of type ...@@ -340,8 +336,9 @@ operator defined in the catalog, and it takes arguments of type
The scanner assigns an initial type of <type>integer</type> to both arguments The scanner assigns an initial type of <type>integer</type> to both arguments
of this query expression: of this query expression:
<screen> <screen>
tgl=> SELECT 2 ^ 3 AS "Exp"; SELECT 2 ^ 3 AS "exp";
Exp
exp
----- -----
8 8
(1 row) (1 row)
...@@ -351,30 +348,8 @@ So the parser does a type conversion on both operands and the query ...@@ -351,30 +348,8 @@ So the parser does a type conversion on both operands and the query
is equivalent to is equivalent to
<screen> <screen>
tgl=> SELECT CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "Exp"; SELECT CAST(2 AS double precision) ^ CAST(3 AS double precision) AS "exp";
Exp
-----
8
(1 row)
</screen>
or
<screen>
tgl=> SELECT 2.0 ^ 3.0 AS "Exp";
Exp
-----
8
(1 row)
</screen> </screen>
<note>
<para>
This last form has the least overhead, since no functions are called to do
implicit type conversion. This is not an issue for small queries, but may
have an impact on the performance of queries involving large tables.
</para>
</note>
</para> </para>
</example> </example>
...@@ -383,15 +358,16 @@ have an impact on the performance of queries involving large tables. ...@@ -383,15 +358,16 @@ have an impact on the performance of queries involving large tables.
<para> <para>
A string-like syntax is used for working with string types as well as for A string-like syntax is used for working with string types as well as for
working with complex extended types. working with complex extension types.
Strings with unspecified type are matched with likely operator candidates. Strings with unspecified type are matched with likely operator candidates.
</para> </para>
<para> <para>
An example with one unspecified argument: An example with one unspecified argument:
<screen> <screen>
tgl=> SELECT text 'abc' || 'def' AS "Text and Unknown"; SELECT text 'abc' || 'def' AS "text and unknown";
Text and Unknown
text and unknown
------------------ ------------------
abcdef abcdef
(1 row) (1 row)
...@@ -405,10 +381,11 @@ be interpreted as of type <type>text</type>. ...@@ -405,10 +381,11 @@ be interpreted as of type <type>text</type>.
</para> </para>
<para> <para>
Concatenation on unspecified types: Here is a concatenation on unspecified types:
<screen> <screen>
tgl=> SELECT 'abc' || 'def' AS "Unspecified"; SELECT 'abc' || 'def' AS "unspecified";
Unspecified
unspecified
------------- -------------
abcdef abcdef
(1 row) (1 row)
...@@ -421,7 +398,7 @@ are specified in the query. So, the parser looks for all candidate operators ...@@ -421,7 +398,7 @@ are specified in the query. So, the parser looks for all candidate operators
and finds that there are candidates accepting both string-category and and finds that there are candidates accepting both string-category and
bit-string-category inputs. Since string category is preferred when available, bit-string-category inputs. Since string category is preferred when available,
that category is selected, and then the that category is selected, and then the
<quote>preferred type</quote> for strings, <type>text</type>, is used as the specific preferred type for strings, <type>text</type>, is used as the specific
type to resolve the unknown literals to. type to resolve the unknown literals to.
</para> </para>
</example> </example>
...@@ -437,27 +414,29 @@ entries is for type <type>float8</type>, which is the preferred type in ...@@ -437,27 +414,29 @@ entries is for type <type>float8</type>, which is the preferred type in
the numeric category. Therefore, <productname>PostgreSQL</productname> the numeric category. Therefore, <productname>PostgreSQL</productname>
will use that entry when faced with a non-numeric input: will use that entry when faced with a non-numeric input:
<screen> <screen>
tgl=> select @ text '-4.5' as "abs"; SELECT @ '-4.5' AS "abs";
abs abs
----- -----
4.5 4.5
(1 row) (1 row)
</screen> </screen>
Here the system has performed an implicit text-to-float8 conversion Here the system has performed an implicit conversion from <type>text</type> to <type>float8</type>
before applying the chosen operator. We can verify that float8 and before applying the chosen operator. We can verify that <type>float8</type> and
not some other type was used: not some other type was used:
<screen> <screen>
tgl=> select @ text '-4.5e500' as "abs"; SELECT @ '-4.5e500' AS "abs";
ERROR: Input '-4.5e500' is out of range for float8 ERROR: Input '-4.5e500' is out of range for float8
</screen> </screen>
</para> </para>
<para> <para>
On the other hand, the postfix operator <literal>!</> (factorial) On the other hand, the postfix operator <literal>!</> (factorial)
is defined only for integer data types, not for float8. So, if we is defined only for integer data types, not for <type>float8</type>. So, if we
try a similar case with <literal>!</>, we get: try a similar case with <literal>!</>, we get:
<screen> <screen>
tgl=> select text '20' ! as "factorial"; SELECT '20' ! AS "factorial";
ERROR: Unable to identify a postfix operator '!' for type 'text' ERROR: Unable to identify a postfix operator '!' for type 'text'
You may need to add parentheses or an explicit cast You may need to add parentheses or an explicit cast
</screen> </screen>
...@@ -465,7 +444,8 @@ This happens because the system can't decide which of the several ...@@ -465,7 +444,8 @@ This happens because the system can't decide which of the several
possible <literal>!</> operators should be preferred. We can help possible <literal>!</> operators should be preferred. We can help
it out with an explicit cast: it out with an explicit cast:
<screen> <screen>
tgl=> select cast(text '20' as int8) ! as "factorial"; SELECT CAST('20' AS int8) ! AS "factorial";
factorial factorial
--------------------- ---------------------
2432902008176640000 2432902008176640000
...@@ -491,7 +471,7 @@ tgl=> select cast(text '20' as int8) ! as "factorial"; ...@@ -491,7 +471,7 @@ tgl=> select cast(text '20' as int8) ! as "factorial";
<para> <para>
Select the functions to be considered from the Select the functions to be considered from the
<classname>pg_proc</classname> system catalog. If an unqualified <classname>pg_proc</classname> system catalog. If an unqualified
function name is used, the functions function name was used, the functions
considered are those of the right name and argument count that are considered are those of the right name and argument count that are
visible in the current search path (see <xref linkend="ddl-schemas-path">). visible in the current search path (see <xref linkend="ddl-schemas-path">).
If a qualified function name was given, only functions in the specified If a qualified function name was given, only functions in the specified
...@@ -517,16 +497,18 @@ If one exists (there can be only one exact match in the set of ...@@ -517,16 +497,18 @@ If one exists (there can be only one exact match in the set of
functions considered), use it. functions considered), use it.
(Cases involving <type>unknown</type> will never find a match at (Cases involving <type>unknown</type> will never find a match at
this step.) this step.)
</para></step> </para>
</step>
<step performance="required"> <step performance="required">
<para> <para>
If no exact match is found, see whether the function call appears If no exact match is found, see whether the function call appears
to be a trivial type coercion request. This happens if the function call to be a trivial type conversion request. This happens if the function call
has just one argument and the function name is the same as the (internal) has just one argument and the function name is the same as the (internal)
name of some data type. Furthermore, the function argument must be either name of some data type. Furthermore, the function argument must be either
an unknown-type literal or a type that is binary-compatible with the named an unknown-type literal or a type that is binary-compatible with the named
data type. When these conditions are met, the function argument is coerced data type. When these conditions are met, the function argument is converted
to the named data type without any explicit function call. to the named data type without any actual function call.
</para> </para>
</step> </step>
<step performance="required"> <step performance="required">
...@@ -537,9 +519,9 @@ Look for the best match. ...@@ -537,9 +519,9 @@ Look for the best match.
<step performance="required"> <step performance="required">
<para> <para>
Discard candidate functions for which the input types do not match Discard candidate functions for which the input types do not match
and cannot be coerced (using an implicit coercion function) to match. and cannot be converted (using an implicit conversion) to match.
<type>unknown</type> literals are <type>unknown</type> literals are
assumed to be coercible to anything for this purpose. If only one assumed to be convertible to anything for this purpose. If only one
candidate remains, use it; else continue to the next step. candidate remains, use it; else continue to the next step.
</para> </para>
</step> </step>
...@@ -561,7 +543,7 @@ If only one candidate remains, use it; else continue to the next step. ...@@ -561,7 +543,7 @@ If only one candidate remains, use it; else continue to the next step.
<step performance="required"> <step performance="required">
<para> <para>
Run through all candidates and keep those that accept preferred types at Run through all candidates and keep those that accept preferred types at
the most positions where type coercion will be required. the most positions where type conversion will be required.
Keep all candidates if none accept preferred types. Keep all candidates if none accept preferred types.
If only one candidate remains, use it; else continue to the next step. If only one candidate remains, use it; else continue to the next step.
</para> </para>
...@@ -570,13 +552,12 @@ If only one candidate remains, use it; else continue to the next step. ...@@ -570,13 +552,12 @@ If only one candidate remains, use it; else continue to the next step.
<para> <para>
If any input arguments are <type>unknown</type>, check the type categories accepted If any input arguments are <type>unknown</type>, check the type categories accepted
at those argument positions by the remaining candidates. At each position, at those argument positions by the remaining candidates. At each position,
select the <type>string</type> category if any candidate accepts that category select the <type>string</type> category if any candidate accepts that category.
(this bias towards string (This bias towards string
is appropriate since an unknown-type literal does look like a string). is appropriate since an unknown-type literal does look like a string.)
Otherwise, if all the remaining candidates accept the same type category, Otherwise, if all the remaining candidates accept the same type category,
select that category; otherwise fail because select that category; otherwise fail because
the correct choice cannot be deduced without more clues. Also note whether the correct choice cannot be deduced without more clues.
any of the candidates accept a preferred data type within the selected category.
Now discard candidates that do not accept the selected type category; Now discard candidates that do not accept the selected type category;
furthermore, if any candidate accepts a preferred type at a given argument furthermore, if any candidate accepts a preferred type at a given argument
position, discard candidates that accept non-preferred types for that position, discard candidates that accept non-preferred types for that
...@@ -594,32 +575,41 @@ then fail. ...@@ -594,32 +575,41 @@ then fail.
</step> </step>
</procedure> </procedure>
<bridgehead renderas="sect2">Examples</bridgehead> <para>
Some examples follow.
</para>
<example> <example>
<title>Factorial Function Argument Type Resolution</title> <title>Rounding Function Argument Type Resolution</title>
<para> <para>
There is only one <function>int4fac</function> function defined in the There is only one <function>round</function> function with two
<classname>pg_proc</classname> catalog. arguments. (The first is <type>numeric</type>, the second is
So the following query automatically converts the <type>int2</type> argument <type>integer</type>.) So the following query automatically converts
to <type>int4</type>: the first argument of type <type>integer</type> to
<type>numeric</type>:
<screen> <screen>
tgl=> SELECT int4fac(int2 '4'); SELECT round(4, 4);
int4fac
--------- round
24 --------
4.0000
(1 row) (1 row)
</screen> </screen>
and is actually transformed by the parser to That query is actually transformed by the parser to
<screen> <screen>
tgl=> SELECT int4fac(int4(int2 '4')); SELECT round(CAST (4 AS numeric), 4);
int4fac </screen>
--------- </para>
24
(1 row) <para>
Since numeric constants with decimal points are initially assigned the
type <type>numeric</type>, the following query will require no type
conversion and may therefore be slightly more efficient:
<screen>
SELECT round(4.0, 4);
</screen> </screen>
</para> </para>
</example> </example>
...@@ -628,15 +618,15 @@ tgl=> SELECT int4fac(int4(int2 '4')); ...@@ -628,15 +618,15 @@ tgl=> SELECT int4fac(int4(int2 '4'));
<title>Substring Function Type Resolution</title> <title>Substring Function Type Resolution</title>
<para> <para>
There are two <function>substr</function> functions declared in <classname>pg_proc</classname>. However, There are several <function>substr</function> functions, one of which
only one takes two arguments, of types <type>text</type> and <type>int4</type>. takes types <type>text</type> and <type>integer</type>. If called
</para> with a string constant of unspecified type, the system chooses the
candidate function that accepts an argument of the preferred category
<literal>string</literal> (namely of type <type>text</type>).
<para>
If called with a string constant of unspecified type, the type is matched up
directly with the only candidate function type:
<screen> <screen>
tgl=> SELECT substr('1234', 3); SELECT substr('1234', 3);
substr substr
-------- --------
34 34
...@@ -646,28 +636,26 @@ tgl=> SELECT substr('1234', 3); ...@@ -646,28 +636,26 @@ tgl=> SELECT substr('1234', 3);
<para> <para>
If the string is declared to be of type <type>varchar</type>, as might be the case If the string is declared to be of type <type>varchar</type>, as might be the case
if it comes from a table, then the parser will try to coerce it to become <type>text</type>: if it comes from a table, then the parser will try to convert it to become <type>text</type>:
<screen> <screen>
tgl=> SELECT substr(varchar '1234', 3); SELECT substr(varchar '1234', 3);
substr substr
-------- --------
34 34
(1 row) (1 row)
</screen> </screen>
which is transformed by the parser to become
This is transformed by the parser to effectively become
<screen> <screen>
tgl=> SELECT substr(text(varchar '1234'), 3); SELECT substr(CAST (varchar '1234' AS text), 3);
substr
--------
34
(1 row)
</screen> </screen>
</para> </para>
<para> <para>
<note> <note>
<para> <para>
Actually, the parser is aware that <type>text</type> and <type>varchar</type> The parser is aware that <type>text</type> and <type>varchar</type>
are <firstterm>binary-compatible</>, meaning that one can be passed to a function that are binary-compatible, meaning that one can be passed to a function that
accepts the other without doing any physical conversion. Therefore, no accepts the other without doing any physical conversion. Therefore, no
explicit type conversion call is really inserted in this case. explicit type conversion call is really inserted in this case.
</para> </para>
...@@ -675,64 +663,67 @@ explicit type conversion call is really inserted in this case. ...@@ -675,64 +663,67 @@ explicit type conversion call is really inserted in this case.
</para> </para>
<para> <para>
And, if the function is called with an <type>int4</type>, the parser will And, if the function is called with an argument of type <type>integer</type>, the parser will
try to convert that to <type>text</type>: try to convert that to <type>text</type>:
<screen> <screen>
tgl=> SELECT substr(1234, 3); SELECT substr(1234, 3);
substr substr
-------- --------
34 34
(1 row) (1 row)
</screen> </screen>
which actually executes as
This actually executes as
<screen> <screen>
tgl=> SELECT substr(text(1234), 3); SELECT substr(CAST (1234 AS text), 3);
substr
--------
34
(1 row)
</screen> </screen>
This succeeds because there is a conversion function text(int4) in the This automatic transformation can succeed because there is an
system catalog. implicitly invocable cast from <type>integer</type> to
<type>text</type>.
</para> </para>
</example> </example>
</sect1> </sect1>
<sect1 id="typeconv-query"> <sect1 id="typeconv-query">
<title>Query Targets</title> <title>Value Storage</title>
<para> <para>
Values to be inserted into a table are coerced to the destination Values to be inserted into a table are converted to the destination
column's data type according to the column's data type according to the
following steps. following steps.
</para> </para>
<procedure> <procedure>
<title>Query Target Type Resolution</title> <title>Value Storage Type Conversion</title>
<step performance="required"> <step performance="required">
<para> <para>
Check for an exact match with the target. Check for an exact match with the target.
</para></step> </para>
</step>
<step performance="required"> <step performance="required">
<para> <para>
Otherwise, try to coerce the expression to the target type. This will succeed Otherwise, try to convert the expression to the target type. This will succeed
if the two types are known binary-compatible, or if there is a conversion if there is a registered cast between the two types.
function. If the expression is an unknown-type literal, the contents of If the expression is an unknown-type literal, the contents of
the literal string will be fed to the input conversion routine for the target the literal string will be fed to the input conversion routine for the target
type. type.
</para></step> </para>
</step>
<step performance="required"> <step performance="required">
<para> <para>
If the target is a fixed-length type (e.g. <type>char</type> or <type>varchar</type> If the target is a fixed-length type (e.g., <type>char</type> or <type>varchar</type>
declared with a length) then try to find a sizing function for the target declared with a length) then try to find a sizing function for the target
type. A sizing function is a function of the same name as the type, type. A sizing function is a function of the same name as the type,
taking two arguments of which the first is that type and the second is an taking two arguments of which the first is that type and the second is of type
integer, and returning the same type. If one is found, it is applied, <type>integer</type>, and returning the same type. If one is found, it is applied,
passing the column's declared length as the second parameter. passing the column's declared length as the second parameter.
</para></step> </para>
</step>
</procedure> </procedure>
...@@ -740,30 +731,31 @@ passing the column's declared length as the second parameter. ...@@ -740,30 +731,31 @@ passing the column's declared length as the second parameter.
<title><type>character</type> Storage Type Conversion</title> <title><type>character</type> Storage Type Conversion</title>
<para> <para>
For a target column declared as <type>character(20)</type> the following query For a target column declared as <type>character(20)</type> the following statement
ensures that the target is sized correctly: ensures that the stored value is sized correctly:
<screen> <screen>
tgl=> CREATE TABLE vv (v character(20)); CREATE TABLE vv (v character(20));
CREATE INSERT INTO vv SELECT 'abc' || 'def';
tgl=> INSERT INTO vv SELECT 'abc' || 'def'; SELECT v, length(v) FROM vv;
INSERT 392905 1
tgl=> SELECT v, length(v) FROM vv;
v | length v | length
----------------------+-------- ----------------------+--------
abcdef | 20 abcdef | 20
(1 row) (1 row)
</screen> </screen>
</para>
<para>
What has really happened here is that the two unknown literals are resolved What has really happened here is that the two unknown literals are resolved
to <type>text</type> by default, allowing the <literal>||</literal> operator to <type>text</type> by default, allowing the <literal>||</literal> operator
to be resolved as <type>text</type> concatenation. Then the <type>text</type> to be resolved as <type>text</type> concatenation. Then the <type>text</type>
result of the operator is coerced to <type>bpchar</type> (<quote>blank-padded result of the operator is converted to <type>bpchar</type> (<quote>blank-padded
char</>, the internal name of the character data type) to match the target char</>, the internal name of the <type>character</type> data type) to match the target
column type. (Since the parser knows that <type>text</type> and column type. (Since the types <type>text</type> and
<type>bpchar</type> are binary-compatible, this coercion is implicit and does <type>bpchar</type> are binary-compatible, this conversion does
not insert any real function call.) Finally, the sizing function not insert any real function call.) Finally, the sizing function
<literal>bpchar(bpchar, integer)</literal> is found in the system catalogs <literal>bpchar(bpchar, integer)</literal> is found in the system catalog
and applied to the operator's result and the stored column length. This and applied to the operator's result and the stored column length. This
type-specific function performs the required length check and addition of type-specific function performs the required length check and addition of
padding spaces. padding spaces.
...@@ -783,78 +775,87 @@ to each output column of a union query. The <literal>INTERSECT</> and ...@@ -783,78 +775,87 @@ to each output column of a union query. The <literal>INTERSECT</> and
A <literal>CASE</> construct also uses the identical algorithm to match up its A <literal>CASE</> construct also uses the identical algorithm to match up its
component expressions and select a result data type. component expressions and select a result data type.
</para> </para>
<procedure> <procedure>
<title><literal>UNION</> and <literal>CASE</> Type Resolution</title> <title><literal>UNION</> and <literal>CASE</> Type Resolution</title>
<step performance="required"> <step performance="required">
<para> <para>
If all inputs are of type <type>unknown</type>, resolve as type If all inputs are of type <type>unknown</type>, resolve as type
<type>text</type> (the preferred type for string category). <type>text</type> (the preferred type of the string category).
Otherwise, ignore the <type>unknown</type> inputs while choosing the type. Otherwise, ignore the <type>unknown</type> inputs while choosing the result type.
</para></step> </para>
</step>
<step performance="required"> <step performance="required">
<para> <para>
If the non-unknown inputs are not all of the same type category, fail. If the non-unknown inputs are not all of the same type category, fail.
</para></step> </para>
</step>
<step performance="required"> <step performance="required">
<para> <para>
Choose the first non-unknown input type which is a preferred type in Choose the first non-unknown input type which is a preferred type in
that category or allows all the non-unknown inputs to be implicitly that category or allows all the non-unknown inputs to be implicitly
coerced to it. converted to it.
</para></step> </para>
</step>
<step performance="required"> <step performance="required">
<para> <para>
Coerce all inputs to the selected type. Convert all inputs to the selected type.
</para></step> </para>
</step>
</procedure> </procedure>
<bridgehead renderas="sect2">Examples</bridgehead> <para>
Some examples follow.
</para>
<example> <example>
<title>Underspecified Types in a Union</title> <title>Type Resolution with Underspecified Types in a Union</title>
<para> <para>
<screen> <screen>
tgl=> SELECT text 'a' AS "Text" UNION SELECT 'b'; SELECT text 'a' AS "text" UNION SELECT 'b';
Text
text
------ ------
a a
b b
(2 rows) (2 rows)
</screen> </screen>
Here, the unknown-type literal <literal>'b'</literal> will be resolved as type text. Here, the unknown-type literal <literal>'b'</literal> will be resolved as type <type>text</type>.
</para> </para>
</example> </example>
<example> <example>
<title>Type Conversion in a Simple Union</title> <title>Type Resolution in a Simple Union</title>
<para> <para>
<screen> <screen>
tgl=> SELECT 1.2 AS "Numeric" UNION SELECT 1; SELECT 1.2 AS "numeric" UNION SELECT 1;
Numeric
numeric
--------- ---------
1 1
1.2 1.2
(2 rows) (2 rows)
</screen> </screen>
The literal <literal>1.2</> is of type <type>numeric</>, The literal <literal>1.2</> is of type <type>numeric</>,
and the integer value <literal>1</> can be cast implicitly to and the <type>integer</type> value <literal>1</> can be cast implicitly to
<type>numeric</>, so that type is used. <type>numeric</>, so that type is used.
</para> </para>
</example> </example>
<example> <example>
<title>Type Conversion in a Transposed Union</title> <title>Type Resolution in a Transposed Union</title>
<para> <para>
<screen> <screen>
tgl=> SELECT 1 AS "Real" SELECT 1 AS "real" UNION SELECT CAST('2.2' AS REAL);
tgl-> UNION SELECT CAST('2.2' AS REAL);
Real real
------ ------
1 1
2.2 2.2
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/user-manag.sgml,v 1.18 2002/11/11 20:14:04 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/user-manag.sgml,v 1.19 2003/03/13 01:30:29 petere Exp $
--> -->
<chapter id="user-manag"> <chapter id="user-manag">
...@@ -31,20 +31,20 @@ $Header: /cvsroot/pgsql/doc/src/sgml/user-manag.sgml,v 1.18 2002/11/11 20:14:04 ...@@ -31,20 +31,20 @@ $Header: /cvsroot/pgsql/doc/src/sgml/user-manag.sgml,v 1.18 2002/11/11 20:14:04
per individual database). To create a user use the <command>CREATE per individual database). To create a user use the <command>CREATE
USER</command> SQL command: USER</command> SQL command:
<synopsis> <synopsis>
CREATE USER <replaceable>name</replaceable> CREATE USER <replaceable>name</replaceable>;
</synopsis> </synopsis>
<replaceable>name</replaceable> follows the rules for SQL <replaceable>name</replaceable> follows the rules for SQL
identifiers: either unadorned without special characters, or identifiers: either unadorned without special characters, or
double-quoted. To remove an existing user, use the analogous double-quoted. To remove an existing user, use the analogous
<command>DROP USER</command> command: <command>DROP USER</command> command:
<synopsis> <synopsis>
DROP USER <replaceable>name</replaceable> DROP USER <replaceable>name</replaceable>;
</synopsis> </synopsis>
</para> </para>
<para> <para>
For convenience, the programs <application>createuser</application> For convenience, the programs <command>createuser</command>
and <application>dropuser</application> are provided as wrappers and <command>dropuser</command> are provided as wrappers
around these SQL commands that can be called from the shell command around these SQL commands that can be called from the shell command
line: line:
<synopsis> <synopsis>
...@@ -57,11 +57,11 @@ dropuser <replaceable>name</replaceable> ...@@ -57,11 +57,11 @@ dropuser <replaceable>name</replaceable>
In order to bootstrap the database system, a freshly initialized In order to bootstrap the database system, a freshly initialized
system always contains one predefined user. This user will have the system always contains one predefined user. This user will have the
fixed ID 1, and by default (unless altered when running fixed ID 1, and by default (unless altered when running
<application>initdb</application>) it will have the same name as <command>initdb</command>) it will have the same name as the
the operating system user that initialized the database operating system user that initialized the database
cluster. Customarily, this user will be named cluster. Customarily, this user will be named
<systemitem>postgres</systemitem>. In order to create more users <literal>postgres</literal>. In order to create more users you
you first have to connect as this initial user. first have to connect as this initial user.
</para> </para>
<para> <para>
...@@ -69,11 +69,11 @@ dropuser <replaceable>name</replaceable> ...@@ -69,11 +69,11 @@ dropuser <replaceable>name</replaceable>
database server. The user name to use for a particular database database server. The user name to use for a particular database
connection is indicated by the client that is initiating the connection is indicated by the client that is initiating the
connection request in an application-specific fashion. For example, connection request in an application-specific fashion. For example,
the <application>psql</application> program uses the the <command>psql</command> program uses the
<option>-U</option> command line option to indicate the user to <option>-U</option> command line option to indicate the user to
connect as. Many applications assume the name of the current connect as. Many applications assume the name of the current
operating system user by default (including operating system user by default (including
<application>createuser</> and <application>psql</>). Therefore it <command>createuser</> and <command>psql</>). Therefore it
is convenient to maintain a naming correspondence between the two is convenient to maintain a naming correspondence between the two
user sets. user sets.
</para> </para>
...@@ -134,7 +134,7 @@ dropuser <replaceable>name</replaceable> ...@@ -134,7 +134,7 @@ dropuser <replaceable>name</replaceable>
make use of passwords. Database passwords are separate from make use of passwords. Database passwords are separate from
operating system passwords. Specify a password upon user operating system passwords. Specify a password upon user
creation with <literal>CREATE USER creation with <literal>CREATE USER
<replaceable>name</replaceable> PASSWORD 'string'</literal>. <replaceable>name</replaceable> PASSWORD '<replaceable>string</>'</literal>.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -172,12 +172,12 @@ ALTER USER myname SET enable_indexscan TO off; ...@@ -172,12 +172,12 @@ ALTER USER myname SET enable_indexscan TO off;
management of privileges: privileges can be granted to, or revoked management of privileges: privileges can be granted to, or revoked
from, a group as a whole. To create a group, use from, a group as a whole. To create a group, use
<synopsis> <synopsis>
CREATE GROUP <replaceable>name</replaceable> CREATE GROUP <replaceable>name</replaceable>;
</synopsis> </synopsis>
To add users to or remove users from a group, use To add users to or remove users from a group, use
<synopsis> <synopsis>
ALTER GROUP <replaceable>name</replaceable> ADD USER <replaceable>uname1</replaceable>, ... ALTER GROUP <replaceable>name</replaceable> ADD USER <replaceable>uname1</replaceable>, ... ;
ALTER GROUP <replaceable>name</replaceable> DROP USER <replaceable>uname1</replaceable>, ... ALTER GROUP <replaceable>name</replaceable> DROP USER <replaceable>uname1</replaceable>, ... ;
</synopsis> </synopsis>
</para> </para>
</sect1> </sect1>
...@@ -247,7 +247,7 @@ REVOKE ALL ON accounts FROM PUBLIC; ...@@ -247,7 +247,7 @@ REVOKE ALL ON accounts FROM PUBLIC;
<para> <para>
Functions and triggers allow users to insert code into the backend Functions and triggers allow users to insert code into the backend
server that other users may execute without knowing it. Hence, both server that other users may execute without knowing it. Hence, both
mechanisms permit users to <firstterm>Trojan horse</firstterm> mechanisms permit users to <quote>Trojan horse</quote>
others with relative impunity. The only real protection is tight others with relative impunity. The only real protection is tight
control over who can define functions. control over who can define functions.
</para> </para>
......
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