*
*
* 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
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;
-}
*
*
* 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"
/*
* 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
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;
}
/*
}
/*
- * 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)
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)))