aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-11-15 16:10:48 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2020-11-15 16:10:48 -0500
commit9cebe49524af365d48f9e63048c79f537d6b135c (patch)
treea960704df20ced28a150036da0d3f7d73aed18ad
parenta87d7801c24ffb3593841838ba0e3d4883d34853 (diff)
downloadpostgresql-9cebe49524af365d48f9e63048c79f537d6b135c.tar.gz
postgresql-9cebe49524af365d48f9e63048c79f537d6b135c.zip
Fix fuzzy thinking about amcanmulticol versus amcaninclude.
These flags should be independent: in particular an index AM should be able to say that it supports include columns without necessarily supporting multiple key columns. The included-columns patch got this wrong, possibly aided by the fact that it didn't bother to update the documentation. While here, clarify some text about amcanreturn, which was a little vague about what should happen when amcanreturn reports that only some of the index columns are returnable. Noted while reviewing the SP-GiST included-columns patch, which quite incorrectly (and unsafely) changed SP-GiST to claim amcanmulticol = true as a workaround for this bug. Backpatch to v11 where included columns were introduced.
-rw-r--r--doc/src/sgml/indexam.sgml35
-rw-r--r--src/backend/commands/indexcmds.c4
2 files changed, 29 insertions, 10 deletions
diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml
index da3d423abd5..843fa1dcf4e 100644
--- a/doc/src/sgml/indexam.sgml
+++ b/doc/src/sgml/indexam.sgml
@@ -181,7 +181,7 @@ typedef struct IndexAmRoutine
implications. The requirements of <structfield>amcanunique</structfield>
are discussed in <xref linkend="index-unique-checks"/>.
The <structfield>amcanmulticol</structfield> flag asserts that the
- access method supports multicolumn indexes, while
+ access method supports multi-key-column indexes, while
<structfield>amoptionalkey</structfield> asserts that it allows scans
where no indexable restriction clause is given for the first index column.
When <structfield>amcanmulticol</structfield> is false,
@@ -217,6 +217,19 @@ typedef struct IndexAmRoutine
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>
+
</sect1>
<sect1 id="index-functions">
@@ -368,10 +381,13 @@ amcanreturn (Relation indexRelation, int attno);
</programlisting>
Check whether the index can support <link
linkend="indexes-index-only-scans"><firstterm>index-only scans</firstterm></link> on
- the given column, by returning the indexed column values for an index entry
- in the form of an <structname>IndexTuple</structname>. The attribute number
- is 1-based, i.e., the first column's attno is 1. Returns true if supported,
- else false. If the access method does not support index-only scans at all,
+ the given column, by returning the column's original indexed value.
+ The attribute number is 1-based, i.e., the first column's attno is 1.
+ Returns true if supported, else false.
+ This function should always return true for included columns
+ (if those are supported), since there's little point in an included
+ column that can't be retrieved.
+ If the access method does not support index-only scans at all,
the <structfield>amcanreturn</structfield> field in its <structname>IndexAmRoutine</structname>
struct can be set to NULL.
</para>
@@ -461,7 +477,7 @@ amproperty (Oid index_oid, int attno,
core code does not know how to do that and will return NULL. It may
also be advantageous to implement <literal>AMPROP_RETURNABLE</literal> testing,
if that can be done more cheaply than by opening the index and calling
- <structfield>amcanreturn</structfield>, which is the core code's default behavior.
+ <function>amcanreturn</function>, which is the core code's default behavior.
The default behavior should be satisfactory for all other standard
properties.
</para>
@@ -553,10 +569,13 @@ amgettuple (IndexScanDesc scan,
<para>
If the index supports <link linkend="indexes-index-only-scans">index-only
- scans</link> (i.e., <function>amcanreturn</function> returns true for it),
+ scans</link> (i.e., <function>amcanreturn</function> returns true for any
+ of its columns),
then on success the AM must also check <literal>scan-&gt;xs_want_itup</literal>,
and if that is true it must return the originally indexed data for the
- index entry. The data can be returned in the form of an
+ index entry. Columns for which <function>amcanreturn</function> returns
+ false can be returned as nulls.
+ The data can be returned in the form of an
<structname>IndexTuple</structname> pointer stored at <literal>scan-&gt;xs_itup</literal>,
with tuple descriptor <literal>scan-&gt;xs_itupdesc</literal>; or in the form of
a <structname>HeapTuple</structname> pointer stored at <literal>scan-&gt;xs_hitup</literal>,
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 3424954594a..7a96fdc1fc4 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -402,7 +402,7 @@ DefineIndex(Oid relationId,
list_copy(stmt->indexIncludingParams));
numberOfAttributes = list_length(allIndexParams);
- if (numberOfAttributes <= 0)
+ if (numberOfKeyAttributes <= 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("must specify at least one column")));
@@ -618,7 +618,7 @@ DefineIndex(Oid relationId,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("access method \"%s\" does not support included columns",
accessMethodName)));
- if (numberOfAttributes > 1 && !amRoutine->amcanmulticol)
+ if (numberOfKeyAttributes > 1 && !amRoutine->amcanmulticol)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("access method \"%s\" does not support multicolumn indexes",