diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/cluster.c | 66 | ||||
-rw-r--r-- | src/backend/commands/command.c | 21 | ||||
-rw-r--r-- | src/backend/commands/copy.c | 241 | ||||
-rw-r--r-- | src/backend/commands/indexcmds.c | 312 | ||||
-rw-r--r-- | src/backend/commands/vacuum.c | 110 |
5 files changed, 242 insertions, 508 deletions
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 38539707cd8..5c176254d66 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.57 2000/07/04 06:11:27 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/cluster.c,v 1.58 2000/07/14 22:17:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -198,35 +198,31 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap) Relation OldIndex, NewHeap; HeapTuple Old_pg_index_Tuple, - Old_pg_index_relation_Tuple, - pg_proc_Tuple; + Old_pg_index_relation_Tuple; Form_pg_index Old_pg_index_Form; Form_pg_class Old_pg_index_relation_Form; - Form_pg_proc pg_proc_Form; + IndexInfo *indexInfo; char *NewIndexName; - AttrNumber *attnumP; - int natts; - FuncIndexInfo *finfo; NewHeap = heap_open(OIDNewHeap, AccessExclusiveLock); OldIndex = index_open(OIDOldIndex); /* * OK. Create a new (temporary) index for the one that's already here. - * To do this I get the info from pg_index, re-build the FunctInfo if - * I have to, and add a new index with a temporary name. + * To do this I get the info from pg_index, and add a new index with + * a temporary name. */ - Old_pg_index_Tuple = SearchSysCacheTuple(INDEXRELID, + Old_pg_index_Tuple = SearchSysCacheTupleCopy(INDEXRELID, ObjectIdGetDatum(RelationGetRelid(OldIndex)), - 0, 0, 0); - + 0, 0, 0); Assert(Old_pg_index_Tuple); Old_pg_index_Form = (Form_pg_index) GETSTRUCT(Old_pg_index_Tuple); - Old_pg_index_relation_Tuple = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(RelationGetRelid(OldIndex)), - 0, 0, 0); + indexInfo = BuildIndexInfo(Old_pg_index_Tuple); + Old_pg_index_relation_Tuple = SearchSysCacheTupleCopy(RELOID, + ObjectIdGetDatum(RelationGetRelid(OldIndex)), + 0, 0, 0); Assert(Old_pg_index_relation_Tuple); Old_pg_index_relation_Form = (Form_pg_class) GETSTRUCT(Old_pg_index_relation_Tuple); @@ -234,50 +230,12 @@ copy_index(Oid OIDOldIndex, Oid OIDNewHeap) NewIndexName = palloc(NAMEDATALEN); /* XXX */ snprintf(NewIndexName, NAMEDATALEN, "temp_%x", OIDOldIndex); - /* - * Ugly as it is, the only way I have of working out the number of - * attribues is to count them. Mostly there'll be just one but I've - * got to be sure. - */ - for (attnumP = &(Old_pg_index_Form->indkey[0]), natts = 0; - natts < INDEX_MAX_KEYS && *attnumP != InvalidAttrNumber; - attnumP++, natts++); - - /* - * If this is a functional index, I need to rebuild the functional - * component to pass it to the defining procedure. - */ - if (Old_pg_index_Form->indproc != InvalidOid) - { - finfo = (FuncIndexInfo *) palloc(sizeof(FuncIndexInfo)); - FIgetnArgs(finfo) = natts; - FIgetProcOid(finfo) = Old_pg_index_Form->indproc; - - pg_proc_Tuple = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(Old_pg_index_Form->indproc), - 0, 0, 0); - - Assert(pg_proc_Tuple); - pg_proc_Form = (Form_pg_proc) GETSTRUCT(pg_proc_Tuple); - namecpy(&(finfo->funcName), &(pg_proc_Form->proname)); - natts = 1; /* function result is a single column */ - } - else - { - finfo = (FuncIndexInfo *) NULL; - } - index_create(RelationGetRelationName(NewHeap), NewIndexName, - finfo, - NULL, /* type info is in the old index */ + indexInfo, Old_pg_index_relation_Form->relam, - natts, - Old_pg_index_Form->indkey, Old_pg_index_Form->indclass, - (Node *) NULL, /* XXX where's the predicate? */ Old_pg_index_Form->indislossy, - Old_pg_index_Form->indisunique, Old_pg_index_Form->indisprimary, allowSystemTableMods); diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c index 6648e66f4e3..be24c696a7c 100644 --- a/src/backend/commands/command.c +++ b/src/backend/commands/command.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.88 2000/07/05 23:11:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.89 2000/07/14 22:17:42 tgl Exp $ * * NOTES * The PerformAddAttribute() code, like most of the relation @@ -1205,7 +1205,7 @@ AlterTableCreateToastTable(const char *relationName, bool silent) char toast_relname[NAMEDATALEN + 1]; char toast_idxname[NAMEDATALEN + 1]; Relation toast_rel; - AttrNumber attNums[1]; + IndexInfo *indexInfo; Oid classObjectId[1]; /* @@ -1334,11 +1334,20 @@ AlterTableCreateToastTable(const char *relationName, bool silent) CommandCounterIncrement(); /* create index on chunk_id */ - attNums[0] = 1; + + indexInfo = makeNode(IndexInfo); + indexInfo->ii_NumIndexAttrs = 1; + indexInfo->ii_NumKeyAttrs = 1; + indexInfo->ii_KeyAttrNumbers[0] = 1; + indexInfo->ii_Predicate = NULL; + indexInfo->ii_FuncOid = InvalidOid; + indexInfo->ii_Unique = false; + classObjectId[0] = OID_OPS_OID; - index_create(toast_relname, toast_idxname, NULL, NULL, BTREE_AM_OID, - 1, attNums, classObjectId, - (Node *) NULL, false, false, false, true); + + index_create(toast_relname, toast_idxname, indexInfo, + BTREE_AM_OID, classObjectId, + false, false, true); /* make the index visible in this transaction */ CommandCounterIncrement(); diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 355b218e640..52100e92dd9 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.118 2000/07/12 02:36:58 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.119 2000/07/14 22:17:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -50,10 +50,6 @@ static Oid GetOutputFunction(Oid type); static Oid GetTypeElement(Oid type); static Oid GetInputFunction(Oid type); static Oid IsTypeByVal(Oid type); -static void GetIndexRelations(Oid main_relation_oid, - int *n_indices, - Relation **index_rels); - static void CopyReadNewline(FILE *fp, int *newline); static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline, char *null_print); @@ -576,53 +572,35 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_p } static void -CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_print) +CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, + char *delim, char *null_print) { HeapTuple tuple; - AttrNumber attr_count; + TupleDesc tupDesc; Form_pg_attribute *attr; + AttrNumber attr_count; FmgrInfo *in_functions; + Oid *elements; + int32 *typmod; int i; Oid in_func_oid; Datum *values; - char *nulls, - *index_nulls; + char *nulls; bool *byval; bool isnull; - bool has_index; int done = 0; char *string = NULL, *ptr; - Relation *index_rels; int32 len, null_ct, null_id; int32 ntuples, tuples_read = 0; bool reading_to_eof = true; - Oid *elements; - int32 *typmod; - FuncIndexInfo *finfo, - **finfoP = NULL; - TupleDesc *itupdescArr; - HeapTuple pgIndexTup; - Form_pg_index *pgIndexP = NULL; - int *indexNatts = NULL; - char *predString; - Node **indexPred = NULL; - TupleDesc rtupdesc; + RelationInfo *relationInfo; EState *estate = makeNode(EState); /* for ExecConstraints() */ -#ifndef OMIT_PARTIAL_INDEX - ExprContext *econtext = NULL; TupleTable tupleTable; - TupleTableSlot *slot = NULL; -#endif - int natts; - AttrNumber *attnumP; - Datum *idatum; - int n_indices; - InsertIndexResult indexRes; - TupleDesc tupDesc; + TupleTableSlot *slot; Oid loaded_oid = InvalidOid; bool skip_tuple = false; @@ -630,71 +608,26 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null attr = tupDesc->attrs; attr_count = tupDesc->natts; - has_index = false; - /* - * This may be a scalar or a functional index. We initialize all - * kinds of arrays here to avoid doing extra work at every tuple copy. + * We need a RelationInfo so we can use the regular executor's + * index-entry-making machinery. (There used to be a huge amount + * of code here that basically duplicated execUtils.c ...) */ + relationInfo = makeNode(RelationInfo); + relationInfo->ri_RangeTableIndex = 1; /* dummy */ + relationInfo->ri_RelationDesc = rel; + relationInfo->ri_NumIndices = 0; + relationInfo->ri_IndexRelationDescs = NULL; + relationInfo->ri_IndexRelationInfo = NULL; - if (rel->rd_rel->relhasindex) - { - GetIndexRelations(RelationGetRelid(rel), &n_indices, &index_rels); - if (n_indices > 0) - { - has_index = true; - itupdescArr = (TupleDesc *) palloc(n_indices * sizeof(TupleDesc)); - pgIndexP = (Form_pg_index *) palloc(n_indices * sizeof(Form_pg_index)); - indexNatts = (int *) palloc(n_indices * sizeof(int)); - finfo = (FuncIndexInfo *) palloc(n_indices * sizeof(FuncIndexInfo)); - finfoP = (FuncIndexInfo **) palloc(n_indices * sizeof(FuncIndexInfo *)); - indexPred = (Node **) palloc(n_indices * sizeof(Node *)); - for (i = 0; i < n_indices; i++) - { - itupdescArr[i] = RelationGetDescr(index_rels[i]); - pgIndexTup = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(RelationGetRelid(index_rels[i])), - 0, 0, 0); - Assert(pgIndexTup); - pgIndexP[i] = (Form_pg_index) GETSTRUCT(pgIndexTup); - for (attnumP = &(pgIndexP[i]->indkey[0]), natts = 0; - natts < INDEX_MAX_KEYS && *attnumP != InvalidAttrNumber; - attnumP++, natts++); - if (pgIndexP[i]->indproc != InvalidOid) - { - FIgetnArgs(&finfo[i]) = natts; - natts = 1; - FIgetProcOid(&finfo[i]) = pgIndexP[i]->indproc; - *(FIgetname(&finfo[i])) = '\0'; - finfoP[i] = &finfo[i]; - } - else - finfoP[i] = (FuncIndexInfo *) NULL; - indexNatts[i] = natts; - if (VARSIZE(&pgIndexP[i]->indpred) != 0) - { - predString = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(&pgIndexP[i]->indpred))); - indexPred[i] = stringToNode(predString); - pfree(predString); -#ifndef OMIT_PARTIAL_INDEX - /* make dummy ExprContext for use by ExecQual */ - if (econtext == NULL) - { - tupleTable = ExecCreateTupleTable(1); - slot = ExecAllocTableSlot(tupleTable); - rtupdesc = RelationGetDescr(rel); - ExecSetSlotDescriptor(slot, rtupdesc); - econtext = MakeExprContext(slot, - TransactionCommandContext); - } -#endif /* OMIT_PARTIAL_INDEX */ - } - else - indexPred[i] = NULL; - } - } - } + ExecOpenIndices(relationInfo); + + estate->es_result_relation_info = relationInfo; + + /* Set up a dummy tuple table too */ + tupleTable = ExecCreateTupleTable(1); + slot = ExecAllocTableSlot(tupleTable); + ExecSetSlotDescriptor(slot, tupDesc); if (!binary) { @@ -723,16 +656,13 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null reading_to_eof = false; } - values = (Datum *) palloc(sizeof(Datum) * attr_count); - nulls = (char *) palloc(attr_count); - index_nulls = (char *) palloc(attr_count); - idatum = (Datum *) palloc(sizeof(Datum) * attr_count); + values = (Datum *) palloc(attr_count * sizeof(Datum)); + nulls = (char *) palloc(attr_count * sizeof(char)); byval = (bool *) palloc(attr_count * sizeof(bool)); for (i = 0; i < attr_count; i++) { nulls[i] = ' '; - index_nulls[i] = ' '; #ifdef _DROP_COLUMN_HACK__ if (COLUMN_IS_DROPPED(attr[i])) { @@ -873,6 +803,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null tuple->t_data->t_oid = loaded_oid; skip_tuple = false; + /* BEFORE ROW INSERT Triggers */ if (rel->trigdesc && rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0) @@ -893,45 +824,25 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null if (!skip_tuple) { /* ---------------- - * Check the constraints of a tuple + * Check the constraints of the tuple * ---------------- */ if (rel->rd_att->constr) ExecConstraints("CopyFrom", rel, tuple, estate); + /* ---------------- + * OK, store the tuple and create index entries for it + * ---------------- + */ heap_insert(rel, tuple); - if (has_index) + if (relationInfo->ri_NumIndices > 0) { - for (i = 0; i < n_indices; i++) - { -#ifndef OMIT_PARTIAL_INDEX - if (indexPred[i] != NULL) - { - /* - * if tuple doesn't satisfy predicate, don't - * update index - */ - slot->val = tuple; - /* SetSlotContents(slot, tuple); */ - if (!ExecQual((List *) indexPred[i], econtext, false)) - continue; - } -#endif /* OMIT_PARTIAL_INDEX */ - FormIndexDatum(indexNatts[i], - (AttrNumber *) &(pgIndexP[i]->indkey[0]), - tuple, - tupDesc, - idatum, - index_nulls, - finfoP[i]); - indexRes = index_insert(index_rels[i], idatum, index_nulls, - &(tuple->t_self), rel); - if (indexRes) - pfree(indexRes); - } + ExecStoreTuple(tuple, slot, InvalidBuffer, false); + ExecInsertIndexTuples(slot, &(tuple->t_self), estate, false); } + /* AFTER ROW INSERT Triggers */ if (rel->trigdesc && rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0) @@ -948,8 +859,8 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null if (!binary) pfree((void *) values[i]); } - else if (nulls[i] == 'n') - nulls[i] = ' '; + /* reset nulls[] array for next time */ + nulls[i] = ' '; } heap_freetuple(tuple); @@ -958,11 +869,14 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null if (!reading_to_eof && ntuples == tuples_read) done = true; } + + /* + * Done, clean up + */ lineno = 0; + pfree(values); pfree(nulls); - pfree(index_nulls); - pfree(idatum); pfree(byval); if (!binary) @@ -972,21 +886,10 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null pfree(typmod); } - if (has_index) - { - for (i = 0; i < n_indices; i++) - { - if (index_rels[i] == NULL) - continue; - /* see comments in ExecOpenIndices() in execUtils.c */ - if ((index_rels[i])->rd_rel->relam != BTREE_AM_OID && - (index_rels[i])->rd_rel->relam != HASH_AM_OID) - UnlockRelation(index_rels[i], AccessExclusiveLock); - index_close(index_rels[i]); - } - } -} + ExecDropTupleTable(tupleTable, true); + ExecCloseIndices(relationInfo); +} static Oid @@ -1054,52 +957,6 @@ IsTypeByVal(Oid type) return InvalidOid; } -/* - * Given the OID of a relation, return an array of index relation descriptors - * and the number of index relations. These relation descriptors are open - * using index_open(). - * - * Space for the array itself is palloc'ed. - */ - -static void -GetIndexRelations(Oid main_relation_oid, - int *n_indices, - Relation **index_rels) -{ - Relation relation; - List *indexoidlist, - *indexoidscan; - int i; - - relation = heap_open(main_relation_oid, AccessShareLock); - indexoidlist = RelationGetIndexList(relation); - - *n_indices = length(indexoidlist); - - if (*n_indices > 0) - *index_rels = (Relation *) palloc(*n_indices * sizeof(Relation)); - else - *index_rels = NULL; - - i = 0; - foreach(indexoidscan, indexoidlist) - { - Oid indexoid = lfirsti(indexoidscan); - Relation index = index_open(indexoid); - - /* see comments in ExecOpenIndices() in execUtils.c */ - if (index != NULL && - index->rd_rel->relam != BTREE_AM_OID && - index->rd_rel->relam != HASH_AM_OID) - LockRelation(index, AccessExclusiveLock); - (*index_rels)[i] = index; - i++; - } - - freeList(indexoidlist); - heap_close(relation, AccessShareLock); -} /* * Reads input from fp until an end of line is seen. diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index efe8a44180a..6ede4f51c12 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.34 2000/07/05 23:11:11 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.35 2000/07/14 22:17:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ #include "catalog/catname.h" #include "catalog/heap.h" #include "catalog/index.h" +#include "catalog/pg_am.h" #include "catalog/pg_amop.h" #include "catalog/pg_database.h" #include "catalog/pg_index.h" @@ -47,14 +48,14 @@ static void CheckPredicate(List *predList, List *rangeTable, Oid baseRelOid); static void CheckPredExpr(Node *predicate, List *rangeTable, Oid baseRelOid); static void CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid); -static void FuncIndexArgs(IndexElem *funcIndex, FuncIndexInfo *funcInfo, - AttrNumber *attNumP, Oid *opOidP, Oid relId, +static void FuncIndexArgs(IndexInfo *indexInfo, Oid *classOidP, + IndexElem *funcIndex, + Oid relId, char *accessMethodName, Oid accessMethodId); -static void NormIndexAttrs(List *attList, AttrNumber *attNumP, - Oid *opOidP, Oid relId, +static void NormIndexAttrs(IndexInfo *indexInfo, Oid *classOidP, + List *attList, + Oid relId, char *accessMethodName, Oid accessMethodId); -static void ProcessAttrTypename(IndexElem *attribute, - Oid defType, int32 defTypmod); static Oid GetAttrOpClass(IndexElem *attribute, Oid attrType, char *accessMethodName, Oid accessMethodId); static char *GetDefaultOpClass(Oid atttypid); @@ -67,10 +68,7 @@ static char *GetDefaultOpClass(Oid atttypid); * index or a list of attributes to index on. * 'parameterList' is a list of DefElem specified in the with clause. * 'predicate' is the qual specified in the where clause. - * 'rangetable' is for the predicate - * - * Exceptions: - * XXX + * 'rangetable' is needed to interpret the predicate */ void DefineIndex(char *heapRelationName, @@ -86,16 +84,15 @@ DefineIndex(char *heapRelationName, Oid *classObjectId; Oid accessMethodId; Oid relationId; + IndexInfo *indexInfo; int numberOfAttributes; - AttrNumber *attributeNumberA; HeapTuple tuple; - FuncIndexInfo fInfo; - List *cnfPred = NULL; + List *cnfPred = NIL; bool lossy = false; List *pl; /* - * count attributes + * count attributes in index */ numberOfAttributes = length(attributeList); if (numberOfAttributes <= 0) @@ -108,21 +105,8 @@ DefineIndex(char *heapRelationName, * compute heap relation id */ if ((relationId = RelnameFindRelid(heapRelationName)) == InvalidOid) - { elog(ERROR, "DefineIndex: relation \"%s\" not found", heapRelationName); - } - - /* - * XXX Hardwired hacks to check for limitations on supported index types. - * We really ought to be learning this info from entries in the pg_am - * table, instead of having it wired in here! - */ - if (unique && strcmp(accessMethodName, "btree") != 0) - elog(ERROR, "DefineIndex: unique indices are only available with the btree access method"); - - if (numberOfAttributes > 1 && strcmp(accessMethodName, "btree") != 0) - elog(ERROR, "DefineIndex: multi-column indices are only available with the btree access method"); /* * compute access method id @@ -131,13 +115,22 @@ DefineIndex(char *heapRelationName, PointerGetDatum(accessMethodName), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - { elog(ERROR, "DefineIndex: access method \"%s\" not found", accessMethodName); - } accessMethodId = tuple->t_data->t_oid; /* + * XXX Hardwired hacks to check for limitations on supported index types. + * We really ought to be learning this info from entries in the pg_am + * table, instead of having it wired in here! + */ + if (unique && accessMethodId != BTREE_AM_OID) + elog(ERROR, "DefineIndex: unique indices are only available with the btree access method"); + + if (numberOfAttributes > 1 && accessMethodId != BTREE_AM_OID) + elog(ERROR, "DefineIndex: multi-column indices are only available with the btree access method"); + + /* * WITH clause reinstated to handle lossy indices. -- JMH, 7/22/96 */ foreach(pl, parameterList) @@ -145,7 +138,7 @@ DefineIndex(char *heapRelationName, DefElem *param = (DefElem *) lfirst(pl); if (!strcasecmp(param->defname, "islossy")) - lossy = TRUE; + lossy = true; else elog(NOTICE, "Unrecognized index attribute \"%s\" ignored", param->defname); @@ -169,55 +162,51 @@ DefineIndex(char *heapRelationName, if (!IsBootstrapProcessingMode() && !IndexesAreActive(relationId, false)) elog(ERROR, "Existing indexes are inactive. REINDEX first"); + /* + * Prepare arguments for index_create, primarily an IndexInfo structure + */ + indexInfo = makeNode(IndexInfo); + indexInfo->ii_Predicate = (Node *) cnfPred; + indexInfo->ii_FuncOid = InvalidOid; + indexInfo->ii_Unique = unique; + if (IsFuncIndex(attributeList)) { - IndexElem *funcIndex = lfirst(attributeList); + IndexElem *funcIndex = (IndexElem *) lfirst(attributeList); int nargs; + /* Parser should have given us only one list item, but check */ + if (numberOfAttributes != 1) + elog(ERROR, "Functional index can only have one attribute"); + nargs = length(funcIndex->args); if (nargs > INDEX_MAX_KEYS) elog(ERROR, "Index function can take at most %d arguments", INDEX_MAX_KEYS); - FIsetnArgs(&fInfo, nargs); - - namestrcpy(&fInfo.funcName, funcIndex->name); - - attributeNumberA = (AttrNumber *) palloc(nargs * - sizeof attributeNumberA[0]); + indexInfo->ii_NumIndexAttrs = 1; + indexInfo->ii_NumKeyAttrs = nargs; classObjectId = (Oid *) palloc(sizeof(Oid)); - FuncIndexArgs(funcIndex, &fInfo, attributeNumberA, - classObjectId, relationId, - accessMethodName, accessMethodId); - - index_create(heapRelationName, indexRelationName, - &fInfo, NULL, - accessMethodId, numberOfAttributes, attributeNumberA, - classObjectId, - (Node *) cnfPred, - lossy, unique, primary, allowSystemTableMods); + FuncIndexArgs(indexInfo, classObjectId, funcIndex, + relationId, accessMethodName, accessMethodId); } else { - attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * - sizeof attributeNumberA[0]); + indexInfo->ii_NumIndexAttrs = numberOfAttributes; + indexInfo->ii_NumKeyAttrs = numberOfAttributes; classObjectId = (Oid *) palloc(numberOfAttributes * sizeof(Oid)); - NormIndexAttrs(attributeList, attributeNumberA, - classObjectId, relationId, - accessMethodName, accessMethodId); - - index_create(heapRelationName, indexRelationName, - NULL, attributeList, - accessMethodId, numberOfAttributes, attributeNumberA, - classObjectId, - (Node *) cnfPred, - lossy, unique, primary, allowSystemTableMods); + NormIndexAttrs(indexInfo, classObjectId, attributeList, + relationId, accessMethodName, accessMethodId); } + index_create(heapRelationName, indexRelationName, + indexInfo, accessMethodId, classObjectId, + lossy, primary, allowSystemTableMods); + /* * We update the relation's pg_class tuple even if it already has * relhasindex = true. This is needed to cause a shared-cache-inval @@ -232,83 +221,48 @@ DefineIndex(char *heapRelationName, /* * ExtendIndex * Extends a partial index. - * - * Exceptions: - * XXX */ void ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) { - Oid *classObjectId; - Oid accessMethodId; - Oid indexId, + Relation heapRelation; + Relation indexRelation; + Oid accessMethodId, + indexId, relationId; - Oid indproc; - int numberOfAttributes; - AttrNumber *attributeNumberA; HeapTuple tuple; - FuncIndexInfo fInfo; - FuncIndexInfo *funcInfo = NULL; - bool unique; Form_pg_index index; - Node *oldPred = NULL; - List *cnfPred = NULL; - PredInfo *predInfo; - Relation heapRelation; - Relation indexRelation; - int i; + List *cnfPred = NIL; + IndexInfo *indexInfo; + Node *oldPred; /* - * compute index relation id and access method id + * Get index's relation id and access method id from pg_class */ tuple = SearchSysCacheTuple(RELNAME, PointerGetDatum(indexRelationName), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - { elog(ERROR, "ExtendIndex: index \"%s\" not found", indexRelationName); - } indexId = tuple->t_data->t_oid; accessMethodId = ((Form_pg_class) GETSTRUCT(tuple))->relam; /* - * find pg_index tuple + * Extract info from the pg_index tuple for the index */ tuple = SearchSysCacheTuple(INDEXRELID, ObjectIdGetDatum(indexId), 0, 0, 0); if (!HeapTupleIsValid(tuple)) - { elog(ERROR, "ExtendIndex: relation \"%s\" is not an index", indexRelationName); - } - - /* - * Extract info from the pg_index tuple - */ index = (Form_pg_index) GETSTRUCT(tuple); Assert(index->indexrelid == indexId); relationId = index->indrelid; - indproc = index->indproc; - unique = index->indisunique; - - for (i = 0; i < INDEX_MAX_KEYS; i++) - { - if (index->indkey[i] == InvalidAttrNumber) - break; - } - numberOfAttributes = i; + indexInfo = BuildIndexInfo(tuple); + oldPred = indexInfo->ii_Predicate; - if (VARSIZE(&index->indpred) != 0) - { - char *predString; - - predString = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(&index->indpred))); - oldPred = stringToNode(predString); - pfree(predString); - } if (oldPred == NULL) elog(ERROR, "ExtendIndex: \"%s\" is not a partial index", indexRelationName); @@ -316,8 +270,11 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) /* * Convert the extension predicate from parsetree form to plan form, * so it can be readily evaluated during index creation. Note: - * "predicate" comes in as a list containing (1) the predicate itself - * (a where_clause), and (2) a corresponding range table. + * "predicate" comes in two parts (1) the predicate expression itself, + * and (2) a corresponding range table. + * + * XXX I think this code is broken --- index_build expects a single + * expression not a list --- tgl Jul 00 */ if (rangetable != NIL) { @@ -326,47 +283,20 @@ ExtendIndex(char *indexRelationName, Expr *predicate, List *rangetable) CheckPredicate(cnfPred, rangetable, relationId); } - /* make predInfo list to pass to index_build */ - predInfo = (PredInfo *) palloc(sizeof(PredInfo)); - predInfo->pred = (Node *) cnfPred; - predInfo->oldPred = oldPred; - - attributeNumberA = (AttrNumber *) palloc(numberOfAttributes * - sizeof attributeNumberA[0]); - classObjectId = (Oid *) palloc(numberOfAttributes * sizeof classObjectId[0]); - - - for (i = 0; i < numberOfAttributes; i++) - { - attributeNumberA[i] = index->indkey[i]; - classObjectId[i] = index->indclass[i]; - } - - if (indproc != InvalidOid) - { - funcInfo = &fInfo; - FIsetnArgs(funcInfo, numberOfAttributes); - - tuple = SearchSysCacheTuple(PROCOID, - ObjectIdGetDatum(indproc), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "ExtendIndex: index procedure %u not found", - indproc); - - namecpy(&(funcInfo->funcName), - &(((Form_pg_proc) GETSTRUCT(tuple))->proname)); - - FIsetProcOid(funcInfo, tuple->t_data->t_oid); - } + /* pass new predicate to index_build */ + indexInfo->ii_Predicate = (Node *) cnfPred; + /* Open heap and index rels, and get suitable locks */ heapRelation = heap_open(relationId, ShareLock); indexRelation = index_open(indexId); - InitIndexStrategy(numberOfAttributes, indexRelation, accessMethodId); + /* Obtain exclusive lock on it, just to be sure */ + LockRelation(indexRelation, AccessExclusiveLock); + + InitIndexStrategy(indexInfo->ii_NumIndexAttrs, + indexRelation, accessMethodId); - index_build(heapRelation, indexRelation, numberOfAttributes, - attributeNumberA, funcInfo, predInfo, unique); + index_build(heapRelation, indexRelation, indexInfo, oldPred); /* heap and index rels are closed as a side-effect of index_build */ } @@ -431,15 +361,15 @@ CheckPredClause(Expr *predicate, List *rangeTable, Oid baseRelOid) static void -FuncIndexArgs(IndexElem *funcIndex, - FuncIndexInfo *funcInfo, - AttrNumber *attNumP, - Oid *opOidP, +FuncIndexArgs(IndexInfo *indexInfo, + Oid *classOidP, + IndexElem *funcIndex, Oid relId, char *accessMethodName, Oid accessMethodId) { - List *rest; + Oid argTypes[FUNC_MAX_ARGS]; + List *arglist; HeapTuple tuple; Oid retType; int argn = 0; @@ -447,68 +377,77 @@ FuncIndexArgs(IndexElem *funcIndex, /* * process the function arguments, which are a list of T_String * (someday ought to allow more general expressions?) + * + * Note caller already checked that list is not too long. */ - MemSet(funcInfo->arglist, 0, FUNC_MAX_ARGS * sizeof(Oid)); + MemSet(argTypes, 0, sizeof(argTypes)); - foreach(rest, funcIndex->args) + foreach(arglist, funcIndex->args) { - char *arg = strVal(lfirst(rest)); + char *arg = strVal(lfirst(arglist)); Form_pg_attribute att; tuple = SearchSysCacheTuple(ATTNAME, ObjectIdGetDatum(relId), - PointerGetDatum(arg), 0, 0); - + PointerGetDatum(arg), + 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg); att = (Form_pg_attribute) GETSTRUCT(tuple); - *attNumP++ = att->attnum; - funcInfo->arglist[argn++] = att->atttypid; + + indexInfo->ii_KeyAttrNumbers[argn] = att->attnum; + argTypes[argn] = att->atttypid; + argn++; } /* ---------------- * Lookup the function procedure to get its OID and result type. + * + * XXX need to accept binary-compatible functions here, not just + * an exact match. * ---------------- */ tuple = SearchSysCacheTuple(PROCNAME, - PointerGetDatum(FIgetname(funcInfo)), - Int32GetDatum(FIgetnArgs(funcInfo)), - PointerGetDatum(FIgetArglist(funcInfo)), + PointerGetDatum(funcIndex->name), + Int32GetDatum(indexInfo->ii_NumKeyAttrs), + PointerGetDatum(argTypes), 0); - if (!HeapTupleIsValid(tuple)) { - func_error("DefineIndex", FIgetname(funcInfo), - FIgetnArgs(funcInfo), FIgetArglist(funcInfo), NULL); + func_error("DefineIndex", funcIndex->name, + indexInfo->ii_NumKeyAttrs, argTypes, NULL); } - FIsetProcOid(funcInfo, tuple->t_data->t_oid); + indexInfo->ii_FuncOid = tuple->t_data->t_oid; retType = ((Form_pg_proc) GETSTRUCT(tuple))->prorettype; - /* Process type and opclass, using func return type as default */ + /* Process opclass, using func return type as default type */ - ProcessAttrTypename(funcIndex, retType, -1); + classOidP[0] = GetAttrOpClass(funcIndex, retType, + accessMethodName, accessMethodId); - *opOidP = GetAttrOpClass(funcIndex, retType, - accessMethodName, accessMethodId); + /* Need to do the fmgr function lookup now, too */ + + fmgr_info(indexInfo->ii_FuncOid, & indexInfo->ii_FuncInfo); } static void -NormIndexAttrs(List *attList, /* list of IndexElem's */ - AttrNumber *attNumP, +NormIndexAttrs(IndexInfo *indexInfo, Oid *classOidP, + List *attList, /* list of IndexElem's */ Oid relId, char *accessMethodName, Oid accessMethodId) { List *rest; + int attn = 0; /* * process attributeList */ foreach(rest, attList) { - IndexElem *attribute = lfirst(rest); + IndexElem *attribute = (IndexElem *) lfirst(rest); HeapTuple atttuple; Form_pg_attribute attform; @@ -524,36 +463,13 @@ NormIndexAttrs(List *attList, /* list of IndexElem's */ attribute->name); attform = (Form_pg_attribute) GETSTRUCT(atttuple); - *attNumP++ = attform->attnum; - - ProcessAttrTypename(attribute, attform->atttypid, attform->atttypmod); + indexInfo->ii_KeyAttrNumbers[attn] = attform->attnum; - *classOidP++ = GetAttrOpClass(attribute, attform->atttypid, - accessMethodName, accessMethodId); + classOidP[attn] = GetAttrOpClass(attribute, attform->atttypid, + accessMethodName, accessMethodId); heap_freetuple(atttuple); - } -} - -static void -ProcessAttrTypename(IndexElem *attribute, - Oid defType, int32 defTypmod) -{ - HeapTuple tuple; - - /* build a type node so we can set the proper alignment, etc. */ - if (attribute->typename == NULL) - { - tuple = SearchSysCacheTuple(TYPEOID, - ObjectIdGetDatum(defType), - 0, 0, 0); - if (!HeapTupleIsValid(tuple)) - elog(ERROR, "DefineIndex: type for attribute \"%s\" undefined", - attribute->name); - - attribute->typename = makeNode(TypeName); - attribute->typename->name = nameout(&((Form_pg_type) GETSTRUCT(tuple))->typname); - attribute->typename->typmod = defTypmod; + attn++; } } @@ -626,7 +542,7 @@ GetAttrOpClass(IndexElem *attribute, Oid attrType, * * If the opclass was the default for the datatype, assume we can skip * this check --- that saves a few cycles in the most common case. - * If pg_opclass is messed up then we're probably screwed anyway... + * If pg_opclass is wrong then we're probably screwed anyway... */ if (doTypeCheck) { diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 71682baa8cd..ee0ebeb4bb7 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.162 2000/07/05 16:17:38 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.163 2000/07/14 22:17:42 tgl Exp $ * *------------------------------------------------------------------------- @@ -28,6 +28,7 @@ #include "catalog/index.h" #include "commands/vacuum.h" #include "miscadmin.h" +#include "nodes/execnodes.h" #include "storage/sinval.h" #include "storage/smgr.h" #include "tcop/tcopprot.h" @@ -71,7 +72,8 @@ static void reap_page(VacPageList vacpagelist, VacPage vacpage); static void vpage_insert(VacPageList vacpagelist, VacPage vpnew); static void get_indices(Relation relation, int *nindices, Relation **Irel); static void close_indices(int nindices, Relation *Irel); -static void get_index_desc(Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc); +static IndexInfo **get_index_desc(Relation onerel, int nindices, + Relation *Irel); static void *vac_find_eq(void *bot, int nelem, int size, void *elm, int (*compar) (const void *, const void *)); static int vac_cmp_blk(const void *left, const void *right); @@ -948,9 +950,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, newitemid; HeapTupleData tuple, newtup; - TupleDesc tupdesc = NULL; - Datum *idatum = NULL; - char *inulls = NULL; + TupleDesc tupdesc; + IndexInfo **indexInfo = NULL; + Datum idatum[INDEX_MAX_KEYS]; + char inulls[INDEX_MAX_KEYS]; InsertIndexResult iresult; VacPageListData Nvacpagelist; VacPage cur_page = NULL, @@ -958,8 +961,6 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, vacpage, *curpage; int cur_item = 0; - IndDesc *Idesc, - *idcur; int last_move_dest_block = -1, last_vacuum_block, i = 0; @@ -980,13 +981,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, myXID = GetCurrentTransactionId(); myCID = GetCurrentCommandId(); + tupdesc = RelationGetDescr(onerel); + if (Irel != (Relation *) NULL) /* preparation for index' inserts */ - { - get_index_desc(onerel, nindices, Irel, &Idesc); - tupdesc = RelationGetDescr(onerel); - idatum = (Datum *) palloc(INDEX_MAX_KEYS * sizeof(*idatum)); - inulls = (char *) palloc(INDEX_MAX_KEYS * sizeof(*inulls)); - } + indexInfo = get_index_desc(onerel, nindices, Irel); Nvacpagelist.num_pages = 0; num_fraged_pages = fraged_pages->num_pages; @@ -1456,15 +1454,22 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, if (Irel != (Relation *) NULL) { - for (i = 0, idcur = Idesc; i < nindices; i++, idcur++) + /* + * XXX using CurrentMemoryContext here means + * intra-vacuum memory leak for functional indexes. + * Should fix someday. + * + * XXX This code fails to handle partial indexes! + * Probably should change it to use ExecOpenIndices. + */ + for (i = 0; i < nindices; i++) { - FormIndexDatum(idcur->natts, - (AttrNumber *) &(idcur->tform->indkey[0]), + FormIndexDatum(indexInfo[i], &newtup, tupdesc, + CurrentMemoryContext, idatum, - inulls, - idcur->finfoP); + inulls); iresult = index_insert(Irel[i], idatum, inulls, @@ -1575,15 +1580,22 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)", /* insert index' tuples if needed */ if (Irel != (Relation *) NULL) { - for (i = 0, idcur = Idesc; i < nindices; i++, idcur++) + /* + * XXX using CurrentMemoryContext here means + * intra-vacuum memory leak for functional indexes. + * Should fix someday. + * + * XXX This code fails to handle partial indexes! + * Probably should change it to use ExecOpenIndices. + */ + for (i = 0; i < nindices; i++) { - FormIndexDatum(idcur->natts, - (AttrNumber *) &(idcur->tform->indkey[0]), + FormIndexDatum(indexInfo[i], &newtup, tupdesc, + CurrentMemoryContext, idatum, - inulls, - idcur->finfoP); + inulls); iresult = index_insert(Irel[i], idatum, inulls, @@ -1821,10 +1833,8 @@ failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)", if (Irel != (Relation *) NULL) /* pfree index' allocations */ { - pfree(Idesc); - pfree(idatum); - pfree(inulls); close_indices(nindices, Irel); + pfree(indexInfo); } pfree(vacpage); @@ -2347,46 +2357,30 @@ close_indices(int nindices, Relation *Irel) } -static void -get_index_desc(Relation onerel, int nindices, Relation *Irel, IndDesc **Idesc) +/* + * Obtain IndexInfo data for each index on the rel + */ +static IndexInfo ** +get_index_desc(Relation onerel, int nindices, Relation *Irel) { - IndDesc *idcur; - HeapTuple cachetuple; - AttrNumber *attnumP; - int natts; + IndexInfo **indexInfo; int i; + HeapTuple cachetuple; - *Idesc = (IndDesc *) palloc(nindices * sizeof(IndDesc)); + indexInfo = (IndexInfo **) palloc(nindices * sizeof(IndexInfo *)); - for (i = 0, idcur = *Idesc; i < nindices; i++, idcur++) + for (i = 0; i < nindices; i++) { - cachetuple = SearchSysCacheTupleCopy(INDEXRELID, + cachetuple = SearchSysCacheTuple(INDEXRELID, ObjectIdGetDatum(RelationGetRelid(Irel[i])), - 0, 0, 0); - Assert(cachetuple); - - /* - * we never free the copy we make, because Idesc needs it for - * later - */ - idcur->tform = (Form_pg_index) GETSTRUCT(cachetuple); - for (attnumP = &(idcur->tform->indkey[0]), natts = 0; - natts < INDEX_MAX_KEYS && *attnumP != InvalidAttrNumber; - attnumP++, natts++); - if (idcur->tform->indproc != InvalidOid) - { - idcur->finfoP = &(idcur->finfo); - FIgetnArgs(idcur->finfoP) = natts; - natts = 1; - FIgetProcOid(idcur->finfoP) = idcur->tform->indproc; - *(FIgetname(idcur->finfoP)) = '\0'; - } - else - idcur->finfoP = (FuncIndexInfo *) NULL; - - idcur->natts = natts; + 0, 0, 0); + if (!HeapTupleIsValid(cachetuple)) + elog(ERROR, "get_index_desc: index %u not found", + RelationGetRelid(Irel[i])); + indexInfo[i] = BuildIndexInfo(cachetuple); } + return indexInfo; } |