OSDN Git Service

pgindent run. Make it all clean.
[pg-rex/syncrep.git] / src / backend / commands / indexcmds.c
index efe8a44..2d3e70c 100644 (file)
@@ -3,12 +3,12 @@
  * indexcmds.c
  *       POSTGRES define, extend and remove index code.
  *
- * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.34 2000/07/05 23:11:11 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.46 2001/03/22 03:59:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #include "catalog/catname.h"
 #include "catalog/heap.h"
 #include "catalog/index.h"
+#include "catalog/pg_am.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_index.h"
 static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid);
 static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid);
 static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid);
-static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo,
-                                                 AttrNumber *attNumP, Oid *opOidP, Oid relId,
-                                                 char *accessMethodName, Oid accessMethodId);
-static void NormIndexAttrs(List *attList, AttrNumber *attNumP,
-                                                  Oid *opOidP, Oid relId,
-                                                  char *accessMethodName, Oid accessMethodId);
-static void ProcessAttrTypename(IndexElem *attribute,
-                                       Oid defType, int32 defTypmod);
-static Oid     GetAttrOpClass(IndexElem *attribute, Oid attrType,
-                                                  char *accessMethodName, Oid accessMethodId);
+static void FuncIndexArgs(IndexInfo *indexInfo, Oid *classOidP,
+                         IndexElem *funcIndex,
+                         Oid relId,
+                         char *accessMethodName, Oid accessMethodId);
+static void NormIndexAttrs(IndexInfo *indexInfo, Oid *classOidP,
+                          List *attList,
+                          Oid relId,
+                          char *accessMethodName, Oid accessMethodId);
+static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType,
+                          char *accessMethodName, Oid accessMethodId);
 static char *GetDefaultOpClass(Oid atttypid);
 
 /*
@@ -67,10 +68,7 @@ static char *GetDefaultOpClass(Oid atttypid);
  *             index or a list of attributes to index on.
  * 'parameterList' is a list of DefElem specified in the with clause.
  * 'predicate' is the qual specified in the where clause.
- * 'rangetable' is for the predicate
- *
- * Exceptions:
- *             XXX
+ * 'rangetable' is needed to interpret the predicate
  */
 void
 DefineIndex(char *heapRelationName,
@@ -86,16 +84,14 @@ DefineIndex(char *heapRelationName,
        Oid                *classObjectId;
        Oid                     accessMethodId;
        Oid                     relationId;
+       IndexInfo  *indexInfo;
        int                     numberOfAttributes;
-       AttrNumber *attributeNumberA;
-       HeapTuple       tuple;
-       FuncIndexInfo fInfo;
-       List       *cnfPred = NULL;
+       List       *cnfPred = NIL;
        bool            lossy = false;
        List       *pl;
 
        /*
-        * count attributes
+        * count attributes in index
         */
        numberOfAttributes = length(attributeList);
        if (numberOfAttributes <= 0)
@@ -108,34 +104,29 @@ DefineIndex(char *heapRelationName,
         * compute heap relation id
         */
        if ((relationId = RelnameFindRelid(heapRelationName)) == InvalidOid)
-       {
                elog(ERROR, "DefineIndex: relation \"%s\" not found",
                         heapRelationName);
-       }
-
-       /*
-        * XXX Hardwired hacks to check for limitations on supported index types.
-        * We really ought to be learning this info from entries in the pg_am
-        * table, instead of having it wired in here!
-        */
-       if (unique && strcmp(accessMethodName, "btree") != 0)
-               elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
-
-       if (numberOfAttributes > 1 && strcmp(accessMethodName, "btree") != 0)
-               elog(ERROR, "DefineIndex: multi-column indices are only available with the btree access method");
 
        /*
         * compute access method id
         */
-       tuple = SearchSysCacheTuple(AMNAME,
-                                                               PointerGetDatum(accessMethodName),
-                                                               0, 0, 0);
-       if (!HeapTupleIsValid(tuple))
-       {
+       accessMethodId = GetSysCacheOid(AMNAME,
+                                                                       PointerGetDatum(accessMethodName),
+                                                                       0, 0, 0);
+       if (!OidIsValid(accessMethodId))
                elog(ERROR, "DefineIndex: access method \"%s\" not found",
                         accessMethodName);
-       }
-       accessMethodId = tuple->t_data->t_oid;
+
+       /*
+        * XXX Hardwired hacks to check for limitations on supported index
+        * types. We really ought to be learning this info from entries in the
+        * pg_am table, instead of having it wired in here!
+        */
+       if (unique && accessMethodId != BTREE_AM_OID)
+               elog(ERROR, "DefineIndex: unique indices are only available with the btree access method");
+
+       if (numberOfAttributes > 1 && accessMethodId != BTREE_AM_OID)
+               elog(ERROR, "DefineIndex: multi-column indices are only available with the btree access method");
 
        /*
         * WITH clause reinstated to handle lossy indices. -- JMH, 7/22/96
@@ -145,7 +136,7 @@ DefineIndex(char *heapRelationName,
                DefElem    *param = (DefElem *) lfirst(pl);
 
                if (!strcasecmp(param->defname, "islossy"))
-                       lossy = TRUE;
+                       lossy = true;
                else
                        elog(NOTICE, "Unrecognized index attribute \"%s\" ignored",
                                 param->defname);
@@ -169,146 +160,110 @@ DefineIndex(char *heapRelationName,
        if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false))
                elog(ERROR, "Existing indexes are inactive. REINDEX first");
 
+       /*
+        * Prepare arguments for index_create, primarily an IndexInfo
+        * structure
+        */
+       indexInfo = makeNode(IndexInfo);
+       indexInfo->ii_Predicate = (Node *) cnfPred;
+       indexInfo->ii_FuncOid = InvalidOid;
+       indexInfo->ii_Unique = unique;
+
        if (IsFuncIndex(attributeList))
        {
-               IndexElem  *funcIndex = lfirst(attributeList);
+               IndexElem  *funcIndex = (IndexElem *) lfirst(attributeList);
                int                     nargs;
 
+               /* Parser should have given us only one list item, but check */
+               if (numberOfAttributes != 1)
+                       elog(ERROR, "Functional index can only have one attribute");
+
                nargs = length(funcIndex->args);
                if (nargs > INDEX_MAX_KEYS)
                        elog(ERROR, "Index function can take at most %d arguments",
                                 INDEX_MAX_KEYS);
 
-               FIsetnArgs(&fInfo, nargs);
-
-               namestrcpy(&fInfo.funcName, funcIndex->name);
-
-               attributeNumberA = (AttrNumber *) palloc(nargs *
-                                                                                        sizeof attributeNumberA[0]);
+               indexInfo->ii_NumIndexAttrs = 1;
+               indexInfo->ii_NumKeyAttrs = nargs;
 
                classObjectId = (Oid *) palloc(sizeof(Oid));
 
-               FuncIndexArgs(funcIndex, &fInfo, attributeNumberA,
-                                         classObjectId, relationId,
-                                         accessMethodName, accessMethodId);
-
-               index_create(heapRelationName, indexRelationName,
-                                        &fInfo, NULL,
-                                        accessMethodId, numberOfAttributes, attributeNumberA,
-                                        classObjectId,
-                                        (Node *) cnfPred,
-                                        lossy, unique, primary, allowSystemTableMods);
+               FuncIndexArgs(indexInfo, classObjectId, funcIndex,
+                                         relationId, accessMethodName, accessMethodId);
        }
        else
        {
-               attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
-                                                                                        sizeof attributeNumberA[0]);
+               indexInfo->ii_NumIndexAttrs = numberOfAttributes;
+               indexInfo->ii_NumKeyAttrs = numberOfAttributes;
 
                classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid));
 
-               NormIndexAttrs(attributeList, attributeNumberA,
-                                          classObjectId, relationId,
-                                          accessMethodName, accessMethodId);
-
-               index_create(heapRelationName, indexRelationName,
-                                        NULL, attributeList,
-                                        accessMethodId, numberOfAttributes, attributeNumberA,
-                                        classObjectId,
-                                        (Node *) cnfPred,
-                                        lossy, unique, primary, allowSystemTableMods);
+               NormIndexAttrs(indexInfo, classObjectId, attributeList,
+                                          relationId, accessMethodName, accessMethodId);
        }
 
