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>
<para>
The <function>amcostestimate</function> function is given information describing
a possible index scan, including lists of WHERE and ORDER BY clauses that
have been determined to be usable with the index. It must return estimates
of the cost of accessing the index and the selectivity of the WHERE
clauses (that is, the fraction of parent-table rows that will be
retrieved during the index scan). For simple cases, nearly all the
work of the cost estimator can be done by calling standard routines
in the optimizer; the point of having an <function>amcostestimate</function> function is
to allow index access methods to provide index-type-specific knowledge,
in case it is possible to improve on the standard estimates.
</para>
<para>
Each <function>amcostestimate</function> function must have the signature:
<programlisting>
void
amcostestimate (PlannerInfo *root,
IndexPath *path,
double loop_count,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity,
double *indexCorrelation,
double *indexPages);
</programlisting>
The first three parameters are inputs:
<variablelist>
<varlistentry>
<term><parameter>root</parameter></term>
<listitem>
<para>
The planner's information about the query being processed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>path</parameter></term>
<listitem>
<para>
The index access path being considered. All fields except cost and
selectivity values are valid.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>loop_count</parameter></term>
<listitem>
<para>
The number of repetitions of the index scan that should be factored
into the cost estimates. This will typically be greater than one when
considering a parameterized scan for use in the inside of a nestloop
join. Note that the cost estimates should still be for just one scan;
a larger <parameter>loop_count</parameter> means that it may be appropriate
to allow for some caching effects across multiple scans.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
The last five parameters are pass-by-reference outputs:
<variablelist>
<varlistentry>
<term><parameter>*indexStartupCost</parameter></term>
<listitem>
<para>
Set to cost of index start-up processing
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>*indexTotalCost</parameter></term>
<listitem>
<para>
Set to total cost of index processing
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><parameter>*indexSelectivity</parameter></term>
<listitem>
<para>
Set to index