Big editing for consistent content and presentation.

This commit is contained in:
Peter Eisentraut 2003-03-13 01:30:29 +00:00
parent 31e69ccb21
commit 706a32cdf6
24 changed files with 4695 additions and 5079 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$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
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>

View File

@ -1,4 +1,4 @@
<!-- $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 @@
<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 (
); );
</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
</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;
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';
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';
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
</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
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;
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;
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;
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;
<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 ('{"\\\\","\\""}');
<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>

View File

@ -1,4 +1,4 @@
<!-- $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 @@
<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").
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</>
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.

View File

@ -1,5 +1,5 @@
<!-- <!--
$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
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
<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
<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> <
<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> <
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> <
<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> <
<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> <
<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> <
<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> <
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> <
<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
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
<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
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
<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
</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
<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
</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
<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
<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
<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
<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
</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
</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
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
<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

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,9 @@
<!-- <!--
$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
<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
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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
<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
</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

View File

@ -1,4 +1,4 @@
<!-- $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;
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;
<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;
<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;
</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;
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;
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;
</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;
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;
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

View File

@ -1,5 +1,5 @@
<!-- <!--
$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
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>
<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>
<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;
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];
<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
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
/* 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
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
<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
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
<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
</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
</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
<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
<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>;
<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>;
<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
</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
<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</></>
<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</></>
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</></>
<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</></>
<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</></>
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 = ? ",
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>

View File

@ -1,5 +1,5 @@
<!-- <!--
$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
<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.

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
<!-- $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);
</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);
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);
<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>
<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>
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);
</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
<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
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));
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));
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>
<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,
<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;
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;
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>

View File

@ -1,4 +1,4 @@
<!-- $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
<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
<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
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
<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
</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
</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
<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.
<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.
<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.
</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
<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 )
<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 \
<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 \
<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 \
<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 \
<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 \
<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>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
<!-- <!--
$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
<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
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
(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
<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
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);
<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
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
<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)
<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)
<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)
<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)
<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)
<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
</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
</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>
/*-------------------------------------------------------------- /*--------------------------------------------------------------
* *

View File

@ -1,5 +1,5 @@
<!-- <!--
$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
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
(<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
</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</>
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</>
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</>
<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</>
<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</>
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</>
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</>
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;
<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;
<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
<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
<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
<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</>
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>

View File

@ -1,5 +1,5 @@
<!-- <!--
$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
<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
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
<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
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;
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;
<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;
<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
</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
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
<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
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
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
</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
<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;
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;
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;
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;
<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;
<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>

View File

@ -1,5 +1,5 @@
<!-- <!--
$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
<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
<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
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
<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';
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;
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;
</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';
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';
</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;
<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;
</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;
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;
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;
<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%';
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%';
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%';
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=#
<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=#
<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=#
</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=#
<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;
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;
<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);
<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);
<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 ...;
<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
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
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
</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

View File

@ -1,4 +1,4 @@
<!-- $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
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
<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
</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)
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>
</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>
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>
</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
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
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 ...
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 ...
<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 ...
</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>
<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>
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>

View File

@ -1,5 +1,5 @@
<!-- <!--
$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');
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;
</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
<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)
<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.)

View File

@ -1,24 +1,17 @@
<!-- $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 @@
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 @@
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 @@
<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 @@
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 @@
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 @@
<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 @@
<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 @@
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 @@
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
</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
<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
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.
<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
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
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>

View File

@ -1,5 +1,5 @@
<!-- <!--
$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;
<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> )
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> )
<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;
<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>

View File

@ -1,8 +1,12 @@
<!--
$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.
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.
<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.
<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";
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.
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
<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.
</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.
</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
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)
<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
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
<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.
<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.
<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.
<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.
</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
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
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> </screen>
or
<screen>
tgl=> SELECT 2.0 ^ 3.0 AS "Exp";
Exp
-----
8
(1 row)
</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.
<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>.
</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
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
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
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";
<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
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.
<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.
<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.
<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.
</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'));
<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);
<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.
</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 performance="required"> </step>
<para>
Otherwise, try to coerce the expression to the target type. This will succeed
if the two types are known binary-compatible, or if there is a conversion
function. 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
type.
</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> Otherwise, try to convert the expression to the target type. This will succeed
if there is a registered cast between the two types.
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
type.
</para>
</step>
<step performance="required">
<para>
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.
<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
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

View File

@ -1,5 +1,5 @@
<!-- <!--
$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
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>
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>
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>
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;
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;
<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>