+       index_create(heapRelationName, indexRelationName,
+                                indexInfo, accessMethodId, classObjectId,
+                                lossy, primary, allowSystemTableMods);
+
        /*
         * We update the relation's pg_class tuple even if it already has
-        * relhasindex = true.  This is needed to cause a shared-cache-inval
+        * relhasindex = true.  This is needed to cause a shared-cache-inval
         * message to be sent for the pg_class tuple, which will cause other
         * backends to flush their relcache entries and in particular their
         * cached lists of the indexes for this relation.
         */
-       setRelhasindexInplace(relationId, true, false);
+       setRelhasindex(relationId, true);
 }
 
 
 /*
  * ExtendIndex
  *             Extends a partial index.
- *
- * Exceptions:
- *             XXX
  */
 void
 ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
 {
-       Oid                *classObjectId;
-       Oid                     accessMethodId;
-       Oid                     indexId,
+       Relation        heapRelation;
+       Relation        indexRelation;
+       Oid                     accessMethodId,
+                               indexId,
                                relationId;
-       Oid                     indproc;
-       int                     numberOfAttributes;
-       AttrNumber *attributeNumberA;
        HeapTuple       tuple;
-       FuncIndexInfo fInfo;
-       FuncIndexInfo *funcInfo = NULL;
-       bool            unique;
        Form_pg_index index;
-       Node       *oldPred = NULL;
-       List       *cnfPred = NULL;
-       PredInfo   *predInfo;
-       Relation        heapRelation;
-       Relation        indexRelation;
-       int                     i;
+       List       *cnfPred = NIL;
+       IndexInfo  *indexInfo;
+       Node       *oldPred;
 
        /*
-        * compute index relation id and access method id
+        * Get index's relation id and access method id from pg_class
         */
-       tuple = SearchSysCacheTuple(RELNAME,
-                                                               PointerGetDatum(indexRelationName),
-                                                               0, 0, 0);
+       tuple = SearchSysCache(RELNAME,
+                                                  PointerGetDatum(indexRelationName),
+                                                  0, 0, 0);
        if (!HeapTupleIsValid(tuple))
-       {
                elog(ERROR, "ExtendIndex: index \"%s\" not found",
                         indexRelationName);
-       }
        indexId = tuple->t_data->t_oid;
        accessMethodId = ((Form_pg_class) GETSTRUCT(tuple))->relam;
+       ReleaseSysCache(tuple);
 
        /*
-        * find pg_index tuple
+        * Extract info from the pg_index tuple for the index
         */
-       tuple = SearchSysCacheTuple(INDEXRELID,
-                                                               ObjectIdGetDatum(indexId),
-                                                               0, 0, 0);
+       tuple = SearchSysCache(INDEXRELID,
+                                                  ObjectIdGetDatum(indexId),
+                                                  0, 0, 0);
        if (!HeapTupleIsValid(tuple))
-       {
                elog(ERROR, "ExtendIndex: relation \"%s\" is not an index",
                         indexRelationName);
-       }
-
-       /*
-        * Extract info from the pg_index tuple
-        */
        index = (Form_pg_index) GETSTRUCT(tuple);
        Assert(index->indexrelid == indexId);
        relationId = index->indrelid;
-       indproc = index->indproc;
-       unique = index->indisunique;
+       indexInfo = BuildIndexInfo(tuple);
+       oldPred = indexInfo->ii_Predicate;
+       ReleaseSysCache(tuple);
 
-       for (i = 0; i < INDEX_MAX_KEYS; i++)
-       {
-               if (index->indkey[i] == InvalidAttrNumber)
-                       break;
-       }
-       numberOfAttributes = i;
-
-       if (VARSIZE(&index->indpred) != 0)
-       {
-               char       *predString;
-
-               predString = DatumGetCString(DirectFunctionCall1(textout,
-                                                                                       PointerGetDatum(&index->indpred)));
-               oldPred = stringToNode(predString);
-               pfree(predString);
-       }
        if (oldPred == NULL)
                elog(ERROR, "ExtendIndex: \"%s\" is not a partial index",
                         indexRelationName);
@@ -316,8 +271,11 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
        /*
         * Convert the extension predicate from parsetree form to plan form,
         * so it can be readily evaluated during index creation. Note:
-        * "predicate" comes in as a list containing (1) the predicate itself
-        * (a where_clause), and (2) a corresponding range table.
+        * "predicate" comes in two parts (1) the predicate expression itself,
+        * and (2) a corresponding range table.
+        *
+        * XXX I think this code is broken --- index_build expects a single
+        * expression not a list --- tgl Jul 00
         */
        if (rangetable != NIL)
        {
@@ -326,47 +284,20 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable)
                CheckPredicate(cnfPred, rangetable, relationId);
        }
 
-       /* make predInfo list to pass to index_build */
-       predInfo = (PredInfo *) palloc(sizeof(PredInfo));
-       predInfo->pred = (Node *) cnfPred;
-       predInfo->oldPred = oldPred;
-
-       attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
-                                                                                        sizeof attributeNumberA[0]);
-       classObjectId = (Oid *) palloc(numberOfAttributes * sizeof classObjectId[0]);
-
-
-       for (i = 0; i < numberOfAttributes; i++)
-       {
-               attributeNumberA[i] = index->indkey[i];
-               classObjectId[i] = index->indclass[i];
-       }
-
-       if (indproc != InvalidOid)
-       {
-               funcInfo = &fInfo;
-               FIsetnArgs(funcInfo, numberOfAttributes);
-
-               tuple = SearchSysCacheTuple(PROCOID,
-                                                                       ObjectIdGetDatum(indproc),
-                                                                       0, 0, 0);
-               if (!HeapTupleIsValid(tuple))
-                       elog(ERROR, "ExtendIndex: index procedure %u not found",
-                                indproc);
-
-               namecpy(&(funcInfo->funcName),
-                               &(((Form_pg_proc) GETSTRUCT(tuple))->proname));
-
-               FIsetProcOid(funcInfo, tuple->t_data->t_oid);
-       }
+       /* pass new predicate to index_build */
+       indexInfo->ii_Predicate = (Node *) cnfPred;
 
+       /* Open heap and index rels, and get suitable locks */
        heapRelation = heap_open(relationId, ShareLock);
        indexRelation = index_open(indexId);
 
-       InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId);
+       /* Obtain exclusive lock on it, just to be sure */
+       LockRelation(indexRelation, AccessExclusiveLock);
+
+       InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
+                                         indexRelation, accessMethodId);
 
-       index_build(heapRelation, indexRelation, numberOfAttributes,
-                               attributeNumberA, funcInfo, predInfo, unique);
+       index_build(heapRelation, indexRelation, indexInfo, oldPred);
 
        /* heap and index rels are closed as a side-effect of index_build */
 }
@@ -431,129 +362,126 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid)
 
 
 static void
-FuncIndexArgs(IndexElem *funcIndex,
-                         FuncIndexInfo *funcInfo,
-                         AttrNumber *attNumP,
-                         Oid *opOidP,
+FuncIndexArgs(IndexInfo *indexInfo,
+                         Oid *classOidP,
+                         IndexElem *funcIndex,
                          Oid relId,
                          char *accessMethodName,
                          Oid accessMethodId)
 {
-       List       *rest;
-       HeapTuple       tuple;
-       Oid                     retType;
-       int                     argn = 0;
+       Oid                     argTypes[FUNC_MAX_ARGS];
+       List       *arglist;
+       int                     nargs = 0;
+       int                     i;
+       Oid                     funcid;
+       Oid                     rettype;
+       bool            retset;
+       Oid                *true_typeids;
 
        /*
         * process the function arguments, which are a list of T_String
         * (someday ought to allow more general expressions?)
+        *
+        * Note caller already checked that list is not too long.
         */
-       MemSet(funcInfo->arglist, 0, FUNC_MAX_ARGS * sizeof(Oid));
+       MemSet(argTypes, 0, sizeof(argTypes));
 
-       foreach(rest, funcIndex->args)
+       foreach(arglist, funcIndex->args)
        {
-               char       *arg = strVal(lfirst(rest));
+               char       *arg = strVal(lfirst(arglist));
+               HeapTuple       tuple;
                Form_pg_attribute att;
 
-               tuple = SearchSysCacheTuple(ATTNAME,
-                                                                       ObjectIdGetDatum(relId),
-                                                                       PointerGetDatum(arg), 0, 0);
-
+               tuple = SearchSysCache(ATTNAME,
+                                                          ObjectIdGetDatum(relId),
+                                                          PointerGetDatum(arg),
+                                                          0, 0);
                if (!HeapTupleIsValid(tuple))
                        elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg);
                att = (Form_pg_attribute) GETSTRUCT(tuple);
-               *attNumP++ = att->attnum;
-               funcInfo->arglist[argn++] = att->atttypid;
+               indexInfo->ii_KeyAttrNumbers[nargs] = att->attnum;
+               argTypes[nargs] = att->atttypid;
+               ReleaseSysCache(tuple);
+               nargs++;
        }
 
        /* ----------------
         * Lookup the function procedure to get its OID and result type.
+        *
+        * We rely on parse_func.c to find the correct function in the
+        * possible presence of binary-compatible types.  However, parse_func
+        * may do too much: it will accept a function that requires run-time
+        * coercion of input types, and the executor is not currently set up
+        * to support that.  So, check to make sure that the selected function
+        * has exact-match or binary-compatible input types.
         * ----------------
         */
-       tuple = SearchSysCacheTuple(PROCNAME,
-                                                               PointerGetDatum(FIgetname(funcInfo)),
-                                                               Int32GetDatum(FIgetnArgs(funcInfo)),
-                                                               PointerGetDatum(FIgetArglist(funcInfo)),
-                                                               0);
+       if (!func_get_detail(funcIndex->name, nargs, argTypes,
+                                                &funcid, &rettype, &retset, &true_typeids))
+               func_error("DefineIndex", funcIndex->name, nargs, argTypes, NULL);
 
-       if (!HeapTupleIsValid(tuple))
+       if (retset)
+               elog(ERROR, "DefineIndex: cannot index on a function returning a set");
+
+       for (i = 0; i < nargs; i++)
        {
-               func_error("DefineIndex", FIgetname(funcInfo),
-                                  FIgetnArgs(funcInfo), FIgetArglist(funcInfo), NULL);
+               if (argTypes[i] != true_typeids[i] &&
+                       !IS_BINARY_COMPATIBLE(argTypes[i], true_typeids[i]))
+                       func_error("DefineIndex", funcIndex->name, nargs, argTypes,
+                                          "Index function must be binary-compatible with table datatype");
        }
 
-       FIsetProcOid(funcInfo, tuple->t_data->t_oid);
-       retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype;
+       /* Process opclass, using func return type as default type */
 
-       /* Process type and opclass, using func return type as default */
+       classOidP[0] = GetAttrOpClass(funcIndex, rettype,
+                                                                 accessMethodName, accessMethodId);
 
-       ProcessAttrTypename(funcIndex, retType, -1);
+       /* OK, return results */
 
-       *opOidP = GetAttrOpClass(funcIndex, retType,
-                                                        accessMethodName, accessMethodId);
+       indexInfo->ii_FuncOid = funcid;
+       /* Need to do the fmgr function lookup now, too */
+       fmgr_info(funcid, &indexInfo->ii_FuncInfo);
 }
 
 static void
