index can be used for queries that do not restrict
these columns. For example, consider an index on (a,b) and a query with
<literal>WHERE a = 4</literal>. The system will assume the index can be
used to scan for rows with <literal>a = 4</literal>, which is wrong if the
index omits rows where <literal>b</literal> is null.
It is, however, OK to omit rows where the first indexed column is null.
An index access method that does index nulls may also set
<structfield>amsearchnulls</structfield>, indicating that it supports
<literal>IS NULL</literal> and <literal>IS NOT NULL</literal> clauses as search
conditions.
</para>
<para>
The <structfield>amcaninclude</structfield> flag indicates whether the
access method supports <quote>included</quote> columns, that is it can
store (without processing) additional columns beyond the key column(s).
The requirements of the preceding paragraph apply only to the key
columns. In particular, the combination
of <structfield>amcanmulticol</structfield>=<literal>false</literal>
and <structfield>amcaninclude</structfield>=<literal>true</literal> is
sensible: it means that there can only be one key column, but there can
also be included column(s). Also, included columns must be allowed to be
null, independently of <structfield>amoptionalkey</structfield>.
</para>
<para>
The <structfield>amsummarizing</structfield> flag indicates whether the
access method summarizes the indexed tuples, with summarizing granularity
of at least per block.
Access methods that do not point to individual tuples, but to block ranges
(like <acronym>BRIN</acronym>), may allow the <acronym>HOT</acronym> optimization
to continue. This does not apply to attributes referenced in index
predicates, an update of such an attribute always disables <acronym>HOT</acronym>.
</para>
</sect1>
<sect1 id="index-functions">
<title>Index Access Method Functions</title>
<para>
The index construction and maintenance functions that an index access
method must provide in <structname>IndexAmRoutine</structname> are:
</para>
<para>
<programlisting>
IndexBuildResult *
ambuild (Relation heapRelation,
Relation indexRelation,
IndexInfo *indexInfo);
</programlisting>
Build a new index. The index relation has been physically created,
but is empty. It must be filled in with whatever fixed data the
access method requires, plus entries for all tuples already existing
in the table. Ordinarily the <function>ambuild</function> function will call
<function>table_index_build_scan()</function> to scan the table for existing tuples
and compute the keys that need to be inserted into the index.
The function must return a palloc'd struct containing statistics about
the new index.
The <structfield>amcanbuildparallel</structfield> flag indicates whether
the access method supports parallel index builds. When set to <literal>true</literal>,
the system will attempt to allocate parallel workers for the build.
Access methods supporting only non-parallel index builds should leave
this flag set to <literal>false</literal>.
</para>
<para>
<programlisting>
void
ambuildempty (Relation indexRelation);
</programlisting>
Build an empty index, and write it to the initialization fork (<symbol>INIT_FORKNUM</symbol>)
of the given relation. This method is called only for unlogged indexes; the
empty index written to the initialization fork will be copied over the main
relation fork on each server restart.
</para>
<para>
<programlisting>
bool
aminsert (Relation indexRelation,
Datum *values,
bool *isnull,
ItemPointer heap_tid,
Relation heapRelation,
IndexUniqueCheck checkUnique,
bool indexUnchanged,
IndexInfo *indexInfo);
</programlisting>
Insert a new tuple into an existing index. The <literal>values</literal> and
<literal>isnull</literal>