]> granicus.if.org Git - postgresql/commitdiff
Combine index_info and find_secondary_indexes into a single routine that
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 21 Nov 1999 23:25:47 +0000 (23:25 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 21 Nov 1999 23:25:47 +0000 (23:25 +0000)
returns a list of RelOptInfos, eliminating the need for static state
in index_info.  That static state was a direct cause of coredumps; if
anything decided to elog(ERROR) partway through an index_info search of
pg_index, the next query would try to close a scan pointer that was
pointing at no-longer-valid memory.  Another example of the reasons to
avoid static state variables...

src/backend/optimizer/util/indexnode.c
src/backend/optimizer/util/plancat.c
src/include/optimizer/plancat.h

index 4817232f2fb2a96de065aac80cd0b2b026f2c1e5..350209690b706dd4ae7fde4b7d4cb75b138293bb 100644 (file)
@@ -7,21 +7,16 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/indexnode.c,v 1.20 1999/08/16 02:17:57 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/indexnode.c,v 1.21 1999/11/21 23:25:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
-#include <sys/types.h>
-
 #include "postgres.h"
 
-
 #include "optimizer/pathnode.h"
 #include "optimizer/plancat.h"
 
 
-static List *find_secondary_index(Query *root, Oid relid);
-
 /*
  * find_relation_indices
  *       Returns a list of index nodes containing appropriate information for
@@ -32,56 +27,7 @@ List *
 find_relation_indices(Query *root, RelOptInfo *rel)
 {
        if (rel->indexed)
-               return find_secondary_index(root, lfirsti(rel->relids));
+               return find_secondary_indexes(root, lfirsti(rel->relids));
        else
                return NIL;
 }
-
-/*
- * find_secondary_index
- *       Creates a list of RelOptInfo nodes containing information for each
- *       secondary index defined on a relation by searching through the index
- *       catalog.
- *
- * 'relid' is the OID of the relation for which indices are being located
- *
- * Returns a list of new index RelOptInfo nodes.
- */
-static List *
-find_secondary_index(Query *root, Oid relid)
-{
-       IdxInfoRetval indexinfo;
-       List       *indexes = NIL;
-       bool            first = true;
-
-       while (index_info(root, first, relid, &indexinfo))
-       {
-               RelOptInfo *indexnode = makeNode(RelOptInfo);
-
-               indexnode->relids = lconsi(indexinfo.relid, NIL);
-               indexnode->relam = indexinfo.relam;
-               indexnode->pages = indexinfo.pages;
-               indexnode->tuples = indexinfo.tuples;
-               indexnode->classlist = indexinfo.classlist;
-               indexnode->indexkeys = indexinfo.indexkeys;
-               indexnode->ordering = indexinfo.orderOprs;
-               indexnode->indproc = indexinfo.indproc;
-               indexnode->indpred = (List *) indexinfo.indpred;
-
-               indexnode->indexed = false;             /* not indexed itself */
-               indexnode->size = 0;
-               indexnode->width = 0;
-               indexnode->targetlist = NIL;
-               indexnode->pathlist = NIL;
-               indexnode->cheapestpath = NULL;
-               indexnode->pruneable = true;
-               indexnode->restrictinfo = NIL;
-               indexnode->joininfo = NIL;
-               indexnode->innerjoin = NIL;
-
-               indexes = lcons(indexnode, indexes);
-               first = false;
-       }
-
-       return indexes;
-}
index ef120f8d2fe513df543ac5203102e955391ac782..b023c5451d0525d35dfb527a4aee81fab5133dd9 100644 (file)
@@ -8,13 +8,14 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.38 1999/09/18 19:07:06 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.39 1999/11/21 23:25:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <math.h>
 
 #include "postgres.h"
+
 #include "access/genam.h"
 #include "access/heapam.h"
 #include "catalog/catname.h"
@@ -38,8 +39,8 @@ static void IndexSelectivity(Oid indexrelid, Oid baserelid, int nIndexKeys,
 
 /*
  * relation_info -
- *       Retrieves catalog information for a given relation. Given the oid of
- *       the relation, return the following information:
+ *       Retrieves catalog information for a given relation.
+ *       Given the rangetable index of the relation, return the following info:
  *                             whether the relation has secondary indices
  *                             number of pages
  *                             number of tuples
@@ -54,166 +55,141 @@ relation_info(Query *root, Index relid,
 
        relationObjectId = getrelid(relid, root->rtable);
        relationTuple = SearchSysCacheTuple(RELOID,
-                                                                         ObjectIdGetDatum(relationObjectId),
+                                                                               ObjectIdGetDatum(relationObjectId),
                                                                                0, 0, 0);
        if (HeapTupleIsValid(relationTuple))
        {
                relation = (Form_pg_class) GETSTRUCT(relationTuple);
 
-               *hasindex = (relation->relhasindex) ? TRUE : FALSE;
+               *hasindex = (relation->relhasindex) ? true : false;
                *pages = relation->relpages;
                *tuples = relation->reltuples;
        }
        else
        {
-               elog(ERROR, "RelationCatalogInformation: Relation %u not found",
+               elog(ERROR, "relation_info: Relation %u not found",
                         relationObjectId);
        }
-
-       return;
 }
 
-
 /*
- * index_info
- *       Retrieves catalog information on an index on a given relation.
+ * find_secondary_indexes
+ *       Creates a list of RelOptInfo nodes containing information for each
+ *       secondary index defined on the given relation.
  *
- *       The index relation is opened on the first invocation. The current
- *       retrieves the next index relation within the catalog that has not
- *       already been retrieved by a previous call.  The index catalog
- *       is closed when no more indices for 'relid' can be found.
- *
- * 'first' is 1 if this is the first call
- *
- * Returns true if successful and false otherwise. Index info is returned
- * via the transient data structure 'info'.
+ * 'relid' is the RT index of the relation for which indices are being located
  *
+ * Returns a list of new index RelOptInfo nodes.
  */
-bool
-index_info(Query *root, bool first, int relid, IdxInfoRetval *info)
+List *
+find_secondary_indexes(Query *root, Index relid)
 {
-       int                     i;
-       HeapTuple       indexTuple,
-                               amopTuple;
-       Form_pg_index index;
-       Relation        indexRelation;
-       uint16          amstrategy;
-       Oid                     relam;
-       Oid                     indrelid;
-
-       static Relation relation = (Relation) NULL;
-       static HeapScanDesc scan = (HeapScanDesc) NULL;
-       static ScanKeyData indexKey;
+       List       *indexes = NIL;
+       Oid                     indrelid = getrelid(relid, root->rtable);
+       Relation        relation;
+       HeapScanDesc scan;
+       ScanKeyData     indexKey;
+       HeapTuple       indexTuple;
 
+       /* Scan pg_index for tuples describing indexes of this rel */
+       relation = heap_openr(IndexRelationName, AccessShareLock);
 
-       /* find the oid of the indexed relation */
-       indrelid = getrelid(relid, root->rtable);
+       ScanKeyEntryInitialize(&indexKey, 0,
+                                                  Anum_pg_index_indrelid,
+                                                  F_OIDEQ,
+                                                  ObjectIdGetDatum(indrelid));
 
-       MemSet(info, 0, sizeof(IdxInfoRetval));
+       scan = heap_beginscan(relation, 0, SnapshotNow,
+                                                 1, &indexKey);
 
-       /*
-        * the maximum number of elements in each of the following arrays is
-        * 8. We allocate one more for a terminating 0 to indicate the end of
-        * the array.
-        */
-       info->indexkeys = (int *) palloc(sizeof(int) * 9);
-       MemSet(info->indexkeys, 0, sizeof(int) * 9);
-       info->orderOprs = (Oid *) palloc(sizeof(Oid) * 9);
-       MemSet(info->orderOprs, 0, sizeof(Oid) * 9);
-       info->classlist = (Oid *) palloc(sizeof(Oid) * 9);
-       MemSet(info->classlist, 0, sizeof(Oid) * 9);
-
-       /* Find an index on the given relation */
-       if (first)
-       {
-               if (HeapScanIsValid(scan))
-                       heap_endscan(scan);
-               scan = (HeapScanDesc) NULL;
-               if (RelationIsValid(relation))
-                       heap_close(relation, AccessShareLock);
-               relation = (Relation) NULL;
-
-               ScanKeyEntryInitialize(&indexKey, 0,
-                                                          Anum_pg_index_indrelid,
-                                                          F_OIDEQ,
-                                                          ObjectIdGetDatum(indrelid));
-
-               relation = heap_openr(IndexRelationName, AccessShareLock);
-               scan = heap_beginscan(relation, 0, SnapshotNow,
-                                                         1, &indexKey);
-       }
-       if (!HeapScanIsValid(scan))
-               elog(ERROR, "index_info: scan not started");
-       indexTuple = heap_getnext(scan, 0);
-       if (!HeapTupleIsValid(indexTuple))
-       {
-               heap_endscan(scan);
-               heap_close(relation, AccessShareLock);
-               scan = (HeapScanDesc) NULL;
-               relation = (Relation) NULL;
-               return 0;
-       }
-
-       /* Extract info from the index tuple */
-       index = (Form_pg_index) GETSTRUCT(indexTuple);
-       info->relid = index->indexrelid;        /* index relation */
-       for (i = 0; i < INDEX_MAX_KEYS; i++)
-               info->indexkeys[i] = index->indkey[i];
-       for (i = 0; i < INDEX_MAX_KEYS; i++)
-               info->classlist[i] = index->indclass[i];
-
-       info->indproc = index->indproc;         /* functional index ?? */
-
-       /* partial index ?? */
-       if (VARSIZE(&index->indpred) != 0)
+       while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
        {
+               Form_pg_index   index = (Form_pg_index) GETSTRUCT(indexTuple);
+               RelOptInfo         *info = makeNode(RelOptInfo);
+               int                             i;
+               Relation                indexRelation;
+               uint16                  amstrategy;
+               Oid                             relam;
 
                /*
-                * The memory allocated here for the predicate (in lispReadString)
-                * only needs to stay around until it's used in find_index_paths,
-                * which is all within a command, so the automatic pfree at end of
-                * transaction should be ok.
+                * Need to make these arrays large enough to be sure there is a
+                * terminating 0 at the end of each one.
                 */
-               char       *predString;
+               info->classlist = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS+1));
+               info->indexkeys = (int *) palloc(sizeof(int) * (INDEX_MAX_KEYS+1));
+               info->ordering = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS+1));
+
+               /* Extract info from the pg_index tuple */
+               info->relids = lconsi(index->indexrelid, NIL);
+               info->indproc = index->indproc;         /* functional index ?? */
+               if (VARSIZE(&index->indpred) != 0)      /* partial index ?? */
+               {
+                       char       *predString = fmgr(F_TEXTOUT, &index->indpred);
+                       info->indpred = (List *) stringToNode(predString);
+                       pfree(predString);
+               }
+               else
+                       info->indpred = NIL;
 
-               predString = fmgr(F_TEXTOUT, &index->indpred);
-               info->indpred = (Node *) stringToNode(predString);
-               pfree(predString);
-       }
+               for (i = 0; i < INDEX_MAX_KEYS; i++)
+                       info->indexkeys[i] = index->indkey[i];
+               info->indexkeys[INDEX_MAX_KEYS] = 0;
+               for (i = 0; i < INDEX_MAX_KEYS; i++)
+                       info->classlist[i] = index->indclass[i];
+               info->classlist[INDEX_MAX_KEYS] = (Oid) 0;
 
-       /* Extract info from the relation descriptor for the index */
-       indexRelation = index_open(index->indexrelid);
+               /* Extract info from the relation descriptor for the index */
+               indexRelation = index_open(index->indexrelid);
 #ifdef notdef
-       /* XXX should iterate through strategies -- but how?  use #1 for now */
-       amstrategy = indexRelation->rd_am->amstrategies;
+               /* XXX should iterate through strategies -- but how?  use #1 for now */
+               amstrategy = indexRelation->rd_am->amstrategies;
 #endif  /* notdef */
-       amstrategy = 1;
-       relam = indexRelation->rd_rel->relam;
-       info->relam = relam;
-       info->pages = indexRelation->rd_rel->relpages;
-       info->tuples = indexRelation->rd_rel->reltuples;
-       index_close(indexRelation);
+               amstrategy = 1;
+               relam = indexRelation->rd_rel->relam;
+               info->relam = relam;
+               info->pages = indexRelation->rd_rel->relpages;
+               info->tuples = indexRelation->rd_rel->reltuples;
+               index_close(indexRelation);
 