-NormIndexAttrs(List *attList,  /* list of IndexElem's */
-                          AttrNumber *attNumP,
+NormIndexAttrs(IndexInfo *indexInfo,
                           Oid *classOidP,
+                          List *attList,       /* list of IndexElem's */
                           Oid relId,
                           char *accessMethodName,
                           Oid accessMethodId)
 {
        List       *rest;
+       int                     attn = 0;
 
        /*
         * process attributeList
         */
        foreach(rest, attList)
        {
-               IndexElem  *attribute = lfirst(rest);
+               IndexElem  *attribute = (IndexElem *) lfirst(rest);
                HeapTuple       atttuple;
                Form_pg_attribute attform;
 
                if (attribute->name == NULL)
                        elog(ERROR, "missing attribute for define index");
 
-               atttuple = SearchSysCacheTupleCopy(ATTNAME,
-                                                                                  ObjectIdGetDatum(relId),
-                                                                               PointerGetDatum(attribute->name),
-                                                                                  0, 0);
+               atttuple = SearchSysCache(ATTNAME,
+                                                                 ObjectIdGetDatum(relId),
+                                                                 PointerGetDatum(attribute->name),
+                                                                 0, 0);
                if (!HeapTupleIsValid(atttuple))
                        elog(ERROR, "DefineIndex: attribute \"%s\" not found",
                                 attribute->name);
                attform = (Form_pg_attribute) GETSTRUCT(atttuple);
 
-               *attNumP++ = attform->attnum;
-
-               ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod);
+               indexInfo->ii_KeyAttrNumbers[attn] = attform->attnum;
 
-               *classOidP++ = GetAttrOpClass(attribute, attform->atttypid,
-                                                                         accessMethodName, accessMethodId);
+               classOidP[attn] = GetAttrOpClass(attribute, attform->atttypid,
+                                                                          accessMethodName, accessMethodId);
 
-               heap_freetuple(atttuple);
-       }
-}
-
-static void
-ProcessAttrTypename(IndexElem *attribute,
-                                       Oid defType, int32 defTypmod)
-{
-       HeapTuple       tuple;
-
-       /* build a type node so we can set the proper alignment, etc. */
-       if (attribute->typename == NULL)
-       {
-               tuple = SearchSysCacheTuple(TYPEOID,
-                                                                       ObjectIdGetDatum(defType),
-                                                                       0, 0, 0);
-               if (!HeapTupleIsValid(tuple))
-                       elog(ERROR, "DefineIndex: type for attribute \"%s\" undefined",
-                                attribute->name);
-
-               attribute->typename = makeNode(TypeName);
-               attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname);
-               attribute->typename->typmod = defTypmod;
+               ReleaseSysCache(atttuple);
+               attn++;
        }
 }
 
