diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 4779f3eb5b3b9fbcfe1eb7dda943abcac5202e02..94f0dd2f070cd6e44f9893793e8fba7757e499b1 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 224bea45d7c57eba92bd7de8951afdf048700224..6ed66f6bc81da59811e6546006008e7b9a6486e9 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 */