&rangetypes;
+ <sect1 id="domains">
+ <title>Domain Types</title>
+
+ <indexterm zone="domains">
+ <primary>domain</primary>
+ </indexterm>
+
+ <indexterm zone="domains">
+ <primary>data type</primary>
+ <secondary>domain</secondary>
+ </indexterm>
+
+ <para>
+ A <firstterm>domain</firstterm> is a user-defined data type that is
+ based on another <firstterm>underlying type</firstterm>. Optionally,
+ it can have constraints that restrict its valid values to a subset of
+ what the underlying type would allow. Otherwise it behaves like the
+ underlying type — for example, any operator or function that
+ can be applied to the underlying type will work on the domain type.
+ The underlying type can be any built-in or user-defined base type,
+ enum type, array or range type, or another domain. (Currently, domains
+ over composite types are not implemented.)
+ </para>
+
+ <para>
+ For example, we could create a domain over integers that accepts only
+ positive integers:
+<programlisting>
+CREATE DOMAIN posint AS integer CHECK (VALUE > 0);
+CREATE TABLE mytable (id posint);
+INSERT INTO mytable VALUES(1); -- works
+INSERT INTO mytable VALUES(-1); -- fails
+</programlisting>
+ </para>
+
+ <para>
+ When an operator or function of the underlying type is applied to a
+ domain value, the domain is automatically down-cast to the underlying
+ type. Thus, for example, the result of <literal>mytable.id - 1</literal>
+ is considered to be of type <type>integer</type> not <type>posint</type>.
+ We could write <literal>(mytable.id - 1)::posint</literal> to cast the
+ result back to <type>posint</type>, causing the domain's constraints
+ to be rechecked. In this case, that would result in an error if the
+ expression had been applied to an <structfield>id</structfield> value of
+ 1. Assigning a value of the underlying type to a field or variable of
+ the domain type is allowed without writing an explicit cast, but the
+ domain's constraints will be checked.
+ </para>
+
+ <para>
+ For additional information see <xref linkend="sql-createdomain">.
+ </para>
+ </sect1>
+
<sect1 id="datatype-oid">
<title>Object Identifier Types</title>
<secondary>composite</secondary>
</indexterm>
+ <indexterm zone="extend-type-system">
+ <primary>container type</primary>
+ </indexterm>
+
+ <indexterm zone="extend-type-system">
+ <primary>data type</primary>
+ <secondary>container</secondary>
+ </indexterm>
+
<para>
- <productname>PostgreSQL</productname> data types are divided into base
- types, composite types, domains, and pseudo-types.
+ <productname>PostgreSQL</productname> data types can be divided into base
+ types, container types, domains, and pseudo-types.
</para>
<sect2>
<title>Base Types</title>
<para>
- Base types are those, like <type>int4</type>, that are
+ Base types are those, like <type>integer</type>, that are
implemented below the level of the <acronym>SQL</acronym> language
(typically in a low-level language such as C). They generally
correspond to what are often known as abstract data types.
<productname>PostgreSQL</productname> can only operate on such
types through functions provided by the user and only understands
the behavior of such types to the extent that the user describes
- them. Base types are further subdivided into scalar and array
- types. For each scalar type, a corresponding array type is
- automatically created that can hold variable-size arrays of that
- scalar type.
+ them.
+ The built-in base types are described in <xref linkend="datatype">.
+ </para>
+
+ <para>
+ Enumerated (enum) types can be considered as a subcategory of base
+ types. The main difference is that they can be created using
+ just <acronym>SQL</acronym> commands, without any low-level programming.
+ Refer to <xref linkend="datatype-enum"> for more information.
</para>
</sect2>
<sect2>
- <title>Composite Types</title>
+ <title>Container Types</title>
+
+ <para>
+ <productname>PostgreSQL</productname> has three kinds
+ of <quote>container</quote> types, which are types that contain multiple
+ values of other types. These are arrays, composites, and ranges.
+ </para>
+
+ <para>
+ Arrays can hold multiple values that are all of the same type. An array
+ type is automatically created for each base type, composite type, range
+ type, and domain type. But there are no arrays of arrays. So far as
+ the type system is concerned, multi-dimensional arrays are the same as
+ one-dimensional arrays. Refer to <xref linkend="arrays"> for more
+ information.
+ </para>
<para>
Composite types, or row types, are created whenever the user
define a <quote>stand-alone</quote> composite type with no associated
table. A composite type is simply a list of types with
associated field names. A value of a composite type is a row or
- record of field values. The user can access the component fields
- from <acronym>SQL</acronym> queries. Refer to <xref linkend="rowtypes">
- for more information on composite types.
+ record of field values. Refer to <xref linkend="rowtypes">
+ for more information.
+ </para>
+
+ <para>
+ A range type can hold two values of the same type, which are the lower
+ and upper bounds of the range. Range types are user-created, although
+ a few built-in ones exist. Refer to <xref linkend="rangetypes">
+ for more information.
</para>
</sect2>
<title>Domains</title>
<para>
- A domain is based on a particular base type and for many purposes
- is interchangeable with its base type. However, a domain can
- have constraints that restrict its valid values to a subset of
- what the underlying base type would allow.
- </para>
-
- <para>
- Domains can be created using the <acronym>SQL</acronym> command
- <xref linkend="sql-createdomain">.
- Their creation and use is not discussed in this chapter.
+ A domain is based on a particular underlying type and for many purposes
+ is interchangeable with its underlying type. However, a domain can have
+ constraints that restrict its valid values to a subset of what the
+ underlying type would allow. Domains are created using
+ the <acronym>SQL</acronym> command <xref linkend="sql-createdomain">.
+ Refer to <xref linkend="domains"> for more information.
</para>
</sect2>
<para>
There are a few <quote>pseudo-types</quote> for special purposes.
- Pseudo-types cannot appear as columns of tables or attributes of
- composite types, but they can be used to declare the argument and
+ Pseudo-types cannot appear as columns of tables or components of
+ container types, but they can be used to declare the argument and
result types of functions. This provides a mechanism within the
type system to identify special classes of functions. <xref
linkend="datatype-pseudotypes-table"> lists the existing
</indexterm>
<indexterm zone="extend-types-polymorphic">
- <primary>type</primary>
+ <primary>data type</primary>
<secondary>polymorphic</secondary>
</indexterm>
</varlistentry>
<varlistentry>
- <term><replaceable class="parameter">NOT VALID</replaceable></term>
+ <term><literal>NOT VALID</literal></term>
<listitem>
<para>
Do not verify existing column data for constraint validity.
<para>
Currently, <command>ALTER DOMAIN ADD CONSTRAINT</command>, <command>ALTER
- DOMAIN VALIDATE CONSTRAINT</command>, and <command>ALTER DOMAIN SET NOT NULL</command>
- will fail if the validated named domain or
- any derived domain is used within a composite-type column of any
- table in the database. They should eventually be improved to be
- able to verify the new constraint for such nested columns.
+ DOMAIN VALIDATE CONSTRAINT</command>, and <command>ALTER DOMAIN SET NOT
+ NULL</command> will fail if the named domain or any derived domain is used
+ within a container-type column (a composite, array, or range column) in
+ any table in the database. They should eventually be improved to be able
+ to verify the new constraint for such nested values.
</para>
</refsect1>
with either syntax. If it's an expensive function you may wish to
avoid that, which you can do with a query like:
<programlisting>
-SELECT (m).* FROM (SELECT myfunc(x) AS m FROM some_table OFFSET 0) ss;
+SELECT m.* FROM some_table, LATERAL myfunc(x) AS m;
</programlisting>
- The <literal>OFFSET 0</literal> clause keeps the optimizer
- from <quote>flattening</quote> the sub-select to arrive at the form with
- multiple calls of <function>myfunc()</function>.
+ Placing the function in
+ a <literal>LATERAL</literal> <literal>FROM</literal> item keeps it from
+ being invoked more than once per row. <literal>m.*</literal> is still
+ expanded into <literal>m.a, m.b, m.c</literal>, but now those variables
+ are just references to the output of the <literal>FROM</literal> item.
+ (The <literal>LATERAL</literal> keyword is optional here, but we show it
+ to clarify that the function is getting <structfield>x</structfield>
+ from <structname>some_table</structname>.)
</para>
</tip>