Commit 7e2f9062 authored by Tom Lane's avatar Tom Lane

Remove pg_am.amindexnulls.

The only use we have had for amindexnulls is in determining whether an
index is safe to cluster on; but since the addition of the amclusterable
flag, that usage is pretty redundant.

In passing, clean up assorted sloppiness from the last patch that touched
pg_am.h: Natts_pg_am was wrong, and ambuildempty was not documented.
parent 56a57473
...@@ -469,13 +469,6 @@ ...@@ -469,13 +469,6 @@
for the first index column?</entry> for the first index column?</entry>
</row> </row>
<row>
<entry><structfield>amindexnulls</structfield></entry>
<entry><type>bool</type></entry>
<entry></entry>
<entry>Does the access method support null index entries?</entry>
</row>
<row> <row>
<entry><structfield>amsearchnulls</structfield></entry> <entry><structfield>amsearchnulls</structfield></entry>
<entry><type>bool</type></entry> <entry><type>bool</type></entry>
...@@ -567,6 +560,13 @@ ...@@ -567,6 +560,13 @@
<entry><quote>Build new index</quote> function</entry> <entry><quote>Build new index</quote> function</entry>
</row> </row>
<row>
<entry><structfield>ambuildempty</structfield></entry>
<entry><type>regproc</type></entry>
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry><quote>Build empty index</quote> function</entry>
</row>
<row> <row>
<entry><structfield>ambulkdelete</structfield></entry> <entry><structfield>ambulkdelete</structfield></entry>
<entry><type>regproc</type></entry> <entry><type>regproc</type></entry>
......
...@@ -105,14 +105,15 @@ ...@@ -105,14 +105,15 @@
where no indexable restriction clause is given for the first index column. where no indexable restriction clause is given for the first index column.
When <structfield>amcanmulticol</structfield> is false, When <structfield>amcanmulticol</structfield> is false,
<structfield>amoptionalkey</structfield> essentially says whether the <structfield>amoptionalkey</structfield> essentially says whether the
access method allows full-index scans without any restriction clause. access method supports full-index scans without any restriction clause.
Access methods that support multiple index columns <emphasis>must</> Access methods that support multiple index columns <emphasis>must</>
support scans that omit restrictions on any or all of the columns after support scans that omit restrictions on any or all of the columns after
the first; however they are permitted to require some restriction to the first; however they are permitted to require some restriction to
appear for the first index column, and this is signaled by setting appear for the first index column, and this is signaled by setting
<structfield>amoptionalkey</structfield> false. <structfield>amoptionalkey</structfield> false.
<structfield>amindexnulls</structfield> asserts that index entries are One reason that an index AM might set
created for NULL key values. Since most indexable operators are <structfield>amoptionalkey</structfield> false is if it doesn't index
NULLs. Since most indexable operators are
strict and hence cannot return TRUE for NULL inputs, strict and hence cannot return TRUE for NULL inputs,
it is at first sight attractive to not store index entries for null values: it is at first sight attractive to not store index entries for null values:
they could never be returned by an index scan anyway. However, this they could never be returned by an index scan anyway. However, this
...@@ -129,10 +130,7 @@ ...@@ -129,10 +130,7 @@
used to scan for rows with <literal>a = 4</literal>, which is wrong if the used to scan for rows with <literal>a = 4</literal>, which is wrong if the
index omits rows where <literal>b</> is null. index omits rows where <literal>b</> is null.
It is, however, OK to omit rows where the first indexed column is null. It is, however, OK to omit rows where the first indexed column is null.
Thus, <structfield>amindexnulls</structfield> should be set true only if the An index access method that does index nulls may also set
index access method indexes all rows, including arbitrary combinations of
null values. An index access method that sets
<structfield>amindexnulls</structfield> may also set
<structfield>amsearchnulls</structfield>, indicating that it supports <structfield>amsearchnulls</structfield>, indicating that it supports
<literal>IS NULL</> and <literal>IS NOT NULL</> clauses as search <literal>IS NULL</> and <literal>IS NOT NULL</> clauses as search
conditions. conditions.
......
...@@ -436,43 +436,6 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck, LOCKMOD ...@@ -436,43 +436,6 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck, LOCKMOD
errmsg("cannot cluster on partial index \"%s\"", errmsg("cannot cluster on partial index \"%s\"",
RelationGetRelationName(OldIndex)))); RelationGetRelationName(OldIndex))));
if (!OldIndex->rd_am->amindexnulls)
{
AttrNumber colno;
/*
* If the AM doesn't index nulls, then it's a partial index unless we
* can prove all the rows are non-null. Note we only need look at the
* first column; multicolumn-capable AMs are *required* to index nulls
* in columns after the first.
*/
colno = OldIndex->rd_index->indkey.values[0];
if (colno > 0)
{
/* ordinary user attribute */
if (!OldHeap->rd_att->attrs[colno - 1]->attnotnull)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot cluster on index \"%s\" because access method does not handle null values",
RelationGetRelationName(OldIndex)),
recheck
? errhint("You might be able to work around this by marking column \"%s\" NOT NULL, or use ALTER TABLE ... SET WITHOUT CLUSTER to remove the cluster specification from the table.",
NameStr(OldHeap->rd_att->attrs[colno - 1]->attname))
: errhint("You might be able to work around this by marking column \"%s\" NOT NULL.",
NameStr(OldHeap->rd_att->attrs[colno - 1]->attname))));
}
else if (colno < 0)
{
/* system column --- okay, always non-null */
}
else
/* index expression, lose... */
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot cluster on expressional index \"%s\" because its index access method does not handle null values",
RelationGetRelationName(OldIndex))));
}
/* /*
* Disallow if index is left over from a failed CREATE INDEX CONCURRENTLY; * Disallow if index is left over from a failed CREATE INDEX CONCURRENTLY;
* it might well not contain entries for every heap row, or might not even * it might well not contain entries for every heap row, or might not even
......
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 201101071 #define CATALOG_VERSION_NO 201101081
#endif #endif
...@@ -46,7 +46,6 @@ CATALOG(pg_am,2601) ...@@ -46,7 +46,6 @@ CATALOG(pg_am,2601)
bool amcanunique; /* does AM support UNIQUE indexes? */ bool amcanunique; /* does AM support UNIQUE indexes? */
bool amcanmulticol; /* does AM support multi-column indexes? */ bool amcanmulticol; /* does AM support multi-column indexes? */
bool amoptionalkey; /* can query omit key for the first column? */ bool amoptionalkey; /* can query omit key for the first column? */
bool amindexnulls; /* does AM support NULL index entries? */
bool amsearchnulls; /* can AM search for NULL/NOT NULL entries? */ bool amsearchnulls; /* can AM search for NULL/NOT NULL entries? */
bool amstorage; /* can storage type differ from column type? */ bool amstorage; /* can storage type differ from column type? */
bool amclusterable; /* does AM support cluster command? */ bool amclusterable; /* does AM support cluster command? */
...@@ -88,41 +87,40 @@ typedef FormData_pg_am *Form_pg_am; ...@@ -88,41 +87,40 @@ typedef FormData_pg_am *Form_pg_am;
#define Anum_pg_am_amcanunique 7 #define Anum_pg_am_amcanunique 7
#define Anum_pg_am_amcanmulticol 8 #define Anum_pg_am_amcanmulticol 8
#define Anum_pg_am_amoptionalkey 9 #define Anum_pg_am_amoptionalkey 9
#define Anum_pg_am_amindexnulls 10 #define Anum_pg_am_amsearchnulls 10
#define Anum_pg_am_amsearchnulls 11 #define Anum_pg_am_amstorage 11
#define Anum_pg_am_amstorage 12 #define Anum_pg_am_amclusterable 12
#define Anum_pg_am_amclusterable 13 #define Anum_pg_am_amkeytype 13
#define Anum_pg_am_amkeytype 14 #define Anum_pg_am_aminsert 14
#define Anum_pg_am_aminsert 15 #define Anum_pg_am_ambeginscan 15
#define Anum_pg_am_ambeginscan 16 #define Anum_pg_am_amgettuple 16
#define Anum_pg_am_amgettuple 17 #define Anum_pg_am_amgetbitmap 17
#define Anum_pg_am_amgetbitmap 18 #define Anum_pg_am_amrescan 18
#define Anum_pg_am_amrescan 19 #define Anum_pg_am_amendscan 19
#define Anum_pg_am_amendscan 20 #define Anum_pg_am_ammarkpos 20
#define Anum_pg_am_ammarkpos 21 #define Anum_pg_am_amrestrpos 21
#define Anum_pg_am_amrestrpos 22 #define Anum_pg_am_ambuild 22
#define Anum_pg_am_ambuild 23 #define Anum_pg_am_ambuildempty 23
#define Anum_pg_am_ambuildempty 24 #define Anum_pg_am_ambulkdelete 24
#define Anum_pg_am_ambulkdelete 25 #define Anum_pg_am_amvacuumcleanup 25
#define Anum_pg_am_amvacuumcleanup 26 #define Anum_pg_am_amcostestimate 26
#define Anum_pg_am_amcostestimate 27 #define Anum_pg_am_amoptions 27
#define Anum_pg_am_amoptions 28
/* ---------------- /* ----------------
* initial contents of pg_am * initial contents of pg_am
* ---------------- * ----------------
*/ */
DATA(insert OID = 403 ( btree 5 1 t f t t t t t t f t 0 btinsert btbeginscan btgettuple btgetbitmap btrescan btendscan btmarkpos btrestrpos btbuild btbuildempty btbulkdelete btvacuumcleanup btcostestimate btoptions )); DATA(insert OID = 403 ( btree 5 1 t f t t t t t f t 0 btinsert btbeginscan btgettuple btgetbitmap btrescan btendscan btmarkpos btrestrpos btbuild btbuildempty btbulkdelete btvacuumcleanup btcostestimate btoptions ));
DESCR("b-tree index access method"); DESCR("b-tree index access method");
#define BTREE_AM_OID 403 #define BTREE_AM_OID 403
DATA(insert OID = 405 ( hash 1 1 f f t f f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbuildempty hashbulkdelete hashvacuumcleanup hashcostestimate hashoptions )); DATA(insert OID = 405 ( hash 1 1 f f t f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbuildempty hashbulkdelete hashvacuumcleanup hashcostestimate hashoptions ));
DESCR("hash index access method"); DESCR("hash index access method");
#define HASH_AM_OID 405 #define HASH_AM_OID 405
DATA(insert OID = 783 ( gist 0 8 f t f f t t t t t t 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup gistcostestimate gistoptions )); DATA(insert OID = 783 ( gist 0 8 f t f f t t t t t 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup gistcostestimate gistoptions ));
DESCR("GiST index access method"); DESCR("GiST index access method");
#define GIST_AM_OID 783 #define GIST_AM_OID 783
DATA(insert OID = 2742 ( gin 0 5 f f f f t t f f t f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbuildempty ginbulkdelete ginvacuumcleanup gincostestimate ginoptions )); DATA(insert OID = 2742 ( gin 0 5 f f f f t t f t f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbuildempty ginbulkdelete ginvacuumcleanup gincostestimate ginoptions ));
DESCR("GIN index access method"); DESCR("GIN index access method");
#define GIN_AM_OID 2742 #define GIN_AM_OID 2742
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment