diff options
Diffstat (limited to 'src/backend/catalog/index.c')
-rw-r--r-- | src/backend/catalog/index.c | 666 |
1 files changed, 289 insertions, 377 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 41d747b0dbf..2cbcb91ac06 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,13 +8,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.125 2000/07/12 02:36:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.126 2000/07/14 22:17:41 tgl Exp $ * * * INTERFACE ROUTINES * index_create() - Create a cataloged index relation * index_drop() - Removes index relation from catalogs - * + * BuildIndexInfo() - Prepare to insert index tuples + * FormIndexDatum() - Construct datum vector for one index tuple * *------------------------------------------------------------------------- */ @@ -58,28 +59,29 @@ /* non-export function prototypes */ static Oid GetHeapRelationOid(char *heapRelationName, char *indexRelationName, bool istemp); -static TupleDesc BuildFuncTupleDesc(FuncIndexInfo *funcInfo); +static TupleDesc BuildFuncTupleDesc(Oid funcOid); static TupleDesc ConstructTupleDescriptor(Oid heapoid, Relation heapRelation, - List *attributeList, int numatts, AttrNumber *attNums); - + int numatts, AttrNumber *attNums); static void ConstructIndexReldesc(Relation indexRelation, Oid amoid); static Oid UpdateRelationRelation(Relation indexRelation, char *temp_relname); static void InitializeAttributeOids(Relation indexRelation, int numatts, Oid indexoid); static void AppendAttributeTuples(Relation indexRelation, int numatts); static void UpdateIndexRelation(Oid indexoid, Oid heapoid, - FuncIndexInfo *funcInfo, int natts, - AttrNumber *attNums, Oid *classOids, Node *predicate, - List *attributeList, bool islossy, bool unique, bool primary); + IndexInfo *indexInfo, + Oid *classOids, + bool islossy, bool primary); static void DefaultBuild(Relation heapRelation, Relation indexRelation, - int numberOfAttributes, AttrNumber *attributeNumber, - FuncIndexInfoPtr funcInfo, PredInfo *predInfo, - bool unique, IndexStrategy indexStrategy); + IndexInfo *indexInfo, Node *oldPred, + IndexStrategy indexStrategy); static Oid IndexGetRelation(Oid indexId); static bool activate_index(Oid indexId, bool activate); + static bool reindexing = false; -extern bool + + +bool SetReindexProcessing(bool reindexmode) { bool old = reindexing; @@ -87,7 +89,8 @@ SetReindexProcessing(bool reindexmode) reindexing = reindexmode; return old; } -extern bool + +bool IsReindexProcessing(void) { return reindexing; @@ -154,14 +157,11 @@ GetHeapRelationOid(char *heapRelationName, char *indexRelationName, bool istemp) } static TupleDesc -BuildFuncTupleDesc(FuncIndexInfo *funcInfo) +BuildFuncTupleDesc(Oid funcOid) { - HeapTuple tuple; TupleDesc funcTupDesc; + HeapTuple tuple; Oid retType; - char *funcname; - int4 nargs; - Oid *argtypes; /* * Allocate and zero a tuple descriptor. @@ -171,30 +171,29 @@ BuildFuncTupleDesc(FuncIndexInfo *funcInfo) MemSet(funcTupDesc->attrs[0], 0, ATTRIBUTE_TUPLE_SIZE); /* - * Lookup the function for the return type. + * Lookup the function to get its name and return type. */ - funcname = FIgetname(funcInfo); - nargs = FIgetnArgs(funcInfo); - argtypes = FIgetArglist(funcInfo); - tuple = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(funcname), - Int32GetDatum(nargs), - PointerGetDatum(argtypes), - 0); - + tuple = SearchSysCacheTuple(PROCOID, + ObjectIdGetDatum(funcOid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) - func_error("BuildFuncTupleDesc", funcname, nargs, argtypes, NULL); - + elog(ERROR, "Function %u does not exist", funcOid); retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype; /* - * Look up the return type in pg_type for the type length. + * make the attributes name the same as the functions + */ + namestrcpy(&funcTupDesc->attrs[0]->attname, + NameStr(((Form_pg_proc) GETSTRUCT(tuple))->proname)); + + /* + * Lookup the return type in pg_type for the type length etc. */ tuple = SearchSysCacheTuple(TYPEOID, ObjectIdGetDatum(retType), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "Function %s return type does not exist", FIgetname(funcInfo)); + elog(ERROR, "Type %u does not exist", retType); /* * Assign some of the attributes values. Leave the rest as 0. @@ -208,57 +207,48 @@ BuildFuncTupleDesc(FuncIndexInfo *funcInfo) funcTupDesc->attrs[0]->attstorage = 'p'; funcTupDesc->attrs[0]->attalign = ((Form_pg_type) GETSTRUCT(tuple))->typalign; - /* - * make the attributes name the same as the functions - */ - namestrcpy(&funcTupDesc->attrs[0]->attname, funcname); - return funcTupDesc; } /* ---------------------------------------------------------------- * ConstructTupleDescriptor + * + * Build an index tuple descriptor for a new index (plain not functional) * ---------------------------------------------------------------- */ static TupleDesc ConstructTupleDescriptor(Oid heapoid, Relation heapRelation, - List *attributeList, int numatts, AttrNumber *attNums) { TupleDesc heapTupDesc; TupleDesc indexTupDesc; - IndexElem *IndexKey; - TypeName *IndexKeyType; - AttrNumber atnum; /* attributeNumber[attributeOffset] */ - AttrNumber atind; - int natts; /* Form_pg_class->relnatts */ - char *from; /* used to simplify memcpy below */ - char *to; /* used to simplify memcpy below */ + int natts; /* #atts in heap rel --- for error checks */ int i; + heapTupDesc = RelationGetDescr(heapRelation); + natts = RelationGetForm(heapRelation)->relnatts; + /* ---------------- * allocate the new tuple descriptor * ---------------- */ - natts = RelationGetForm(heapRelation)->relnatts; indexTupDesc = CreateTemplateTupleDesc(numatts); /* ---------------- - * - * ---------------- - */ - - /* ---------------- * for each attribute we are indexing, obtain its attribute * tuple form from either the static table of system attribute * tuple forms or the relation tuple descriptor * ---------------- */ - for (i = 0; i < numatts; i += 1) + for (i = 0; i < numatts; i++) { + AttrNumber atnum; /* attributeNumber[attributeOffset] */ + AttrNumber atind; + char *from; /* used to simplify memcpy below */ + char *to; /* used to simplify memcpy below */ /* ---------------- * get the attribute number and make sure it's valid @@ -268,16 +258,9 @@ ConstructTupleDescriptor(Oid heapoid, if (atnum > natts) elog(ERROR, "Cannot create index: attribute %d does not exist", atnum); - if (attributeList) - { - IndexKey = (IndexElem *) lfirst(attributeList); - IndexKeyType = IndexKey->typename; - attributeList = lnext(attributeList); - } - else - IndexKeyType = NULL; - indexTupDesc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); + indexTupDesc->attrs[i] = + (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); /* ---------------- * determine which tuple descriptor to copy @@ -285,10 +268,9 @@ ConstructTupleDescriptor(Oid heapoid, */ if (!AttrNumberIsForUserDefinedAttr(atnum)) { - /* ---------------- - * here we are indexing on a system attribute (-1...-12) - * so we convert atnum into a usable index 0...11 so we can + * here we are indexing on a system attribute (-1...-n) + * so we convert atnum into a usable index 0...n-1 so we can * use it to dereference the array sysatts[] which stores * tuple descriptor information for system attributes. * ---------------- @@ -298,7 +280,6 @@ ConstructTupleDescriptor(Oid heapoid, atind = (-atnum) - 1; from = (char *) (&sysatts[atind]); - } else { @@ -306,7 +287,6 @@ ConstructTupleDescriptor(Oid heapoid, * here we are indexing on a normal attribute (1...n) * ---------------- */ - heapTupDesc = RelationGetDescr(heapRelation); atind = AttrNumberGetAttrOffset(atnum); from = (char *) (heapTupDesc->attrs[atind]); @@ -317,43 +297,18 @@ ConstructTupleDescriptor(Oid heapoid, * the tuple desc data... * ---------------- */ - to = (char *) (indexTupDesc->attrs[i]); memcpy(to, from, ATTRIBUTE_TUPLE_SIZE); + /* + * Fix the stuff that should not be the same as the underlying attr + */ ((Form_pg_attribute) to)->attnum = i + 1; + ((Form_pg_attribute) to)->attdisbursion = 0.0; ((Form_pg_attribute) to)->attnotnull = false; ((Form_pg_attribute) to)->atthasdef = false; ((Form_pg_attribute) to)->attcacheoff = -1; - ((Form_pg_attribute) to)->atttypmod = -1; - ((Form_pg_attribute) to)->attalign = 'i'; - - /* - * if the keytype is defined, we need to change the tuple form's - * atttypid & attlen field to match that of the key's type - */ - if (IndexKeyType != NULL) - { - HeapTuple tup; - - tup = SearchSysCacheTuple(TYPENAME, - PointerGetDatum(IndexKeyType->name), - 0, 0, 0); - if (!HeapTupleIsValid(tup)) - elog(ERROR, "create index: type '%s' undefined", - IndexKeyType->name); - ((Form_pg_attribute) to)->atttypid = tup->t_data->t_oid; - ((Form_pg_attribute) to)->attbyval = - ((Form_pg_type) GETSTRUCT(tup))->typbyval; - ((Form_pg_attribute) to)->attlen = - ((Form_pg_type) GETSTRUCT(tup))->typlen; - ((Form_pg_attribute) to)->attstorage = 'p'; - ((Form_pg_attribute) to)->attalign = - ((Form_pg_type) GETSTRUCT(tup))->typalign; - ((Form_pg_attribute) to)->atttypmod = IndexKeyType->typmod; - } - /* ---------------- * now we have to drop in the proper relation descriptor @@ -539,17 +494,14 @@ AppendAttributeTuples(Relation indexRelation, int numatts) new_tuple; bool hasind; Relation idescs[Num_pg_attr_indices]; - Datum value[Natts_pg_attribute]; char nullv[Natts_pg_attribute]; char replace[Natts_pg_attribute]; - TupleDesc indexTupDesc; int i; /* ---------------- * open the attribute relation - * XXX ADD INDEXING * ---------------- */ pg_attribute = heap_openr(AttributeRelationName, RowExclusiveLock); @@ -641,7 +593,6 @@ AppendAttributeTuples(Relation indexRelation, int numatts) heap_close(pg_attribute, RowExclusiveLock); if (hasind) CatalogCloseIndices(Num_pg_attr_indices, idescs); - } /* ---------------------------------------------------------------- @@ -651,18 +602,12 @@ AppendAttributeTuples(Relation indexRelation, int numatts) static void UpdateIndexRelation(Oid indexoid, Oid heapoid, - FuncIndexInfo *funcInfo, - int natts, - AttrNumber *attNums, + IndexInfo *indexInfo, Oid *classOids, - Node *predicate, - List *attributeList, bool islossy, - bool unique, bool primary) { Form_pg_index indexForm; - IndexElem *IndexKey; char *predString; text *predText; int predLen, @@ -673,13 +618,13 @@ UpdateIndexRelation(Oid indexoid, Relation idescs[Num_pg_index_indices]; /* ---------------- - * allocate an Form_pg_index big enough to hold the + * allocate a Form_pg_index big enough to hold the * index-predicate (if any) in string form * ---------------- */ - if (predicate != NULL) + if (indexInfo->ii_Predicate != NULL) { - predString = nodeToString(predicate); + predString = nodeToString(indexInfo->ii_Predicate); predText = DatumGetTextP(DirectFunctionCall1(textin, CStringGetDatum(predString))); pfree(predString); @@ -691,57 +636,33 @@ UpdateIndexRelation(Oid indexoid, predLen = VARSIZE(predText); itupLen = predLen + sizeof(FormData_pg_index); indexForm = (Form_pg_index) palloc(itupLen); - memset(indexForm, 0, sizeof(FormData_pg_index)); - - memmove((char *) &indexForm->indpred, (char *) predText, predLen); + MemSet(indexForm, 0, sizeof(FormData_pg_index)); /* ---------------- - * store the oid information into the index tuple form + * store information into the index tuple form * ---------------- */ - indexForm->indrelid = heapoid; indexForm->indexrelid = indexoid; - indexForm->indproc = (PointerIsValid(funcInfo)) ? - FIgetProcOid(funcInfo) : InvalidOid; + indexForm->indrelid = heapoid; + indexForm->indproc = indexInfo->ii_FuncOid; + indexForm->indisclustered = false; indexForm->indislossy = islossy; + indexForm->indhaskeytype = true; /* not actually used anymore */ + indexForm->indisunique = indexInfo->ii_Unique; indexForm->indisprimary = primary; - indexForm->indisunique = unique; - - indexForm->indhaskeytype = 0; - while (attributeList != NIL) - { - IndexKey = (IndexElem *) lfirst(attributeList); - if (IndexKey->typename != NULL) - { - indexForm->indhaskeytype = 1; - break; - } - attributeList = lnext(attributeList); - } - - MemSet((char *) &indexForm->indkey[0], 0, sizeof indexForm->indkey); - MemSet((char *) &indexForm->indclass[0], 0, sizeof indexForm->indclass); + memcpy((char *) &indexForm->indpred, (char *) predText, predLen); /* ---------------- * copy index key and op class information + * + * We zeroed the extra slots (if any) above --- that's essential. * ---------------- */ - for (i = 0; i < natts; i += 1) - { - indexForm->indkey[i] = attNums[i]; - indexForm->indclass[i] = classOids[i]; - } - - /* - * If we have a functional index, add all attribute arguments - */ - if (PointerIsValid(funcInfo)) - { - for (i = 1; i < FIgetnArgs(funcInfo); i++) - indexForm->indkey[i] = attNums[i]; - } + for (i = 0; i < indexInfo->ii_NumKeyAttrs; i++) + indexForm->indkey[i] = indexInfo->ii_KeyAttrNumbers[i]; - indexForm->indisclustered = '\0'; /* XXX constant */ + for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++) + indexForm->indclass[i] = classOids[i]; /* ---------------- * open the system catalog index relation @@ -759,13 +680,12 @@ UpdateIndexRelation(Oid indexoid, /* ---------------- * insert the tuple into the pg_index - * XXX ADD INDEX TUPLES TOO * ---------------- */ heap_insert(pg_index, tuple); /* ---------------- - * insert the index tuple into the pg_index + * add index tuples for it * ---------------- */ if (!IsIgnoringSystemIndexes()) @@ -774,6 +694,7 @@ UpdateIndexRelation(Oid indexoid, CatalogIndexInsert(idescs, Num_pg_index_indices, pg_index, tuple); CatalogCloseIndices(Num_pg_index_indices, idescs); } + /* ---------------- * close the relation and free the tuple * ---------------- @@ -923,6 +844,7 @@ InitIndexStrategy(int numatts, CommandCounterIncrement(); IndexSupportInitialize(strategy, support, + &indexRelation->rd_uniqueindex, attrelid, accessMethodObjectId, amstrategies, amsupport, numatts); @@ -941,15 +863,10 @@ InitIndexStrategy(int numatts, void index_create(char *heapRelationName, char *indexRelationName, - FuncIndexInfo *funcInfo, - List *attributeList, + IndexInfo *indexInfo, Oid accessMethodObjectId, - int numatts, - AttrNumber *attNums, Oid *classObjectId, - Node *predicate, bool islossy, - bool unique, bool primary, bool allow_system_table_mods) { @@ -958,16 +875,17 @@ index_create(char *heapRelationName, TupleDesc indexTupDesc; Oid heapoid; Oid indexoid; - PredInfo *predInfo; bool istemp = (get_temp_rel_by_username(heapRelationName) != NULL); char *temp_relname = NULL; + SetReindexProcessing(false); + /* ---------------- * check parameters * ---------------- */ - SetReindexProcessing(false); - if (numatts < 1) + if (indexInfo->ii_NumIndexAttrs < 1 || + indexInfo->ii_NumKeyAttrs < 1) elog(ERROR, "must index at least one attribute"); /* ---------------- @@ -985,14 +903,13 @@ index_create(char *heapRelationName, * construct new tuple descriptor * ---------------- */ - if (PointerIsValid(funcInfo)) - indexTupDesc = BuildFuncTupleDesc(funcInfo); + if (OidIsValid(indexInfo->ii_FuncOid)) + indexTupDesc = BuildFuncTupleDesc(indexInfo->ii_FuncOid); else indexTupDesc = ConstructTupleDescriptor(heapoid, heapRelation, - attributeList, - numatts, - attNums); + indexInfo->ii_NumKeyAttrs, + indexInfo->ii_KeyAttrNumbers); if (istemp) { @@ -1035,13 +952,15 @@ index_create(char *heapRelationName, * tuple forms in the index relation's tuple descriptor * ---------------- */ - InitializeAttributeOids(indexRelation, numatts, indexoid); + InitializeAttributeOids(indexRelation, + indexInfo->ii_NumIndexAttrs, + indexoid); /* ---------------- - * append ATTRIBUTE tuples + * append ATTRIBUTE tuples for the index * ---------------- */ - AppendAttributeTuples(indexRelation, numatts); + AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs); /* ---------------- * update pg_index @@ -1051,19 +970,16 @@ index_create(char *heapRelationName, * (Or, could define a rule to maintain the predicate) --Nels, Feb '92 * ---------------- */ - UpdateIndexRelation(indexoid, heapoid, funcInfo, - numatts, attNums, classObjectId, predicate, - attributeList, islossy, unique, primary); - - predInfo = (PredInfo *) palloc(sizeof(PredInfo)); - predInfo->pred = predicate; - predInfo->oldPred = NULL; + UpdateIndexRelation(indexoid, heapoid, indexInfo, + classObjectId, islossy, primary); /* ---------------- * initialize the index strategy * ---------------- */ - InitIndexStrategy(numatts, indexRelation, accessMethodObjectId); + InitIndexStrategy(indexInfo->ii_NumIndexAttrs, + indexRelation, + accessMethodObjectId); /* * If this is bootstrap (initdb) time, then we don't actually fill in @@ -1078,14 +994,12 @@ index_create(char *heapRelationName, */ if (IsBootstrapProcessingMode()) { - index_register(heapRelationName, indexRelationName, numatts, attNums, - funcInfo, predInfo, unique); + index_register(heapRelationName, indexRelationName, indexInfo); /* XXX shouldn't we close the heap and index rels here? */ } else { - index_build(heapRelation, indexRelation, numatts, attNums, - funcInfo, predInfo, unique); + index_build(heapRelation, indexRelation, indexInfo, NULL); } } @@ -1238,43 +1152,163 @@ index_drop(Oid indexId) * index_build support * ---------------------------------------------------------------- */ + +/* ---------------- + * BuildIndexInfo + * Construct an IndexInfo record given the index's pg_index tuple + * + * IndexInfo stores the information about the index that's needed by + * FormIndexDatum, which is used for both index_build() and later insertion + * of individual index tuples. Normally we build an IndexInfo for an index + * just once per command, and then use it for (potentially) many tuples. + * ---------------- + */ +IndexInfo * +BuildIndexInfo(HeapTuple indexTuple) +{ + Form_pg_index indexStruct = (Form_pg_index) GETSTRUCT(indexTuple); + IndexInfo *ii = makeNode(IndexInfo); + int i; + int numKeys; + + /* ---------------- + * count the number of keys, and copy them into the IndexInfo + * ---------------- + */ + numKeys = 0; + for (i = 0; i < INDEX_MAX_KEYS && + indexStruct->indkey[i] != InvalidAttrNumber; i++) + { + ii->ii_KeyAttrNumbers[i] = indexStruct->indkey[i]; + numKeys++; + } + ii->ii_NumKeyAttrs = numKeys; + + /* ---------------- + * Handle functional index. + * + * If we have a functional index then the number of + * attributes defined in the index must be 1 (the function's + * single return value). Otherwise it's same as number of keys. + * ---------------- + */ + ii->ii_FuncOid = indexStruct->indproc; + + if (OidIsValid(indexStruct->indproc)) + { + ii->ii_NumIndexAttrs = 1; + /* Do a lookup on the function, too */ + fmgr_info(indexStruct->indproc, & ii->ii_FuncInfo); + } + else + ii->ii_NumIndexAttrs = numKeys; + + /* ---------------- + * If partial index, convert predicate into expression nodetree + * ---------------- + */ + if (VARSIZE(&indexStruct->indpred) != 0) + { + char *predString; + + predString = DatumGetCString(DirectFunctionCall1(textout, + PointerGetDatum(&indexStruct->indpred))); + ii->ii_Predicate = stringToNode(predString); + pfree(predString); + } + else + ii->ii_Predicate = NULL; + + /* Other info */ + ii->ii_Unique = indexStruct->indisunique; + + return ii; +} + /* ---------------- * FormIndexDatum + * Construct Datum[] and nullv[] arrays for a new index tuple. + * + * indexInfo Info about the index + * heapTuple Heap tuple for which we must prepare an index entry + * heapDescriptor tupledesc for heap tuple + * resultCxt Temporary memory context for any palloc'd datums created + * datum Array of index Datums (output area) + * nullv Array of is-null indicators (output area) + * + * For largely historical reasons, we don't actually call index_formtuple() + * here, we just prepare its input arrays datum[] and nullv[]. * ---------------- */ void -FormIndexDatum(int numberOfAttributes, - AttrNumber *attributeNumber, +FormIndexDatum(IndexInfo *indexInfo, HeapTuple heapTuple, TupleDesc heapDescriptor, + MemoryContext resultCxt, Datum *datum, - char *nullv, - FuncIndexInfoPtr fInfo) + char *nullv) { - AttrNumber i; - int offset; + MemoryContext oldContext; + int i; + Datum iDatum; bool isNull; - /* ---------------- - * for each attribute we need from the heap tuple, - * get the attribute and stick it into the datum and - * null arrays. - * ---------------- - */ + oldContext = MemoryContextSwitchTo(resultCxt); - for (i = 1; i <= numberOfAttributes; i++) + if (OidIsValid(indexInfo->ii_FuncOid)) { - offset = AttrNumberGetAttrOffset(i); + /* ---------------- + * Functional index --- compute the single index attribute + * ---------------- + */ + FunctionCallInfoData fcinfo; + bool anynull = false; - datum[offset] = PointerGetDatum(GetIndexValue(heapTuple, - heapDescriptor, - offset, - attributeNumber, - fInfo, - &isNull)); + MemSet(&fcinfo, 0, sizeof(fcinfo)); + fcinfo.flinfo = &indexInfo->ii_FuncInfo; + fcinfo.nargs = indexInfo->ii_NumKeyAttrs; - nullv[offset] = (isNull) ? 'n' : ' '; + for (i = 0; i < indexInfo->ii_NumKeyAttrs; i++) + { + fcinfo.arg[i] = heap_getattr(heapTuple, + indexInfo->ii_KeyAttrNumbers[i], + heapDescriptor, + &fcinfo.argnull[i]); + anynull |= fcinfo.argnull[i]; + } + if (indexInfo->ii_FuncInfo.fn_strict && anynull) + { + /* force a null result for strict function */ + iDatum = (Datum) 0; + isNull = true; + } + else + { + iDatum = FunctionCallInvoke(&fcinfo); + isNull = fcinfo.isnull; + } + datum[0] = iDatum; + nullv[0] = (isNull) ? 'n' : ' '; + } + else + { + /* ---------------- + * Plain index --- for each attribute we need from the heap tuple, + * get the attribute and stick it into the datum and nullv arrays. + * ---------------- + */ + for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++) + { + iDatum = heap_getattr(heapTuple, + indexInfo->ii_KeyAttrNumbers[i], + heapDescriptor, + &isNull); + datum[i] = iDatum; + nullv[i] = (isNull) ? 'n' : ' '; + } } + + MemoryContextSwitchTo(oldContext); } @@ -1282,9 +1316,9 @@ FormIndexDatum(int numberOfAttributes, * Lock class info for update * -------------------------------------------- */ -static -bool -LockClassinfoForUpdate(Oid relid, HeapTuple rtup, Buffer *buffer, bool confirmCommitted) +static bool +LockClassinfoForUpdate(Oid relid, HeapTuple rtup, + Buffer *buffer, bool confirmCommitted) { HeapTuple classTuple; Form_pg_class pgcform; @@ -1429,7 +1463,7 @@ setRelhasindexInplace(Oid relid, bool hasindex, bool immediate) /* * Confirm that target tuple is locked by this transaction in case of - * immedaite updation. + * immediate updation. */ if (immediate) { @@ -1682,32 +1716,23 @@ UpdateStats(Oid relid, long reltuples, bool inplace) static void DefaultBuild(Relation heapRelation, Relation indexRelation, - int numberOfAttributes, - AttrNumber *attributeNumber, - FuncIndexInfoPtr funcInfo, - PredInfo *predInfo, - bool unique, /* not used */ + IndexInfo *indexInfo, + Node *oldPred, IndexStrategy indexStrategy) /* not used */ { HeapScanDesc scan; HeapTuple heapTuple; - IndexTuple indexTuple; TupleDesc heapDescriptor; - TupleDesc indexDescriptor; - Datum *datum; - char *nullv; + Datum datum[INDEX_MAX_KEYS]; + char nullv[INDEX_MAX_KEYS]; long reltuples, indtuples; - + Node *predicate = indexInfo->ii_Predicate; #ifndef OMIT_PARTIAL_INDEX - ExprContext *econtext; TupleTable tupleTable; TupleTableSlot *slot; - #endif - Node *predicate; - Node *oldPred; - + ExprContext *econtext; InsertIndexResult insertResult; /* ---------------- @@ -1716,48 +1741,33 @@ DefaultBuild(Relation heapRelation, */ Assert(OidIsValid(indexRelation->rd_rel->relam)); /* XXX */ - /* ---------------- - * get the tuple descriptors from the relations so we know - * how to form the index tuples.. - * ---------------- - */ heapDescriptor = RelationGetDescr(heapRelation); - indexDescriptor = RelationGetDescr(indexRelation); - - /* ---------------- - * datum and null are arrays in which we collect the index attributes - * when forming a new index tuple. - * ---------------- - */ - datum = (Datum *) palloc(numberOfAttributes * sizeof *datum); - nullv = (char *) palloc(numberOfAttributes * sizeof *nullv); /* * If this is a predicate (partial) index, we will need to evaluate * the predicate using ExecQual, which requires the current tuple to * be in a slot of a TupleTable. In addition, ExecQual must have an * ExprContext referring to that slot. Here, we initialize dummy - * TupleTable and ExprContext objects for this purpose. --Nels, Feb - * '92 + * TupleTable and ExprContext objects for this purpose. --Nels, Feb 92 + * + * We construct the ExprContext anyway since we need a per-tuple + * temporary memory context for function evaluation -- tgl July 00 */ - - predicate = predInfo->pred; - oldPred = predInfo->oldPred; - #ifndef OMIT_PARTIAL_INDEX if (predicate != NULL || oldPred != NULL) { tupleTable = ExecCreateTupleTable(1); slot = ExecAllocTableSlot(tupleTable); ExecSetSlotDescriptor(slot, heapDescriptor); - econtext = MakeExprContext(slot, TransactionCommandContext); } else { tupleTable = NULL; slot = NULL; - econtext = NULL; } + econtext = MakeExprContext(slot, TransactionCommandContext); +#else + econtext = MakeExprContext(NULL, TransactionCommandContext); #endif /* OMIT_PARTIAL_INDEX */ /* ---------------- @@ -1781,6 +1791,8 @@ DefaultBuild(Relation heapRelation, */ while (HeapTupleIsValid(heapTuple = heap_getnext(scan, 0))) { + MemoryContextReset(econtext->ecxt_per_tuple_memory); + reltuples++; #ifndef OMIT_PARTIAL_INDEX @@ -1790,7 +1802,6 @@ DefaultBuild(Relation heapRelation, */ if (oldPred != NULL) { - /* SetSlotContents(slot, heapTuple); */ slot->val = heapTuple; if (ExecQual((List *) oldPred, econtext, false)) { @@ -1805,7 +1816,6 @@ DefaultBuild(Relation heapRelation, */ if (predicate != NULL) { - /* SetSlotContents(slot, heapTuple); */ slot->val = heapTuple; if (!ExecQual((List *) predicate, econtext, false)) continue; @@ -1819,26 +1829,18 @@ DefaultBuild(Relation heapRelation, * with attribute information taken from the given heap tuple. * ---------------- */ - FormIndexDatum(numberOfAttributes, /* num attributes */ - attributeNumber, /* array of att nums to extract */ - heapTuple, /* tuple from base relation */ - heapDescriptor, /* heap tuple's descriptor */ - datum, /* return: array of attributes */ - nullv, /* return: array of char's */ - funcInfo); - - indexTuple = index_formtuple(indexDescriptor, - datum, - nullv); - - indexTuple->t_tid = heapTuple->t_self; + FormIndexDatum(indexInfo, + heapTuple, + heapDescriptor, + econtext->ecxt_per_tuple_memory, + datum, + nullv); insertResult = index_insert(indexRelation, datum, nullv, &(heapTuple->t_self), heapRelation); if (insertResult) pfree(insertResult); - pfree(indexTuple); } heap_endscan(scan); @@ -1846,14 +1848,10 @@ DefaultBuild(Relation heapRelation, #ifndef OMIT_PARTIAL_INDEX if (predicate != NULL || oldPred != NULL) { - /* parameter was 'false', almost certainly wrong --- tgl 9/21/99 */ ExecDropTupleTable(tupleTable, true); - FreeExprContext(econtext); } #endif /* OMIT_PARTIAL_INDEX */ - - pfree(nullv); - pfree(datum); + FreeExprContext(econtext); /* * Since we just counted the tuples in the heap, we update its stats @@ -1893,11 +1891,8 @@ DefaultBuild(Relation heapRelation, void index_build(Relation heapRelation, Relation indexRelation, - int numberOfAttributes, - AttrNumber *attributeNumber, - FuncIndexInfo *funcInfo, - PredInfo *predInfo, - bool unique) + IndexInfo *indexInfo, + Node *oldPred) { RegProcedure procedure; @@ -1915,23 +1910,17 @@ index_build(Relation heapRelation, * ---------------- */ if (RegProcedureIsValid(procedure)) - OidFunctionCall8(procedure, + OidFunctionCall5(procedure, PointerGetDatum(heapRelation), PointerGetDatum(indexRelation), - Int32GetDatum(numberOfAttributes), - PointerGetDatum(attributeNumber), - PointerGetDatum(funcInfo), - PointerGetDatum(predInfo), - BoolGetDatum(unique), + PointerGetDatum(indexInfo), + PointerGetDatum(oldPred), PointerGetDatum(RelationGetIndexStrategy(indexRelation))); else DefaultBuild(heapRelation, indexRelation, - numberOfAttributes, - attributeNumber, - funcInfo, - predInfo, - unique, + indexInfo, + oldPred, RelationGetIndexStrategy(indexRelation)); } @@ -1959,34 +1948,9 @@ IndexGetRelation(Oid indexId) return index->indrelid; } -/* - * IndexIsUnique: given an index's relation OID, see if it - * is unique using the system cache. - */ -bool -IndexIsUnique(Oid indexId) -{ - HeapTuple tuple; - Form_pg_index index; - - tuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexId), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - { - elog(ERROR, "IndexIsUnique: can't find index id %u", - indexId); - } - index = (Form_pg_index) GETSTRUCT(tuple); - Assert(index->indexrelid == indexId); - - return index->indisunique; -} - - /* --------------------------------- * activate_index -- activate/deactivate the specified index. - * Note that currelntly PostgreSQL doesn't hold the + * Note that currently PostgreSQL doesn't hold the * status per index * --------------------------------- */ @@ -2011,92 +1975,47 @@ reindex_index(Oid indexId, bool force) ScanKeyData entry; HeapScanDesc scan; HeapTuple indexTuple, - procTuple, classTuple; - Form_pg_index index; + IndexInfo *indexInfo; Oid heapId, - procId, accessMethodId; - Node *oldPred = NULL; - PredInfo *predInfo; - AttrNumber *attributeNumberA; - FuncIndexInfo fInfo, - *funcInfo = NULL; - int i, - numberOfAttributes; - bool unique; - char *predString; bool old; old = SetReindexProcessing(true); - /* Scan pg_index to find indexes on heapRelation */ + + /* Scan pg_index to find the index's pg_index entry */ indexRelation = heap_openr(IndexRelationName, AccessShareLock); ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indexrelid, F_OIDEQ, ObjectIdGetDatum(indexId)); scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry); indexTuple = heap_getnext(scan, 0); if (!HeapTupleIsValid(indexTuple)) - elog(ERROR, "reindex_index index %d tuple is invalid", indexId); - - /* - * For the index, fetch index attributes so we can apply index_build - */ - index = (Form_pg_index) GETSTRUCT(indexTuple); - heapId = index->indrelid; - procId = index->indproc; - unique = index->indisunique; - - for (i = 0; i < INDEX_MAX_KEYS; i++) - { - if (index->indkey[i] == InvalidAttrNumber) - break; - } - numberOfAttributes = i; + elog(ERROR, "reindex_index: index %u not found in pg_index", indexId); - /* If a valid where predicate, compute predicate Node */ - if (VARSIZE(&index->indpred) != 0) - { - predString = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(&index->indpred))); - oldPred = stringToNode(predString); - pfree(predString); - } - predInfo = (PredInfo *) palloc(sizeof(PredInfo)); - predInfo->pred = (Node *) oldPred; - predInfo->oldPred = NULL; + /* Get OID of index's parent table */ + heapId = ((Form_pg_index) GETSTRUCT(indexTuple))->indrelid; + /* Fetch info needed for index_build */ + indexInfo = BuildIndexInfo(indexTuple); - /* Assign Index keys to attributes array */ - attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * sizeof(AttrNumber)); - for (i = 0; i < numberOfAttributes; i++) - attributeNumberA[i] = index->indkey[i]; - - /* If this is a procedural index, initialize our FuncIndexInfo */ - if (procId != InvalidOid) - { - funcInfo = &fInfo; - FIsetnArgs(funcInfo, numberOfAttributes); - procTuple = SearchSysCacheTuple(PROCOID, ObjectIdGetDatum(procId), - 0, 0, 0); - if (!HeapTupleIsValid(procTuple)) - elog(ERROR, "RelationTruncateIndexes: index procedure not found"); - namecpy(&(funcInfo->funcName), - &(((Form_pg_proc) GETSTRUCT(procTuple))->proname)); - FIsetProcOid(funcInfo, procTuple->t_data->t_oid); - } + /* Complete the scan and close pg_index */ + heap_endscan(scan); + heap_close(indexRelation, AccessShareLock); /* Fetch the classTuple associated with this index */ - classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId), 0, 0, 0); + classTuple = SearchSysCacheTuple(RELOID, + ObjectIdGetDatum(indexId), + 0, 0, 0); if (!HeapTupleIsValid(classTuple)) - elog(ERROR, "RelationTruncateIndexes: index access method not found"); + elog(ERROR, "reindex_index: index %u not found in pg_class", indexId); accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam; /* Open our index relation */ - iRel = index_open(indexId); - if (iRel == NULL) - elog(ERROR, "reindex_index: can't open index relation"); heapRelation = heap_open(heapId, ExclusiveLock); if (heapRelation == NULL) elog(ERROR, "reindex_index: can't open heap relation"); + iRel = index_open(indexId); + if (iRel == NULL) + elog(ERROR, "reindex_index: can't open index relation"); /* Obtain exclusive lock on it, just to be sure */ LockRelation(iRel, AccessExclusiveLock); @@ -2112,23 +2031,16 @@ reindex_index(Oid indexId, bool force) iRel->rd_nblocks = 0; /* Initialize the index and rebuild */ - InitIndexStrategy(numberOfAttributes, iRel, accessMethodId); - index_build(heapRelation, iRel, numberOfAttributes, - attributeNumberA, funcInfo, predInfo, unique); + InitIndexStrategy(indexInfo->ii_NumIndexAttrs, iRel, accessMethodId); + index_build(heapRelation, iRel, indexInfo, NULL); /* * index_build will close both the heap and index relations (but not - * give up the locks we hold on them). That's fine for the index, but - * we need to open the heap again. We need no new lock, since this - * backend still has the exclusive lock grabbed by heap_truncate. + * give up the locks we hold on them). So we're done. */ - iRel = index_open(indexId); - Assert(iRel != NULL); - /* Complete the scan and close pg_index */ - heap_endscan(scan); - heap_close(indexRelation, AccessShareLock); SetReindexProcessing(old); + return true; } |