From: Tom Lane Date: Sun, 21 Nov 1999 23:25:47 +0000 (+0000) Subject: Combine index_info and find_secondary_indexes into a single routine that X-Git-Tag: REL7_0~1153 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=610dfa6d5560ebcd72ecca82c64c91503efc9bc5;p=postgresql Combine index_info and find_secondary_indexes into a single routine that 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... --- diff --git a/src/backend/optimizer/util/indexnode.c b/src/backend/optimizer/util/indexnode.c index 4817232f2f..350209690b 100644 --- a/src/backend/optimizer/util/indexnode.c +++ b/src/backend/optimizer/util/indexnode.c @@ -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 - #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; -} diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index ef120f8d2f..b023c5451d 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -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 #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))) diff --git a/src/include/optimizer/plancat.h b/src/include/optimizer/plancat.h index 9a12ecb1d8..34c853d68f 100644 --- a/src/include/optimizer/plancat.h +++ b/src/include/optimizer/plancat.h @@ -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 $ * *------------------------------------------------------------------------- */ @@ -15,32 +15,11 @@ #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,