From 7e2f906201c8bb95f7fb17e56b8740c38bda5441 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
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 67ba3400da2..cd390d8aaaf 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -469,13 +469,6 @@
        for the first index column?</entry>
      </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>
       <entry><structfield>amsearchnulls</structfield></entry>
       <entry><type>bool</type></entry>
@@ -567,6 +560,13 @@
       <entry><quote>Build new index</quote> function</entry>
      </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>
       <entry><structfield>ambulkdelete</structfield></entry>
       <entry><type>regproc</type></entry>
diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml
index 51e70e92006..241064a40fb 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 <structfield>amcanmulticol</structfield> is false,
    <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</>
    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
    <structfield>amoptionalkey</structfield> false.
-   <structfield>amindexnulls</structfield> asserts that index entries are
-   created for NULL key values.  Since most indexable operators are
+   One reason that an index AM might set
+   <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,
    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 <literal>a = 4</literal>, which is wrong if the
    index omits rows where <literal>b</> 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
-   index access method indexes all rows, including arbitrary combinations of
-   null values.  An index access method that sets
-   <structfield>amindexnulls</structfield> may also set
+   An index access method that does index nulls may also set
    <structfield>amsearchnulls</structfield>, indicating that it supports
    <literal>IS NULL</> and <literal>IS NOT NULL</> clauses as search
    conditions.
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 560f42b65e8..19c3cf9674c 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 92e1a0fe62c..7a03b1c1173 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 a0822dbee6e..16fbdd629a9 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
 
-- 
GitLab