@@ -580,17 +508,16 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
                doTypeCheck = false;
        }
 
-       tuple = SearchSysCacheTuple(CLANAME,
-                                                               PointerGetDatum(attribute->class),
-                                                               0, 0, 0);
-       if (!HeapTupleIsValid(tuple))
+       opClassId = GetSysCacheOid(CLANAME,
+                                                          PointerGetDatum(attribute->class),
+                                                          0, 0, 0);
+       if (!OidIsValid(opClassId))
                elog(ERROR, "DefineIndex: opclass \"%s\" not found",
                         attribute->class);
-       opClassId = tuple->t_data->t_oid;
 
        /*
-        * Assume the opclass is supported by this index access method
-        * if we can find at least one relevant entry in pg_amop.
+        * Assume the opclass is supported by this index access method if we
+        * can find at least one relevant entry in pg_amop.
         */
        ScanKeyEntryInitialize(&entry[0], 0,
                                                   Anum_pg_amop_amopid,
@@ -604,11 +531,9 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
        relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
        scan = heap_beginscan(relation, false, SnapshotNow, 2, entry);
 
-       if (! HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
-       {
+       if (!HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
                elog(ERROR, "DefineIndex: opclass \"%s\" not supported by access method \"%s\"",
                         attribute->class, accessMethodName);
-       }
 
        oprId = ((Form_pg_amop) GETSTRUCT(tuple))->amopopr;
 
@@ -616,33 +541,35 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType,
        heap_close(relation, AccessShareLock);
 
        /*
-        * Make sure the operators associated with this opclass actually accept
-        * the column data type.  This prevents possible coredumps caused by
-        * user errors like applying text_ops to an int4 column.  We will accept
-        * an opclass as OK if the operator's input datatype is binary-compatible
-        * with the actual column datatype.  Note we assume that all the operators
-        * associated with an opclass accept the same datatypes, so checking the
-        * first one we happened to find in the table is sufficient.
+        * Make sure the operators associated with this opclass actually
+        * accept the column data type.  This prevents possible coredumps
+        * caused by user errors like applying text_ops to an int4 column.      We
+        * will accept an opclass as OK if the operator's input datatype is
+        * binary-compatible with the actual column datatype.  Note we assume
+        * that all the operators associated with an opclass accept the same
+        * datatypes, so checking the first one we happened to find in the
+        * table is sufficient.
         *
         * If the opclass was the default for the datatype, assume we can skip
-        * this check --- that saves a few cycles in the most common case.
-        * If pg_opclass is messed up then we're probably screwed anyway...
+        * this check --- that saves a few cycles in the most common case. If
+        * pg_opclass is wrong then we're probably screwed anyway...
         */
        if (doTypeCheck)
        {
-               tuple = SearchSysCacheTuple(OPEROID,
-                                                                       ObjectIdGetDatum(oprId),
-                                                                       0, 0, 0);
+               tuple = SearchSysCache(OPEROID,
+                                                          ObjectIdGetDatum(oprId),
+                                                          0, 0, 0);
                if (HeapTupleIsValid(tuple))
                {
                        Form_pg_operator optup = (Form_pg_operator) GETSTRUCT(tuple);
-                       Oid             opInputType = (optup->oprkind == 'l') ?
-                               optup->oprright : optup->oprleft;
+                       Oid                     opInputType = (optup->oprkind == 'l') ?
+                       optup->oprright : optup->oprleft;
 
                        if (attrType != opInputType &&
-                               ! IS_BINARY_COMPATIBLE(attrType, opInputType))
+                               !IS_BINARY_COMPATIBLE(attrType, opInputType))
                                elog(ERROR, "DefineIndex: opclass \"%s\" does not accept datatype \"%s\"",
                                         attribute->class, typeidTypeName(attrType));
+                       ReleaseSysCache(tuple);
                }
        }
 
@@ -653,14 +580,18 @@ static char *
 GetDefaultOpClass(Oid atttypid)
 {
        HeapTuple       tuple;
+       char       *result;
 
-       tuple = SearchSysCacheTuple(CLADEFTYPE,
-                                                               ObjectIdGetDatum(atttypid),
-                                                               0, 0, 0);
+       tuple = SearchSysCache(CLADEFTYPE,
+                                                  ObjectIdGetDatum(atttypid),
+                                                  0, 0, 0);
        if (!HeapTupleIsValid(tuple))
                return NULL;
 
-       return nameout(&((Form_pg_opclass) GETSTRUCT(tuple))->opcname);
+       result = pstrdup(NameStr(((Form_pg_opclass) GETSTRUCT(tuple))->opcname));
+
+       ReleaseSysCache(tuple);
+       return result;
 }
 
 /*
@@ -669,7 +600,7 @@ GetDefaultOpClass(Oid atttypid)
  *
  * Exceptions:
  *             BadArg if name is invalid.
- *             "WARN" if index nonexistent.
+ *             "ERROR" if index nonexistent.
  *             ...
  */
 void
@@ -677,21 +608,19 @@ RemoveIndex(char *name)
 {
        HeapTuple       tuple;
 
-       tuple = SearchSysCacheTuple(RELNAME,
-                                                               PointerGetDatum(name),
-                                                               0, 0, 0);
-
+       tuple = SearchSysCache(RELNAME,
+                                                  PointerGetDatum(name),
+                                                  0, 0, 0);
        if (!HeapTupleIsValid(tuple))
-               elog(ERROR, "index \"%s\" nonexistent", name);
+               elog(ERROR, "index \"%s\" does not exist", name);
 
        if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX)
-       {
                elog(ERROR, "relation \"%s\" is of type \"%c\"",
-                        name,
-                        ((Form_pg_class) GETSTRUCT(tuple))->relkind);
-       }
+                        name, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
 
        index_drop(tuple->t_data->t_oid);
+
+       ReleaseSysCache(tuple);
 }
 
 /*
@@ -706,23 +635,37 @@ void
 ReindexIndex(const char *name, bool force /* currently unused */ )
 {
        HeapTuple       tuple;
+       bool            overwrite = false;
 
-       tuple = SearchSysCacheTuple(RELNAME,
-                                                               PointerGetDatum(name),
-                                                               0, 0, 0);
+       /* ----------------
+        *      REINDEX within a transaction block is dangerous, because
+        *      if the transaction is later rolled back we have no way to
+        *      undo truncation of the index's physical file.  Disallow it.
+        * ----------------
+        */
+       if (IsTransactionBlock())
+               elog(ERROR, "REINDEX cannot run inside a BEGIN/END block");
 
+       tuple = SearchSysCache(RELNAME,
+                                                  PointerGetDatum(name),
+                                                  0, 0, 0);
        if (!HeapTupleIsValid(tuple))
-               elog(ERROR, "index \"%s\" nonexistent", name);
+               elog(ERROR, "index \"%s\" does not exist", name);
 
        if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_INDEX)
