diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-15 16:10:48 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-15 16:10:48 -0500 |
commit | 7c89246d0bb233be7d6670f0a8f024e99423e8cc (patch) | |
tree | 00ddaaebb2baba37d1de8d053425a005a422bd4d | |
parent | 0e0e71abdcaeb8a3887094de078b77cb35bd03ba (diff) | |
download | postgresql-7c89246d0bb233be7d6670f0a8f024e99423e8cc.tar.gz postgresql-7c89246d0bb233be7d6670f0a8f024e99423e8cc.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.sgml | 35 | ||||
-rw-r--r-- | src/backend/commands/indexcmds.c | 4 |
2 files changed, 29 insertions, 10 deletions
diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index 76fa5891b00..2f73b7b5b87 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -196,7 +196,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, @@ -232,6 +232,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"> @@ -383,10 +396,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> @@ -476,7 +492,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> @@ -580,10 +596,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->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->xs_itup</literal>, with tuple descriptor <literal>scan->xs_itupdesc</literal>; or in the form of a <structname>HeapTuple</structname> pointer stored at <literal>scan->xs_hitup</literal>, diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 4d9a19a16a7..69329361fa7 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -584,7 +584,7 @@ DefineIndex(Oid relationId, 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"))); @@ -807,7 +807,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", |