Remove pg_am.amindexnulls.
authorTom Lane
Sat, 8 Jan 2011 21:08:05 +0000 (16:08 -0500)
committerTom Lane
Sat, 8 Jan 2011 21:08:05 +0000 (16:08 -0500)
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
doc/src/sgml/indexam.sgml
src/backend/commands/cluster.c
src/include/catalog/catversion.h
src/include/catalog/pg_am.h

index 67ba3400da2c12a61f79ff87d0bcd7623cc4229b..cd390d8aaaf9df85a0aa66e398729997bbf63ce7 100644 (file)
        for the first index column?
      
 
-     
-      amindexnulls
-      bool
-      
-      Does the access method support null index entries?
-     
-
      
       amsearchnulls
       bool
       Build new index function
      
 
+     
+      ambuildempty
+      regproc
+      pg_proc.oid
+      Build empty index function
+     
+
      
       ambulkdelete
       regproc
index 51e70e9200648c6bacb591308132ceb6fd63c4ee..241064a40fb01d858514a69f25ce241b5addbdc0 100644 (file)
    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
    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.
index 560f42b65e8b67720c8052dba095fe83125ab5f1..19c3cf9674cfe5a76e1b0070fcaa55a600493655 100644 (file)
@@ -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
index 92e1a0fe62c8d83c6e6a3bf9a607deb53fb1bf68..7a03b1c1173f398572e2f24a5e8a1a22a26daf59 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 201101071
+#define CATALOG_VERSION_NO 201101081
 
 #endif
index a0822dbee6ed83abc043b6558af984884f507c88..16fbdd629a90863d27c52869dea93efa2a42f780 100644 (file)
@@ -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 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 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 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 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