position. The same
position might be restored multiple times. However, only one position need
be remembered per scan; a new <function>ammarkpos</function> call overrides the
previously marked position. An access method that does not support ordered
scans need not provide <function>ammarkpos</function> and <function>amrestrpos</function>
functions in <structname>IndexAmRoutine</structname>; set those pointers to NULL
instead.
</para>
<para>
Both the scan position and the mark position (if any) must be maintained
consistently in the face of concurrent insertions or deletions in the
index. It is OK if a freshly-inserted entry is not returned by a scan that
would have found the entry if it had existed when the scan started, or for
the scan to return such an entry upon rescanning or backing
up even though it had not been returned the first time through. Similarly,
a concurrent delete might or might not be reflected in the results of a scan.
What is important is that insertions or deletions not cause the scan to
miss or multiply return entries that were not themselves being inserted or
deleted.
</para>
<para>
If the index stores the original indexed data values (and not some lossy
representation of them), it is useful to
support <link linkend="indexes-index-only-scans">index-only scans</link>, in
which the index returns the actual data not just the TID of the heap tuple.
This will only avoid I/O if the visibility map shows that the TID is on an
all-visible page; else the heap tuple must be visited anyway to check
MVCC visibility. But that is no concern of the access method's.
</para>
<para>
Instead of using <function>amgettuple</function>, an index scan can be done with
<function>amgetbitmap</function> to fetch all tuples in one call. This can be
noticeably more efficient than <function>amgettuple</function> because it allows
avoiding lock/unlock cycles within the access method. In principle
<function>amgetbitmap</function> should have the same effects as repeated
<function>amgettuple</function> calls, but we impose several restrictions to
simplify matters. First of all, <function>amgetbitmap</function> returns all
tuples at once and marking or restoring scan positions isn't
supported. Secondly, the tuples are returned in a bitmap which doesn't
have any specific ordering, which is why <function>amgetbitmap</function> doesn't
take a <literal>direction</literal> argument. (Ordering operators will never be
supplied for such a scan, either.)
Also, there is no provision for index-only scans with
<function>amgetbitmap</function>, since there is no way to return the contents of
index tuples.
Finally, <function>amgetbitmap</function>
does not guarantee any locking of the returned tuples, with implications
spelled out in <xref linkend="index-locking"/>.
</para>
<para>
Note that it is permitted for an access method to implement only
<function>amgetbitmap</function> and not <function>amgettuple</function>, or vice versa,
if its internal implementation is unsuited to one API or the other.
</para>
</sect1>
<sect1 id="index-locking">
<title>Index Locking Considerations</title>
<para>
Index access methods must handle concurrent updates
of the index by multiple processes.
The core <productname>PostgreSQL</productname> system obtains
<literal>AccessShareLock</literal> on the index during an index scan, and
<literal>RowExclusiveLock</literal> when updating the index (including plain
<command>VACUUM</command>). Since these lock types do not conflict, the access
method is responsible for handling any fine-grained locking it might need.
An <literal>ACCESS EXCLUSIVE</literal> lock on the index as a whole will be
taken only during index creation, destruction, or <command>REINDEX</command>
(<literal>SHARE UPDATE EXCLUSIVE</literal> is taken instead with