-       {
                elog(ERROR, "relation \"%s\" is of type \"%c\"",
-                        name,
-                        ((Form_pg_class) GETSTRUCT(tuple))->relkind);
-       }
-
-       if (!reindex_index(tuple->t_data->t_oid, force))
-               elog(NOTICE, "index '%s' wasn't reindexed", name);
+                        name, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
+
+#ifdef OLD_FILE_NAMING
+       if (!reindex_index(tuple->t_data->t_oid, force, false))
+#else
+       if (IsIgnoringSystemIndexes())
+               overwrite = true;
+       if (!reindex_index(tuple->t_data->t_oid, force, overwrite))
+#endif  /* OLD_FILE_NAMING */
+               elog(NOTICE, "index \"%s\" wasn't reindexed", name);
+
+       ReleaseSysCache(tuple);
 }
 
 /*
@@ -738,22 +681,29 @@ ReindexTable(const char *name, bool force)
 {
        HeapTuple       tuple;
 
-       tuple = SearchSysCacheTuple(RELNAME,
-                                                               PointerGetDatum(name),
-                                                               0, 0, 0);
+       /* ----------------
+        *      REINDEX within a transaction block is dangerous, because
+        *      if the transaction is later rolled back we have no way to
+        *      undo truncation of the index's physical file.  Disallow it.
+        * ----------------
+        */
+       if (IsTransactionBlock())
+               elog(ERROR, "REINDEX cannot run inside a BEGIN/END block");
 
+       tuple = SearchSysCache(RELNAME,
+                                                  PointerGetDatum(name),
+                                                  0, 0, 0);
        if (!HeapTupleIsValid(tuple))
