diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2018-09-04 13:45:35 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2018-09-04 13:45:35 -0400 |
commit | 17b7c302b5fc92bd0241c452599019e18df074dc (patch) | |
tree | 16f56764ba643cc2950934c0cec70df245563076 /doc/src | |
parent | f30c6f523f9caa73c9ba6ebd82c8d29fe45866a3 (diff) | |
download | postgresql-17b7c302b5fc92bd0241c452599019e18df074dc.tar.gz postgresql-17b7c302b5fc92bd0241c452599019e18df074dc.zip |
Fully enforce uniqueness of constraint names.
It's been true for a long time that we expect names of table and domain
constraints to be unique among the constraints of that table or domain.
However, the enforcement of that has been pretty haphazard, and it missed
some corner cases such as creating a CHECK constraint and then an index
constraint of the same name (as per recent report from André Hänsel).
Also, due to the lack of an actual unique index enforcing this, duplicates
could be created through race conditions.
Moreover, the code that searches pg_constraint has been quite inconsistent
about how to handle duplicate names if one did occur: some places checked
and threw errors if there was more than one match, while others just
processed the first match they came to.
To fix, create a unique index on (conrelid, contypid, conname). Since
either conrelid or contypid is zero, this will separately enforce
uniqueness of constraint names among constraints of any one table and any
one domain. (If we ever implement SQL assertions, and put them into this
catalog, more thought might be needed. But it'd be at least as reasonable
to put them into a new catalog; having overloaded this one catalog with
two kinds of constraints was a mistake already IMO.) This index can replace
the existing non-unique index on conrelid, though we need to keep the one
on contypid for query performance reasons.
Having done that, we can simplify the logic in various places that either
coped with duplicates or neglected to, as well as potentially improve
lookup performance when searching for a constraint by name.
Also, as per our usual practice, install a preliminary check so that you
get something more friendly than a unique-index violation report in the
case complained of by André. And teach ChooseIndexName to avoid choosing
autogenerated names that would draw such a failure.
While it's not possible to make such a change in the back branches,
it doesn't seem quite too late to put this into v11, so do so.
Discussion: https://postgr.es/m/0c1001d4428f$0942b430$1bc81c90$@webkr.de
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/ref/alter_index.sgml | 3 | ||||
-rw-r--r-- | doc/src/sgml/ref/alter_table.sgml | 37 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_table.sgml | 24 |
3 files changed, 48 insertions, 16 deletions
diff --git a/doc/src/sgml/ref/alter_index.sgml b/doc/src/sgml/ref/alter_index.sgml index 7290d9a5bda..d0a62123583 100644 --- a/doc/src/sgml/ref/alter_index.sgml +++ b/doc/src/sgml/ref/alter_index.sgml @@ -48,6 +48,9 @@ ALTER INDEX ALL IN TABLESPACE <replaceable class="parameter">name</replaceable> <listitem> <para> The <literal>RENAME</literal> form changes the name of the index. + If the index is associated with a table constraint (either + <literal>UNIQUE</literal>, <literal>PRIMARY KEY</literal>, + or <literal>EXCLUDE</literal>), the constraint is renamed as well. There is no effect on the stored data. </para> </listitem> diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml index 1cce00eaf92..ec6b4c33113 100644 --- a/doc/src/sgml/ref/alter_table.sgml +++ b/doc/src/sgml/ref/alter_table.sgml @@ -474,7 +474,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM <term><literal>DROP CONSTRAINT [ IF EXISTS ]</literal></term> <listitem> <para> - This form drops the specified constraint on a table. + This form drops the specified constraint on a table, along with + any index underlying the constraint. If <literal>IF EXISTS</literal> is specified and the constraint does not exist, no error is thrown. In this case a notice is issued instead. </para> @@ -822,8 +823,10 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM <listitem> <para> The <literal>RENAME</literal> forms change the name of a table - (or an index, sequence, view, materialized view, or foreign table), the name - of an individual column in a table, or the name of a constraint of the table. + (or an index, sequence, view, materialized view, or foreign table), the + name of an individual column in a table, or the name of a constraint of + the table. When renaming a constraint that has an underlying index, + the index is renamed as well. There is no effect on the stored data. </para> </listitem> @@ -1270,10 +1273,12 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM <para> If a table has any descendant tables, it is not permitted to add, rename, or change the type of a column in the parent table without doing - same to the descendants. This ensures that the descendants always have - columns matching the parent. Similarly, a constraint cannot be renamed - in the parent without also renaming it in all descendants, so that - constraints also match between the parent and its descendants. + the same to the descendants. This ensures that the descendants always + have columns matching the parent. Similarly, a <literal>CHECK</literal> + constraint cannot be renamed in the parent without also renaming it in + all descendants, so that <literal>CHECK</literal> constraints also match + between the parent and its descendants. (That restriction does not apply + to index-based constraints, however.) Also, because selecting from the parent also selects from its descendants, a constraint on the parent cannot be marked valid unless it is also marked valid for those descendants. In all of these cases, <command>ALTER TABLE @@ -1481,35 +1486,35 @@ ALTER TABLE distributors DROP CONSTRAINT distributors_pkey, </programlisting></para> <para> - Attach a partition to range partitioned table: + To attach a partition to a range-partitioned table: <programlisting> ALTER TABLE measurement ATTACH PARTITION measurement_y2016m07 FOR VALUES FROM ('2016-07-01') TO ('2016-08-01'); </programlisting></para> <para> - Attach a partition to list partitioned table: + To attach a partition to a list-partitioned table: <programlisting> ALTER TABLE cities ATTACH PARTITION cities_ab FOR VALUES IN ('a', 'b'); </programlisting></para> <para> - Attach a default partition to a partitioned table: + To attach a partition to a hash-partitioned table: <programlisting> -ALTER TABLE cities - ATTACH PARTITION cities_partdef DEFAULT; +ALTER TABLE orders + ATTACH PARTITION orders_p4 FOR VALUES WITH (MODULUS 4, REMAINDER 3); </programlisting></para> <para> - Attach a partition to hash partitioned table: + To attach a default partition to a partitioned table: <programlisting> -ALTER TABLE orders - ATTACH PARTITION orders_p4 FOR VALUES WITH (MODULUS 4, REMAINDER 3); +ALTER TABLE cities + ATTACH PARTITION cities_partdef DEFAULT; </programlisting></para> <para> - Detach a partition from partitioned table: + To detach a partition from a partitioned table: <programlisting> ALTER TABLE measurement DETACH PARTITION measurement_y2015m12; diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index d936de3f238..5a19f94ce91 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -2005,6 +2005,30 @@ CREATE TABLE cities_partdef </refsect2> <refsect2> + <title>Constraint Naming</title> + + <para> + The SQL standard says that table and domain constraints must have names + that are unique across the schema containing the table or domain. + <productname>PostgreSQL</productname> is laxer: it only requires + constraint names to be unique across the constraints attached to a + particular table or domain. However, this extra freedom does not exist + for index-based constraints (<literal>UNIQUE</literal>, + <literal>PRIMARY KEY</literal>, and <literal>EXCLUDE</literal> + constraints), because the associated index is named the same as the + constraint, and index names must be unique across all relations within + the same schema. + </para> + + <para> + Currently, <productname>PostgreSQL</productname> does not record names + for <literal>NOT NULL</literal> constraints at all, so they are not + subject to the uniqueness restriction. This might change in a future + release. + </para> + </refsect2> + + <refsect2> <title>Inheritance</title> <para> |