diff options
Diffstat (limited to 'src/backend/executor/execUtils.c')
-rw-r--r-- | src/backend/executor/execUtils.c | 385 |
1 files changed, 85 insertions, 300 deletions
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 852ff5872ce..c1b6e5d79a3 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.59 2000/06/15 04:09:52 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.60 2000/06/17 21:48:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,8 @@ #include "miscadmin.h" #include "utils/builtins.h" #include "utils/fmgroids.h" +#include "utils/relcache.h" +#include "utils/syscache.h" static void ExecGetIndexKeyInfo(Form_pg_index indexTuple, int *numAttsOutP, AttrNumber **attsOutP, FuncIndexInfoPtr fInfoP); @@ -657,7 +659,7 @@ ExecGetIndexKeyInfo(Form_pg_index indexTuple, * check parameters * ---------------- */ - if (numAttsOutP == NULL && attsOutP == NULL) + if (numAttsOutP == NULL || attsOutP == NULL) { elog(DEBUG, "ExecGetIndexKeyInfo: %s", "invalid parameters: numAttsOutP and attsOutP must be non-NULL"); @@ -724,115 +726,112 @@ ExecGetIndexKeyInfo(Form_pg_index indexTuple, /* ---------------------------------------------------------------- * ExecOpenIndices * - * Here we scan the pg_index relation to find indices - * associated with a given heap relation oid. Since we - * don't know in advance how many indices we have, we - * form lists containing the information we need from - * pg_index and then process these lists. + * Find the indices associated with a result relation, open them, + * and save information about them in the result RelationInfo. * - * Note: much of this code duplicates effort done by - * the IndexCatalogInformation function in plancat.c - * because IndexCatalogInformation is poorly written. + * At entry, caller has already opened and locked + * resultRelationInfo->ri_RelationDesc. * - * It would be much better if the functionality provided - * by this function and IndexCatalogInformation was - * in the form of a small set of orthogonal routines.. - * If you are trying to understand this, I suggest you - * look at the code to IndexCatalogInformation and - * FormIndexTuple.. -cim 9/27/89 + * This used to be horribly ugly code, and slow too because it + * did a sequential scan of pg_index. Now we rely on the relcache + * to cache a list of the OIDs of the indices associated with any + * specific relation, and we use the pg_index syscache to get the + * entries we need from pg_index. * ---------------------------------------------------------------- */ void -ExecOpenIndices(Oid resultRelationOid, - RelationInfo *resultRelationInfo) +ExecOpenIndices(RelationInfo *resultRelationInfo) { - Relation indexRd; - HeapScanDesc indexSd; - ScanKeyData key; - HeapTuple tuple; - Form_pg_index indexStruct; - Oid indexOid; - List *oidList; - List *nkeyList; - List *keyList; - List *fiList; - char *predString; - List *predList; - List *indexoid; - List *numkeys; - List *indexkeys; - List *indexfuncs; - List *indexpreds; - int len; - + Relation resultRelation = resultRelationInfo->ri_RelationDesc; + List *indexoidlist, + *indexoidscan; + int len, + i; RelationPtr relationDescs; IndexInfo **indexInfoArray; - FuncIndexInfoPtr fInfoP; - int numKeyAtts; - AttrNumber *indexKeyAtts; - PredInfo *predicate; - int i; resultRelationInfo->ri_NumIndices = 0; - if (!RelationGetForm(resultRelationInfo->ri_RelationDesc)->relhasindex) + + /* checks for disabled indexes */ + if (! RelationGetForm(resultRelation)->relhasindex) return; if (IsIgnoringSystemIndexes() && - IsSystemRelationName(RelationGetRelationName(resultRelationInfo->ri_RelationDesc))) + IsSystemRelationName(RelationGetRelationName(resultRelation))) return; + /* ---------------- - * open pg_index + * Get cached list of index OIDs * ---------------- */ - indexRd = heap_openr(IndexRelationName, AccessShareLock); + indexoidlist = RelationGetIndexList(resultRelation); + len = length(indexoidlist); + if (len == 0) + return; /* ---------------- - * form a scan key + * allocate space for result arrays * ---------------- */ - ScanKeyEntryInitialize(&key, 0, Anum_pg_index_indrelid, - F_OIDEQ, - ObjectIdGetDatum(resultRelationOid)); + relationDescs = (RelationPtr) palloc(len * sizeof(Relation)); + indexInfoArray = (IndexInfo **) palloc(len * sizeof(IndexInfo *)); + + resultRelationInfo->ri_NumIndices = len; + resultRelationInfo->ri_IndexRelationDescs = relationDescs; + resultRelationInfo->ri_IndexRelationInfo = indexInfoArray; /* ---------------- - * scan the index relation, looking for indices for our - * result relation.. + * For each index, open the index relation and save pg_index info. * ---------------- */ - indexSd = heap_beginscan(indexRd, /* scan desc */ - false, /* scan backward flag */ - SnapshotNow, /* NOW snapshot */ - 1, /* number scan keys */ - &key); /* scan keys */ - - oidList = NIL; - nkeyList = NIL; - keyList = NIL; - fiList = NIL; - predList = NIL; - - while (HeapTupleIsValid(tuple = heap_getnext(indexSd, 0))) + i = 0; + foreach(indexoidscan, indexoidlist) { + Oid indexOid = lfirsti(indexoidscan); + Relation indexDesc; + HeapTuple indexTuple; + Form_pg_index indexStruct; + int numKeyAtts; + AttrNumber *indexKeyAtts; + FuncIndexInfoPtr fInfoP; + PredInfo *predicate; + IndexInfo *ii; /* ---------------- - * For each index relation we find, extract the information - * we need and store it in a list.. + * Open (and lock, if necessary) the index relation * - * first get the oid of the index relation from the tuple + * Hack for not btree and hash indices: they use relation + * level exclusive locking on update (i.e. - they are not + * ready for MVCC) and so we have to exclusively lock + * indices here to prevent deadlocks if we will scan them + * - index_beginscan places AccessShareLock, indices + * update methods don't use locks at all. We release this + * lock in ExecCloseIndices. Note, that hashes use page + * level locking - i.e. are not deadlock-free, - let's + * them be on their way -:)) vadim 03-12-1998 * ---------------- */ - indexStruct = (Form_pg_index) GETSTRUCT(tuple); - indexOid = indexStruct->indexrelid; + indexDesc = index_open(indexOid); + + if (indexDesc->rd_rel->relam != BTREE_AM_OID && + indexDesc->rd_rel->relam != HASH_AM_OID) + LockRelation(indexDesc, AccessExclusiveLock); /* ---------------- - * allocate space for functional index information. + * Get the pg_index tuple for the index * ---------------- */ - fInfoP = (FuncIndexInfoPtr) palloc(sizeof(*fInfoP)); + indexTuple = SearchSysCacheTupleCopy(INDEXRELID, + ObjectIdGetDatum(indexOid), + 0, 0, 0); + if (!HeapTupleIsValid(indexTuple)) + elog(ERROR, "ExecOpenIndices: index %u not found", indexOid); + indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); /* ---------------- - * next get the index key information from the tuple + * extract the index key information from the tuple * ---------------- */ + fInfoP = (FuncIndexInfoPtr) palloc(sizeof(*fInfoP)); ExecGetIndexKeyInfo(indexStruct, &numKeyAtts, &indexKeyAtts, @@ -844,6 +843,8 @@ ExecOpenIndices(Oid resultRelationOid, */ if (VARSIZE(&indexStruct->indpred) != 0) { + char *predString; + predString = textout(&indexStruct->indpred); predicate = (PredInfo *) stringToNode(predString); pfree(predString); @@ -851,152 +852,21 @@ ExecOpenIndices(Oid resultRelationOid, else predicate = NULL; - /* ---------------- - * save the index information into lists - * ---------------- - */ - oidList = lconsi(indexOid, oidList); - nkeyList = lconsi(numKeyAtts, nkeyList); - keyList = lcons(indexKeyAtts, keyList); - fiList = lcons(fInfoP, fiList); - predList = lcons(predicate, predList); - } - - /* ---------------- - * we have the info we need so close the pg_index relation.. - * ---------------- - */ - heap_endscan(indexSd); - heap_close(indexRd, AccessShareLock); - - /* ---------------- - * Now that we've collected the index information into three - * lists, we open the index relations and store the descriptors - * and the key information into arrays. - * ---------------- - */ - len = length(oidList); - if (len > 0) - { - /* ---------------- - * allocate space for relation descs - * ---------------- - */ - CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext); - relationDescs = (RelationPtr) - palloc(len * sizeof(Relation)); - - /* ---------------- - * initialize index info array - * ---------------- - */ - CXT1_printf("ExecOpenIndices: context is %d\n", CurrentMemoryContext); - indexInfoArray = (IndexInfo **) - palloc(len * sizeof(IndexInfo *)); - - for (i = 0; i < len; i++) - { - IndexInfo *ii = makeNode(IndexInfo); + /* Save the index info */ + ii = makeNode(IndexInfo); + ii->ii_NumKeyAttributes = numKeyAtts; + ii->ii_KeyAttributeNumbers = indexKeyAtts; + ii->ii_FuncIndexInfo = fInfoP; + ii->ii_Predicate = (Node *) predicate; - ii->ii_NumKeyAttributes = 0; - ii->ii_KeyAttributeNumbers = (AttrNumber *) NULL; - ii->ii_FuncIndexInfo = (FuncIndexInfoPtr) NULL; - ii->ii_Predicate = NULL; - indexInfoArray[i] = ii; - } + heap_freetuple(indexTuple); - /* ---------------- - * attempt to open each of the indices. If we succeed, - * then store the index relation descriptor into the - * relation descriptor array. - * ---------------- - */ - i = 0; - foreach(indexoid, oidList) - { - Relation indexDesc; - - indexOid = lfirsti(indexoid); - indexDesc = index_open(indexOid); - if (indexDesc != NULL) - { - relationDescs[i++] = indexDesc; - - /* - * Hack for not btree and hash indices: they use relation - * level exclusive locking on update (i.e. - they are not - * ready for MVCC) and so we have to exclusively lock - * indices here to prevent deadlocks if we will scan them - * - index_beginscan places AccessShareLock, indices - * update methods don't use locks at all. We release this - * lock in ExecCloseIndices. Note, that hashes use page - * level locking - i.e. are not deadlock-free, - let's - * them be on their way -:)) vadim 03-12-1998 - */ - if (indexDesc->rd_rel->relam != BTREE_AM_OID && - indexDesc->rd_rel->relam != HASH_AM_OID) - LockRelation(indexDesc, AccessExclusiveLock); - } - } - - /* ---------------- - * store the relation descriptor array and number of - * descs into the result relation info. - * ---------------- - */ - resultRelationInfo->ri_NumIndices = i; - resultRelationInfo->ri_IndexRelationDescs = relationDescs; - - /* ---------------- - * store the index key information collected in our - * lists into the index info array - * ---------------- - */ - i = 0; - foreach(numkeys, nkeyList) - { - numKeyAtts = lfirsti(numkeys); - indexInfoArray[i++]->ii_NumKeyAttributes = numKeyAtts; - } - - i = 0; - foreach(indexkeys, keyList) - { - indexKeyAtts = (AttrNumber *) lfirst(indexkeys); - indexInfoArray[i++]->ii_KeyAttributeNumbers = indexKeyAtts; - } - - i = 0; - foreach(indexfuncs, fiList) - { - FuncIndexInfoPtr fiP = (FuncIndexInfoPtr) lfirst(indexfuncs); - - indexInfoArray[i++]->ii_FuncIndexInfo = fiP; - } - - i = 0; - foreach(indexpreds, predList) - indexInfoArray[i++]->ii_Predicate = lfirst(indexpreds); - /* ---------------- - * store the index info array into relation info - * ---------------- - */ - resultRelationInfo->ri_IndexRelationInfo = indexInfoArray; + relationDescs[i] = indexDesc; + indexInfoArray[i] = ii; + i++; } - /* ---------------- - * All done, resultRelationInfo now contains complete information - * on the indices associated with the result relation. - * ---------------- - */ - - /* should free oidList, nkeyList and keyList here */ - /* OK - let's do it -jolly */ - freeList(oidList); - freeList(nkeyList); - freeList(keyList); - freeList(fiList); - freeList(predList); + freeList(indexoidlist); } /* ---------------------------------------------------------------- @@ -1036,91 +906,6 @@ ExecCloseIndices(RelationInfo *resultRelationInfo) } /* ---------------------------------------------------------------- - * ExecFormIndexTuple - * - * Most of this code is cannabilized from DefaultBuild(). - * As said in the comments for ExecOpenIndices, most of - * this functionality should be rearranged into a proper - * set of routines.. - * ---------------------------------------------------------------- - */ -#ifdef NOT_USED -IndexTuple -ExecFormIndexTuple(HeapTuple heapTuple, - Relation heapRelation, - Relation indexRelation, - IndexInfo *indexInfo) -{ - IndexTuple indexTuple; - TupleDesc heapDescriptor; - TupleDesc indexDescriptor; - Datum *datum; - char *nulls; - - int numberOfAttributes; - AttrNumber *keyAttributeNumbers; - FuncIndexInfoPtr fInfoP; - - /* ---------------- - * get information from index info structure - * ---------------- - */ - numberOfAttributes = indexInfo->ii_NumKeyAttributes; - keyAttributeNumbers = indexInfo->ii_KeyAttributeNumbers; - fInfoP = indexInfo->ii_FuncIndexInfo; - - /* ---------------- - * datum and null are arrays in which we collect the index attributes - * when forming a new index tuple. - * ---------------- - */ - CXT1_printf("ExecFormIndexTuple: context is %d\n", CurrentMemoryContext); - datum = (Datum *) palloc(numberOfAttributes * sizeof *datum); - nulls = (char *) palloc(numberOfAttributes * sizeof *nulls); - - /* ---------------- - * get the tuple descriptors from the relations so we know - * how to form the index tuples.. - * ---------------- - */ - heapDescriptor = RelationGetDescr(heapRelation); - indexDescriptor = RelationGetDescr(indexRelation); - - /* ---------------- - * FormIndexDatum fills in its datum and null parameters - * with attribute information taken from the given heap tuple. - * ---------------- - */ - FormIndexDatum(numberOfAttributes, /* num attributes */ - keyAttributeNumbers, /* array of att nums to extract */ - heapTuple, /* tuple from base relation */ - heapDescriptor, /* heap tuple's descriptor */ - datum, /* return: array of attributes */ - nulls, /* return: array of char's */ - fInfoP); /* functional index information */ - - indexTuple = index_formtuple(indexDescriptor, - datum, - nulls); - - /* ---------------- - * free temporary arrays - * - * XXX should store these in the IndexInfo instead of allocating - * and freeing on every insertion, but efficency here is not - * that important and FormIndexTuple is wasteful anyways.. - * -cim 9/27/89 - * ---------------- - */ - pfree(nulls); - pfree(datum); - - return indexTuple; -} - -#endif - -/* ---------------------------------------------------------------- * ExecInsertIndexTuples * * This routine takes care of inserting index tuples |