*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
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 *));
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);
*/
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);
}
/* 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 */
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,
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;
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);
}
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)
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);
}
/*
}
/*
- * _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)
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);
+ }
}
/*
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);
+ }
}
/*
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;
}