-       /*
-        * Find the index ordering keys
-        *
-        * Must use indclass to know when to stop looking since with functional
-        * indices there could be several keys (args) for one opclass. -mer 27
-        * Sept 1991
-        */
-       for (i = 0; i < 8 && index->indclass[i]; ++i)
-       {
-               amopTuple = SearchSysCacheTuple(AMOPSTRATEGY,
+               /*
+                * Fetch the ordering operators associated with the index.
+                *
+                * XXX what if it's a hash or other unordered index?
+                */
+               MemSet(info->ordering, 0, sizeof(Oid) * (INDEX_MAX_KEYS+1));
+               for (i = 0; i < INDEX_MAX_KEYS && index->indclass[i]; i++)
+               {
+                       HeapTuple               amopTuple;
+
+                       amopTuple = SearchSysCacheTuple(AMOPSTRATEGY,
                                                                                ObjectIdGetDatum(relam),
-                                                                       ObjectIdGetDatum(index->indclass[i]),
+                                                                               ObjectIdGetDatum(index->indclass[i]),
                                                                                UInt16GetDatum(amstrategy),
                                                                                0);
-               if (!HeapTupleIsValid(amopTuple))
-                       elog(ERROR, "index_info: no amop %u %u %d",
-                                relam, index->indclass[i], amstrategy);
-               info->orderOprs[i] = ((Form_pg_amop) GETSTRUCT(amopTuple))->amopopr;
+                       if (!HeapTupleIsValid(amopTuple))
+                               elog(ERROR, "find_secondary_indexes: no amop %u %u %d",
+                                        relam, index->indclass[i], amstrategy);
+                       info->ordering[i] = ((Form_pg_amop) GETSTRUCT(amopTuple))->amopopr;
+               }
+
+               info->indexed = false;          /* not indexed itself */
+               info->size = 0;
+               info->width = 0;
+               info->targetlist = NIL;
+               info->pathlist = NIL;
+               info->cheapestpath = NULL;
+               info->pruneable = true;
+               info->restrictinfo = NIL;
+               info->joininfo = NIL;
+               info->innerjoin = NIL;
+
+               indexes = lcons(info, indexes);
        }
-       return TRUE;
+
+       heap_endscan(scan);
+       heap_close(relation, AccessShareLock);
+
+       return indexes;
 }
 
 /*
@@ -370,10 +346,10 @@ join_selectivity(Oid functionObjectId,
 }
 
 /*
- * find_all_inheritors
+ * find_inheritance_children
  *
- * Returns a LISP list containing the OIDs of all relations which
- * inherits from the relation with OID 'inhparent'.
+ * Returns an integer list containing the OIDs of all relations which
+ * inherit *directly* from the relation with OID 'inhparent'.
  */
 List *
 find_inheritance_children(Oid inhparent)
