diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index df486de5120cbd3b74747bca07476b82a72124a8..888a50805542d14baaf511caec59eb61d6015979 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.201 2001/07/02 20:50:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.202 2001/07/11 18:38:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,12 +34,15 @@ #include "catalog/catalog.h" #include "catalog/catname.h" #include "catalog/index.h" +#include "catalog/pg_index.h" #include "commands/vacuum.h" +#include "executor/executor.h" #include "miscadmin.h" #include "nodes/execnodes.h" #include "storage/freespace.h" #include "storage/sinval.h" #include "storage/smgr.h" +#include "tcop/pquery.h" #include "tcop/tcopprot.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -153,8 +156,7 @@ static VacPage copy_vac_page(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 IndexInfo **get_index_desc(Relation onerel, int nindices, - Relation *Irel); +static bool is_partial_index(Relation indrel); static void *vac_bsearch(const void *key, const void *base, size_t nelem, size_t size, int (*compar) (const void *, const void *)); @@ -504,7 +506,7 @@ vacuum_rel(Oid relid) IsSystemRelationName(RelationGetRelationName(onerel))) reindex = true; - /* Now open indices */ + /* Now open all indices of the relation */ nindices = 0; Irel = (Relation *) NULL; get_indices(onerel, &nindices, &Irel); @@ -524,8 +526,7 @@ vacuum_rel(Oid relid) */ if (reindex) { - for (i = 0; i < nindices; i++) - index_close(Irel[i]); + close_indices(nindices, Irel); Irel = (Relation *) NULL; activate_indexes_of_a_table(relid, false); } @@ -553,11 +554,11 @@ vacuum_rel(Oid relid) /* Try to shrink heap */ repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages, nindices, Irel); + close_indices(nindices, Irel); } else { - if (Irel != (Relation *) NULL) - close_indices(nindices, Irel); + close_indices(nindices, Irel); if (vacuum_pages.num_pages > 0) { /* Clean pages from vacuum_pages list */ @@ -1089,10 +1090,10 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, HeapTupleData tuple, newtup; TupleDesc tupdesc; - IndexInfo **indexInfo = NULL; - Datum idatum[INDEX_MAX_KEYS]; - char inulls[INDEX_MAX_KEYS]; - InsertIndexResult iresult; + ResultRelInfo *resultRelInfo; + EState *estate; + TupleTable tupleTable; + TupleTableSlot *slot; VacPageListData Nvacpagelist; VacPage cur_page = NULL, last_vacuum_page, @@ -1119,8 +1120,26 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, tupdesc = RelationGetDescr(onerel); - if (Irel != (Relation *) NULL) /* preparation for index' inserts */ - indexInfo = get_index_desc(onerel, nindices, Irel); + /* + * We need a ResultRelInfo and an EState so we can use the regular + * executor's index-entry-making machinery. + */ + resultRelInfo = makeNode(ResultRelInfo); + resultRelInfo->ri_RangeTableIndex = 1; /* dummy */ + resultRelInfo->ri_RelationDesc = onerel; + resultRelInfo->ri_TrigDesc = NULL; /* we don't fire triggers */ + + ExecOpenIndices(resultRelInfo); + + estate = CreateExecutorState(); + estate->es_result_relations = resultRelInfo; + estate->es_num_result_relations = 1; + estate->es_result_relation_info = resultRelInfo; + + /* Set up a dummy tuple table too */ + tupleTable = ExecCreateTupleTable(1); + slot = ExecAllocTableSlot(tupleTable); + ExecSetSlotDescriptor(slot, tupdesc, false); Nvacpagelist.num_pages = 0; num_fraged_pages = fraged_pages->num_pages; @@ -1645,35 +1664,14 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, if (cur_buffer != Cbuf) LockBuffer(Cbuf, BUFFER_LOCK_UNLOCK); - if (Irel != (Relation *) NULL) + /* Create index entries for the moved tuple */ + if (resultRelInfo->ri_NumIndices > 0) { - - /* - * 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(indexInfo[i], - &newtup, - tupdesc, - CurrentMemoryContext, - idatum, - inulls); - iresult = index_insert(Irel[i], - idatum, - inulls, - &newtup.t_self, - onerel); - if (iresult) - pfree(iresult); - } + ExecStoreTuple(&newtup, slot, InvalidBuffer, false); + ExecInsertIndexTuples(slot, &(newtup.t_self), + estate, true); } + WriteBuffer(cur_buffer); WriteBuffer(Cbuf); } @@ -1780,34 +1778,11 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, LockBuffer(buf, BUFFER_LOCK_UNLOCK); /* insert index' tuples if needed */ - if (Irel != (Relation *) NULL) + if (resultRelInfo->ri_NumIndices > 0) { - - /* - * 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(indexInfo[i], - &newtup, - tupdesc, - CurrentMemoryContext, - idatum, - inulls); - iresult = index_insert(Irel[i], - idatum, - inulls, - &newtup.t_self, - onerel); - if (iresult) - pfree(iresult); - } + ExecStoreTuple(&newtup, slot, InvalidBuffer, false); + ExecInsertIndexTuples(slot, &(newtup.t_self), estate, true); } - } /* walk along page */ if (offnum < maxoff && keep_tuples > 0) @@ -2095,15 +2070,14 @@ repair_frag(VRelStats *vacrelstats, Relation onerel, vacrelstats->rel_pages = blkno; /* set new number of blocks */ } - if (Irel != (Relation *) NULL) /* pfree index' allocations */ - { - close_indices(nindices, Irel); - pfree(indexInfo); - } - + /* clean up */ pfree(vacpage); if (vacrelstats->vtlinks != NULL) pfree(vacrelstats->vtlinks); + + ExecDropTupleTable(tupleTable, true); + + ExecCloseIndices(resultRelInfo); } /* @@ -2200,8 +2174,7 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage) } /* - * _scan_index() -- scan one index relation to update statistic. - * + * scan_index() -- scan one index relation to update statistic. */ static void scan_index(Relation indrel, double num_tuples) @@ -2235,11 +2208,18 @@ scan_index(Relation indrel, double num_tuples) RelationGetRelationName(indrel), nipages, nitups, show_rusage(&ru0)); + /* + * Check for tuple count mismatch. If the index is partial, then + * it's OK for it to have fewer tuples than the heap; else we got trouble. + */ if (nitups != num_tuples) - elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\ + { + if (nitups > num_tuples || + ! is_partial_index(indrel)) + elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\ \n\tRecreate the index.", - RelationGetRelationName(indrel), nitups, num_tuples); - + RelationGetRelationName(indrel), nitups, num_tuples); + } } /* @@ -2315,11 +2295,18 @@ vacuum_index(VacPageList vacpagelist, Relation indrel, num_index_tuples - keep_tuples, tups_vacuumed, show_rusage(&ru0)); + /* + * Check for tuple count mismatch. If the index is partial, then + * it's OK for it to have fewer tuples than the heap; else we got trouble. + */ if (num_index_tuples != num_tuples + keep_tuples) - elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\ + { + if (num_index_tuples > num_tuples + keep_tuples || + ! is_partial_index(indrel)) + elog(NOTICE, "Index %s: NUMBER OF INDEX' TUPLES (%.0f) IS NOT THE SAME AS HEAP' (%.0f).\ \n\tRecreate the index.", - RelationGetRelationName(indrel), num_index_tuples, num_tuples); - + RelationGetRelationName(indrel), num_index_tuples, num_tuples); + } } /* @@ -2640,42 +2627,34 @@ get_indices(Relation relation, int *nindices, Relation **Irel) static void close_indices(int nindices, Relation *Irel) { - if (Irel == (Relation *) NULL) return; while (nindices--) index_close(Irel[nindices]); pfree(Irel); - } -/* - * Obtain IndexInfo data for each index on the rel - */ -static IndexInfo ** -get_index_desc(Relation onerel, int nindices, Relation *Irel) +static bool +is_partial_index(Relation indrel) { - IndexInfo **indexInfo; - int i; + bool result; HeapTuple cachetuple; + Form_pg_index indexStruct; - indexInfo = (IndexInfo **) palloc(nindices * sizeof(IndexInfo *)); + cachetuple = SearchSysCache(INDEXRELID, + ObjectIdGetDatum(RelationGetRelid(indrel)), + 0, 0, 0); + if (!HeapTupleIsValid(cachetuple)) + elog(ERROR, "is_partial_index: index %u not found", + RelationGetRelid(indrel)); + indexStruct = (Form_pg_index) GETSTRUCT(cachetuple); - for (i = 0; i < nindices; i++) - { - cachetuple = SearchSysCache(INDEXRELID, - ObjectIdGetDatum(RelationGetRelid(Irel[i])), - 0, 0, 0); - if (!HeapTupleIsValid(cachetuple)) - elog(ERROR, "get_index_desc: index %u not found", - RelationGetRelid(Irel[i])); - indexInfo[i] = BuildIndexInfo(cachetuple); - ReleaseSysCache(cachetuple); - } + result = (VARSIZE(&indexStruct->indpred) != 0); - return indexInfo; + ReleaseSysCache(cachetuple); + return result; }