Prevent clustering on incomplete indexes: partial indexes are verboten,
authorTom Lane
Mon, 3 Mar 2003 04:37:37 +0000 (04:37 +0000)
committerTom Lane
Mon, 3 Mar 2003 04:37:37 +0000 (04:37 +0000)
as are non-amindexnulls AMs unless first column is attnotnull.

src/backend/commands/cluster.c

index 0a0e0afae34aab2a43b8bdfdf8f305d64d065695..30d251869bc553d08823f21952af732e5f412bcc 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.105 2003/02/09 06:56:26 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.106 2003/03/03 04:37:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -160,6 +160,7 @@ cluster(ClusterStmt *stmt)
                     stmt->indexname, stmt->relation->relname);
        }
 
+       /* All other checks are done in cluster_rel() */
        rvtc.tableOid = tableOid;
        rvtc.indexOid = indexOid;
 
@@ -313,6 +314,34 @@ cluster_rel(RelToCluster *rvtc, bool recheck)
             RelationGetRelationName(OldIndex),
             RelationGetRelationName(OldHeap));
 
+   /*
+    * Disallow clustering on incomplete indexes (those that might not index
+    * every row of the relation).  We could relax this by making a separate
+    * seqscan pass over the table to copy the missing rows, but that seems
+    * expensive and tedious.
+    */
+   if (VARSIZE(&OldIndex->rd_index->indpred) > VARHDRSZ) /* partial? */
+       elog(ERROR, "CLUSTER: cannot cluster on partial index");
+   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.
+        */
+       if (OidIsValid(OldIndex->rd_index->indproc))
+           elog(ERROR, "CLUSTER: cannot cluster on functional index when index access method does not handle nulls");
+       colno = OldIndex->rd_index->indkey[0];
+       if (colno > 0)          /* system columns are non-null */
+           if (!OldHeap->rd_att->attrs[colno - 1]->attnotnull)
+               elog(ERROR, "CLUSTER: cannot cluster when index access method does not handle nulls"
+                    "\n\tYou may be able to work around this by marking column \"%s\" NOT NULL",
+                    NameStr(OldHeap->rd_att->attrs[colno - 1]->attname));
+   }
+
    /*
     * Disallow clustering system relations.  This will definitely NOT
     * work for shared relations (we have no way to update pg_class rows