@@ -390,8 +366,8 @@ find_inheritance_children(Oid inhparent)
 
        fmgr_info(F_OIDEQ, &key[0].sk_func);
        key[0].sk_nargs = key[0].sk_func.fn_nargs;
+       key[0].sk_argument = ObjectIdGetDatum(inhparent);
 
-       key[0].sk_argument = ObjectIdGetDatum((Oid) inhparent);
        relation = heap_openr(InheritsRelationName, AccessShareLock);
        scan = heap_beginscan(relation, 0, SnapshotNow, 1, key);
        while (HeapTupleIsValid(inheritsTuple = heap_getnext(scan, 0)))
index 9a12ecb1d8cb1d88a4ed27d09eccff5821d886a1..34c853d68f8b767dd4c35d73fd00b124251e977f 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: plancat.h,v 1.13 1999/07/25 23:07:23 tgl Exp $
+ * $Id: plancat.h,v 1.14 1999/11/21 23:25:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "nodes/parsenodes.h"
 
-/*
- * transient data structure to hold return value of index_info. Note that
- * indexkeys, orderOprs and classlist is "null-terminated".
- */
-typedef struct IdxInfoRetval
-{
-       Oid                     relid;                  /* OID of the index relation (not the OID
-                                                                * of the relation being indexed) */
-       Oid                     relam;                  /* OID of the pg_am of this index */
-       int                     pages;                  /* number of pages in the index relation */
-       int                     tuples;                 /* number of tuples in the index relation */
-       int                *indexkeys;          /* keys over which we're indexing */
-       Oid                *orderOprs;          /* operators used for ordering purposes */
-       Oid                *classlist;          /* classes of AM operators */
-       Oid                     indproc;
-       Node       *indpred;
-} IdxInfoRetval;
-
-
-extern void relation_info(Query *root,
-                         Oid relid,
-                         bool *hashindex, int *pages,
-                         int *tuples);
-
-extern bool index_info(Query *root,
-                  bool first, int relid, IdxInfoRetval *info);
+
+extern void relation_info(Query *root, Index relid,
+                                                 bool *hasindex, int *pages, int *tuples);
+
+extern List *find_secondary_indexes(Query *root, Index relid);
 
 extern Cost restriction_selectivity(Oid functionObjectId,
                                                Oid operatorObjectId,