Commit 090dd22d authored by Thomas G. Lockhart's avatar Thomas G. Lockhart

Implement SQL99 OVERLAY(). Allows substitution of a substring in a string.

Implement SQL99 SIMILAR TO as a synonym for our existing operator "~".
Implement SQL99 regular expression SUBSTRING(string FROM pat FOR escape).
 Extend the definition to make the FOR clause optional.
 Define textregexsubstr() to actually implement this feature.
Update the regression test to include these new string features.
 All tests pass.
Rename the regular expression support routines from "pg95_xxx" to "pg_xxx".
Define CREATE CHARACTER SET in the parser per SQL99. No implementation yet.
parent 469cb65a
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/advanced.sgml,v 1.27 2002/02/12 22:25:15 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/advanced.sgml,v 1.28 2002/06/11 15:32:32 thomas Exp $
--> -->
<chapter id="tutorial-advanced"> <chapter id="tutorial-advanced">
...@@ -46,14 +46,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/advanced.sgml,v 1.27 2002/02/12 22:25:15 mo ...@@ -46,14 +46,14 @@ $Header: /cvsroot/pgsql/doc/src/sgml/advanced.sgml,v 1.27 2002/02/12 22:25:15 mo
<firstterm>view</firstterm> over the query, which gives a name to <firstterm>view</firstterm> over the query, which gives a name to
the query that you can refer to like an ordinary table. the query that you can refer to like an ordinary table.
<programlisting> <programlisting>
CREATE VIEW myview AS CREATE VIEW myview AS
SELECT city, temp_lo, temp_hi, prcp, date, location SELECT city, temp_lo, temp_hi, prcp, date, location
FROM weather, cities FROM weather, cities
WHERE city = name; WHERE city = name;
SELECT * FROM myview; SELECT * FROM myview;
</programlisting> </programlisting>
</para> </para>
<para> <para>
...@@ -101,7 +101,7 @@ SELECT * FROM myview; ...@@ -101,7 +101,7 @@ SELECT * FROM myview;
<para> <para>
The new declaration of the tables would look like this: The new declaration of the tables would look like this:
<programlisting> <programlisting>
CREATE TABLE cities ( CREATE TABLE cities (
city varchar(80) primary key, city varchar(80) primary key,
location point location point
...@@ -114,19 +114,17 @@ CREATE TABLE weather ( ...@@ -114,19 +114,17 @@ CREATE TABLE weather (
prcp real, prcp real,
date date date date
); );
</programlisting>
</programlisting>
Now try inserting an invalid record: Now try inserting an invalid record:
<programlisting> <programlisting>
INSERT INTO weather VALUES ('Berkeley', 45, 53, 0.0, '1994-11-28'); INSERT INTO weather VALUES ('Berkeley', 45, 53, 0.0, '1994-11-28');
</programlisting> </programlisting>
<screen> <screen>
ERROR: &lt;unnamed&gt; referential integrity violation - key referenced from weather not found in cities ERROR: &lt;unnamed&gt; referential integrity violation - key referenced from weather not found in cities
</screen> </screen>
</para> </para>
<para> <para>
...@@ -162,7 +160,8 @@ ERROR: &lt;unnamed&gt; referential integrity violation - key referenced from we ...@@ -162,7 +160,8 @@ ERROR: &lt;unnamed&gt; referential integrity violation - key referenced from we
Suppose that we want to record a payment of $100.00 from Alice's account Suppose that we want to record a payment of $100.00 from Alice's account
to Bob's account. Simplifying outrageously, the SQL commands for this to Bob's account. Simplifying outrageously, the SQL commands for this
might look like might look like
<programlisting>
<programlisting>
UPDATE accounts SET balance = balance - 100.00 UPDATE accounts SET balance = balance - 100.00
WHERE name = 'Alice'; WHERE name = 'Alice';
UPDATE branches SET balance = balance - 100.00 UPDATE branches SET balance = balance - 100.00
...@@ -171,7 +170,10 @@ UPDATE accounts SET balance = balance + 100.00 ...@@ -171,7 +170,10 @@ UPDATE accounts SET balance = balance + 100.00
WHERE name = 'Bob'; WHERE name = 'Bob';
UPDATE branches SET balance = balance + 100.00 UPDATE branches SET balance = balance + 100.00
WHERE name = (SELECT branch_name FROM accounts WHERE name = 'Bob'); WHERE name = (SELECT branch_name FROM accounts WHERE name = 'Bob');
</programlisting> </programlisting>
</para>
<para>
The details of these commands are not important here; the important The details of these commands are not important here; the important
point is that there are several separate updates involved to accomplish point is that there are several separate updates involved to accomplish
this rather simple operation. Our bank's officers will want to be this rather simple operation. Our bank's officers will want to be
...@@ -219,13 +221,17 @@ UPDATE branches SET balance = balance + 100.00 ...@@ -219,13 +221,17 @@ UPDATE branches SET balance = balance + 100.00
the SQL commands of the transaction with the SQL commands of the transaction with
<command>BEGIN</> and <command>COMMIT</> commands. So our banking <command>BEGIN</> and <command>COMMIT</> commands. So our banking
transaction would actually look like transaction would actually look like
<programlisting>
<programlisting>
BEGIN; BEGIN;
UPDATE accounts SET balance = balance - 100.00 UPDATE accounts SET balance = balance - 100.00
WHERE name = 'Alice'; WHERE name = 'Alice';
-- etc etc -- etc etc
COMMIT; COMMIT;
</programlisting> </programlisting>
</para>
<para>
If, partway through the transaction, we decide we don't want to If, partway through the transaction, we decide we don't want to
commit (perhaps we just noticed that Alice's balance went negative), commit (perhaps we just noticed that Alice's balance went negative),
we can issue the command <command>ROLLBACK</> instead of we can issue the command <command>ROLLBACK</> instead of
...@@ -272,7 +278,7 @@ COMMIT; ...@@ -272,7 +278,7 @@ COMMIT;
implicitly when you list all cities. If you're really clever you implicitly when you list all cities. If you're really clever you
might invent some scheme like this: might invent some scheme like this:
<programlisting> <programlisting>
CREATE TABLE capitals ( CREATE TABLE capitals (
name text, name text,
population real, population real,
...@@ -290,7 +296,7 @@ CREATE VIEW cities AS ...@@ -290,7 +296,7 @@ CREATE VIEW cities AS
SELECT name, population, altitude FROM capitals SELECT name, population, altitude FROM capitals
UNION UNION
SELECT name, population, altitude FROM non_capitals; SELECT name, population, altitude FROM non_capitals;
</programlisting> </programlisting>
This works OK as far as querying goes, but it gets ugly when you This works OK as far as querying goes, but it gets ugly when you
need to update several rows, to name one thing. need to update several rows, to name one thing.
...@@ -299,7 +305,7 @@ CREATE VIEW cities AS ...@@ -299,7 +305,7 @@ CREATE VIEW cities AS
<para> <para>
A better solution is this: A better solution is this:
<programlisting> <programlisting>
CREATE TABLE cities ( CREATE TABLE cities (
name text, name text,
population real, population real,
...@@ -309,8 +315,10 @@ CREATE TABLE cities ( ...@@ -309,8 +315,10 @@ CREATE TABLE cities (
CREATE TABLE capitals ( CREATE TABLE capitals (
state char(2) state char(2)
) INHERITS (cities); ) INHERITS (cities);
</programlisting> </programlisting>
</para>
<para>
In this case, a row of <classname>capitals</classname> In this case, a row of <classname>capitals</classname>
<firstterm>inherits</firstterm> all columns (<structfield>name</>, <firstterm>inherits</firstterm> all columns (<structfield>name</>,
<structfield>population</>, and <structfield>altitude</>) from its <structfield>population</>, and <structfield>altitude</>) from its
...@@ -328,22 +336,22 @@ CREATE TABLE capitals ( ...@@ -328,22 +336,22 @@ CREATE TABLE capitals (
including state capitals, that are located at an altitude including state capitals, that are located at an altitude
over 500 ft.: over 500 ft.:
<programlisting> <programlisting>
SELECT name, altitude SELECT name, altitude
FROM cities FROM cities
WHERE altitude &gt; 500; WHERE altitude &gt; 500;
</programlisting> </programlisting>
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>
...@@ -351,11 +359,11 @@ SELECT name, altitude ...@@ -351,11 +359,11 @@ SELECT name, altitude
all the cities that are not state capitals and all the cities that are not state capitals and
are situated at an altitude of 500 ft. or higher: are situated at an altitude of 500 ft. or higher:
<programlisting> <programlisting>
SELECT name, altitude SELECT name, altitude
FROM ONLY cities FROM ONLY cities
WHERE altitude &gt; 500; WHERE altitude &gt; 500;
</programlisting> </programlisting>
<screen> <screen>
name | altitude name | altitude
...@@ -397,7 +405,6 @@ SELECT name, altitude ...@@ -397,7 +405,6 @@ SELECT name, altitude
site</ulink> for links to more resources. site</ulink> for links to more resources.
</para> </para>
</sect1> </sect1>
</chapter> </chapter>
<!-- Keep this comment at the end of the file <!-- Keep this comment at the end of the file
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.92 2002/05/03 04:11:07 tgl Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.93 2002/06/11 15:32:32 thomas Exp $
--> -->
<chapter id="datatype"> <chapter id="datatype">
...@@ -2637,7 +2637,8 @@ SELECT * FROM test1 WHERE a; ...@@ -2637,7 +2637,8 @@ SELECT * FROM test1 WHERE a;
The <type>inet</type> type holds an IP host address, and The <type>inet</type> type holds an IP host address, and
optionally the identity of the subnet it is in, all in one field. optionally the identity of the subnet it is in, all in one field.
The subnet identity is represented by the number of bits in the The subnet identity is represented by the number of bits in the
network part of the address (the <quote>netmask</quote>). If the netmask is 32, network part of the address (the <quote>netmask</quote>). If the
netmask is 32,
then the value does not indicate a subnet, only a single host. then the value does not indicate a subnet, only a single host.
Note that if you want to accept networks only, you should use the Note that if you want to accept networks only, you should use the
<type>cidr</type> type rather than <type>inet</type>. <type>cidr</type> type rather than <type>inet</type>.
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.99 2002/06/02 21:56:09 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.100 2002/06/11 15:32:32 thomas Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
<chapter id="functions"> <chapter id="functions">
<title>Functions and Operators</title> <title>Functions and Operators</title>
<indexterm zone="functions"> <indexterm zone="functions">
...@@ -28,7 +28,8 @@ PostgreSQL documentation ...@@ -28,7 +28,8 @@ PostgreSQL documentation
If you are concerned about portability then take note that most of If you are concerned about portability then take note that most of
the functions and operators described in this chapter, with the the functions and operators described in this chapter, with the
exception of the most trivial arithmetic and comparison operators exception of the most trivial arithmetic and comparison operators
and some explicitly marked functions, are not specified by the <acronym>SQL</acronym> and some explicitly marked functions, are not specified by the
<acronym>SQL</acronym>
standard. Some of this extended functionality is present in other standard. Some of this extended functionality is present in other
<acronym>RDBMS</acronym> products, and in many cases this <acronym>RDBMS</acronym> products, and in many cases this
functionality is compatible and consistent between various products. functionality is compatible and consistent between various products.
...@@ -172,7 +173,7 @@ PostgreSQL documentation ...@@ -172,7 +173,7 @@ PostgreSQL documentation
</indexterm> </indexterm>
<table> <table>
<title>Comparison Operators</TITLE> <title>Comparison Operators</title>
<tgroup cols="2"> <tgroup cols="2">
<thead> <thead>
<row> <row>
...@@ -239,21 +240,21 @@ PostgreSQL documentation ...@@ -239,21 +240,21 @@ PostgreSQL documentation
</indexterm> </indexterm>
In addition to the comparison operators, the special In addition to the comparison operators, the special
<token>BETWEEN</token> construct is available. <token>BETWEEN</token> construct is available.
<synopsis> <synopsis>
<replaceable>a</replaceable> BETWEEN <replaceable>x</replaceable> AND <replaceable>y</replaceable> <replaceable>a</replaceable> BETWEEN <replaceable>x</replaceable> AND <replaceable>y</replaceable>
</synopsis> </synopsis>
is equivalent to is equivalent to
<synopsis> <synopsis>
<replaceable>a</replaceable> &gt;= <replaceable>x</replaceable> AND <replaceable>a</replaceable> &lt;= <replaceable>y</replaceable> <replaceable>a</replaceable> &gt;= <replaceable>x</replaceable> AND <replaceable>a</replaceable>able> &lt;= <replaceable>y</replaceable>
</synopsis> </synopsis>
Similarly, Similarly,
<synopsis> <synopsis>
<replaceable>a</replaceable> NOT BETWEEN <replaceable>x</replaceable> AND <replaceable>y</replaceable> <replaceable>a</replaceable> NOT BETWEEN <replaceable>x</replaceable> AND <replaceable>y</replaceable>
</synopsis> </synopsis>
is equivalent to is equivalent to
<synopsis> <synopsis>
<replaceable>a</replaceable> &lt; <replaceable>x</replaceable> OR <replaceable>a</replaceable> &gt; <replaceable>y</replaceable> <replaceable>a</replaceable> &lt; <replaceable>x</replaceable> OR <replaceable>a</replaceable>able> &gt; <replaceable>y</replaceable>
</synopsis> </synopsis>
There is no difference between the two respective forms apart from There is no difference between the two respective forms apart from
the <acronym>CPU</acronym> cycles required to rewrite the first one the <acronym>CPU</acronym> cycles required to rewrite the first one
into the second one internally. into the second one internally.
...@@ -261,15 +262,15 @@ PostgreSQL documentation ...@@ -261,15 +262,15 @@ PostgreSQL documentation
<para> <para>
To check whether a value is or is not NULL, use the constructs To check whether a value is or is not NULL, use the constructs
<synopsis> <synopsis>
<replaceable>expression</replaceable> IS NULL <replaceable>expression</replaceable> IS NULL
<replaceable>expression</replaceable> IS NOT NULL <replaceable>expression</replaceable> IS NOT NULL
</synopsis> </synopsis>
or the equivalent, but less standard, constructs or the equivalent, but less standard, constructs
<synopsis> <synopsis>
<replaceable>expression</replaceable> ISNULL <replaceable>expression</replaceable> ISNULL
<replaceable>expression</replaceable> NOTNULL <replaceable>expression</replaceable> NOTNULL
</synopsis> </synopsis>
</para> </para>
<para> <para>
...@@ -287,28 +288,28 @@ PostgreSQL documentation ...@@ -287,28 +288,28 @@ PostgreSQL documentation
the NULL value. To support these applications, the run-time option the NULL value. To support these applications, the run-time option
<varname>transform_null_equals</varname> can be turned on (e.g., <varname>transform_null_equals</varname> can be turned on (e.g.,
<literal>SET transform_null_equals TO ON;</literal>). <literal>SET transform_null_equals TO ON;</literal>).
<productname>PostgreSQL</productname> will then convert <literal>x <productname>PostgreSQL</productname> will then convert
= NULL</literal> clauses to <literal>x IS NULL</literal>. This was <literal>x = NULL</literal> clauses to
<literal>x IS NULL</literal>. This was
the default behavior in releases 6.5 through 7.1. the default behavior in releases 6.5 through 7.1.
</para> </para>
<para> <para>
Boolean values can also be tested using the constructs Boolean values can also be tested using the constructs
<synopsis> <synopsis>
<replaceable>expression</replaceable> IS TRUE <replaceable>expression</replaceable> IS TRUE
<replaceable>expression</replaceable> IS NOT TRUE <replaceable>expression</replaceable> IS NOT TRUE
<replaceable>expression</replaceable> IS FALSE <replaceable>expression</replaceable> IS FALSE
<replaceable>expression</replaceable> IS NOT FALSE <replaceable>expression</replaceable> IS NOT FALSE
<replaceable>expression</replaceable> IS UNKNOWN <replaceable>expression</replaceable> IS UNKNOWN
<replaceable>expression</replaceable> IS NOT UNKNOWN <replaceable>expression</replaceable> IS NOT UNKNOWN
</synopsis> </synopsis>
These are similar to <literal>IS NULL</literal> in that they will These are similar to <literal>IS NULL</literal> in that they will
always return TRUE or FALSE, never NULL, even when the operand is NULL. always return TRUE or FALSE, never NULL, even when the operand is NULL.
A NULL input is treated as the logical value UNKNOWN. A NULL input is treated as the logical value UNKNOWN.
</para> </para>
</sect1> </sect1>
<sect1 id="functions-math"> <sect1 id="functions-math">
<title>Mathematical Functions and Operators</title> <title>Mathematical Functions and Operators</title>
...@@ -595,7 +596,8 @@ PostgreSQL documentation ...@@ -595,7 +596,8 @@ PostgreSQL documentation
</row> </row>
<row> <row>
<entry><function>mod</function>(<parameter>y</parameter>, <parameter>x</parameter>)</entry> <entry><function>mod</function>(<parameter>y</parameter>,
<parameter>x</parameter>)</entry>
<entry>(same as argument types)</entry> <entry>(same as argument types)</entry>
<entry>remainder of <parameter>y</parameter>/<parameter>x</parameter></entry> <entry>remainder of <parameter>y</parameter>/<parameter>x</parameter></entry>
<entry><literal>mod(9,4)</literal></entry> <entry><literal>mod(9,4)</literal></entry>
...@@ -683,7 +685,8 @@ PostgreSQL documentation ...@@ -683,7 +685,8 @@ PostgreSQL documentation
</row> </row>
<row> <row>
<entry><function>trunc</function>(<type>numeric</type>, <parameter>s</parameter> <type>integer</type>)</entry> <entry><function>trunc</function>(<type>numeric</type>,
<parameter>r</parameter>rameter> <type>integer</type>)</entry>
<entry><type>numeric</type></entry> <entry><type>numeric</type></entry>
<entry>truncate to <parameter>s</parameter> decimal places</entry> <entry>truncate to <parameter>s</parameter> decimal places</entry>
<entry><literal>trunc(42.4382, 2)</literal></entry> <entry><literal>trunc(42.4382, 2)</literal></entry>
...@@ -700,8 +703,8 @@ PostgreSQL documentation ...@@ -700,8 +703,8 @@ PostgreSQL documentation
<function>log</function>, <function>pow</function>, <function>log</function>, <function>pow</function>,
<function>round</function> (1 argument), <function>sqrt</function>, <function>round</function> (1 argument), <function>sqrt</function>,
and <function>trunc</function> (1 argument) are also available for and <function>trunc</function> (1 argument) are also available for
the type <type>numeric</type> in place of <type>double the type <type>numeric</type> in place of
precision</type>. <type>double precision</type>.
Functions returning a <type>numeric</type> result take Functions returning a <type>numeric</type> result take
<type>numeric</type> input arguments, unless otherwise specified. <type>numeric</type> input arguments, unless otherwise specified.
Many of these functions are implemented on top Many of these functions are implemented on top
...@@ -737,8 +740,10 @@ PostgreSQL documentation ...@@ -737,8 +740,10 @@ PostgreSQL documentation
</row> </row>
<row> <row>
<entry><function>atan2</function>(<replaceable>x</replaceable>, <replaceable>y</replaceable>)</entry> <entry><function>atan2</function>(<replaceable>x</replaceable>,
<entry>inverse tangent of <replaceable>y</replaceable>/<replaceable>x</replaceable></entry> <replaceable>y</replaceable>)</entry>
<entry>inverse tangent of
<replaceable>a</replaceable>aceable>/<replaceable>x</replaceable></entry>
</row> </row>
<row> <row>
...@@ -811,7 +816,8 @@ PostgreSQL documentation ...@@ -811,7 +816,8 @@ PostgreSQL documentation
<tbody> <tbody>
<row> <row>
<entry> <parameter>string</parameter> <literal>||</literal> <parameter>string</parameter> </entry> <entry> <parameter>string</parameter> <literal>||</literal>
<parameter>string</parameter> </entry>
<entry> <type>text</type> </entry> <entry> <type>text</type> </entry>
<entry> <entry>
string concatenation string concatenation
...@@ -820,8 +826,8 @@ PostgreSQL documentation ...@@ -820,8 +826,8 @@ PostgreSQL documentation
<secondary>concatenation</secondary> <secondary>concatenation</secondary>
</indexterm> </indexterm>
</entry> </entry>
<entry><literal>'Postgre' || 'SQL'</></entry> <entry><literal>'Postgre' || 'SQL'</literal></entry>
<entry><literal>PostgreSQL</></entry> <entry><literal>PostgreSQL</literal></entry>
</row> </row>
<row> <row>
...@@ -847,8 +853,8 @@ PostgreSQL documentation ...@@ -847,8 +853,8 @@ PostgreSQL documentation
<see>character strings, length</see> <see>character strings, length</see>
</indexterm> </indexterm>
</entry> </entry>
<entry><literal>char_length('jose')</></entry> <entry><literal>char_length('jose')</literal></entry>
<entry><literal>4</></entry> <entry><literal>4</literal></entry>
</row> </row>
<row> <row>
...@@ -867,6 +873,19 @@ PostgreSQL documentation ...@@ -867,6 +873,19 @@ PostgreSQL documentation
<entry><literal>4</literal></entry> <entry><literal>4</literal></entry>
</row> </row>
<row>
<entry><function>overlay</function>(<parameter>string</parameter> placing <parameter>string</parameter> from <type>integer</type> <optional>for <type>integer</type></optional>)</entry>
<entry><type>text</type></entry>
<entry>
insert substring
<indexterm>
<primary>overlay</primary>
</indexterm>
</entry>
<entry><literal>overlay('Txxxxas' placing 'hom' from 2 for 4)</literal></entry>
<entry><literal>Thomas</literal></entry>
</row>
<row> <row>
<entry><function>position</function>(<parameter>substring</parameter> in <parameter>string</parameter>)</entry> <entry><function>position</function>(<parameter>substring</parameter> in <parameter>string</parameter>)</entry>
<entry><type>integer</type></entry> <entry><type>integer</type></entry>
...@@ -888,6 +907,19 @@ PostgreSQL documentation ...@@ -888,6 +907,19 @@ PostgreSQL documentation
<entry><literal>hom</literal></entry> <entry><literal>hom</literal></entry>
</row> </row>
<row>
<entry><function>substring</function>(<parameter>string</parameter> <optional>from <replaceable>pattern</replaceable></optional> <optional>for <replaceable>escape</replaceable></optional>)</entry>
<entry><type>text</type></entry>
<entry>
extract regular expression
<indexterm>
<primary>substring</primary>
</indexterm>
</entry>
<entry><literal>substring('Thomas' from 'mas$' for <optional>escape '\\'</optional>)</literal></entry>
<entry><literal>mas</literal></entry>
</row>
<row> <row>
<entry> <entry>
<function>trim</function>(<optional>leading | trailing | both</optional> <function>trim</function>(<optional>leading | trailing | both</optional>
...@@ -965,7 +997,8 @@ PostgreSQL documentation ...@@ -965,7 +997,8 @@ PostgreSQL documentation
<row> <row>
<entry> <entry>
<function>convert</function>(<parameter>string</parameter> <type>text</type>, <function>convert</function>(<parameter>string</parameter>
<type>text</type>,
<optional><parameter>src_encoding</parameter> <type>name</type>,</optional> <optional><parameter>src_encoding</parameter> <type>name</type>,</optional>
<parameter>dest_encoding</parameter> <type>name</type>) <parameter>dest_encoding</parameter> <type>name</type>)
</entry> </entry>
...@@ -1004,8 +1037,8 @@ PostgreSQL documentation ...@@ -1004,8 +1037,8 @@ PostgreSQL documentation
<see>character strings, length</see> <see>character strings, length</see>
</indexterm> </indexterm>
</entry> </entry>
<entry><literal>length('jose')</></entry> <entry><literal>length('jose')</literal></entry>
<entry><literal>4</></entry> <entry><literal>4</literal></entry>
</row> </row>
<row> <row>
...@@ -1028,7 +1061,7 @@ PostgreSQL documentation ...@@ -1028,7 +1061,7 @@ PostgreSQL documentation
</row> </row>
<row> <row>
<entry><function>ltrim</function>(<parameter>string</parameter> <type>text</type>, <parameter>trim</parameter> <type>text</type>)</entry> <entry><function>ltrim</function>(<parameter>string</parameter> <type>text</type>, <parameter>text</parameter> <type>text</type>)</entry>
<entry><type>text</type></entry> <entry><type>text</type></entry>
<entry> <entry>
Removes the longest string containing only characters from Removes the longest string containing only characters from
...@@ -1075,7 +1108,8 @@ PostgreSQL documentation ...@@ -1075,7 +1108,8 @@ PostgreSQL documentation
</row> </row>
<row> <row>
<entry><function>rtrim</function>(<parameter>string</parameter> text, <parameter>trim</parameter> text)</entry> <entry><function>rtrim</function>(<parameter>string</parameter>
text, <parameter>trim</parameter> text)</entry>
<entry><type>text</type></entry> <entry><type>text</type></entry>
<entry> <entry>
Removes the longest string containing only characters from Removes the longest string containing only characters from
...@@ -1102,14 +1136,16 @@ PostgreSQL documentation ...@@ -1102,14 +1136,16 @@ PostgreSQL documentation
<entry><function>substr</function>(<parameter>string</parameter>, <parameter>from</parameter> <optional>, <parameter>count</parameter></optional>)</entry> <entry><function>substr</function>(<parameter>string</parameter>, <parameter>from</parameter> <optional>, <parameter>count</parameter></optional>)</entry>
<entry><type>text</type></entry> <entry><type>text</type></entry>
<entry> <entry>
Extracts specified substring. (same as <literal>substring(<parameter>string</parameter> from <parameter>from</parameter> for <parameter>count</parameter>)</literal>) Extracts specified substring. (same as
<literal>substring(<parameter>string</parameter> from <parameter>from</parameter> for <parameter>count</parameter>)</literal>)
</entry> </entry>
<entry><literal>substr('alphabet', 3, 2)</literal></entry> <entry><literal>substr('alphabet', 3, 2)</literal></entry>
<entry><literal>ph</literal></entry> <entry><literal>ph</literal></entry>
</row> </row>
<row> <row>
<entry><function>to_ascii</function>(<type>text</type> <optional>, <parameter>encoding</parameter></optional>)</entry> <entry><function>to_ascii</function>(<type>text</type>
<optional>ptional>, <parameter>encoding</parameter></optional>)</entry>
<entry><type>text</type></entry> <entry><type>text</type></entry>
<entry>Converts text from multibyte encoding to <acronym>ASCII</acronym>.</entry> <entry>Converts text from multibyte encoding to <acronym>ASCII</acronym>.</entry>
<entry><literal>to_ascii('Karel')</literal></entry> <entry><literal>to_ascii('Karel')</literal></entry>
...@@ -1118,7 +1154,8 @@ PostgreSQL documentation ...@@ -1118,7 +1154,8 @@ PostgreSQL documentation
<row> <row>
<entry> <entry>
<function>translate</function>(<parameter>string</parameter> <type>text</type>, <function>translate</function>(<parameter>string</parameter>
<type>text</type>,
<parameter>from</parameter> <type>text</type>, <parameter>from</parameter> <type>text</type>,
<parameter>to</parameter> <type>text</type>) <parameter>to</parameter> <type>text</type>)
</entry> </entry>
...@@ -1182,11 +1219,14 @@ PostgreSQL documentation ...@@ -1182,11 +1219,14 @@ PostgreSQL documentation
</para> </para>
<para> <para>
<acronym>SQL</acronym> defines some string functions with a special syntax where <acronym>SQL</acronym> defines some string functions with a
special syntax where
certain keywords rather than commas are used to separate the certain keywords rather than commas are used to separate the
arguments. Details are in <xref linkend="functions-binarystring-sql">. arguments. Details are in
<xref linkend="functions-binarystring-sql">.
Some functions are also implemented using the regular syntax for Some functions are also implemented using the regular syntax for
function invocation. (See <xref linkend="functions-binarystring-other">.) function invocation.
(See <xref linkend="functions-binarystring-other">.)
</para> </para>
<table id="functions-binarystring-sql"> <table id="functions-binarystring-sql">
...@@ -1204,7 +1244,8 @@ PostgreSQL documentation ...@@ -1204,7 +1244,8 @@ PostgreSQL documentation
<tbody> <tbody>
<row> <row>
<entry> <parameter>string</parameter> <literal>||</literal> <parameter>string</parameter> </entry> <entry> <parameter>string</parameter> <literal>||</literal>
<parameter>string</parameter> </entry>
<entry> <type>bytea</type> </entry> <entry> <type>bytea</type> </entry>
<entry> <entry>
string concatenation string concatenation
...@@ -1213,8 +1254,8 @@ PostgreSQL documentation ...@@ -1213,8 +1254,8 @@ PostgreSQL documentation
<secondary>concatenation</secondary> <secondary>concatenation</secondary>
</indexterm> </indexterm>
</entry> </entry>
<entry><literal>'\\\\Postgre'::bytea || '\\047SQL\\000'::bytea</></entry> <entry><literal>'\\\\Postgre'::bytea || '\\047SQL\\000'::bytea</literal></entry>
<entry><literal>\\Postgre'SQL\000</></entry> <entry><literal>\\Postgre'SQL\000</literal></entry>
</row> </row>
<row> <row>
...@@ -1261,7 +1302,6 @@ PostgreSQL documentation ...@@ -1261,7 +1302,6 @@ PostgreSQL documentation
<entry><literal>trim('\\000'::bytea from '\\000Tom\\000'::bytea)</literal></entry> <entry><literal>trim('\\000'::bytea from '\\000Tom\\000'::bytea)</literal></entry>
<entry><literal>Tom</literal></entry> <entry><literal>Tom</literal></entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
...@@ -1287,7 +1327,8 @@ PostgreSQL documentation ...@@ -1287,7 +1327,8 @@ PostgreSQL documentation
<tbody> <tbody>
<row> <row>
<entry><function>btrim</function>(<parameter>string</parameter> <type>bytea</type>, <parameter>trim</parameter> <type>bytea</type>)</entry> <entry><function>btrim</function>(<parameter>string</parameter>
<type>bytea</type> <parameter>trim</parameter> <type>bytea</type>)</entry>
<entry><type>bytea</type></entry> <entry><type>bytea</type></entry>
<entry> <entry>
Remove (trim) the longest string consisting only of characters Remove (trim) the longest string consisting only of characters
...@@ -1313,8 +1354,8 @@ PostgreSQL documentation ...@@ -1313,8 +1354,8 @@ PostgreSQL documentation
<see>binary strings, length</see> <see>binary strings, length</see>
</indexterm> </indexterm>
</entry> </entry>
<entry><literal>length('jo\\000se'::bytea)</></entry> <entry><literal>length('jo\\000se'::bytea)</literal></entry>
<entry><literal>5</></entry> <entry><literal>5</literal></entry>
</row> </row>
<row> <row>
...@@ -1357,30 +1398,42 @@ PostgreSQL documentation ...@@ -1357,30 +1398,42 @@ PostgreSQL documentation
<para> <para>
There are two separate approaches to pattern matching provided by There are two separate approaches to pattern matching provided by
<productname>PostgreSQL</productname>: the <acronym>SQL</acronym> <productname>PostgreSQL</productname>: the traditional
<function>LIKE</function> operator and <acronym>SQL</acronym>
<function>LIKE</function> operator and the more recent
<acronym>SQL99</acronym>
<function>SIMILAR TO</function> operator implementing
<acronym>POSIX</acronym>-style regular expressions. <acronym>POSIX</acronym>-style regular expressions.
Additionally, a pattern matching function,
<function>SUBSTRING</function>, is available, as defined in
<acronym>SQL99</acronym>.
</para> </para>
<tip> <tip>
<para> <para>
If you have pattern matching needs that go beyond this, or want to If you have pattern matching needs that go beyond this,
make pattern-driven substitutions or translations, consider consider writing a user-defined function in Perl or Tcl.
writing a user-defined function in Perl or Tcl.
</para> </para>
</tip> </tip>
<para>
Both <function>LIKE</function> and <function>SIMILAR TO</function>
are SQL-standard operators which are also available in alternate
forms as <product>PostgreSQL</product> operators; look at
<literal>~</literal> and <literal>~~</literal> for examples.
</para>
<sect2 id="functions-like"> <sect2 id="functions-like">
<title>Pattern Matching with <function>LIKE</function></title> <title><function>LIKE</function></title>
<indexterm> <indexterm>
<primary>like</primary> <primary>like</primary>
</indexterm> </indexterm>
<synopsis> <synopsis>
<replaceable>string</replaceable> LIKE <replaceable>pattern</replaceable> <optional> ESCAPE <replaceable>escape-character</replaceable> </optional> <replaceable>string</replaceable> LIKE <replaceable>pattern</replaceable> <optional>ESCAPE <replaceable>escape-character</replaceable></optional>
<replaceable>string</replaceable> NOT LIKE <replaceable>pattern</replaceable> <optional> ESCAPE <replaceable>escape-character</replaceable> </optional> <replaceable>string</replaceable> NOT LIKE <replaceable>pattern</replaceable> <optional>ESCAPE <replaceable>escape-character</replaceable></optional>
</synopsis> </synopsis>
<para> <para>
Every <replaceable>pattern</replaceable> defines a set of strings. Every <replaceable>pattern</replaceable> defines a set of strings.
...@@ -1389,8 +1442,8 @@ PostgreSQL documentation ...@@ -1389,8 +1442,8 @@ PostgreSQL documentation
strings represented by <replaceable>pattern</replaceable>. (As strings represented by <replaceable>pattern</replaceable>. (As
expected, the <function>NOT LIKE</function> expression returns expected, the <function>NOT LIKE</function> expression returns
false if <function>LIKE</function> returns true, and vice versa. false if <function>LIKE</function> returns true, and vice versa.
An equivalent expression is <literal>NOT An equivalent expression is
(<replaceable>string</replaceable> LIKE <literal>NOT (<replaceable>string</replaceable> LIKE
<replaceable>pattern</replaceable>)</literal>.) <replaceable>pattern</replaceable>)</literal>.)
</para> </para>
...@@ -1407,12 +1460,12 @@ PostgreSQL documentation ...@@ -1407,12 +1460,12 @@ PostgreSQL documentation
<informalexample> <informalexample>
<para> <para>
Some examples: Some examples:
<programlisting> <programlisting>
'abc' LIKE 'abc' <lineannotation>true</lineannotation> 'abc' LIKE 'abc' <lineannotation>true</lineannotation>
'abc' LIKE 'a%' <lineannotation>true</lineannotation> 'abc' LIKE 'a%' <lineannotation>true</lineannotation>
'abc' LIKE '_b_' <lineannotation>true</lineannotation> 'abc' LIKE '_b_' <lineannotation>true</lineannotation>
'abc' LIKE 'c' <lineannotation>false</lineannotation> 'abc' LIKE 'c' <lineannotation>false</lineannotation>
</programlisting> </programlisting>
</para> </para>
</informalexample> </informalexample>
...@@ -1439,14 +1492,15 @@ PostgreSQL documentation ...@@ -1439,14 +1492,15 @@ PostgreSQL documentation
that actually matches a literal backslash means writing four backslashes that actually matches a literal backslash means writing four backslashes
in the query. You can avoid this by selecting a different escape in the query. You can avoid this by selecting a different escape
character with <literal>ESCAPE</literal>; then backslash is not special character with <literal>ESCAPE</literal>; then backslash is not special
to <function>LIKE</> anymore. (But it is still special to the string to <function>LIKE</function> anymore. (But it is still special to the string
literal parser, so you still need two of them.) literal parser, so you still need two of them.)
</para> </para>
<para> <para>
It's also possible to select no escape character by writing It's also possible to select no escape character by writing
<literal>ESCAPE ''</literal>. In this case there is no way to <literal>ESCAPE ''</literal>. This effectively disables the
turn off the special meaning of underscore and percent signs in escape mechanism and
turns off the special meaning of underscore and percent signs in
the pattern. the pattern.
</para> </para>
...@@ -1470,7 +1524,8 @@ PostgreSQL documentation ...@@ -1470,7 +1524,8 @@ PostgreSQL documentation
<sect2 id="functions-regexp"> <sect2 id="functions-regexp">
<title><acronym>POSIX</acronym> Regular Expressions</title> <title><function>SIMILAR TO</function> and <acronym>POSIX</acronym>
Regular Expressions</title>
<indexterm zone="functions-regexp"> <indexterm zone="functions-regexp">
<primary>regular expressions</primary> <primary>regular expressions</primary>
...@@ -1490,32 +1545,42 @@ PostgreSQL documentation ...@@ -1490,32 +1545,42 @@ PostgreSQL documentation
</thead> </thead>
<tbody> <tbody>
<ROW> <row>
<ENTRY> <literal>~</literal> </ENTRY> <entry> <literal>~</literal> </entry>
<ENTRY>Matches regular expression, case sensitive</ENTRY> <entry>Matches regular expression, case sensitive</entry>
<ENTRY><literal>'thomas' ~ '.*thomas.*'</literal></ENTRY> <entry><literal>'thomas' ~ '.*thomas.*'</literal></entry>
</ROW> </row>
<ROW>
<ENTRY> <literal>~*</literal> </ENTRY> <row>
<ENTRY>Matches regular expression, case insensitive</ENTRY> <entry> <literal>~*</literal> </entry>
<ENTRY><literal>'thomas' ~* '.*Thomas.*'</literal></ENTRY> <entry>Matches regular expression, case insensitive</entry>
</ROW> <entry><literal>'thomas' ~* '.*Thomas.*'</literal></entry>
<ROW> </row>
<ENTRY> <literal>!~</literal> </ENTRY>
<ENTRY>Does not match regular expression, case sensitive</ENTRY> <row>
<ENTRY><literal>'thomas' !~ '.*Thomas.*'</literal></ENTRY> <entry> <literal>!~</literal> </entry>
</ROW> <entry>Does not match regular expression, case sensitive</entry>
<ROW> <entry><literal>'thomas' !~ '.*Thomas.*'</literal></entry>
<ENTRY> <literal>!~*</literal> </ENTRY> </row>
<ENTRY>Does not match regular expression, case insensitive</ENTRY>
<ENTRY><literal>'thomas' !~* '.*vadim.*'</literal></ENTRY> <row>
</ROW> <entry> <literal>!~*</literal> </entry>
<entry>Does not match regular expression, case insensitive</entry>
<entry><literal>'thomas' !~* '.*vadim.*'</literal></entry>
</row>
<row>
<entry> <literal>SIMILAR TO</literal> </entry>
<entry>Matches regular expression, case sensitive</entry>
<entry><literal>'thomas' SIMILAR TO '.*thomas.*'</literal></entry>
</row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
<para> <para>
<acronym>POSIX</acronym> regular expressions provide a more powerful means for <acronym>POSIX</acronym> regular expressions provide a more
powerful means for
pattern matching than the <function>LIKE</function> function. pattern matching than the <function>LIKE</function> function.
Many Unix tools such as <command>egrep</command>, Many Unix tools such as <command>egrep</command>,
<command>sed</command>, or <command>awk</command> use a pattern <command>sed</command>, or <command>awk</command> use a pattern
...@@ -1537,10 +1602,22 @@ PostgreSQL documentation ...@@ -1537,10 +1602,22 @@ PostgreSQL documentation
end of the string. end of the string.
</para> </para>
<informalexample>
<para>
Some examples:
<programlisting>
'abc' SIMILAR TO 'abc' <lineannotation>true</lineannotation>
'abc' SIMILAR TO '^a' <lineannotation>true</lineannotation>
'abc' SIMILAR TO '(b|d)' <lineannotation>true</lineannotation>
'abc' SIMILAR TO '^(b|c)' <lineannotation>false</lineannotation>
</programlisting>
</para>
</informalexample>
<!-- derived from the re_format.7 man page --> <!-- derived from the re_format.7 man page -->
<para> <para>
Regular expressions (<quote>RE</quote>s), as defined in <acronym>POSIX</acronym> Regular expressions (<quote>RE</quote>s), as defined in
<acronym>POSIX</acronym>
1003.2, come in two forms: modern REs (roughly those of 1003.2, come in two forms: modern REs (roughly those of
<command>egrep</command>; 1003.2 calls these <command>egrep</command>; 1003.2 calls these
<quote>extended</quote> REs) and obsolete REs (roughly those of <quote>extended</quote> REs) and obsolete REs (roughly those of
...@@ -1834,7 +1911,8 @@ PostgreSQL documentation ...@@ -1834,7 +1911,8 @@ PostgreSQL documentation
<entry><literal>to_char(125, '999')</literal></entry> <entry><literal>to_char(125, '999')</literal></entry>
</row> </row>
<row> <row>
<entry><function>to_char</function>(<type>double precision</type>, <type>text</type>)</entry> <entry><function>to_char</function>(<type>double precision</type>,
<type>text</type>)</entry>
<entry><type>text</type></entry> <entry><type>text</type></entry>
<entry>convert real/double precision to string</entry> <entry>convert real/double precision to string</entry>
<entry><literal>to_char(125.8, '999D9')</literal></entry> <entry><literal>to_char(125.8, '999D9')</literal></entry>
...@@ -1919,11 +1997,13 @@ PostgreSQL documentation ...@@ -1919,11 +1997,13 @@ PostgreSQL documentation
<entry>seconds past midnight (0-86399)</entry> <entry>seconds past midnight (0-86399)</entry>
</row> </row>
<row> <row>
<entry><literal>AM</literal> or <literal>A.M.</literal> or <literal>PM</literal> or <literal>P.M.</literal></entry> <entry><literal>AM</literal> or <literal>A.M.</literal> or
<literal>li</literal>literal> or <literal>P.M.</literal></entry>
<entry>meridian indicator (upper case)</entry> <entry>meridian indicator (upper case)</entry>
</row> </row>
<row> <row>
<entry><literal>am</literal> or <literal>a.m.</literal> or <literal>pm</literal> or <literal>p.m.</literal></entry> <entry><literal>am</literal> or <literal>a.m.</literal> or
<literal>li</literal>literal> or <literal>p.m.</literal></entry>
<entry>meridian indicator (lower case)</entry> <entry>meridian indicator (lower case)</entry>
</row> </row>
<row> <row>
...@@ -1947,11 +2027,13 @@ PostgreSQL documentation ...@@ -1947,11 +2027,13 @@ PostgreSQL documentation
<entry>last digit of year</entry> <entry>last digit of year</entry>
</row> </row>
<row> <row>
<entry><literal>BC</literal> or <literal>B.C.</literal> or <literal>AD</literal> or <literal>A.D.</literal></entry> <entry><literal>BC</literal> or <literal>B.C.</literal> or
<literal>li</literal>literal> or <literal>A.D.</literal></entry>
<entry>era indicator (upper case)</entry> <entry>era indicator (upper case)</entry>
</row> </row>
<row> <row>
<entry><literal>bc</literal> or <literal>b.c.</literal> or <literal>ad</literal> or <literal>a.d.</literal></entry> <entry><literal>bc</literal> or <literal>b.c.</literal> or
<literal>li</literal>literal> or <literal>a.d.</literal></entry>
<entry>era indicator (lower case)</entry> <entry>era indicator (lower case)</entry>
</row> </row>
<row> <row>
...@@ -2185,10 +2267,10 @@ PostgreSQL documentation ...@@ -2185,10 +2267,10 @@ PostgreSQL documentation
seconds after the decimal point. For example seconds after the decimal point. For example
<literal>to_timestamp('12:3', 'SS:MS')</literal> is not 3 milliseconds, <literal>to_timestamp('12:3', 'SS:MS')</literal> is not 3 milliseconds,
but 300, because the conversion counts it as 12 + 0.3. but 300, because the conversion counts it as 12 + 0.3.
This means for the format <literal>SS:MS</>, the input values This means for the format <literal>SS:MS</literal>, the input values
<literal>12:3</>, <literal>12:30</>, and <literal>12:300</> specify the <literal>12:3</literal>, <literal>12:30</literal>, and <literal>12:300</literal> specify the
same number of milliseconds. To get three milliseconds, one must use same number of milliseconds. To get three milliseconds, one must use
<literal>12:003</>, which the conversion counts as <literal>12:003</literal>, which the conversion counts as
12 + 0.003 = 12.003 seconds. 12 + 0.003 = 12.003 seconds.
</para> </para>
...@@ -2288,11 +2370,11 @@ PostgreSQL documentation ...@@ -2288,11 +2370,11 @@ PostgreSQL documentation
<itemizedlist> <itemizedlist>
<listitem> <listitem>
<para> <para>
A sign formatted using <literal>SG</>, <literal>PL</>, or A sign formatted using <literal>SG</literal>, <literal>PL</literal>, or
<literal>MI</> is not an anchor in <literal>MI</literal> is not an anchor in
the number; for example, the number; for example,
<literal>to_char(-12, 'S9999')</> produces <literal>' -12'</literal>, <literal>to_char(-12, 'S9999')</literal> produces <literal>' -12'</literal>,
but <literal>to_char(-12, 'MI9999')</> produces <literal>'- 12'</literal>. but <literal>to_char(-12, 'MI9999')</literal> produces <literal>'- 12'</literal>.
The Oracle implementation does not allow the use of The Oracle implementation does not allow the use of
<literal>MI</literal> ahead of <literal>9</literal>, but rather <literal>MI</literal> ahead of <literal>9</literal>, but rather
requires that <literal>9</literal> precede requires that <literal>9</literal> precede
...@@ -2614,8 +2696,7 @@ PostgreSQL documentation ...@@ -2614,8 +2696,7 @@ PostgreSQL documentation
<row> <row>
<entry><function>current_date</function></entry> <entry><function>current_date</function></entry>
<entry><type>date</type></entry> <entry><type>date</type></entry>
<entry>Today's date; see <link <entry>Today's date; see <link linkend="functions-datetime-current">below</link>
linkend="functions-datetime-current">below</link>
</entry> </entry>
<entry></entry> <entry></entry>
<entry></entry> <entry></entry>
...@@ -2624,8 +2705,7 @@ PostgreSQL documentation ...@@ -2624,8 +2705,7 @@ PostgreSQL documentation
<row> <row>
<entry><function>current_time</function></entry> <entry><function>current_time</function></entry>
<entry><type>time</type></entry> <entry><type>time</type></entry>
<entry>Time of day; see <link <entry>Time of day; see <link linkend="functions-datetime-current">below</link>
linkend="functions-datetime-current">below</link>
</entry> </entry>
<entry></entry> <entry></entry>
<entry></entry> <entry></entry>
...@@ -2634,8 +2714,7 @@ PostgreSQL documentation ...@@ -2634,8 +2714,7 @@ PostgreSQL documentation
<row> <row>
<entry><function>current_timestamp</function></entry> <entry><function>current_timestamp</function></entry>
<entry><type>timestamp</type></entry> <entry><type>timestamp</type></entry>
<entry>Date and time; see <link <entry>Date and time; see <link linkend="functions-datetime-current">below</link>
linkend="functions-datetime-current">below</link>
</entry> </entry>
<entry></entry> <entry></entry>
<entry></entry> <entry></entry>
...@@ -2674,7 +2753,8 @@ PostgreSQL documentation ...@@ -2674,7 +2753,8 @@ PostgreSQL documentation
</row> </row>
<row> <row>
<entry><function>extract</function>(<parameter>field</parameter> from <type>timestamp</type>)</entry> <entry><function>extract</function>(<parameter>field</parameter> from
<type>timestamp</type>)</entry>
<entry><type>double precision</type></entry> <entry><type>double precision</type></entry>
<entry>Get subfield; see also <link <entry>Get subfield; see also <link
linkend="functions-datetime-extract">below</link> linkend="functions-datetime-extract">below</link>
...@@ -2684,7 +2764,8 @@ PostgreSQL documentation ...@@ -2684,7 +2764,8 @@ PostgreSQL documentation
</row> </row>
<row> <row>
<entry><function>extract</function>(<parameter>field</parameter> from <type>interval</type>)</entry> <entry><function>extract</function>(<parameter>field</parameter> from
<type>interval</type>)</entry>
<entry><type>double precision</type></entry> <entry><type>double precision</type></entry>
<entry>Get subfield; see also <link <entry>Get subfield; see also <link
linkend="functions-datetime-extract">below</link> linkend="functions-datetime-extract">below</link>
...@@ -3187,8 +3268,8 @@ SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40'); ...@@ -3187,8 +3268,8 @@ SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40');
CURRENT_DATE CURRENT_DATE
CURRENT_TIME CURRENT_TIME
CURRENT_TIMESTAMP CURRENT_TIMESTAMP
CURRENT_TIME ( <replaceable>precision</> ) CURRENT_TIME ( <replaceable>precision</replaceable> )
CURRENT_TIMESTAMP ( <replaceable>precision</> ) CURRENT_TIMESTAMP ( <replaceable>precision</replaceable> )
</synopsis> </synopsis>
<function>CURRENT_TIME</function> and <function>CURRENT_TIME</function> and
<function>CURRENT_TIMESTAMP</function> can optionally be given <function>CURRENT_TIMESTAMP</function> can optionally be given
...@@ -3199,7 +3280,7 @@ CURRENT_TIMESTAMP ( <replaceable>precision</> ) ...@@ -3199,7 +3280,7 @@ CURRENT_TIMESTAMP ( <replaceable>precision</> )
<note> <note>
<para> <para>
Prior to <productname>PostgreSQL</> 7.2, the precision parameters Prior to <productname>PostgreSQL</productname> 7.2, the precision parameters
were unimplemented, and the result was always given in integer were unimplemented, and the result was always given in integer
seconds. seconds.
</para> </para>
...@@ -3209,7 +3290,7 @@ CURRENT_TIMESTAMP ( <replaceable>precision</> ) ...@@ -3209,7 +3290,7 @@ CURRENT_TIMESTAMP ( <replaceable>precision</> )
<para> <para>
The <acronym>SQL99</acronym> standard requires these functions to The <acronym>SQL99</acronym> standard requires these functions to
be written without any parentheses, unless a precision parameter be written without any parentheses, unless a precision parameter
is given. As of <productname>PostgreSQL</> 7.2, an empty pair of is given. As of <productname>PostgreSQL</productname> 7.2, an empty pair of
parentheses can be written, but this is deprecated and may be parentheses can be written, but this is deprecated and may be
removed in a future release. removed in a future release.
</para> </para>
...@@ -3259,7 +3340,7 @@ SELECT timeofday(); ...@@ -3259,7 +3340,7 @@ SELECT timeofday();
<para> <para>
All the date/time data types also accept the special literal value All the date/time data types also accept the special literal value
<literal>now</> to specify the current date and time. Thus, <literal>now</literal> to specify the current date and time. Thus,
the following three all return the same result: the following three all return the same result:
<programlisting> <programlisting>
SELECT CURRENT_TIMESTAMP; SELECT CURRENT_TIMESTAMP;
...@@ -3269,7 +3350,7 @@ SELECT TIMESTAMP 'now'; ...@@ -3269,7 +3350,7 @@ SELECT TIMESTAMP 'now';
<note> <note>
<para> <para>
You do not want to use the third form when specifying a DEFAULT You do not want to use the third form when specifying a DEFAULT
value while creating a table. The system will convert <literal>now</> value while creating a table. The system will convert <literal>now</literal>
to a <type>timestamp</type> as soon as the constant is parsed, so that when to a <type>timestamp</type> as soon as the constant is parsed, so that when
the default value is needed, the default value is needed,
the time of the table creation would be used! The first two the time of the table creation would be used! The first two
...@@ -3294,139 +3375,139 @@ SELECT TIMESTAMP 'now'; ...@@ -3294,139 +3375,139 @@ SELECT TIMESTAMP 'now';
</para> </para>
<table> <table>
<TITLE>Geometric Operators</TITLE> <title>Geometric Operators</title>
<TGROUP COLS="3"> <tgroup cols="3">
<THEAD> <thead>
<ROW> <row>
<ENTRY>Operator</ENTRY> <entry>Operator</entry>
<ENTRY>Description</ENTRY> <entry>Description</entry>
<ENTRY>Usage</ENTRY> <entry>Usage</entry>
</ROW> </row>
</THEAD> </thead>
<TBODY> <tbody>
<ROW> <row>
<ENTRY> + </ENTRY> <entry> + </entry>
<ENTRY>Translation</ENTRY> <entry>Translation</entry>
<ENTRY><literal>box '((0,0),(1,1))' + point '(2.0,0)'</literal></ENTRY> <entry><literal>box '((0,0),(1,1))' + point '(2.0,0)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> - </ENTRY> <entry> - </entry>
<ENTRY>Translation</ENTRY> <entry>Translation</entry>
<ENTRY><literal>box '((0,0),(1,1))' - point '(2.0,0)'</literal></ENTRY> <entry><literal>box '((0,0),(1,1))' - point '(2.0,0)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> * </ENTRY> <entry> * </entry>
<ENTRY>Scaling/rotation</ENTRY> <entry>Scaling/rotation</entry>
<ENTRY><literal>box '((0,0),(1,1))' * point '(2.0,0)'</literal></ENTRY> <entry><literal>box '((0,0),(1,1))' * point '(2.0,0)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> / </ENTRY> <entry> / </entry>
<ENTRY>Scaling/rotation</ENTRY> <entry>Scaling/rotation</entry>
<ENTRY><literal>box '((0,0),(2,2))' / point '(2.0,0)'</literal></ENTRY> <entry><literal>box '((0,0),(2,2))' / point '(2.0,0)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> # </ENTRY> <entry> # </entry>
<ENTRY>Intersection</ENTRY> <entry>Intersection</entry>
<ENTRY><literal>'((1,-1),(-1,1))' # '((1,1),(-1,-1))'</literal></ENTRY> <entry><literal>'((1,-1),(-1,1))' # '((1,1),(-1,-1))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> # </ENTRY> <entry> # </entry>
<ENTRY>Number of points in polygon</ENTRY> <entry>Number of points in polygon</entry>
<ENTRY><literal># '((1,0),(0,1),(-1,0))'</literal></ENTRY> <entry><literal># '((1,0),(0,1),(-1,0))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> ## </ENTRY> <entry> ## </entry>
<ENTRY>Point of closest proximity</ENTRY> <entry>Point of closest proximity</entry>
<ENTRY><literal>point '(0,0)' ## lseg '((2,0),(0,2))'</literal></ENTRY> <entry><literal>point '(0,0)' ## lseg '((2,0),(0,2))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &amp;&amp; </ENTRY> <entry> &amp;&amp; </entry>
<ENTRY>Overlaps?</ENTRY> <entry>Overlaps?</entry>
<ENTRY><literal>box '((0,0),(1,1))' &amp;&amp; box '((0,0),(2,2))'</literal></ENTRY> <entry><literal>box '((0,0),(1,1))' &amp;&amp; box '((0,0),(2,2))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &amp;&lt; </ENTRY> <entry> &amp;&lt; </entry>
<ENTRY>Overlaps to left?</ENTRY> <entry>Overlaps to left?</entry>
<ENTRY><literal>box '((0,0),(1,1))' &amp;&lt; box '((0,0),(2,2))'</literal></ENTRY> <entry><literal>box '((0,0),(1,1))' &amp;&lt; box '((0,0),(2,2))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &amp;&gt; </ENTRY> <entry> &amp;&gt; </entry>
<ENTRY>Overlaps to right?</ENTRY> <entry>Overlaps to right?</entry>
<ENTRY><literal>box '((0,0),(3,3))' &amp;&gt; box '((0,0),(2,2))'</literal></ENTRY> <entry><literal>box '((0,0),(3,3))' &amp;&gt; box '((0,0),(2,2))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &lt;-&gt; </ENTRY> <entry> &lt;-&gt; </entry>
<ENTRY>Distance between</ENTRY> <entry>Distance between</entry>
<ENTRY><literal>circle '((0,0),1)' &lt;-&gt; circle '((5,0),1)'</literal></ENTRY> <entry><literal>circle '((0,0),1)' &lt;-&gt; circle '((5,0),1)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &lt;&lt; </ENTRY> <entry> &lt;&lt; </entry>
<ENTRY>Left of?</ENTRY> <entry>Left of?</entry>
<ENTRY><literal>circle '((0,0),1)' &lt;&lt; circle '((5,0),1)'</literal></ENTRY> <entry><literal>circle '((0,0),1)' &lt;&lt; circle '((5,0),1)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &lt;^ </ENTRY> <entry> &lt;^ </entry>
<ENTRY>Is below?</ENTRY> <entry>Is below?</entry>
<ENTRY><literal>circle '((0,0),1)' &lt;^ circle '((0,5),1)'</literal></ENTRY> <entry><literal>circle '((0,0),1)' &lt;^ circle '((0,5),1)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &gt;&gt; </ENTRY> <entry> &gt;&gt; </entry>
<ENTRY>Is right of?</ENTRY> <entry>Is right of?</entry>
<ENTRY><literal>circle '((5,0),1)' &gt;&gt; circle '((0,0),1)'</literal></ENTRY> <entry><literal>circle '((5,0),1)' &gt;&gt; circle '((0,0),1)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &gt;^ </ENTRY> <entry> &gt;^ </entry>
<ENTRY>Is above?</ENTRY> <entry>Is above?</entry>
<ENTRY><literal>circle '((0,5),1)' >^ circle '((0,0),1)'</literal></ENTRY> <entry><literal>circle '((0,5),1)' >^ circle '((0,0),1)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> ?# </ENTRY> <entry> ?# </entry>
<ENTRY>Intersects or overlaps</ENTRY> <entry>Intersects or overlaps</entry>
<ENTRY><literal>lseg '((-1,0),(1,0))' ?# box '((-2,-2),(2,2))'</literal></ENTRY> <entry><literal>lseg '((-1,0),(1,0))' ?# box '((-2,-2),(2,2))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> ?- </ENTRY> <entry> ?- </entry>
<ENTRY>Is horizontal?</ENTRY> <entry>Is horizontal?</entry>
<ENTRY><literal>point '(1,0)' ?- point '(0,0)'</literal></ENTRY> <entry><literal>point '(1,0)' ?- point '(0,0)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> ?-| </ENTRY> <entry> ?-| </entry>
<ENTRY>Is perpendicular?</ENTRY> <entry>Is perpendicular?</entry>
<ENTRY><literal>lseg '((0,0),(0,1))' ?-| lseg '((0,0),(1,0))'</literal></ENTRY> <entry><literal>lseg '((0,0),(0,1))' ?-| lseg '((0,0),(1,0))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> @-@ </ENTRY> <entry> @-@ </entry>
<ENTRY>Length or circumference</ENTRY> <entry>Length or circumference</entry>
<ENTRY><literal>@-@ path '((0,0),(1,0))'</literal></ENTRY> <entry><literal>@-@ path '((0,0),(1,0))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> ?| </ENTRY> <entry> ?| </entry>
<ENTRY>Is vertical?</ENTRY> <entry>Is vertical?</entry>
<ENTRY><literal>point '(0,1)' ?| point '(0,0)'</literal></ENTRY> <entry><literal>point '(0,1)' ?| point '(0,0)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> ?|| </ENTRY> <entry> ?|| </entry>
<ENTRY>Is parallel?</ENTRY> <entry>Is parallel?</entry>
<ENTRY><literal>lseg '((-1,0),(1,0))' ?|| lseg '((-1,2),(1,2))'</literal></ENTRY> <entry><literal>lseg '((-1,0),(1,0))' ?|| lseg '((-1,2),(1,2))'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> @ </ENTRY> <entry> @ </entry>
<ENTRY>Contained or on</ENTRY> <entry>Contained or on</entry>
<ENTRY><literal>point '(1,1)' @ circle '((0,0),2)'</literal></ENTRY> <entry><literal>point '(1,1)' @ circle '((0,0),2)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> @@ </ENTRY> <entry> @@ </entry>
<ENTRY>Center of</ENTRY> <entry>Center of</entry>
<ENTRY><literal>@@ circle '((0,0),10)'</literal></ENTRY> <entry><literal>@@ circle '((0,0),10)'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> ~= </ENTRY> <entry> ~= </entry>
<ENTRY>Same as</ENTRY> <entry>Same as</entry>
<ENTRY><literal>polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))'</literal></ENTRY> <entry><literal>polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))'</literal></entry>
</ROW> </row>
</TBODY> </tbody>
</TGROUP> </tgroup>
</TABLE> </table>
<table> <table>
<title>Geometric Functions</title> <title>Geometric Functions</title>
...@@ -3646,75 +3727,75 @@ SELECT TIMESTAMP 'now'; ...@@ -3646,75 +3727,75 @@ SELECT TIMESTAMP 'now';
<table tocentry="1" id="cidr-inet-operators-table"> <table tocentry="1" id="cidr-inet-operators-table">
<title><type>cidr</> and <type>inet</> Operators</title> <title><type>cidr</type> and <type>inet</type> Operators</title>
<TGROUP COLS="3"> <tgroup cols="3">
<THEAD> <thead>
<ROW> <row>
<ENTRY>Operator</ENTRY> <entry>Operator</entry>
<ENTRY>Description</ENTRY> <entry>Description</entry>
<ENTRY>Usage</ENTRY> <entry>Usage</entry>
</ROW> </row>
</THEAD> </thead>
<TBODY> <tbody>
<ROW> <row>
<ENTRY> &lt; </ENTRY> <entry> &lt; </entry>
<ENTRY>Less than</ENTRY> <entry>Less than</entry>
<ENTRY><literal>inet '192.168.1.5' &lt; inet '192.168.1.6'</literal></ENTRY> <entry><literal>inet '192.168.1.5' &lt; inet '192.168.1.6'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &lt;= </ENTRY> <entry> &lt;= </entry>
<ENTRY>Less than or equal</ENTRY> <entry>Less than or equal</entry>
<ENTRY><literal>inet '192.168.1.5' &lt;= inet '192.168.1.5'</literal></ENTRY> <entry><literal>inet '192.168.1.5' &lt;= inet '192.168.1.5'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> = </ENTRY> <entry> = </entry>
<ENTRY>Equals</ENTRY> <entry>Equals</entry>
<ENTRY><literal>inet '192.168.1.5' = inet '192.168.1.5'</literal></ENTRY> <entry><literal>inet '192.168.1.5' = inet '192.168.1.5'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &gt;= </ENTRY> <entry> &gt;= </entry>
<ENTRY>Greater or equal</ENTRY> <entry>Greater or equal</entry>
<ENTRY><literal>inet '192.168.1.5' &gt;= inet '192.168.1.5'</literal></ENTRY> <entry><literal>inet '192.168.1.5' &gt;= inet '192.168.1.5'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &gt; </ENTRY> <entry> &gt; </entry>
<ENTRY>Greater</ENTRY> <entry>Greater</entry>
<ENTRY><literal>inet '192.168.1.5' &gt; inet '192.168.1.4'</literal></ENTRY> <entry><literal>inet '192.168.1.5' &gt; inet '192.168.1.4'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &lt;&gt; </ENTRY> <entry> &lt;&gt; </entry>
<ENTRY>Not equal</ENTRY> <entry>Not equal</entry>
<ENTRY><literal>inet '192.168.1.5' &lt;&gt; inet '192.168.1.4'</literal></ENTRY> <entry><literal>inet '192.168.1.5' &lt;&gt; inet '192.168.1.4'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &lt;&lt; </ENTRY> <entry> &lt;&lt; </entry>
<ENTRY>is contained within</ENTRY> <entry>is contained within</entry>
<ENTRY><literal>inet '192.168.1.5' &lt;&lt; inet '192.168.1/24'</literal></ENTRY> <entry><literal>inet '192.168.1.5' &lt;&lt; inet '192.168.1/24'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &lt;&lt;= </ENTRY> <entry> &lt;&lt;= </entry>
<ENTRY>is contained within or equals</ENTRY> <entry>is contained within or equals</entry>
<ENTRY><literal>inet '192.168.1/24' &lt;&lt;= inet '192.168.1/24'</literal></ENTRY> <entry><literal>inet '192.168.1/24' &lt;&lt;= inet '192.168.1/24'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &gt;&gt; </ENTRY> <entry> &gt;&gt; </entry>
<ENTRY>contains</ENTRY> <entry>contains</entry>
<ENTRY><literal>inet'192.168.1/24' &gt;&gt; inet '192.168.1.5'</literal></ENTRY> <entry><literal>inet'192.168.1/24' &gt;&gt; inet '192.168.1.5'</literal></entry>
</ROW> </row>
<ROW> <row>
<ENTRY> &gt;&gt;= </ENTRY> <entry> &gt;&gt;= </entry>
<ENTRY>contains or equals</ENTRY> <entry>contains or equals</entry>
<ENTRY><literal>inet '192.168.1/24' &gt;&gt;= inet '192.168.1/24'</literal></ENTRY> <entry><literal>inet '192.168.1/24' &gt;&gt;= inet '192.168.1/24'</literal></entry>
</ROW> </row>
</TBODY> </tbody>
</TGROUP> </tgroup>
</TABLE> </table>
<para> <para>
All of the operators for <type>inet</type> can be applied to All of the operators for <type>inet</type> can be applied to
<type>cidr</type> values as well. The operators <type>cidr</type> values as well. The operators
<literal>&lt;&lt;</>, <literal>&lt;&lt;=</>, <literal>&lt;&lt;</literal>, <literal>&lt;&lt;=</literal>,
<literal>&gt;&gt;</>, <literal>&gt;&gt;=</> <literal>&gt;&gt;</literal>, <literal>&gt;&gt;=</literal>
test for subnet inclusion: they consider only the network parts test for subnet inclusion: they consider only the network parts
of the two addresses, ignoring any host part, and determine whether of the two addresses, ignoring any host part, and determine whether
one network part is identical to or a subnet of the other. one network part is identical to or a subnet of the other.
...@@ -3722,7 +3803,7 @@ SELECT TIMESTAMP 'now'; ...@@ -3722,7 +3803,7 @@ SELECT TIMESTAMP 'now';
<table tocentry="1" id="cidr-inet-functions"> <table tocentry="1" id="cidr-inet-functions">
<title><type>cidr</> and <type>inet</> Functions</title> <title><type>cidr</type> and <type>inet</type> Functions</title>
<tgroup cols="5"> <tgroup cols="5">
<thead> <thead>
<row> <row>
...@@ -3796,15 +3877,15 @@ SELECT TIMESTAMP 'now'; ...@@ -3796,15 +3877,15 @@ SELECT TIMESTAMP 'now';
<para> <para>
All of the functions for <type>inet</type> can be applied to All of the functions for <type>inet</type> can be applied to
<type>cidr</type> values as well. The <function>host</>(), <type>cidr</type> values as well. The <function>host</function>(),
<function>text</>(), and <function>abbrev</>() functions are primarily <function>text</function>(), and <function>abbrev</function>() functions are primarily
intended to offer alternative display formats. You can cast a text intended to offer alternative display formats. You can cast a text
field to inet using normal casting syntax: <literal>inet(expression)</literal> or field to inet using normal casting syntax: <literal>inet(expression)</literal> or
<literal>colname::inet</literal>. <literal>colname::inet</literal>.
</para> </para>
<table tocentry="1" id="macaddr-functions"> <table tocentry="1" id="macaddr-functions">
<title><type>macaddr</> Functions</title> <title><type>macaddr</type> Functions</title>
<tgroup cols="5"> <tgroup cols="5">
<thead> <thead>
<row> <row>
...@@ -3828,16 +3909,16 @@ SELECT TIMESTAMP 'now'; ...@@ -3828,16 +3909,16 @@ SELECT TIMESTAMP 'now';
</table> </table>
<para> <para>
The function <function>trunc</>(<type>macaddr</>) returns a MAC The function <function>trunc</function>(<type>macaddr</type>) returns a MAC
address with the last 3 bytes set to 0. This can be used to address with the last 3 bytes set to 0. This can be used to
associate the remaining prefix with a manufacturer. The directory associate the remaining prefix with a manufacturer. The directory
<filename>contrib/mac</> in the source distribution contains some <filename>contrib/mac</filename> in the source distribution contains some
utilities to create and maintain such an association table. utilities to create and maintain such an association table.
</para> </para>
<para> <para>
The <type>macaddr</> type also supports the standard relational The <type>macaddr</type> type also supports the standard relational
operators (<literal>&gt;</>, <literal>&lt;=</>, etc.) for operators (<literal>&gt;</literal>, <literal>&lt;=</literal>, etc.) for
lexicographical ordering. lexicographical ordering.
</para> </para>
...@@ -3861,32 +3942,32 @@ SELECT TIMESTAMP 'now'; ...@@ -3861,32 +3942,32 @@ SELECT TIMESTAMP 'now';
</indexterm> </indexterm>
<table> <table>
<title>Sequence Functions</> <title>Sequence Functions</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row><entry>Function</> <entry>Returns</> <entry>Description</></row> <row><entry>Function</entry> <entry>Returns</entry> <entry>Description</entry></row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry><function>nextval</function>(<type>text</type>)</entry> <entry><function>nextval</function>(<type>text</type>)</entry>
<entry><type>bigint</type></entry> <entry><type>bigint</type></entry>
<entry>Advance sequence and return new value</> <entry>Advance sequence and return new value</entry>
</row> </row>
<row> <row>
<entry><function>currval</function>(<type>text</type>)</entry> <entry><function>currval</function>(<type>text</type>)</entry>
<entry><type>bigint</type></entry> <entry><type>bigint</type></entry>
<entry>Return value most recently obtained with <function>nextval</></entry> <entry>Return value most recently obtained with <function>nextval</function></entry>
</row> </row>
<row> <row>
<entry><function>setval</function>(<type>text</type>,<type>bigint</type>)</entry> <entry><function>setval</function>(<type>text</type>,<type>bigint</type>)</entry>
<entry><type>bigint</type></entry> <entry><type>bigint</type></entry>
<entry>Set sequence's current value</> <entry>Set sequence's current value</entry>
</row> </row>
<row> <row>
<entry><function>setval</function>(<type>text</type>,<type>bigint</type>,<type>boolean</>)</entry> <entry><function>setval</function>(<type>text</type>,<type>bigint</type>,<type>boolean</type>)</entry>
<entry><type>bigint</type></entry> <entry><type>bigint</type></entry>
<entry>Set sequence's current value and <literal>is_called</> flag</entry> <entry>Set sequence's current value and <literal>is_called</literal> flag</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -3894,10 +3975,10 @@ SELECT TIMESTAMP 'now'; ...@@ -3894,10 +3975,10 @@ SELECT TIMESTAMP 'now';
<para> <para>
This section describes <productname>PostgreSQL</productname>'s functions This section describes <productname>PostgreSQL</productname>'s functions
for operating on <firstterm>sequence objects</>. for operating on <firstterm>sequence objects</firstterm>.
Sequence objects (also called sequence generators or Sequence objects (also called sequence generators or
just sequences) are special single-row tables created with just sequences) are special single-row tables created with
<command>CREATE SEQUENCE</>. A sequence object is usually used to <command>CREATE SEQUENCE</command>. A sequence object is usually used to
generate unique identifiers for rows of a table. The sequence functions generate unique identifiers for rows of a table. The sequence functions
provide simple, multiuser-safe methods for obtaining successive provide simple, multiuser-safe methods for obtaining successive
sequence values from sequence objects. sequence values from sequence objects.
...@@ -3910,15 +3991,16 @@ SELECT TIMESTAMP 'now'; ...@@ -3910,15 +3991,16 @@ SELECT TIMESTAMP 'now';
names, the sequence functions convert their argument to lower case names, the sequence functions convert their argument to lower case
unless the string is double-quoted. Thus unless the string is double-quoted. Thus
<programlisting> <programlisting>
nextval('foo') <lineannotation>operates on sequence </><literal>foo</> nextval('foo') <lineannotation>operates on sequence </><literal>foo</literal>
nextval('FOO') <lineannotation>operates on sequence </><literal>foo</> nextval('FOO') <lineannotation>operates on sequence </><literal>foo</literal>
nextval('"Foo"') <lineannotation>operates on sequence </><literal>Foo</> nextval('"Foo"') <lineannotation>operates on sequence </><literal>Foo</literal>
</programlisting> </programlisting>
The sequence name can be schema-qualified if necessary: The sequence name can be schema-qualified if necessary:
<programlisting> <programlisting>
nextval('myschema.foo') <lineannotation>operates on </><literal>myschema.foo</> nextval('myschema.foo') <lineannotation>operates on </><literal>myschema.foo</literal>
nextval('"myschema".foo') <lineannotation>same as above</> nextval('"myschema".foo') <lineannotation>same as above</lineannotation>
nextval('foo') <lineannotation>searches search path for </><literal>foo</> nextval('foo') <lineannotation>searches search path for
</><literal>foo</literal>
</programlisting> </programlisting>
Of course, the text argument can be the result of an expression, Of course, the text argument can be the result of an expression,
not only a simple literal, which is occasionally useful. not only a simple literal, which is occasionally useful.
...@@ -3929,57 +4011,57 @@ nextval('foo') <lineannotation>searches search path for </><literal>foo</> ...@@ -3929,57 +4011,57 @@ nextval('foo') <lineannotation>searches search path for </><literal>foo</>
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><function>nextval</></term> <term><function>nextval</function></term>
<listitem> <listitem>
<para> <para>
Advance the sequence object to its next value and return that Advance the sequence object to its next value and return that
value. This is done atomically: even if multiple server processes value. This is done atomically: even if multiple server processes
execute <function>nextval</> concurrently, each will safely receive execute <function>nextval</function> concurrently, each will safely receive
a distinct sequence value. a distinct sequence value.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><function>currval</></term> <term><function>currval</function></term>
<listitem> <listitem>
<para> <para>
Return the value most recently obtained by <function>nextval</> Return the value most recently obtained by <function>nextval</function>
for this sequence in the current server process. (An error is for this sequence in the current server process. (An error is
reported if <function>nextval</> has never been called for this reported if <function>nextval</function> has never been called for this
sequence in this process.) Notice that because this is returning sequence in this process.) Notice that because this is returning
a process-local value, it gives a predictable answer even if other a process-local value, it gives a predictable answer even if other
server processes are executing <function>nextval</> meanwhile. server processes are executing <function>nextval</function> meanwhile.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><function>setval</></term> <term><function>setval</function></term>
<listitem> <listitem>
<para> <para>
Reset the sequence object's counter value. The two-parameter Reset the sequence object's counter value. The two-parameter
form sets the sequence's <literal>last_value</> field to the specified form sets the sequence's <literal>last_value</literal> field to the specified
value and sets its <literal>is_called</> field to <literal>true</>, value and sets its <literal>is_called</literal> field to <literal>true</literal>,
meaning that the next <function>nextval</> will advance the sequence meaning that the next <function>nextval</function> will advance the sequence
before returning a value. In the three-parameter form, before returning a value. In the three-parameter form,
<literal>is_called</> may be set either <literal>true</> or <literal>is_called</literal> may be set either <literal>true</literal> or
<literal>false</>. If it's set to <literal>false</>, <literal>false</literal>. If it's set to <literal>false</literal>,
the next <function>nextval</> will return exactly the specified the next <function>nextval</function> will return exactly the specified
value, and sequence advancement commences with the following value, and sequence advancement commences with the following
<function>nextval</>. For example, <function>nextval</function>. For example,
</para> </para>
<informalexample> <informalexample>
<screen> <screen>
SELECT setval('foo', 42); <lineannotation>Next nextval() will return 43</> SELECT setval('foo', 42); <lineannotation>Next nextval() will return 43</lineannotation>
SELECT setval('foo', 42, true); <lineannotation>Same as above</> SELECT setval('foo', 42, true); <lineannotation>Same as above</lineannotation>
SELECT setval('foo', 42, false); <lineannotation>Next nextval() will return 42</> SELECT setval('foo', 42, false); <lineannotation>Next nextval() will return 42</lineannotation>
</screen> </screen>
</informalexample> </informalexample>
<para> <para>
The result returned by <function>setval</> is just the value of its The result returned by <function>setval</function> is just the value of its
second argument. second argument.
</para> </para>
</listitem> </listitem>
...@@ -3990,20 +4072,20 @@ SELECT setval('foo', 42, false); <lineannotation>Next nextval() will return 4 ...@@ -3990,20 +4072,20 @@ SELECT setval('foo', 42, false); <lineannotation>Next nextval() will return 4
<important> <important>
<para> <para>
To avoid blocking of concurrent transactions that obtain numbers from the To avoid blocking of concurrent transactions that obtain numbers from the
same sequence, a <function>nextval</> operation is never rolled back; same sequence, a <function>nextval</function> operation is never rolled back;
that is, once a value has been fetched it is considered used, even if the that is, once a value has been fetched it is considered used, even if the
transaction that did the <function>nextval</> later aborts. This means transaction that did the <function>nextval</function> later aborts. This means
that aborted transactions may leave unused <quote>holes</quote> in the that aborted transactions may leave unused <quote>holes</quote> in the
sequence of assigned values. <function>setval</> operations are never sequence of assigned values. <function>setval</function> operations are never
rolled back, either. rolled back, either.
</para> </para>
</important> </important>
<para> <para>
If a sequence object has been created with default parameters, If a sequence object has been created with default parameters,
<function>nextval()</> calls on it will return successive values <function>nextval()</function> calls on it will return successive values
beginning with one. Other behaviors can be obtained by using beginning with one. Other behaviors can be obtained by using
special parameters in the <command>CREATE SEQUENCE</> command; special parameters in the <command>CREATE SEQUENCE</command> command;
see its command reference page for more information. see its command reference page for more information.
</para> </para>
...@@ -4139,7 +4221,8 @@ END ...@@ -4139,7 +4221,8 @@ END
<bridgehead renderas="sect2">COALESCE</bridgehead> <bridgehead renderas="sect2">COALESCE</bridgehead>
<synopsis> <synopsis>
<function>COALESCE</function>(<replaceable>value</replaceable><optional>, ...</optional>) <function>COALESCE</function>(<replaceable>value</replaceable><optional
>, ...</optional>)
</synopsis> </synopsis>
<para> <para>
...@@ -4159,7 +4242,8 @@ SELECT COALESCE(description, short_description, '(none)') ... ...@@ -4159,7 +4242,8 @@ SELECT COALESCE(description, short_description, '(none)') ...
</indexterm> </indexterm>
<synopsis> <synopsis>
<function>NULLIF</function>(<replaceable>value1</replaceable>, <replaceable>value2</replaceable>) <function>NULLIF</function>(<replaceable>value1</replaceable>,
<replaceable>value2</replaceable>)
</synopsis> </synopsis>
<para> <para>
...@@ -4190,39 +4274,39 @@ SELECT NULLIF(value, '(none)') ... ...@@ -4190,39 +4274,39 @@ SELECT NULLIF(value, '(none)') ...
<sect1 id="functions-misc"> <sect1 id="functions-misc">
<title>Miscellaneous Functions</> <title>Miscellaneous Functions</title>
<table> <table>
<title>Session Information Functions</> <title>Session Information Functions</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row><entry>Name</> <entry>Return Type</> <entry>Description</></row> <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry><function>current_user</></entry> <entry><function>current_user</function></entry>
<entry><type>name</></entry> <entry><type>name</type></entry>
<entry>user name of current execution context</entry> <entry>user name of current execution context</entry>
</row> </row>
<row> <row>
<entry><function>session_user</></entry> <entry><function>session_user</function></entry>
<entry><type>name</></entry> <entry><type>name</type></entry>
<entry>session user name</entry> <entry>session user name</entry>
</row> </row>
<row> <row>
<entry><function>user</></entry> <entry><function>user</function></entry>
<entry><type>name</></entry> <entry><type>name</type></entry>
<entry>equivalent to <function>current_user</></entry> <entry>equivalent to <function>current_user</function></entry>
</row> </row>
<row> <row>
<entry><function>current_schema()</></entry> <entry><function>current_schema()</function></entry>
<entry><type>name</></entry> <entry><type>name</type></entry>
<entry>name of current schema</entry> <entry>name of current schema</entry>
</row> </row>
<row> <row>
<entry><function>current_schemas()</></entry> <entry><function>current_schemas()</function></entry>
<entry><type>name[]</></entry> <entry><type>name[]</type></entry>
<entry>names of schemas in search path</entry> <entry>names of schemas in search path</entry>
</row> </row>
</tbody> </tbody>
...@@ -4245,55 +4329,55 @@ SELECT NULLIF(value, '(none)') ... ...@@ -4245,55 +4329,55 @@ SELECT NULLIF(value, '(none)') ...
</indexterm> </indexterm>
<para> <para>
The <function>session_user</> is the user that initiated a The <function>session_user</function> is the user that initiated a
database connection; it is fixed for the duration of that database connection; it is fixed for the duration of that
connection. The <function>current_user</> is the user identifier connection. The <function>current_user</function> is the user identifier
that is applicable for permission checking. Normally, it is equal that is applicable for permission checking. Normally, it is equal
to the session user, but it changes during the execution of to the session user, but it changes during the execution of
functions with the attribute <literal>SECURITY DEFINER</literal>. functions with the attribute <literal>SECURITY DEFINER</literal>.
In Unix parlance, the session user is the <quote>real user</> and In Unix parlance, the session user is the <quote>real user</quote> and
the current user is the <quote>effective user</>. the current user is the <quote>effective user</quote>.
</para> </para>
<note> <note>
<para> <para>
<function>current_user</>, <function>session_user</>, and <function>current_user</function>, <function>session_user</function>, and
<function>user</> have special syntactic status in <acronym>SQL</>: <function>user</function> have special syntactic status in <acronym>SQL</acronym>:
they must be called without trailing parentheses. they must be called without trailing parentheses.
</para> </para>
</note> </note>
<note> <note>
<title>Deprecated</> <title>Deprecated</title>
<para> <para>
The function <function>getpgusername()</> is an obsolete equivalent The function <function>getpgusername()</function> is an obsolete equivalent
of <function>current_user</>. of <function>current_user</function>.
</para> </para>
</note> </note>
<para> <para>
<function>current_schema</> returns the name of the schema that is <function>current_schema</function> returns the name of the schema that is
at the front of the search path (or NULL if the search path is at the front of the search path (or NULL if the search path is
empty). This is the schema that will be used for any tables or empty). This is the schema that will be used for any tables or
other named objects that are created without specifying a target schema. other named objects that are created without specifying a target schema.
<function>current_schemas</> returns an array of the names of all <function>current_schemas</function> returns an array of the names of all
schemas presently in the search path. Note that these functions show schemas presently in the search path. Note that these functions show
only schemas that are explicitly part of the path; when a system schema only schemas that are explicitly part of the path; when a system schema
is being searched implicitly, it is not listed. is being searched implicitly, it is not listed.
</para> </para>
<table> <table>
<title>System Information Functions</> <title>System Information Functions</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row><entry>Name</> <entry>Return Type</> <entry>Description</></row> <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry><function>version</></entry> <entry><function>version</function></entry>
<entry><type>text</></entry> <entry><type>text</type></entry>
<entry>PostgreSQL version information</> <entry>PostgreSQL version information</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -4304,15 +4388,15 @@ SELECT NULLIF(value, '(none)') ... ...@@ -4304,15 +4388,15 @@ SELECT NULLIF(value, '(none)') ...
</indexterm> </indexterm>
<para> <para>
<function>version()</> returns a string describing the PostgreSQL <function>version()</function> returns a string describing the PostgreSQL
server's version. server's version.
</para> </para>
<table> <table>
<title>Access Privilege Inquiry Functions</> <title>Access Privilege Inquiry Functions</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row><entry>Name</> <entry>Return Type</> <entry>Description</></row> <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
</thead> </thead>
<tbody> <tbody>
...@@ -4321,15 +4405,15 @@ SELECT NULLIF(value, '(none)') ... ...@@ -4321,15 +4405,15 @@ SELECT NULLIF(value, '(none)') ...
<parameter>table</parameter>, <parameter>table</parameter>,
<parameter>access</parameter>) <parameter>access</parameter>)
</entry> </entry>
<entry><type>boolean</type></> <entry><type>boolean</type></entry>
<entry>does user have access to table</> <entry>does user have access to table</entry>
</row> </row>
<row> <row>
<entry><function>has_table_privilege</function>(<parameter>table</parameter>, <entry><function>has_table_privilege</function>(<parameter>table</parameter>,
<parameter>access</parameter>) <parameter>access</parameter>)
</entry> </entry>
<entry><type>boolean</type></> <entry><type>boolean</type></entry>
<entry>does current user have access to table</> <entry>does current user have access to table</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -4340,21 +4424,21 @@ SELECT NULLIF(value, '(none)') ... ...@@ -4340,21 +4424,21 @@ SELECT NULLIF(value, '(none)') ...
</indexterm> </indexterm>
<para> <para>
<function>has_table_privilege</> determines whether a user <function>has_table_privilege</function> determines whether a user
can access a table in a particular way. The user can be can access a table in a particular way. The user can be
specified by name or by ID specified by name or by ID
(<classname>pg_user</>.<structfield>usesysid</>), or if the argument is (<classname>pg_user</classname>.<structfield>usesysid</structfield>), or if the argument is
omitted omitted
<function>current_user</> is assumed. The table can be specified <function>current_user</function> is assumed. The table can be specified
by name or by OID. (Thus, there are actually six variants of by name or by OID. (Thus, there are actually six variants of
<function>has_table_privilege</>, which can be distinguished by <function>has_table_privilege</function>, which can be distinguished by
the number and types of their arguments.) When specifying by name, the number and types of their arguments.) When specifying by name,
the name can be schema-qualified if necessary. the name can be schema-qualified if necessary.
The desired access type The desired access type
is specified by a text string, which must evaluate to one of the is specified by a text string, which must evaluate to one of the
values <literal>SELECT</>, <literal>INSERT</>, <literal>UPDATE</>, values <literal>SELECT</literal>, <literal>INSERT</literal>, <literal>UPDATE</literal>,
<literal>DELETE</>, <literal>RULE</>, <literal>REFERENCES</>, or <literal>DELETE</literal>, <literal>RULE</literal>, <literal>REFERENCES</literal>, or
<literal>TRIGGER</>. (Case of the string is not significant, however.) <literal>TRIGGER</literal>. (Case of the string is not significant, however.)
An example is: An example is:
<programlisting> <programlisting>
SELECT has_table_privilege('myschema.mytable', 'select'); SELECT has_table_privilege('myschema.mytable', 'select');
...@@ -4362,37 +4446,37 @@ SELECT has_table_privilege('myschema.mytable', 'select'); ...@@ -4362,37 +4446,37 @@ SELECT has_table_privilege('myschema.mytable', 'select');
</para> </para>
<table> <table>
<title>Catalog Information Functions</> <title>Catalog Information Functions</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row><entry>Name</> <entry>Return Type</> <entry>Description</></row> <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry><function>pg_get_viewdef</>(<parameter>viewname</parameter>)</entry> <entry><function>pg_get_viewdef</function>(<parameter>viewname</parameter>)</entry>
<entry><type>text</></entry> <entry><type>text</type></entry>
<entry>Get CREATE VIEW command for view</> <entry>Get CREATE VIEW command for view</entry>
</row> </row>
<row> <row>
<entry><function>pg_get_viewdef</>(<parameter>viewOID</parameter>)</entry> <entry><function>pg_get_viewdef</function>(<parameter>viewOID</parameter>)</entry>
<entry><type>text</></entry> <entry><type>text</type></entry>
<entry>Get CREATE VIEW command for view</> <entry>Get CREATE VIEW command for view</entry>
</row> </row>
<row> <row>
<entry><function>pg_get_ruledef</>(<parameter>ruleOID</parameter>)</entry> <entry><function>pg_get_ruledef</function>(<parameter>ruleOID</parameter>)</entry>
<entry><type>text</></entry> <entry><type>text</type></entry>
<entry>Get CREATE RULE command for rule</> <entry>Get CREATE RULE command for rule</entry>
</row> </row>
<row> <row>
<entry><function>pg_get_indexdef</>(<parameter>indexOID</parameter>)</entry> <entry><function>pg_get_indexdef</function>(<parameter>indexOID</parameter>)</entry>
<entry><type>text</></entry> <entry><type>text</type></entry>
<entry>Get CREATE INDEX command for index</> <entry>Get CREATE INDEX command for index</entry>
</row> </row>
<row> <row>
<entry><function>pg_get_userbyid</>(<parameter>userid</parameter>)</entry> <entry><function>pg_get_userbyid</function>(<parameter>userid</parameter>)</entry>
<entry><type>name</></entry> <entry><type>name</type></entry>
<entry>Get user name given ID</> <entry>Get user name given ID</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -4416,36 +4500,36 @@ SELECT has_table_privilege('myschema.mytable', 'select'); ...@@ -4416,36 +4500,36 @@ SELECT has_table_privilege('myschema.mytable', 'select');
<para> <para>
These functions extract information from the system catalogs. These functions extract information from the system catalogs.
<function>pg_get_viewdef()</>, <function>pg_get_ruledef()</>, and <function>pg_get_viewdef()</function>, <function>pg_get_ruledef()</function>, and
<function>pg_get_indexdef()</> respectively reconstruct the creating <function>pg_get_indexdef()</function> respectively reconstruct the creating
command for a view, rule, or index. (Note that this is a decompiled command for a view, rule, or index. (Note that this is a decompiled
reconstruction, not the verbatim text of the command.) reconstruction, not the verbatim text of the command.)
<function>pg_get_userbyid()</> extracts a user's name given a <function>pg_get_userbyid()</function> extracts a user's name given a
<structfield>usesysid</> value. <structfield>usesysid</structfield> value.
</para> </para>
<table> <table>
<title>Comment Information Functions</> <title>Comment Information Functions</title>
<tgroup cols="3"> <tgroup cols="3">
<thead> <thead>
<row><entry>Name</> <entry>Return Type</> <entry>Description</></row> <row><entry>Name</entry> <entry>Return Type</entry> <entry>Description</entry></row>
</thead> </thead>
<tbody> <tbody>
<row> <row>
<entry><function>obj_description</>(<parameter>objectOID</parameter>, <parameter>tablename</>)</entry> <entry><function>obj_description</function>(<parameter>objectOID</parameter>, <parameter>tablename</parameter>)</entry>
<entry><type>text</></entry> <entry><type>text</type></entry>
<entry>Get comment for a database object</> <entry>Get comment for a database object</entry>
</row> </row>
<row> <row>
<entry><function>obj_description</>(<parameter>objectOID</parameter>)</entry> <entry><function>obj_description</function>(<parameter>objectOID</parameter>)</entry>
<entry><type>text</></entry> <entry><type>text</type></entry>
<entry>Get comment for a database object (<emphasis>deprecated</>)</entry> <entry>Get comment for a database object (<emphasis>deprecated</emphasis>)</entry>
</row> </row>
<row> <row>
<entry><function>col_description</>(<parameter>tableOID</parameter>, <parameter>columnnumber</>)</entry> <entry><function>col_description</function>(<parameter>tableOID</parameter>, <parameter>columnnumber</parameter>)</entry>
<entry><type>text</></entry> <entry><type>text</type></entry>
<entry>Get comment for a table column</> <entry>Get comment for a table column</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
...@@ -4461,26 +4545,26 @@ SELECT has_table_privilege('myschema.mytable', 'select'); ...@@ -4461,26 +4545,26 @@ SELECT has_table_privilege('myschema.mytable', 'select');
<para> <para>
These functions extract comments previously stored with the These functions extract comments previously stored with the
<command>COMMENT</> command. <literal>NULL</> is returned if <command>COMMENT</command> command. <literal>NULL</literal> is returned if
no comment can be found matching the specified parameters. no comment can be found matching the specified parameters.
</para> </para>
<para> <para>
The two-parameter form of <function>obj_description()</> returns the The two-parameter form of <function>obj_description()</function> returns the
comment for a database object specified by its OID and the name of the comment for a database object specified by its OID and the name of the
containing system catalog. For example, containing system catalog. For example,
<literal>obj_description(123456,'pg_class')</> <literal>obj_description(123456,'pg_class')</literal>
would retrieve the comment for a table with OID 123456. would retrieve the comment for a table with OID 123456.
The one-parameter form of <function>obj_description()</> requires only The one-parameter form of <function>obj_description()</function> requires only
the object OID. It is now deprecated since there is no guarantee that the object OID. It is now deprecated since there is no guarantee that
OIDs are unique across different system catalogs; therefore, the wrong OIDs are unique across different system catalogs; therefore, the wrong
comment could be returned. comment could be returned.
</para> </para>
<para> <para>
<function>col_description()</> returns the comment for a table column, <function>col_description()</function> returns the comment for a table column,
which is specified by the OID of its table and its column number. which is specified by the OID of its table and its column number.
<function>obj_description()</> cannot be used for table columns since <function>obj_description()</function> cannot be used for table columns since
columns do not have OIDs of their own. columns do not have OIDs of their own.
</para> </para>
...@@ -4570,7 +4654,8 @@ SELECT has_table_privilege('myschema.mytable', 'select'); ...@@ -4570,7 +4654,8 @@ SELECT has_table_privilege('myschema.mytable', 'select');
</row> </row>
<row> <row>
<entry><function>stddev</function>(<replaceable class="parameter">expression</replaceable>)</entry> <entry><function>stddev</function>(<replaceable
class="parameter">expression</replaceable>)</entry>
<entry>the sample standard deviation of the input values</entry> <entry>the sample standard deviation of the input values</entry>
<entry> <entry>
<indexterm> <indexterm>
...@@ -4602,7 +4687,8 @@ SELECT has_table_privilege('myschema.mytable', 'select'); ...@@ -4602,7 +4687,8 @@ SELECT has_table_privilege('myschema.mytable', 'select');
</row> </row>
<row> <row>
<entry><function>variance</function>(<replaceable class="parameter">expression</replaceable>)</entry> <entry><function>variance</function>(<replaceable
class="parameter">expression</replaceable>)</entry>
<entry>the sample variance of the input values</entry> <entry>the sample variance of the input values</entry>
<entry> <entry>
<indexterm> <indexterm>
...@@ -4674,11 +4760,11 @@ EXISTS ( <replaceable>subquery</replaceable> ) ...@@ -4674,11 +4760,11 @@ EXISTS ( <replaceable>subquery</replaceable> )
</synopsis> </synopsis>
<para> <para>
The argument of <token>EXISTS</> is an arbitrary SELECT statement, The argument of <token>EXISTS</token> is an arbitrary SELECT statement,
or <firstterm>subquery</>. The or <firstterm>subquery</firstterm>. The
subquery is evaluated to determine whether it returns any rows. subquery is evaluated to determine whether it returns any rows.
If it returns at least one row, the result of <token>EXISTS</> is If it returns at least one row, the result of <token>EXISTS</token> is
TRUE; if the subquery returns no rows, the result of <token>EXISTS</> TRUE; if the subquery returns no rows, the result of <token>EXISTS</token>
is FALSE. is FALSE.
</para> </para>
...@@ -4700,8 +4786,8 @@ EXISTS ( <replaceable>subquery</replaceable> ) ...@@ -4700,8 +4786,8 @@ EXISTS ( <replaceable>subquery</replaceable> )
and not on the contents of those rows, the output list of the and not on the contents of those rows, the output list of the
subquery is normally uninteresting. A common coding convention is subquery is normally uninteresting. A common coding convention is
to write all EXISTS tests in the form to write all EXISTS tests in the form
<literal>EXISTS(SELECT 1 WHERE ...)</>. There are exceptions to <literal>EXISTS(SELECT 1 WHERE ...)</literal>. There are exceptions to
this rule however, such as subqueries that use <token>INTERSECT</>. this rule however, such as subqueries that use <token>INTERSECT</token>.
</para> </para>
<para> <para>
...@@ -4717,11 +4803,12 @@ SELECT col1 FROM tab1 ...@@ -4717,11 +4803,12 @@ SELECT col1 FROM tab1
<bridgehead renderas="sect2">IN (scalar form)</bridgehead> <bridgehead renderas="sect2">IN (scalar form)</bridgehead>
<synopsis> <synopsis>
<replaceable>expression</replaceable> IN (<replaceable>value</replaceable><optional>, ...</optional>) <replaceable>expression</replaceable> IN
<replaceable>ble>value</replaceable><optional>, ...</optional>)
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>IN</> is a parenthesized list The right-hand side of this form of <token>IN</token> is a parenthesized list
of scalar expressions. The result is TRUE if the left-hand expression's of scalar expressions. The result is TRUE if the left-hand expression's
result is equal to any of the right-hand expressions. This is a shorthand result is equal to any of the right-hand expressions. This is a shorthand
notation for notation for
...@@ -4736,15 +4823,15 @@ OR ...@@ -4736,15 +4823,15 @@ OR
Note that if the left-hand expression yields NULL, or if there are Note that if the left-hand expression yields NULL, or if there are
no equal right-hand values and at least one right-hand expression yields no equal right-hand values and at least one right-hand expression yields
NULL, the result of the <token>IN</> construct will be NULL, not FALSE. NULL, the result of the <token>IN</token> construct will be NULL, not FALSE.
This is in accordance with SQL's normal rules for Boolean combinations This is in accordance with SQL's normal rules for Boolean combinations
of NULL values. of NULL values.
</para> </para>
<note> <note>
<para> <para>
This form of <token>IN</> is not truly a subquery expression, but it This form of <token>IN</token> is not truly a subquery expression, but it
seems best to document it in the same place as subquery <token>IN</>. seems best to document it in the same place as subquery <token>IN</token>.
</para> </para>
</note> </note>
...@@ -4755,10 +4842,10 @@ OR ...@@ -4755,10 +4842,10 @@ OR
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>IN</> is a parenthesized The right-hand side of this form of <token>IN</token> is a parenthesized
subquery, which must return exactly one column. The left-hand expression subquery, which must return exactly one column. The left-hand expression
is evaluated and compared to each row of the subquery result. is evaluated and compared to each row of the subquery result.
The result of <token>IN</> is TRUE if any equal subquery row is found. The result of <token>IN</token> is TRUE if any equal subquery row is found.
The result is FALSE if no equal row is found (including the special The result is FALSE if no equal row is found (including the special
case where the subquery returns no rows). case where the subquery returns no rows).
</para> </para>
...@@ -4766,26 +4853,28 @@ OR ...@@ -4766,26 +4853,28 @@ OR
<para> <para>
Note that if the left-hand expression yields NULL, or if there are Note that if the left-hand expression yields NULL, or if there are
no equal right-hand values and at least one right-hand row yields no equal right-hand values and at least one right-hand row yields
NULL, the result of the <token>IN</> construct will be NULL, not FALSE. NULL, the result of the <token>IN</token> construct will be NULL, not FALSE.
This is in accordance with SQL's normal rules for Boolean combinations This is in accordance with SQL's normal rules for Boolean combinations
of NULL values. of NULL values.
</para> </para>
<para> <para>
As with <token>EXISTS</>, it's unwise to assume that the subquery will As with <token>EXISTS</token>, it's unwise to assume that the subquery will
be evaluated completely. be evaluated completely.
</para> </para>
<synopsis> <synopsis>
(<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) IN (<replaceable>subquery</replaceable>) (<replaceable>expression</replaceable>,
<replaceable>ble>expres</replaceable><optional>nal>,</optional>nal>)
IN (<replaceable>subquery</replaceable>)
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>IN</> is a parenthesized The right-hand side of this form of <token>IN</token> is a parenthesized
subquery, which must return exactly as many columns as there are subquery, which must return exactly as many columns as there are
expressions in the left-hand list. The left-hand expressions are expressions in the left-hand list. The left-hand expressions are
evaluated and compared row-wise to each row of the subquery result. evaluated and compared row-wise to each row of the subquery result.
The result of <token>IN</> is TRUE if any equal subquery row is found. The result of <token>IN</token> is TRUE if any equal subquery row is found.
The result is FALSE if no equal row is found (including the special The result is FALSE if no equal row is found (including the special
case where the subquery returns no rows). case where the subquery returns no rows).
</para> </para>
...@@ -4797,17 +4886,18 @@ OR ...@@ -4797,17 +4886,18 @@ OR
are unequal if any corresponding members are non-null and unequal; are unequal if any corresponding members are non-null and unequal;
otherwise the result of that row comparison is unknown (NULL). otherwise the result of that row comparison is unknown (NULL).
If all the row results are either unequal or NULL, with at least one NULL, If all the row results are either unequal or NULL, with at least one NULL,
then the result of <token>IN</> is NULL. then the result of <token>IN</token> is NULL.
</para> </para>
<bridgehead renderas="sect2">NOT IN (scalar form)</bridgehead> <bridgehead renderas="sect2">NOT IN (scalar form)</bridgehead>
<synopsis> <synopsis>
<replaceable>expression</replaceable> NOT IN (<replaceable>value</replaceable><optional>, ...</optional>) <replaceable>expression</replaceable> NOT IN
<replaceable>ble>value</replaceable><optional>, ...</optional>)
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>NOT IN</> is a parenthesized list The right-hand side of this form of <token>NOT IN</token> is a parenthesized list
of scalar expressions. The result is TRUE if the left-hand expression's of scalar expressions. The result is TRUE if the left-hand expression's
result is unequal to all of the right-hand expressions. This is a shorthand result is unequal to all of the right-hand expressions. This is a shorthand
notation for notation for
...@@ -4822,7 +4912,7 @@ AND ...@@ -4822,7 +4912,7 @@ AND
Note that if the left-hand expression yields NULL, or if there are Note that if the left-hand expression yields NULL, or if there are
no equal right-hand values and at least one right-hand expression yields no equal right-hand values and at least one right-hand expression yields
NULL, the result of the <token>NOT IN</> construct will be NULL, not TRUE NULL, the result of the <token>NOT IN</token> construct will be NULL, not TRUE
as one might naively expect. as one might naively expect.
This is in accordance with SQL's normal rules for Boolean combinations This is in accordance with SQL's normal rules for Boolean combinations
of NULL values. of NULL values.
...@@ -4830,9 +4920,9 @@ AND ...@@ -4830,9 +4920,9 @@ AND
<tip> <tip>
<para> <para>
<literal>x NOT IN y</> is equivalent to <literal>NOT (x IN y)</> in all <literal>x NOT IN y</literal> is equivalent to <literal>NOT (x IN y)</literal> in all
cases. However, NULLs are much more likely to trip up the novice when cases. However, NULLs are much more likely to trip up the novice when
working with <token>NOT IN</> than when working with <token>IN</>. working with <token>NOT IN</token> than when working with <token>IN</token>.
It's best to express your condition positively if possible. It's best to express your condition positively if possible.
</para> </para>
</tip> </tip>
...@@ -4844,10 +4934,10 @@ AND ...@@ -4844,10 +4934,10 @@ AND
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>NOT IN</> is a parenthesized The right-hand side of this form of <token>NOT IN</token> is a parenthesized
subquery, which must return exactly one column. The left-hand expression subquery, which must return exactly one column. The left-hand expression
is evaluated and compared to each row of the subquery result. is evaluated and compared to each row of the subquery result.
The result of <token>NOT IN</> is TRUE if only unequal subquery rows The result of <token>NOT IN</token> is TRUE if only unequal subquery rows
are found (including the special case where the subquery returns no rows). are found (including the special case where the subquery returns no rows).
The result is FALSE if any equal row is found. The result is FALSE if any equal row is found.
</para> </para>
...@@ -4855,26 +4945,28 @@ AND ...@@ -4855,26 +4945,28 @@ AND
<para> <para>
Note that if the left-hand expression yields NULL, or if there are Note that if the left-hand expression yields NULL, or if there are
no equal right-hand values and at least one right-hand row yields no equal right-hand values and at least one right-hand row yields
NULL, the result of the <token>NOT IN</> construct will be NULL, not TRUE. NULL, the result of the <token>NOT IN</token> construct will be NULL, not TRUE.
This is in accordance with SQL's normal rules for Boolean combinations This is in accordance with SQL's normal rules for Boolean combinations
of NULL values. of NULL values.
</para> </para>
<para> <para>
As with <token>EXISTS</>, it's unwise to assume that the subquery will As with <token>EXISTS</token>, it's unwise to assume that the subquery will
be evaluated completely. be evaluated completely.
</para> </para>
<synopsis> <synopsis>
(<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) NOT IN (<replaceable>subquery</replaceable>) (<replaceable>expression</replaceable>,
<replaceable>ble>expres</replaceable><optional>nal>,</optional>nal>)
NOT IN (<replaceable>subquery</replaceable>)
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>NOT IN</> is a parenthesized The right-hand side of this form of <token>NOT IN</token> is a parenthesized
subquery, which must return exactly as many columns as there are subquery, which must return exactly as many columns as there are
expressions in the left-hand list. The left-hand expressions are expressions in the left-hand list. The left-hand expressions are
evaluated and compared row-wise to each row of the subquery result. evaluated and compared row-wise to each row of the subquery result.
The result of <token>NOT IN</> is TRUE if only unequal subquery rows The result of <token>NOT IN</token> is TRUE if only unequal subquery rows
are found (including the special case where the subquery returns no rows). are found (including the special case where the subquery returns no rows).
The result is FALSE if any equal row is found. The result is FALSE if any equal row is found.
</para> </para>
...@@ -4886,59 +4978,63 @@ AND ...@@ -4886,59 +4978,63 @@ AND
are unequal if any corresponding members are non-null and unequal; are unequal if any corresponding members are non-null and unequal;
otherwise the result of that row comparison is unknown (NULL). otherwise the result of that row comparison is unknown (NULL).
If all the row results are either unequal or NULL, with at least one NULL, If all the row results are either unequal or NULL, with at least one NULL,
then the result of <token>NOT IN</> is NULL. then the result of <token>NOT IN</token> is NULL.
</para> </para>
<bridgehead renderas="sect2">ANY</bridgehead> <bridgehead renderas="sect2">ANY</bridgehead>
<synopsis> <synopsis>
<replaceable>expression</replaceable> <replaceable>operator</replaceable> ANY (<replaceable>subquery</replaceable>) <replaceable>expression</replaceable>
<replaceable>expression</replaceable> <replaceable>operator</replaceable> SOME (<replaceable>subquery</replaceable>) <replaceable>ble>oper</replaceable>ble> ANY (<replaceable>subquery</replaceable>)
<replaceable>expression</replaceable>
<replaceable>ble>oper</replaceable>ble> SOME (<replaceable>subquery</replaceable>)
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>ANY</> is a parenthesized The right-hand side of this form of <token>ANY</token> is a parenthesized
subquery, which must return exactly one column. The left-hand expression subquery, which must return exactly one column. The left-hand expression
is evaluated and compared to each row of the subquery result using the is evaluated and compared to each row of the subquery result using the
given <replaceable>operator</replaceable>, which must yield a Boolean given <replaceable>operator</replaceable>, which must yield a Boolean
result. result.
The result of <token>ANY</> is TRUE if any true result is obtained. The result of <token>ANY</token> is TRUE if any true result is obtained.
The result is FALSE if no true result is found (including the special The result is FALSE if no true result is found (including the special
case where the subquery returns no rows). case where the subquery returns no rows).
</para> </para>
<para> <para>
<token>SOME</> is a synonym for <token>ANY</>. <token>SOME</token> is a synonym for <token>ANY</token>.
<token>IN</> is equivalent to <literal>= ANY</>. <token>IN</token> is equivalent to <literal>= ANY</literal>.
</para> </para>
<para> <para>
Note that if there are no successes and at least one right-hand row yields Note that if there are no successes and at least one right-hand row yields
NULL for the operator's result, the result of the <token>ANY</> construct NULL for the operator's result, the result of the <token>ANY</token> construct
will be NULL, not FALSE. will be NULL, not FALSE.
This is in accordance with SQL's normal rules for Boolean combinations This is in accordance with SQL's normal rules for Boolean combinations
of NULL values. of NULL values.
</para> </para>
<para> <para>
As with <token>EXISTS</>, it's unwise to assume that the subquery will As with <token>EXISTS</token>, it's unwise to assume that the subquery will
be evaluated completely. be evaluated completely.
</para> </para>
<synopsis> <synopsis>
(<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) <replaceable>operator</replaceable> ANY (<replaceable>subquery</replaceable>) (<replaceable>expression</replaceable>,
(<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) <replaceable>operator</replaceable> SOME (<replaceable>subquery</replaceable>) <replaceable>ble>expres</replaceable><optional>nal>,</optional>optiona<replaceable>aceable></replaceable>aceable> ANY (<replaceable>subquery</replaceable>)
(<replaceable>expression</replaceable>,
<replaceable>ble>expres</replaceable><optional>nal>,</optional>optiona<replaceable>aceable></replaceable>aceable> SOME (<replaceable>subquery</replaceable>)
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>ANY</> is a parenthesized The right-hand side of this form of <token>ANY</token> is a parenthesized
subquery, which must return exactly as many columns as there are subquery, which must return exactly as many columns as there are
expressions in the left-hand list. The left-hand expressions are expressions in the left-hand list. The left-hand expressions are
evaluated and compared row-wise to each row of the subquery result, evaluated and compared row-wise to each row of the subquery result,
using the given <replaceable>operator</replaceable>. Presently, using the given <replaceable>operator</replaceable>. Presently,
only <literal>=</> and <literal>&lt;&gt;</> operators are allowed only <literal>=</literal> and <literal>&lt;&gt;</literal> operators are allowed
in row-wise <token>ANY</> queries. in row-wise <token>ANY</token> queries.
The result of <token>ANY</> is TRUE if any equal or unequal row is The result of <token>ANY</token> is TRUE if any equal or unequal row is
found, respectively. found, respectively.
The result is FALSE if no such row is found (including the special The result is FALSE if no such row is found (including the special
case where the subquery returns no rows). case where the subquery returns no rows).
...@@ -4950,57 +5046,58 @@ AND ...@@ -4950,57 +5046,58 @@ AND
equal if all their corresponding members are non-null and equal; the rows equal if all their corresponding members are non-null and equal; the rows
are unequal if any corresponding members are non-null and unequal; are unequal if any corresponding members are non-null and unequal;
otherwise the result of that row comparison is unknown (NULL). otherwise the result of that row comparison is unknown (NULL).
If there is at least one NULL row result, then the result of <token>ANY</> If there is at least one NULL row result, then the result of <token>ANY</token>
cannot be FALSE; it will be TRUE or NULL. cannot be FALSE; it will be TRUE or NULL.
</para> </para>
<bridgehead renderas="sect2">ALL</bridgehead> <bridgehead renderas="sect2">ALL</bridgehead>
<synopsis> <synopsis>
<replaceable>expression</replaceable> <replaceable>operator</replaceable> ALL (<replaceable>subquery</replaceable>) <replaceable>expression</replaceable>
<replaceable>ble>oper</replaceable>ble> ALL (<replaceable>subquery</replaceable>)
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>ALL</> is a parenthesized The right-hand side of this form of <token>ALL</token> is a parenthesized
subquery, which must return exactly one column. The left-hand expression subquery, which must return exactly one column. The left-hand expression
is evaluated and compared to each row of the subquery result using the is evaluated and compared to each row of the subquery result using the
given <replaceable>operator</replaceable>, which must yield a Boolean given <replaceable>operator</replaceable>, which must yield a Boolean
result. result.
The result of <token>ALL</> is TRUE if all rows yield TRUE The result of <token>ALL</token> is TRUE if all rows yield TRUE
(including the special case where the subquery returns no rows). (including the special case where the subquery returns no rows).
The result is FALSE if any false result is found. The result is FALSE if any false result is found.
</para> </para>
<para> <para>
<token>NOT IN</> is equivalent to <literal>&lt;&gt; ALL</>. <token>NOT IN</token> is equivalent to <literal>&lt;&gt; ALL</literal>.
</para> </para>
<para> <para>
Note that if there are no failures but at least one right-hand row yields Note that if there are no failures but at least one right-hand row yields
NULL for the operator's result, the result of the <token>ALL</> construct NULL for the operator's result, the result of the <token>ALL</token> construct
will be NULL, not TRUE. will be NULL, not TRUE.
This is in accordance with SQL's normal rules for Boolean combinations This is in accordance with SQL's normal rules for Boolean combinations
of NULL values. of NULL values.
</para> </para>
<para> <para>
As with <token>EXISTS</>, it's unwise to assume that the subquery will As with <token>EXISTS</token>, it's unwise to assume that the subquery will
be evaluated completely. be evaluated completely.
</para> </para>
<synopsis> <synopsis>
(<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) <replaceable>operator</replaceable> ALL (<replaceable>subquery</replaceable>) (<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) <replaceable>operator</replaceable> ALL (<replaceable>subquery</replaceable>)
</synopsis> </synopsis>
<para> <para>
The right-hand side of this form of <token>ALL</> is a parenthesized The right-hand side of this form of <token>ALL</token> is a parenthesized
subquery, which must return exactly as many columns as there are subquery, which must return exactly as many columns as there are
expressions in the left-hand list. The left-hand expressions are expressions in the left-hand list. The left-hand expressions are
evaluated and compared row-wise to each row of the subquery result, evaluated and compared row-wise to each row of the subquery result,
using the given <replaceable>operator</replaceable>. Presently, using the given <replaceable>operator</replaceable>. Presently,
only <literal>=</> and <literal>&lt;&gt;</> operators are allowed only <literal>=</literal> and <literal>&lt;&gt;</literal> operators are allowed
in row-wise <token>ALL</> queries. in row-wise <token>ALL</token> queries.
The result of <token>ALL</> is TRUE if all subquery rows are equal The result of <token>ALL</token> is TRUE if all subquery rows are equal
or unequal, respectively (including the special or unequal, respectively (including the special
case where the subquery returns no rows). case where the subquery returns no rows).
The result is FALSE if any row is found to be unequal or equal, The result is FALSE if any row is found to be unequal or equal,
...@@ -5013,16 +5110,16 @@ AND ...@@ -5013,16 +5110,16 @@ AND
equal if all their corresponding members are non-null and equal; the rows equal if all their corresponding members are non-null and equal; the rows
are unequal if any corresponding members are non-null and unequal; are unequal if any corresponding members are non-null and unequal;
otherwise the result of that row comparison is unknown (NULL). otherwise the result of that row comparison is unknown (NULL).
If there is at least one NULL row result, then the result of <token>ALL</> If there is at least one NULL row result, then the result of <token>ALL</token>
cannot be TRUE; it will be FALSE or NULL. cannot be TRUE; it will be FALSE or NULL.
</para> </para>
<bridgehead renderas="sect2">Row-wise comparison</bridgehead> <bridgehead renderas="sect2">Row-wise comparison</bridgehead>
<synopsis> <synopsis>
(<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) <replaceable>operator</replaceable> (<replaceable>subquery</replaceable>) (<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) <replaceable>operator</replaceable> (<replaceable>subquery</replaceable>)
(<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) <replaceable>operator</replaceable> (<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) (<replaceable>expression</replaceable>, <replaceable>expression</replaceable><optional>, ...</optional>) <replaceable>operator</replaceable> (<replaceable>expression</replaceable> <replaceable>expression</replaceable><optional>, ...</optional>)
</synopsis> </synopsis>
<para> <para>
The left-hand side is a list of scalar expressions. The right-hand side The left-hand side is a list of scalar expressions. The right-hand side
...@@ -5032,7 +5129,7 @@ AND ...@@ -5032,7 +5129,7 @@ AND
return more than one row. (If it returns zero rows, the result is taken to return more than one row. (If it returns zero rows, the result is taken to
be NULL.) The left-hand side is evaluated and compared row-wise to the be NULL.) The left-hand side is evaluated and compared row-wise to the
single subquery result row, or to the right-hand expression list. single subquery result row, or to the right-hand expression list.
Presently, only <literal>=</> and <literal>&lt;&gt;</> operators are allowed Presently, only <literal>=</literal> and <literal>&lt;&gt;</literal> operators are allowed
in row-wise comparisons. in row-wise comparisons.
The result is TRUE if the two rows are equal or unequal, respectively. The result is TRUE if the two rows are equal or unequal, respectively.
</para> </para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.138 2002/05/22 17:20:58 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.139 2002/06/11 15:32:33 thomas Exp $
--> -->
<appendix id="release"> <appendix id="release">
...@@ -44,6 +44,9 @@ Access privileges on procedural languages ...@@ -44,6 +44,9 @@ Access privileges on procedural languages
CREATE DATABASE has OWNER option so superuser can create DB for someone else CREATE DATABASE has OWNER option so superuser can create DB for someone else
Kerberos 5 support now works with Heimdal Kerberos 5 support now works with Heimdal
Database and user-specific session defaults for run-time configuration variables (ALTER DATABASE ... SET and ALTER USER ... SET) Database and user-specific session defaults for run-time configuration variables (ALTER DATABASE ... SET and ALTER USER ... SET)
String function OVERLAY() implemented per SQL99
Regular expression operator SIMILAR TO implemented per SQL99
Regular expression function SUBSTRING() implemented per SQL99
]]></literallayout> ]]></literallayout>
</sect1> </sect1>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment