</programlisting>
</para>
<para>
Note that when running the <command>ATTACH PARTITION</command> command,
the table will be scanned to validate the partition constraint while
holding an <literal>ACCESS EXCLUSIVE</literal> lock on that partition.
As shown above, it is recommended to avoid this scan by creating a
<literal>CHECK</literal> constraint matching the expected partition
constraint on the table prior to attaching it. Once the
<command>ATTACH PARTITION</command> is complete, it is recommended to drop
the now-redundant <literal>CHECK</literal> constraint.
If the table being attached is itself a partitioned table, then each of its
sub-partitions will be recursively locked and scanned until either a
suitable <literal>CHECK</literal> constraint is encountered or the leaf
partitions are reached.
</para>
<para>
Similarly, if the partitioned table has a <literal>DEFAULT</literal>
partition, it is recommended to create a <literal>CHECK</literal>
constraint which excludes the to-be-attached partition's constraint. If
this is not done, the <literal>DEFAULT</literal> partition will be
scanned to verify that it contains no records which should be located in
the partition being attached. This operation will be performed whilst
holding an <literal>ACCESS EXCLUSIVE</literal> lock on the <literal>
DEFAULT</literal> partition. If the <literal>DEFAULT</literal> partition
is itself a partitioned table, then each of its partitions will be
recursively checked in the same way as the table being attached, as
mentioned above.
</para>
<para>
As mentioned earlier, it is possible to create indexes on partitioned
tables so that they are applied automatically to the entire hierarchy.
This can be very convenient as not only will all existing partitions be
indexed, but any future partitions will be as well. However, one
limitation when creating new indexes on partitioned tables is that it
is not possible to use the <literal>CONCURRENTLY</literal>
qualifier, which could lead to long lock times. To avoid this, you can
use <command>CREATE INDEX ON ONLY</command> the partitioned table, which
creates the new index marked as invalid, preventing automatic application
to existing partitions. Instead, indexes can then be created individually
on each partition using <literal>CONCURRENTLY</literal> and
<firstterm>attached</firstterm> to the partitioned index on the parent
using <command>ALTER INDEX ... ATTACH PARTITION</command>. Once indexes for
all the partitions are attached to the parent index, the parent index will
be marked valid automatically. Example:
<programlisting>
CREATE INDEX measurement_usls_idx ON ONLY measurement (unitsales);
CREATE INDEX CONCURRENTLY measurement_usls_200602_idx
ON measurement_y2006m02 (unitsales);
ALTER INDEX measurement_usls_idx
ATTACH PARTITION measurement_usls_200602_idx;
...
</programlisting>
This technique can be used with <literal>UNIQUE</literal> and
<literal>PRIMARY KEY</literal> constraints too; the indexes are created
implicitly when the constraint is created. Example:
<programlisting>
ALTER TABLE ONLY measurement ADD UNIQUE (city_id, logdate);
ALTER TABLE measurement_y2006m02 ADD UNIQUE (city_id, logdate);
ALTER INDEX measurement_city_id_logdate_key
ATTACH PARTITION measurement_y2006m02_city_id_logdate_key;
...
</programlisting>
</para>
</sect3>
<sect3 id="ddl-partitioning-declarative-limitations">
<title>Limitations</title>
<para>
The following limitations apply to partitioned tables:
<itemizedlist>
<listitem>
<para>
To create a unique or primary key constraint on a partitioned table,
the partition keys must not include any expressions or function calls
and the constraint's columns must include all of the partition