worthwhile, this can be worked around by
adding <literal>x</literal> as an included column, for example
<programlisting>
CREATE INDEX tab_f_x ON tab (f(x)) INCLUDE (x);
</programlisting>
An additional caveat, if the goal is to avoid
recalculating <literal>f(x)</literal>, is that the planner won't
necessarily match uses of <literal>f(x)</literal> that aren't in
indexable <literal>WHERE</literal> clauses to the index column. It will
usually get this right in simple queries such as shown above, but not in
queries that involve joins. These deficiencies may be remedied in future
versions of <productname>PostgreSQL</productname>.
</para>
<para>
Partial indexes also have interesting interactions with index-only scans.
Consider the partial index shown in <xref linkend="indexes-partial-ex3"/>:
<programlisting>
CREATE UNIQUE INDEX tests_success_constraint ON tests (subject, target)
WHERE success;
</programlisting>
In principle, we could do an index-only scan on this index to satisfy a
query like
<programlisting>
SELECT target FROM tests WHERE subject = 'some-subject' AND success;
</programlisting>
But there's a problem: the <literal>WHERE</literal> clause refers
to <literal>success</literal> which is not available as a result column
of the index. Nonetheless, an index-only scan is possible because the
plan does not need to recheck that part of the <literal>WHERE</literal>
clause at run time: all entries found in the index necessarily
have <literal>success = true</literal> so this need not be explicitly
checked in the plan. <productname>PostgreSQL</productname> versions 9.6
and later will recognize such cases and allow index-only scans to be
generated, but older versions will not.
</para>
</sect1>
<sect1 id="indexes-opclass">
<title>Operator Classes and Operator Families</title>
<indexterm zone="indexes-opclass">
<primary>operator class</primary>
</indexterm>
<indexterm zone="indexes-opclass">
<primary>operator family</primary>
</indexterm>
<para>
An index definition can specify an <firstterm>operator
class</firstterm> for each column of an index.
<synopsis>
CREATE INDEX <replaceable>name</replaceable> ON <replaceable>table</replaceable> (<replaceable>column</replaceable> <replaceable>opclass</replaceable> [ ( <replaceable>opclass_options</replaceable> ) ] <optional><replaceable>sort options</replaceable></optional> <optional>, ...</optional>);
</synopsis>
The operator class identifies the operators to be used by the index
for that column. For example, a B-tree index on the type <type>int4</type>
would use the <literal>int4_ops</literal> class; this operator
class includes comparison functions for values of type <type>int4</type>.
In practice the default operator class for the column's data type is
usually sufficient. The main reason for having operator classes is
that for some data types, there could be more than one meaningful
index behavior. For example, we might want to sort a complex-number data
type either by absolute value or by real part. We could do this by
defining two operator classes for the data type and then selecting
the proper class when making an index. The operator class determines
the basic sort ordering (which can then be modified by adding sort options
<literal>COLLATE</literal>,
<literal>ASC</literal>/<literal>DESC</literal> and/or
<literal>NULLS FIRST</literal>/<literal>NULLS LAST</literal>).
</para>
<para>
There are also some built-in operator classes besides the default ones:
<itemizedlist>
<listitem>
<para>
The operator classes <literal>text_pattern_ops</literal>,
<literal>varchar_pattern_ops</literal>, and
<literal>bpchar_pattern_ops</literal> support B-tree indexes on
the types <type>text</type>, <type>varchar</type>, and
<type>char</type> respectively. The
difference from the default operator classes