Home Explore Blog CI



postgresql

21th chunk of `doc/src/sgml/indexam.sgml`
df04ba9b2f7d200d62e54fa8e9b311cb6d25b24834393aab0000000100000fa9
 to
   insert the new row's index entry.  What's more, there is no obvious way
   to avoid race conditions unless the conflict check is an integral part
   of insertion of the new index entry.
  </para>

  <para>
   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</quote> actually
   means <quote>any tuple in the index entry's HOT chain is live</quote>.)
   To implement this, the <function>aminsert</function> function is passed a
   <literal>checkUnique</literal> parameter having one of the following values:

    <itemizedlist>
     <listitem>
      <para>
       <literal>UNIQUE_CHECK_NO</literal> indicates that no uniqueness checking
       should be done (this is not a unique index).
      </para>
     </listitem>
     <listitem>
      <para>
       <literal>UNIQUE_CHECK_YES</literal> 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</literal> 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</function>.
       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</literal> 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</function>, the
       access method must <emphasis>not</emphasis> 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</literal> 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</function> 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>

 <sect1 id="index-cost-estimation">
  <title>Index Cost Estimation Functions</title>

Title: Unique Constraint Deferral and aminsert Function
Summary
This section discusses the complexity introduced by deferrable unique constraints and the role of the aminsert function in handling uniqueness checks. The aminsert function receives a checkUnique parameter with values like UNIQUE_CHECK_NO, UNIQUE_CHECK_YES, UNIQUE_CHECK_PARTIAL, and UNIQUE_CHECK_EXISTING, each indicating different levels of uniqueness checking required. UNIQUE_CHECK_PARTIAL allows duplicate entries temporarily for deferrable constraints, while UNIQUE_CHECK_EXISTING performs a deferred recheck without inserting a new entry. The function also handles the verification of the target row's presence in the index during rechecks to ensure consistent tuple values.