aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/vacuum.c353
-rw-r--r--src/include/commands/vacuum.h9
2 files changed, 230 insertions, 132 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 4779f3eb5b3..94f0dd2f070 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.29 1997/04/17 01:45:36 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.30 1997/04/23 06:25:43 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,6 +42,7 @@
#include <utils/mcxt.h>
#include <utils/inval.h>
#include <utils/syscache.h>
+#include <utils/builtins.h>
#include <commands/vacuum.h>
#include <parser/catalog_utils.h>
#include <storage/bufpage.h>
@@ -56,38 +57,41 @@
#include <port-protos.h>
bool VacuumRunning = false;
+
+static Portal vc_portal;
+
static int MESSAGE_LEVEL; /* message level */
#define swapLong(a,b) {long tmp; tmp=a; a=b; b=tmp;}
#define swapInt(a,b) {int tmp; tmp=a; a=b; b=tmp;}
#define swapDatum(a,b) {Datum tmp; tmp=a; a=b; b=tmp;}
-#define VacAttrStatsEqValid(stats) ( RegProcedureIsValid(stats->cmpeq))
-#define VacAttrStatsLtGtValid(stats) ( RegProcedureIsValid(stats->cmplt) && \
- RegProcedureIsValid(stats->cmpgt) && \
+#define VacAttrStatsEqValid(stats) ( stats->f_cmpeq != NULL )
+#define VacAttrStatsLtGtValid(stats) ( stats->f_cmplt != NULL && \
+ stats->f_cmpgt != NULL && \
RegProcedureIsValid(stats->outfunc) )
/* non-export function prototypes */
static void vc_init(void);
static void vc_shutdown(void);
-static void vc_vacuum(NameData *VacRelP);
-static VRelList vc_getrels(Portal p, NameData *VacRelP);
-static void vc_vacone (Oid relid);
+static void vc_vacuum(NameData *VacRelP, bool analyze, List *va_cols);
+static VRelList vc_getrels(NameData *VacRelP);
+static void vc_vacone (Oid relid, bool analyze, List *va_cols);
static void vc_scanheap (VRelStats *vacrelstats, Relation onerel, VPageList Vvpl, VPageList Fvpl);
static void vc_rpfheap (VRelStats *vacrelstats, Relation onerel, VPageList Vvpl, VPageList Fvpl, int nindices, Relation *Irel);
static void vc_vacheap (VRelStats *vacrelstats, Relation onerel, VPageList vpl);
static void vc_vacpage (Page page, VPageDescr vpd, Relation archrel);
static void vc_vaconeind (VPageList vpl, Relation indrel, int nhtups);
static void vc_scanoneind (Relation indrel, int nhtups);
-static void vc_attrstats(Relation onerel, VacAttrStats *vacattrstats, HeapTuple htup);
+static void vc_attrstats(Relation onerel, VRelStats *vacrelstats, HeapTuple htup);
static void vc_bucketcpy(AttributeTupleForm attr, Datum value, Datum *bucket, int16 *bucket_len);
-static void vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VacAttrStats *vacattrstats);
-static void vc_delhilowstats(Oid relid);
+static void vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VRelStats *vacrelstats);
+static void vc_delhilowstats (Oid relid, int attcnt, int *attnums);
static void vc_setpagelock(Relation rel, BlockNumber blkno);
static VPageDescr vc_tidreapped (ItemPointer itemptr, VPageList vpl);
static void vc_reappage (VPageList vpl, VPageDescr vpc);
static void vc_vpinsert (VPageList vpl, VPageDescr vpnew);
-static void vc_free(Portal p, VRelList vrl);
+static void vc_free(VRelList vrl);
static void vc_getindices (Oid relid, int *nindices, Relation **Irel);
static void vc_clsindices (int nindices, Relation *Irel);
static Relation vc_getarchrel(Relation heaprel);
@@ -100,9 +104,25 @@ static int vc_cmp_offno (char *left, char *right);
static bool vc_enough_space (VPageDescr vpd, Size len);
void
-vacuum(char *vacrel, bool verbose)
+vacuum(char *vacrel, bool verbose, bool analyze, List *va_spec)
{
+ char *pname;
+ MemoryContext old;
+ PortalVariableMemory pmem;
NameData VacRel;
+ List *le;
+ List *va_cols = NIL;
+
+ /*
+ * Create a portal for safe memory across transctions. We need to
+ * palloc the name space for it because our hash function expects
+ * the name to be on a longword boundary. CreatePortal copies the
+ * name to safe storage for us.
+ */
+ pname = (char *) palloc(strlen(VACPNAME) + 1);
+ strcpy(pname, VACPNAME);
+ vc_portal = CreatePortal(pname);
+ pfree(pname);
if (verbose)
MESSAGE_LEVEL = NOTICE;
@@ -112,15 +132,32 @@ vacuum(char *vacrel, bool verbose)
/* vacrel gets de-allocated on transaction commit */
if (vacrel)
strcpy(VacRel.data,vacrel);
+
+ pmem = PortalGetVariableMemory(vc_portal);
+ old = MemoryContextSwitchTo((MemoryContext)pmem);
+
+ Assert ( va_spec == NIL || analyze );
+ foreach (le, va_spec)
+ {
+ char *col = (char*)lfirst(le);
+ char *dest;
+
+ dest = (char*) palloc (strlen (col) + 1);
+ strcpy (dest, col);
+ va_cols = lappend (va_cols, dest);
+ }
+ (void) MemoryContextSwitchTo(old);
/* initialize vacuum cleaner */
vc_init();
/* vacuum the database */
if (vacrel)
- vc_vacuum(&VacRel);
+ vc_vacuum (&VacRel, analyze, va_cols);
else
- vc_vacuum(NULL);
+ vc_vacuum (NULL, analyze, NIL);
+
+ PortalDestroy (&vc_portal);
/* clean up */
vc_shutdown();
@@ -199,46 +236,25 @@ vc_abort()
* locks at one time.
*/
static void
-vc_vacuum(NameData *VacRelP)
+vc_vacuum(NameData *VacRelP, bool analyze, List *va_cols)
{
VRelList vrl, cur;
- char *pname;
- Portal p;
-
- /*
- * Create a portal for safe memory across transctions. We need to
- * palloc the name space for it because our hash function expects
- * the name to be on a longword boundary. CreatePortal copies the
- * name to safe storage for us.
- */
-
- pname = (char *) palloc(strlen(VACPNAME) + 1);
- strcpy(pname, VACPNAME);
- p = CreatePortal(pname);
- pfree(pname);
/* get list of relations */
- vrl = vc_getrels(p, VacRelP);
+ vrl = vc_getrels(VacRelP);
- if ( vrl != NULL )
- {
- if (VacRelP != NULL)
- vc_delhilowstats(vrl->vrl_relid);
- else
- vc_delhilowstats(InvalidOid);
- }
+ if ( analyze && VacRelP == NULL && vrl != NULL )
+ vc_delhilowstats (InvalidOid, 0, NULL);
/* vacuum each heap relation */
for (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next)
- vc_vacone (cur->vrl_relid);
-
- vc_free(p, vrl);
+ vc_vacone (cur->vrl_relid, analyze, va_cols);
- PortalDestroy(&p);
+ vc_free(vrl);
}
static VRelList
-vc_getrels(Portal p, NameData *VacRelP)
+vc_getrels(NameData *VacRelP)
{
Relation pgclass;
TupleDesc pgcdesc;
@@ -267,7 +283,7 @@ vc_getrels(Portal p, NameData *VacRelP)
CharacterEqualRegProcedure, CharGetDatum('r'));
}
- portalmem = PortalGetVariableMemory(p);
+ portalmem = PortalGetVariableMemory(vc_portal);
vrl = cur = (VRelList) NULL;
pgclass = heap_openr(RelationRelationName);
@@ -370,7 +386,7 @@ vc_getrels(Portal p, NameData *VacRelP)
* us to lock the entire database during one pass of the vacuum cleaner.
*/
static void
-vc_vacone (Oid relid)
+vc_vacone (Oid relid, bool analyze, List *va_cols)
{
Relation pgclass;
TupleDesc pgcdesc;
@@ -383,8 +399,7 @@ vc_vacone (Oid relid)
VPageListData Fvpl; /* List of pages with space enough for re-using */
VPageDescr *vpp;
Relation *Irel;
- int32 nindices, i, attr_cnt;
- AttributeTupleForm *attr;
+ int32 nindices, i;
VRelStats *vacrelstats;
StartTransactionCommand();
@@ -412,55 +427,117 @@ vc_vacone (Oid relid)
/* now open the class and vacuum it */
onerel = heap_open(relid);
- attr_cnt = onerel->rd_att->natts;
- attr = onerel->rd_att->attrs;
-
vacrelstats = (VRelStats *) palloc(sizeof(VRelStats));
vacrelstats->relid = relid;
vacrelstats->npages = vacrelstats->ntups = 0;
vacrelstats->hasindex = false;
- vacrelstats->vacattrstats =
- (VacAttrStats *) palloc(attr_cnt * sizeof(VacAttrStats));
+ if ( analyze && !IsSystemRelationName ((RelationGetRelationName (onerel))->data) )
+ {
+ int attr_cnt, *attnums = NULL;
+ AttributeTupleForm *attr;
+
+ attr_cnt = onerel->rd_att->natts;
+ attr = onerel->rd_att->attrs;
+
+ if ( va_cols != NIL )
+ {
+ int tcnt = 0;
+ List *le;
+
+ if ( length (va_cols) > attr_cnt )
+ elog (WARN, "vacuum: too many attributes specified for relation %.*s",
+ NAMEDATALEN, (RelationGetRelationName(onerel))->data);
+ attnums = (int*) palloc (attr_cnt * sizeof (int));
+ foreach (le, va_cols)
+ {
+ char *col = (char*) lfirst(le);
+
+ for (i = 0; i < attr_cnt; i++)
+ {
+ if ( namestrcmp (&(attr[i]->attname), col) == 0 )
+ break;
+ }
+ if ( i < attr_cnt ) /* found */
+ attnums[tcnt++] = i;
+ else
+ {
+ elog (WARN, "vacuum: there is no attribute %s in %.*s",
+ col, NAMEDATALEN, (RelationGetRelationName(onerel))->data);
+ }
+ }
+ attr_cnt = tcnt;
+ }
+
+ vacrelstats->vacattrstats =
+ (VacAttrStats *) palloc (attr_cnt * sizeof(VacAttrStats));
- for (i = 0; i < attr_cnt; i++) {
- Operator func_operator;
- OperatorTupleForm pgopform;
- VacAttrStats *stats = &vacrelstats->vacattrstats[i];
-
- stats->attr = palloc(ATTRIBUTE_TUPLE_SIZE);
- memmove(stats->attr,attr[i],ATTRIBUTE_TUPLE_SIZE);
- stats->best = stats->guess1 = stats->guess2 = 0;
- stats->max = stats->min = 0;
- stats->best_len = stats->guess1_len = stats->guess2_len = 0;
- stats->max_len = stats->min_len = 0;
- stats->initialized = false;
- stats->best_cnt = stats->guess1_cnt = stats->guess1_hits = stats->guess2_hits = 0;
- stats->max_cnt = stats->min_cnt = stats->null_cnt = stats->nonnull_cnt = 0;
+ for (i = 0; i < attr_cnt; i++)
+ {
+ Operator func_operator;
+ OperatorTupleForm pgopform;
+ VacAttrStats *stats;
+
+ stats = &vacrelstats->vacattrstats[i];
+ stats->attr = palloc(ATTRIBUTE_TUPLE_SIZE);
+ memmove (stats->attr, attr[((attnums) ? attnums[i] : i)], ATTRIBUTE_TUPLE_SIZE);
+ stats->best = stats->guess1 = stats->guess2 = 0;
+ stats->max = stats->min = 0;
+ stats->best_len = stats->guess1_len = stats->guess2_len = 0;
+ stats->max_len = stats->min_len = 0;
+ stats->initialized = false;
+ stats->best_cnt = stats->guess1_cnt = stats->guess1_hits = stats->guess2_hits = 0;
+ stats->max_cnt = stats->min_cnt = stats->null_cnt = stats->nonnull_cnt = 0;
- func_operator = oper("=",stats->attr->atttypid,stats->attr->atttypid,true);
- if (func_operator != NULL) {
- pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
- stats->cmpeq = pgopform->oprcode;
- }
- else stats->cmpeq = InvalidOid;
- func_operator = oper("<",stats->attr->atttypid,stats->attr->atttypid,true);
- if (func_operator != NULL) {
- pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
- stats->cmplt = pgopform->oprcode;
- }
- else stats->cmplt = InvalidOid;
- func_operator = oper(">",stats->attr->atttypid,stats->attr->atttypid,true);
- if (func_operator != NULL) {
- pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
- stats->cmpgt = pgopform->oprcode;
- }
- else stats->cmpgt = InvalidOid;
- pgttup = SearchSysCacheTuple(TYPOID,
+ func_operator = oper("=",stats->attr->atttypid,stats->attr->atttypid,true);
+ if (func_operator != NULL)
+ {
+ int nargs;
+
+ pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
+ fmgr_info (pgopform->oprcode, &(stats->f_cmpeq), &nargs);
+ }
+ else
+ stats->f_cmpeq = NULL;
+
+ func_operator = oper("<",stats->attr->atttypid,stats->attr->atttypid,true);
+ if (func_operator != NULL)
+ {
+ int nargs;
+
+ pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
+ fmgr_info (pgopform->oprcode, &(stats->f_cmplt), &nargs);
+ }
+ else
+ stats->f_cmplt = NULL;
+
+ func_operator = oper(">",stats->attr->atttypid,stats->attr->atttypid,true);
+ if (func_operator != NULL)
+ {
+ int nargs;
+
+ pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
+ fmgr_info (pgopform->oprcode, &(stats->f_cmpgt), &nargs);
+ }
+ else
+ stats->f_cmpgt = NULL;
+
+ pgttup = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(stats->attr->atttypid),
0,0,0);
- if (HeapTupleIsValid(pgttup))
- stats->outfunc = ((TypeTupleForm) GETSTRUCT(pgttup))->typoutput;
- else stats->outfunc = InvalidOid;
+ if (HeapTupleIsValid(pgttup))
+ stats->outfunc = ((TypeTupleForm) GETSTRUCT(pgttup))->typoutput;
+ else
+ stats->outfunc = InvalidOid;
+ }
+ vacrelstats->va_natts = attr_cnt;
+ vc_delhilowstats (relid, ((attnums) ? attr_cnt : 0), attnums);
+ if ( attnums )
+ pfree (attnums);
+ }
+ else
+ {
+ vacrelstats->va_natts = 0;
+ vacrelstats->vacattrstats = (VacAttrStats *) NULL;
}
/* we require the relation to be locked until the indices are cleaned */
@@ -522,7 +599,7 @@ vc_vacone (Oid relid)
/* update statistics in pg_class */
vc_updstats(vacrelstats->relid, vacrelstats->npages, vacrelstats->ntups,
- vacrelstats->hasindex, vacrelstats->vacattrstats);
+ vacrelstats->hasindex, vacrelstats);
/* next command frees attribute stats */
@@ -748,7 +825,7 @@ DELETE_TRANSACTION_ID_VALID %d, TUPGONE %d.",
min_tlen = htup->t_len;
if ( htup->t_len > max_tlen )
max_tlen = htup->t_len;
- vc_attrstats(onerel, vacrelstats->vacattrstats, htup);
+ vc_attrstats(onerel, vacrelstats, htup);
}
}
@@ -1384,8 +1461,8 @@ vc_scanoneind (Relation indrel, int nhtups)
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
if ( nitups != nhtups )
- elog (NOTICE, "NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
- nitups, nhtups);
+ elog (NOTICE, "Ind %.*s: NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
+ NAMEDATALEN, indrel->rd_rel->relname.data, nitups, nhtups);
} /* vc_scanoneind */
@@ -1463,8 +1540,8 @@ vc_vaconeind(VPageList vpl, Relation indrel, int nhtups)
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
if ( nitups != nhtups )
- elog (NOTICE, "NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
- nitups, nhtups);
+ elog (NOTICE, "Ind %.*s: NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
+ NAMEDATALEN, indrel->rd_rel->relname.data, nitups, nhtups);
} /* vc_vaconeind */
@@ -1532,23 +1609,20 @@ vc_tidreapped(ItemPointer itemptr, VPageList vpl)
*
*/
static void
-vc_attrstats(Relation onerel, VacAttrStats *vacattrstats, HeapTuple htup)
+vc_attrstats(Relation onerel, VRelStats *vacrelstats, HeapTuple htup)
{
- int i, attr_cnt;
- AttributeTupleForm *attr;
- TupleDesc tupDesc;
+ int i, attr_cnt = vacrelstats->va_natts;
+ VacAttrStats *vacattrstats = vacrelstats->vacattrstats;
+ TupleDesc tupDesc = onerel->rd_att;
Datum value;
bool isnull;
- attr_cnt = onerel->rd_att->natts;
- attr = onerel->rd_att->attrs;
- tupDesc = onerel->rd_att;
-
for (i = 0; i < attr_cnt; i++) {
VacAttrStats *stats = &vacattrstats[i];
bool value_hit = true;
- value = (Datum) heap_getattr(htup, InvalidBuffer, i+1, tupDesc, &isnull);
+ value = (Datum) heap_getattr (htup, InvalidBuffer,
+ stats->attr->attnum, tupDesc, &isnull);
if (!VacAttrStatsEqValid(stats))
continue;
@@ -1571,26 +1645,26 @@ vc_attrstats(Relation onerel, VacAttrStats *vacattrstats, HeapTuple htup)
stats->initialized = true;
}
if (VacAttrStatsLtGtValid(stats)) {
- if (fmgr(stats->cmplt,value,stats->min)) {
+ if ( (*(stats->f_cmplt)) (value,stats->min) ) {
vc_bucketcpy(stats->attr, value, &stats->min, &stats->min_len);
stats->min_cnt = 0;
}
- if (fmgr(stats->cmpgt,value,stats->max)) {
+ if ( (*(stats->f_cmpgt)) (value,stats->max) ) {
vc_bucketcpy(stats->attr, value, &stats->max, &stats->max_len);
stats->max_cnt = 0;
}
- if (fmgr(stats->cmpeq,value,stats->min))
+ if ( (*(stats->f_cmpeq)) (value,stats->min) )
stats->min_cnt++;
- else if (fmgr(stats->cmpeq,value,stats->max))
+ else if ( (*(stats->f_cmpeq)) (value,stats->max) )
stats->max_cnt++;
}
- if (fmgr(stats->cmpeq,value,stats->best))
- stats-> best_cnt++;
- else if (fmgr(stats->cmpeq,value,stats->guess1)) {
+ if ( (*(stats->f_cmpeq)) (value,stats->best) )
+ stats->best_cnt++;
+ else if ( (*(stats->f_cmpeq)) (value,stats->guess1) ) {
stats->guess1_cnt++;
- stats-> guess1_hits++;
+ stats->guess1_hits++;
}
- else if (fmgr(stats->cmpeq,value,stats->guess2))
+ else if ( (*(stats->f_cmpeq)) (value,stats->guess2) )
stats->guess2_hits++;
else value_hit = false;
@@ -1605,12 +1679,12 @@ vc_attrstats(Relation onerel, VacAttrStats *vacattrstats, HeapTuple htup)
swapInt(stats->best_len,stats->guess1_len);
swapLong(stats->best_cnt,stats->guess1_cnt);
stats->guess1_hits = 1;
- stats-> guess2_hits = 1;
+ stats->guess2_hits = 1;
}
if (!value_hit) {
vc_bucketcpy(stats->attr, value, &stats->guess2, &stats->guess2_len);
stats->guess1_hits = 1;
- stats-> guess2_hits = 1;
+ stats->guess2_hits = 1;
}
}
}
@@ -1652,7 +1726,7 @@ vc_bucketcpy(AttributeTupleForm attr, Datum value, Datum *bucket, int16 *bucket_
* historical queries very expensive.
*/
static void
-vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VacAttrStats *vacattrstats)
+vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VRelStats *vacrelstats)
{
Relation rd, ad, sd;
HeapScanDesc rsdesc, asdesc;
@@ -1684,8 +1758,11 @@ vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VacAttrStats *vacat
pgcform->relpages = npages;
pgcform->relhasindex = hasindex;
- if (vacattrstats != NULL)
+ if ( vacrelstats != NULL && vacrelstats->va_natts > 0 )
{
+ VacAttrStats *vacattrstats = vacrelstats->vacattrstats;
+ int natts = vacrelstats->va_natts;
+
ad = heap_openr(AttributeRelationName);
sd = heap_openr(StatisticRelationName);
ScanKeyEntryInitialize(&askey, 0, Anum_pg_attribute_attrelid,
@@ -1693,19 +1770,27 @@ vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VacAttrStats *vacat
asdesc = heap_beginscan(ad, false, NowTimeQual, 1, &askey);
- while (HeapTupleIsValid(atup = heap_getnext(asdesc, 0, &abuf))) {
- int slot, i;
+ while (HeapTupleIsValid(atup = heap_getnext(asdesc, 0, &abuf)))
+ {
+ int i;
double selratio; /* average ratio of rows selected for a random constant */
VacAttrStats *stats;
Datum values[ Natts_pg_statistic ];
char nulls[ Natts_pg_statistic ];
attp = (AttributeTupleForm) GETSTRUCT(atup);
- slot = attp->attnum - 1;
- if (slot < 0) /* skip system attributes for now,
- they are unique anyway */
- continue;
- stats = &vacattrstats[slot];
+ if ( attp->attnum <= 0) /* skip system attributes for now, */
+ /* they are unique anyway */
+ continue;
+
+ for (i = 0; i < natts; i++)
+ {
+ if ( attp->attnum == vacattrstats[i].attr->attnum )
+ break;
+ }
+ if ( i >= natts )
+ continue;
+ stats = &(vacattrstats[i]);
/* overwrite the existing statistics in the tuple */
if (VacAttrStatsEqValid(stats)) {
@@ -1794,7 +1879,6 @@ vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VacAttrStats *vacat
/* that's all, folks */
heap_endscan(rsdesc);
heap_close(rd);
-
}
/*
@@ -1802,7 +1886,7 @@ vc_updstats(Oid relid, int npages, int ntups, bool hasindex, VacAttrStats *vacat
*
*/
static void
-vc_delhilowstats(Oid relid)
+vc_delhilowstats(Oid relid, int attcnt, int *attnums)
{
Relation pgstatistic;
HeapScanDesc pgsscan;
@@ -1820,7 +1904,21 @@ vc_delhilowstats(Oid relid)
else
pgsscan = heap_beginscan(pgstatistic, false, NowTimeQual, 0, NULL);
- while (HeapTupleIsValid(pgstup = heap_getnext(pgsscan, 0, NULL))) {
+ while (HeapTupleIsValid(pgstup = heap_getnext(pgsscan, 0, NULL)))
+ {
+ if ( attcnt > 0 )
+ {
+ Form_pg_statistic pgs = (Form_pg_statistic) GETSTRUCT (pgstup);
+ int i;
+
+ for (i = 0; i < attcnt; i++)
+ {
+ if ( pgs->staattnum == attnums[i] + 1 )
+ break;
+ }
+ if ( i >= attcnt )
+ continue; /* don't delete it */
+ }
heap_delete(pgstatistic, &pgstup->t_ctid);
}
@@ -1837,7 +1935,6 @@ static void vc_setpagelock(Relation rel, BlockNumber blkno)
RelationSetLockForWritePage(rel, &itm);
}
-
/*
* vc_reappage() -- save a page on the array of reapped pages.
*
@@ -1881,13 +1978,13 @@ vc_vpinsert (VPageList vpl, VPageDescr vpnew)
}
static void
-vc_free(Portal p, VRelList vrl)
+vc_free(VRelList vrl)
{
VRelList p_vrl;
MemoryContext old;
PortalVariableMemory pmem;
- pmem = PortalGetVariableMemory(p);
+ pmem = PortalGetVariableMemory(vc_portal);
old = MemoryContextSwitchTo((MemoryContext)pmem);
while (vrl != (VRelList) NULL) {
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 224bea45d7c..6ed66f6bc81 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: vacuum.h,v 1.6 1997/02/07 16:23:57 momjian Exp $
+ * $Id: vacuum.h,v 1.7 1997/04/23 06:28:48 vadim Exp $
*
*-------------------------------------------------------------------------
*/
@@ -54,7 +54,8 @@ typedef struct {
int16 best_len, guess1_len, guess2_len, max_len, min_len;
int32 best_cnt, guess1_cnt, guess1_hits, guess2_hits, null_cnt,nonnull_cnt;
int32 max_cnt, min_cnt;
- regproc cmpeq, cmplt, cmpgt, outfunc;
+ func_ptr f_cmpeq, f_cmplt, f_cmpgt;
+ regproc outfunc;
bool initialized;
} VacAttrStats;
@@ -72,14 +73,14 @@ typedef struct VRelStats {
Size min_tlen;
Size max_tlen;
bool hasindex;
- int natts;
+ int va_natts; /* number of attrs being analyzed */
VacAttrStats *vacattrstats;
} VRelStats;
extern bool VacuumRunning;
extern void vc_abort(void);
-extern void vacuum(char *vacrel, bool verbose);
+extern void vacuum(char *vacrel, bool verbose, bool analyze, List *va_spec);
#define ATTNVALS_SCALE 1000000000 /* XXX so it can act as a float4 */