diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 10 | ||||
-rw-r--r-- | doc/src/sgml/indexam.sgml | 108 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_table.sgml | 40 | ||||
-rw-r--r-- | doc/src/sgml/ref/set_constraints.sgml | 23 |
4 files changed, 149 insertions, 32 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index a70c11aa889..99aee810da4 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.202 2009/07/28 02:56:29 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.203 2009/07/29 20:56:17 tgl Exp $ --> <!-- Documentation of the system catalogs, directed toward PostgreSQL developers --> @@ -2676,6 +2676,14 @@ </row> <row> + <entry><structfield>indimmediate</structfield></entry> + <entry><type>bool</type></entry> + <entry></entry> + <entry>If true, the uniqueness check is enforced immediately on insertion + (<structfield>indisunique</> should always be true when this is true)</entry> + </row> + + <row> <entry><structfield>indisclustered</structfield></entry> <entry><type>bool</type></entry> <entry></entry> diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index 19b3c70814e..b81cd27d313 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.30 2009/03/24 20:17:08 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.31 2009/07/29 20:56:17 tgl Exp $ --> <chapter id="indexam"> <title>Index Access Method Interface Definition</title> @@ -172,20 +172,32 @@ aminsert (Relation indexRelation, bool *isnull, ItemPointer heap_tid, Relation heapRelation, - bool check_uniqueness); + IndexUniqueCheck checkUnique); </programlisting> Insert a new tuple into an existing index. The <literal>values</> and <literal>isnull</> arrays give the key values to be indexed, and <literal>heap_tid</> is the TID to be indexed. If the access method supports unique indexes (its <structname>pg_am</>.<structfield>amcanunique</> flag is true) then - <literal>check_uniqueness</> might be true, in which case the access method - must verify that there is no conflicting row; this is the only situation in - which the access method normally needs the <literal>heapRelation</> - parameter. See <xref linkend="index-unique-checks"> for details. - The result is TRUE if an index entry was inserted, FALSE if not. (A FALSE - result does not denote an error condition, but is used for cases such - as an index method refusing to index a NULL.) + <literal>checkUnique</> indicates the type of uniqueness check to + perform. This varies depending on whether the unique constraint is + deferrable; see <xref linkend="index-unique-checks"> for details. + Normally the access method only needs the <literal>heapRelation</> + parameter when performing uniqueness checking (since then it will have to + look into the heap to verify tuple liveness). + </para> + + <para> + The function's boolean result value is significant only when + <literal>checkUnique</> is <literal>UNIQUE_CHECK_PARTIAL</>. + In this case a TRUE result means the new entry is known unique, whereas + FALSE means it might be non-unique (and a deferred uniqueness check must + be scheduled). For other cases a constant FALSE result is recommended. + </para> + + <para> + Some indexes might not index all tuples. If the tuple is not to be + indexed, <function>aminsert</> should just return without doing anything. </para> <para> @@ -706,10 +718,10 @@ amrestrpos (IndexScanDesc scan); </para> <para> - Furthermore, immediately before raising a uniqueness violation + Furthermore, immediately before reporting a uniqueness violation according to the above rules, the access method must recheck the liveness of the row being inserted. If it is committed dead then - no error should be raised. (This case cannot occur during the + no violation should be reported. (This case cannot occur during the ordinary scenario of inserting a row that's just been created by the current transaction. It can happen during <command>CREATE UNIQUE INDEX CONCURRENTLY</>, however.) @@ -728,8 +740,78 @@ amrestrpos (IndexScanDesc scan); </para> <para> - The main limitation of this scheme is that it has no convenient way - to support deferred uniqueness checks. + If the unique constraint is deferrable, there is additional complexity: + we need to be able to insert an index entry for a new row, but defer any + uniqueness-violation error until end of statement or even later. To + avoid unnecessary repeat searches of the index, the index access method + should do a preliminary uniqueness check during the initial insertion. + If this shows that there is definitely no conflicting live tuple, we + are done. Otherwise, we schedule a recheck to occur when it is time to + enforce the constraint. If, at the time of the recheck, both the inserted + tuple and some other tuple with the same key are live, then the error + must be reported. (Note that for this purpose, <quote>live</> actually + means <quote>any tuple in the index entry's HOT chain is live</>.) + To implement this, the <function>aminsert</> function is passed a + <literal>checkUnique</> parameter having one of the following values: + + <itemizedlist> + <listitem> + <para> + <literal>UNIQUE_CHECK_NO</> indicates that no uniqueness checking + should be done (this is not a unique index). + </para> + </listitem> + <listitem> + <para> + <literal>UNIQUE_CHECK_YES</> indicates that this is a non-deferrable + unique index, and the uniqueness check must be done immediately, as + described above. + </para> + </listitem> + <listitem> + <para> + <literal>UNIQUE_CHECK_PARTIAL</> indicates that the unique + constraint is deferrable. <productname>PostgreSQL</productname> + will use this mode to insert each row's index entry. The access + method must allow duplicate entries into the index, and report any + potential duplicates by returning FALSE from <function>aminsert</>. + For each row for which FALSE is returned, a deferred recheck will + be scheduled. + </para> + + <para> + The access method must identify any rows which might violate the + unique constraint, but it is not an error for it to report false + positives. This allows the check to be done without waiting for other + transactions to finish; conflicts reported here are not treated as + errors and will be rechecked later, by which time they may no longer + be conflicts. + </para> + </listitem> + <listitem> + <para> + <literal>UNIQUE_CHECK_EXISTING</> indicates that this is a deferred + recheck of a row that was reported as a potential uniqueness violation. + Although this is implemented by calling <function>aminsert</>, the + access method must <emphasis>not</> insert a new index entry in this + case. The index entry is already present. Rather, the access method + must check to see if there is another live index entry. If so, and + if the target row is also still live, report error. + </para> + + <para> + It is recommended that in a <literal>UNIQUE_CHECK_EXISTING</> call, + the access method further verify that the target row actually does + have an existing entry in the index, and report error if not. This + is a good idea because the index tuple values passed to + <function>aminsert</> will have been recomputed. If the index + definition involves functions that are not really immutable, we + might be checking the wrong area of the index. Checking that the + target row is found in the recheck verifies that we are scanning + for the same tuple values as were used in the original insertion. + </para> + </listitem> + </itemizedlist> </para> </sect1> diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml index 64971752eb4..1f986bcd88c 100644 --- a/doc/src/sgml/ref/create_table.sgml +++ b/doc/src/sgml/ref/create_table.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.114 2009/02/12 13:25:33 momjian Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/create_table.sgml,v 1.115 2009/07/29 20:56:17 tgl Exp $ PostgreSQL documentation --> @@ -35,8 +35,8 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PAR where <replaceable class="PARAMETER">column_constraint</replaceable> is: [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ] -{ NOT NULL | - NULL | +{ NOT NULL | + NULL | UNIQUE <replaceable class="PARAMETER">index_parameters</replaceable> | PRIMARY KEY <replaceable class="PARAMETER">index_parameters</replaceable> | CHECK ( <replaceable class="PARAMETER">expression</replaceable> ) | @@ -423,11 +423,10 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is: contain values that match values in the referenced column(s) of some row of the referenced table. If <replaceable class="parameter">refcolumn</replaceable> is omitted, the - primary key of the <replaceable - class="parameter">reftable</replaceable> is used. The - referenced columns must be the columns of a unique or primary - key constraint in the referenced table. Note that foreign key - constraints cannot be defined between temporary tables and + primary key of the <replaceable class="parameter">reftable</replaceable> + is used. The referenced columns must be the columns of a non-deferrable + unique or primary key constraint in the referenced table. Note that + foreign key constraints cannot be defined between temporary tables and permanent tables. </para> @@ -534,9 +533,11 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is: after every command. Checking of constraints that are deferrable can be postponed until the end of the transaction (using the <xref linkend="sql-set-constraints" endterm="sql-set-constraints-title"> command). - <literal>NOT DEFERRABLE</literal> is the default. Only foreign - key constraints currently accept this clause. All other - constraint types are not deferrable. + <literal>NOT DEFERRABLE</literal> is the default. + Currently, only <literal>UNIQUE</>, <literal>PRIMARY KEY</>, and + <literal>REFERENCES</> (foreign key) constraints accept this + clause. <literal>NOT NULL</> and <literal>CHECK</> constraints are not + deferrable. </para> </listitem> </varlistentry> @@ -1141,6 +1142,23 @@ CREATE TABLE cinemas ( </refsect2> <refsect2> + <title>Non-deferred Uniqueness Constraints</title> + + <para> + When a <literal>UNIQUE</> or <literal>PRIMARY KEY</> constraint is + not deferrable, <productname>PostgreSQL</productname> checks for + uniqueness immediately whenever a row is inserted or modified. + The SQL standard says that uniqueness should be enforced only at + the end of the statement; this makes a difference when, for example, + a single command updates multiple key values. To obtain + standard-compliant behavior, declare the constraint as + <literal>DEFERRABLE</> but not deferred (i.e., <literal>INITIALLY + IMMEDIATE</>). Be aware that this can be significantly slower than + immediate uniqueness checking. + </para> + </refsect2> + + <refsect2> <title>Column Check Constraints</title> <para> diff --git a/doc/src/sgml/ref/set_constraints.sgml b/doc/src/sgml/ref/set_constraints.sgml index 58f64b2437c..e03910e2529 100644 --- a/doc/src/sgml/ref/set_constraints.sgml +++ b/doc/src/sgml/ref/set_constraints.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/set_constraints.sgml,v 1.16 2008/11/14 10:22:47 petere Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/set_constraints.sgml,v 1.17 2009/07/29 20:56:17 tgl Exp $ --> <refentry id="SQL-SET-CONSTRAINTS"> <refmeta> <refentrytitle id="SQL-SET-CONSTRAINTS-title">SET CONSTRAINTS</refentrytitle> @@ -48,7 +48,7 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ... <command>SET CONSTRAINTS</command> with a list of constraint names changes the mode of just those constraints (which must all be deferrable). The current schema search path is used to find the first matching name if - no schema name is specified. <command>SET CONSTRAINTS ALL</command> + no schema name is specified. <command>SET CONSTRAINTS ALL</command> changes the mode of all deferrable constraints. </para> @@ -66,10 +66,19 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ... </para> <para> - Currently, only foreign key constraints are affected by this - setting. Check and unique constraints are always effectively - not deferrable. Triggers that are declared as <quote>constraint - triggers</> are also affected. + Currently, only <literal>UNIQUE</>, <literal>PRIMARY KEY</>, and + <literal>REFERENCES</> (foreign key) constraints are affected by this + setting. <literal>NOT NULL</> and <literal>CHECK</> constraints are + always checked immediately when a row is inserted or modified + (<emphasis>not</> at the end of the statement). + Uniqueness constraints that have not been declared <literal>DEFERRABLE</> + are also checked immediately. + </para> + + <para> + The firing of triggers that are declared as <quote>constraint triggers</> + is also controlled by this setting — they fire at the same time + that the associated constraint should be checked. </para> </refsect1> @@ -92,7 +101,7 @@ SET CONSTRAINTS { ALL | <replaceable class="parameter">name</replaceable> [, ... This command complies with the behavior defined in the SQL standard, except for the limitation that, in <productname>PostgreSQL</productname>, it only applies to - foreign-key constraints. + foreign-key and uniqueness constraints. </para> </refsect1> |