-               elog(ERROR, "table \"%s\" nonexistent", name);
+               elog(ERROR, "table \"%s\" does not exist", name);
 
        if (((Form_pg_class) GETSTRUCT(tuple))->relkind != RELKIND_RELATION)
-       {
                elog(ERROR, "relation \"%s\" is of type \"%c\"",
-                        name,
-                        ((Form_pg_class) GETSTRUCT(tuple))->relkind);
-       }
+                        name, ((Form_pg_class) GETSTRUCT(tuple))->relkind);
 
        if (!reindex_relation(tuple->t_data->t_oid, force))
-               elog(NOTICE, "table '%s' wasn't reindexed", name);
+               elog(NOTICE, "table \"%s\" wasn't reindexed", name);
+
+       ReleaseSysCache(tuple);
 }
 
 /*
@@ -769,15 +719,11 @@ ReindexDatabase(const char *dbname, bool force, bool all)
 {
        Relation        relation,
                                relationRelation;
-       HeapTuple       usertuple,
-                               dbtuple,
+       HeapTuple       dbtuple,
                                tuple;
        HeapScanDesc scan;
-       int4            user_id,
-                               db_owner;
-       bool            superuser;
+       int4            db_owner;
        Oid                     db_id;
-       char       *username;
        ScanKeyData scankey;
        MemoryContext private_context;
        MemoryContext old;
@@ -789,45 +735,37 @@ ReindexDatabase(const char *dbname, bool force, bool all)
 
        AssertArg(dbname);
 
-       username = GetPgUserName();
-       usertuple = SearchSysCacheTuple(SHADOWNAME, PointerGetDatum(username),
-                                                                       0, 0, 0);
-       if (!HeapTupleIsValid(usertuple))
-               elog(ERROR, "Current user \"%s\" is invalid.", username);
-       user_id = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesysid;
-       superuser = ((Form_pg_shadow) GETSTRUCT(usertuple))->usesuper;
-
        relation = heap_openr(DatabaseRelationName, AccessShareLock);
        ScanKeyEntryInitialize(&scankey, 0, Anum_pg_database_datname,
                                                   F_NAMEEQ, NameGetDatum(dbname));
        scan = heap_beginscan(relation, 0, SnapshotNow, 1, &scankey);
        dbtuple = heap_getnext(scan, 0);
        if (!HeapTupleIsValid(dbtuple))
-               elog(ERROR, "Database \"%s\" doesn't exist", dbname);
+               elog(ERROR, "Database \"%s\" does not exist", dbname);
        db_id = dbtuple->t_data->t_oid;
        db_owner = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
        heap_endscan(scan);
        heap_close(relation, NoLock);
 
-       if (user_id != db_owner && !superuser)
+       if (GetUserId() != db_owner && !superuser())
                elog(ERROR, "REINDEX DATABASE: Permission denied.");
 
        if (db_id != MyDatabaseId)
                elog(ERROR, "REINDEX DATABASE: Can be executed only on the currently open database.");
 
        /*
-        * We cannot run inside a user transaction block; if we were
-        * inside a transaction, then our commit- and
-        * start-transaction-command calls would not have the intended effect!
+        * We cannot run inside a user transaction block; if we were inside a
+        * transaction, then our commit- and start-transaction-command calls
+        * would not have the intended effect!
         */
        if (IsTransactionBlock())
                elog(ERROR, "REINDEX DATABASE cannot run inside a BEGIN/END block");
 
        /*
-        * Create a memory context that will survive forced transaction commits
-        * we do below.  Since it is a child of QueryContext, it will go away
-        * eventually even if we suffer an error; there's no need for special
-        * abort cleanup logic.
+        * Create a memory context that will survive forced transaction
+        * commits we do below.  Since it is a child of QueryContext, it will
+        * go away eventually even if we suffer an error; there's no need for
+        * special abort cleanup logic.
         */
        private_context = AllocSetContextCreate(QueryContext,
                                                                                        "ReindexDatabase",
@@ -873,7 +811,7 @@ ReindexDatabase(const char *dbname, bool force, bool all)
        {
                StartTransactionCommand();
                if (reindex_relation(relids[i], force))
-                       elog(NOTICE, "relation %d was reindexed", relids[i]);
+                       elog(NOTICE, "relation %u was reindexed", relids[i]);
                CommitTransactionCommand();
        }
        StartTransactionCommand();