From 7e2f906201c8bb95f7fb17e56b8740c38bda5441 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sat, 8 Jan 2011 16:08:05 -0500 Subject: [PATCH] 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. --- doc/src/sgml/catalogs.sgml | 14 +++++----- doc/src/sgml/indexam.sgml | 12 ++++----- src/backend/commands/cluster.c | 37 ------------------------- src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_am.h | 46 +++++++++++++++----------------- 5 files changed, 35 insertions(+), 76 deletions(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 67ba3400da..cd390d8aaa 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -469,13 +469,6 @@ for the first index column? - - amindexnulls - bool - - Does the access method support null index entries? - - amsearchnulls bool @@ -567,6 +560,13 @@ Build new index function + + ambuildempty + regproc + pg_proc.oid + Build empty index function + + ambulkdelete regproc diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index 51e70e9200..241064a40f 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -105,14 +105,15 @@ where no indexable restriction clause is given for the first index column. When amcanmulticol is false, amoptionalkey 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 must support scans that omit restrictions on any or all of the columns after the first; however they are permitted to require some restriction to appear for the first index column, and this is signaled by setting amoptionalkey false. - amindexnulls asserts that index entries are - created for NULL key values. Since most indexable operators are + One reason that an index AM might set + amoptionalkey false is if it doesn't index + NULLs. Since most indexable operators are strict and hence cannot return TRUE for NULL inputs, 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 @@ -129,10 +130,7 @@ used to scan for rows with a = 4, which is wrong if the index omits rows where b is null. It is, however, OK to omit rows where the first indexed column is null. - Thus, amindexnulls should be set true only if the - index access method indexes all rows, including arbitrary combinations of - null values. An index access method that sets - amindexnulls may also set + An index access method that does index nulls may also set amsearchnulls, indicating that it supports IS NULL and IS NOT NULL clauses as search conditions. diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 560f42b65e..19c3cf9674 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -436,43 +436,6 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck, LOCKMOD errmsg("cannot cluster on partial index \"%s\"", 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; * it might well not contain entries for every heap row, or might not even diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 92e1a0fe62..7a03b1c117 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201101071 +#define CATALOG_VERSION_NO 201101081 #endif diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h index a0822dbee6..16fbdd629a 100644 --- a/src/include/catalog/pg_am.h +++ b/src/include/catalog/pg_am.h @@ -46,7 +46,6 @@ CATALOG(pg_am,2601) bool amcanunique; /* does AM support UNIQUE indexes? */ bool amcanmulticol; /* does AM support multi-column indexes? */ 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 amstorage; /* can storage type differ from column type? */ bool amclusterable; /* does AM support cluster command? */ @@ -88,41 +87,40 @@ typedef FormData_pg_am *Form_pg_am; #define Anum_pg_am_amcanunique 7 #define Anum_pg_am_amcanmulticol 8 #define Anum_pg_am_amoptionalkey 9 -#define Anum_pg_am_amindexnulls 10 -#define Anum_pg_am_amsearchnulls 11 -#define Anum_pg_am_amstorage 12 -#define Anum_pg_am_amclusterable 13 -#define Anum_pg_am_amkeytype 14 -#define Anum_pg_am_aminsert 15 -#define Anum_pg_am_ambeginscan 16 -#define Anum_pg_am_amgettuple 17 -#define Anum_pg_am_amgetbitmap 18 -#define Anum_pg_am_amrescan 19 -#define Anum_pg_am_amendscan 20 -#define Anum_pg_am_ammarkpos 21 -#define Anum_pg_am_amrestrpos 22 -#define Anum_pg_am_ambuild 23 -#define Anum_pg_am_ambuildempty 24 -#define Anum_pg_am_ambulkdelete 25 -#define Anum_pg_am_amvacuumcleanup 26 -#define Anum_pg_am_amcostestimate 27 -#define Anum_pg_am_amoptions 28 +#define Anum_pg_am_amsearchnulls 10 +#define Anum_pg_am_amstorage 11 +#define Anum_pg_am_amclusterable 12 +#define Anum_pg_am_amkeytype 13 +#define Anum_pg_am_aminsert 14 +#define Anum_pg_am_ambeginscan 15 +#define Anum_pg_am_amgettuple 16 +#define Anum_pg_am_amgetbitmap 17 +#define Anum_pg_am_amrescan 18 +#define Anum_pg_am_amendscan 19 +#define Anum_pg_am_ammarkpos 20 +#define Anum_pg_am_amrestrpos 21 +#define Anum_pg_am_ambuild 22 +#define Anum_pg_am_ambuildempty 23 +#define Anum_pg_am_ambulkdelete 24 +#define Anum_pg_am_amvacuumcleanup 25 +#define Anum_pg_am_amcostestimate 26 +#define Anum_pg_am_amoptions 27 /* ---------------- * 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"); #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"); #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"); #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"); #define GIN_AM_OID 2742