summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/analyze.c32
-rw-r--r--src/backend/commands/vacuum.c125
-rw-r--r--src/backend/commands/vacuumlazy.c13
-rw-r--r--src/backend/nodes/copyfuncs.c4
-rw-r--r--src/backend/nodes/equalfuncs.c4
-rw-r--r--src/backend/parser/gram.y50
-rw-r--r--src/backend/postmaster/autovacuum.c58
-rw-r--r--src/backend/tcop/utility.c2
-rw-r--r--src/include/commands/vacuum.h28
-rw-r--r--src/include/nodes/parsenodes.h13
10 files changed, 159 insertions, 170 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index d2856a379e7..75b45f7cd5d 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -85,7 +85,7 @@ static MemoryContext anl_context = NULL;
static BufferAccessStrategy vac_strategy;
-static void do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
+static void do_analyze_rel(Relation onerel, int options, List *va_cols,
AcquireSampleRowsFunc acquirefunc, BlockNumber relpages,
bool inh, bool in_outer_xact, int elevel);
static void BlockSampler_Init(BlockSampler bs, BlockNumber nblocks,
@@ -115,7 +115,7 @@ static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
* analyze_rel() -- analyze one relation
*/
void
-analyze_rel(Oid relid, VacuumStmt *vacstmt,
+analyze_rel(Oid relid, RangeVar *relation, int options, List *va_cols,
bool in_outer_xact, BufferAccessStrategy bstrategy)
{
Relation onerel;
@@ -124,7 +124,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
BlockNumber relpages = 0;
/* Select logging level */
- if (vacstmt->options & VACOPT_VERBOSE)
+ if (options & VACOPT_VERBOSE)
elevel = INFO;
else
elevel = DEBUG2;
@@ -144,7 +144,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
* matter if we ever try to accumulate stats on dead tuples.) If the rel
* has been dropped since we last saw it, we don't need to process it.
*/
- if (!(vacstmt->options & VACOPT_NOWAIT))
+ if (!(options & VACOPT_NOWAIT))
onerel = try_relation_open(relid, ShareUpdateExclusiveLock);
else if (ConditionalLockRelationOid(relid, ShareUpdateExclusiveLock))
onerel = try_relation_open(relid, NoLock);
@@ -155,7 +155,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
ereport(LOG,
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("skipping analyze of \"%s\" --- lock not available",
- vacstmt->relation->relname)));
+ relation->relname)));
}
if (!onerel)
return;
@@ -167,7 +167,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
(pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
{
/* No need for a WARNING if we already complained during VACUUM */
- if (!(vacstmt->options & VACOPT_VACUUM))
+ if (!(options & VACOPT_VACUUM))
{
if (onerel->rd_rel->relisshared)
ereport(WARNING,
@@ -248,7 +248,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
else
{
/* No need for a WARNING if we already complained during VACUUM */
- if (!(vacstmt->options & VACOPT_VACUUM))
+ if (!(options & VACOPT_VACUUM))
ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot analyze non-tables or special system tables",
RelationGetRelationName(onerel))));
@@ -266,14 +266,14 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
/*
* Do the normal non-recursive ANALYZE.
*/
- do_analyze_rel(onerel, vacstmt, acquirefunc, relpages,
+ do_analyze_rel(onerel, options, va_cols, acquirefunc, relpages,
false, in_outer_xact, elevel);
/*
* If there are child tables, do recursive ANALYZE.
*/
if (onerel->rd_rel->relhassubclass)
- do_analyze_rel(onerel, vacstmt, acquirefunc, relpages,
+ do_analyze_rel(onerel, options, va_cols, acquirefunc, relpages,
true, in_outer_xact, elevel);
/*
@@ -302,7 +302,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
* acquirefunc for each child table.
*/
static void
-do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
+do_analyze_rel(Relation onerel, int options, List *va_cols,
AcquireSampleRowsFunc acquirefunc, BlockNumber relpages,
bool inh, bool in_outer_xact, int elevel)
{
@@ -372,14 +372,14 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
*
* Note that system attributes are never analyzed.
*/
- if (vacstmt->va_cols != NIL)
+ if (va_cols != NIL)
{
ListCell *le;
- vacattrstats = (VacAttrStats **) palloc(list_length(vacstmt->va_cols) *
+ vacattrstats = (VacAttrStats **) palloc(list_length(va_cols) *
sizeof(VacAttrStats *));
tcnt = 0;
- foreach(le, vacstmt->va_cols)
+ foreach(le, va_cols)
{
char *col = strVal(lfirst(le));
@@ -436,7 +436,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
thisdata->indexInfo = indexInfo = BuildIndexInfo(Irel[ind]);
thisdata->tupleFract = 1.0; /* fix later if partial */
- if (indexInfo->ii_Expressions != NIL && vacstmt->va_cols == NIL)
+ if (indexInfo->ii_Expressions != NIL && va_cols == NIL)
{
ListCell *indexpr_item = list_head(indexInfo->ii_Expressions);
@@ -595,7 +595,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by
* VACUUM.
*/
- if (!inh && !(vacstmt->options & VACOPT_VACUUM))
+ if (!inh && !(options & VACOPT_VACUUM))
{
for (ind = 0; ind < nindexes; ind++)
{
@@ -623,7 +623,7 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
pgstat_report_analyze(onerel, totalrows, totaldeadrows);
/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
- if (!(vacstmt->options & VACOPT_VACUUM))
+ if (!(options & VACOPT_VACUUM))
{
for (ind = 0; ind < nindexes; ind++)
{
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 74475684fc2..bd57b683d83 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -71,35 +71,79 @@ static void vac_truncate_clog(TransactionId frozenXID,
MultiXactId minMulti,
TransactionId lastSaneFrozenXid,
MultiXactId lastSaneMinMulti);
-static bool vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast,
- bool for_wraparound);
+static bool vacuum_rel(Oid relid, RangeVar *relation, int options,
+ VacuumParams *params);
+/*
+ * Primary entry point for manual VACUUM and ANALYZE commands
+ *
+ * This is mainly a preparation wrapper for the real operations that will
+ * happen in vacuum().
+ */
+void
+ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel)
+{
+ VacuumParams params;
+
+ /* sanity checks on options */
+ Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE));
+ Assert((vacstmt->options & VACOPT_VACUUM) ||
+ !(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE)));
+ Assert((vacstmt->options & VACOPT_ANALYZE) || vacstmt->va_cols == NIL);
+ Assert(!(vacstmt->options & VACOPT_SKIPTOAST));
+
+ /*
+ * All freeze ages are zero if the FREEZE option is given; otherwise pass
+ * them as -1 which means to use the default values.
+ */
+ if (vacstmt->options & VACOPT_FREEZE)
+ {
+ params.freeze_min_age = 0;
+ params.freeze_table_age = 0;
+ params.multixact_freeze_min_age = 0;
+ params.multixact_freeze_table_age = 0;
+ }
+ else
+ {
+ params.freeze_min_age = -1;
+ params.freeze_table_age = -1;
+ params.multixact_freeze_min_age = -1;
+ params.multixact_freeze_table_age = -1;
+ }
+
+ /* user-invoked vacuum is never "for wraparound" */
+ params.is_wraparound = false;
+
+ /* Now go through the common routine */
+ vacuum(vacstmt->options, vacstmt->relation, InvalidOid, &params,
+ vacstmt->va_cols, NULL, isTopLevel);
+}
/*
* Primary entry point for VACUUM and ANALYZE commands.
*
- * relid is normally InvalidOid; if it is not, then it provides the relation
- * OID to be processed, and vacstmt->relation is ignored. (The non-invalid
- * case is currently only used by autovacuum.)
+ * options is a bitmask of VacuumOption flags, indicating what to do.
*
- * do_toast is passed as FALSE by autovacuum, because it processes TOAST
- * tables separately.
+ * relid, if not InvalidOid, indicate the relation to process; otherwise,
+ * the RangeVar is used. (The latter must always be passed, because it's
+ * used for error messages.)
*
- * for_wraparound is used by autovacuum to let us know when it's forcing
- * a vacuum for wraparound, which should not be auto-canceled.
+ * params contains a set of parameters that can be used to customize the
+ * behavior.
+ *
+ * va_cols is a list of columns to analyze, or NIL to process them all.
*
* bstrategy is normally given as NULL, but in autovacuum it can be passed
* in to use the same buffer strategy object across multiple vacuum() calls.
*
* isTopLevel should be passed down from ProcessUtility.
*
- * It is the caller's responsibility that vacstmt and bstrategy
- * (if given) be allocated in a memory context that won't disappear
- * at transaction commit.
+ * It is the caller's responsibility that all parameters are allocated in a
+ * memory context that will not disappear at transaction commit.
*/
void
-vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
- BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
+vacuum(int options, RangeVar *relation, Oid relid, VacuumParams *params,
+ List *va_cols, BufferAccessStrategy bstrategy, bool isTopLevel)
{
const char *stmttype;
volatile bool in_outer_xact,
@@ -107,13 +151,9 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
List *relations;
static bool in_vacuum = false;
- /* sanity checks on options */
- Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE));
- Assert((vacstmt->options & VACOPT_VACUUM) ||
- !(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE)));
- Assert((vacstmt->options & VACOPT_ANALYZE) || vacstmt->va_cols == NIL);
+ Assert(params != NULL);
- stmttype = (vacstmt->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
+ stmttype = (options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
/*
* We cannot run VACUUM inside a user transaction block; if we were inside
@@ -123,7 +163,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
*
* ANALYZE (without VACUUM) can run either way.
*/
- if (vacstmt->options & VACOPT_VACUUM)
+ if (options & VACOPT_VACUUM)
{
PreventTransactionChain(isTopLevel, stmttype);
in_outer_xact = false;
@@ -143,7 +183,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
* Send info about dead objects to the statistics collector, unless we are
* in autovacuum --- autovacuum.c does this for itself.
*/
- if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
+ if ((options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
pgstat_vacuum_stat();
/*
@@ -175,7 +215,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
* Build list of relations to process, unless caller gave us one. (If we
* build one, we put it in vac_context for safekeeping.)
*/
- relations = get_rel_oids(relid, vacstmt->relation);
+ relations = get_rel_oids(relid, relation);
/*
* Decide whether we need to start/commit our own transactions.
@@ -191,11 +231,11 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
* transaction block, and also in an autovacuum worker, use own
* transactions so we can release locks sooner.
*/
- if (vacstmt->options & VACOPT_VACUUM)
+ if (options & VACOPT_VACUUM)
use_own_xacts = true;
else
{
- Assert(vacstmt->options & VACOPT_ANALYZE);
+ Assert(options & VACOPT_ANALYZE);
if (IsAutoVacuumWorkerProcess())
use_own_xacts = true;
else if (in_outer_xact)
@@ -245,13 +285,13 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
{
Oid relid = lfirst_oid(cur);
- if (vacstmt->options & VACOPT_VACUUM)
+ if (options & VACOPT_VACUUM)
{
- if (!vacuum_rel(relid, vacstmt, do_toast, for_wraparound))
+ if (!vacuum_rel(relid, relation, options, params))
continue;
}
- if (vacstmt->options & VACOPT_ANALYZE)
+ if (options & VACOPT_ANALYZE)
{
/*
* If using separate xacts, start one for analyze. Otherwise,
@@ -264,7 +304,8 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
PushActiveSnapshot(GetTransactionSnapshot());
}
- analyze_rel(relid, vacstmt, in_outer_xact, vac_strategy);
+ analyze_rel(relid, relation, options,
+ va_cols, in_outer_xact, vac_strategy);
if (use_own_xacts)
{
@@ -299,7 +340,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
StartTransactionCommand();
}
- if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
+ if ((options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
{
/*
* Update pg_database.datfrozenxid, and truncate pg_clog if possible.
@@ -1113,7 +1154,7 @@ vac_truncate_clog(TransactionId frozenXID,
* At entry and exit, we are not inside a transaction.
*/
static bool
-vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
+vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
{
LOCKMODE lmode;
Relation onerel;
@@ -1123,6 +1164,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
int save_sec_context;
int save_nestlevel;
+ Assert(params != NULL);
+
/* Begin a transaction for vacuuming this relation */
StartTransactionCommand();
@@ -1132,7 +1175,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
*/
PushActiveSnapshot(GetTransactionSnapshot());
- if (!(vacstmt->options & VACOPT_FULL))
+ if (!(options & VACOPT_FULL))
{
/*
* In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
@@ -1156,7 +1199,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
*/
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
MyPgXact->vacuumFlags |= PROC_IN_VACUUM;
- if (for_wraparound)
+ if (params->is_wraparound)
MyPgXact->vacuumFlags |= PROC_VACUUM_FOR_WRAPAROUND;
LWLockRelease(ProcArrayLock);
}
@@ -1172,7 +1215,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
* vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
* way, we can be sure that no other backend is vacuuming the same table.
*/
- lmode = (vacstmt->options & VACOPT_FULL) ? AccessExclusiveLock : ShareUpdateExclusiveLock;
+ lmode = (options & VACOPT_FULL) ? AccessExclusiveLock : ShareUpdateExclusiveLock;
/*
* Open the relation and get the appropriate lock on it.
@@ -1183,7 +1226,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
* If we've been asked not to wait for the relation lock, acquire it first
* in non-blocking mode, before calling try_relation_open().
*/
- if (!(vacstmt->options & VACOPT_NOWAIT))
+ if (!(options & VACOPT_NOWAIT))
onerel = try_relation_open(relid, lmode);
else if (ConditionalLockRelationOid(relid, lmode))
onerel = try_relation_open(relid, NoLock);
@@ -1194,7 +1237,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
ereport(LOG,
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
errmsg("skipping vacuum of \"%s\" --- lock not available",
- vacstmt->relation->relname)));
+ relation->relname)));
}
if (!onerel)
@@ -1286,7 +1329,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
* us to process it. In VACUUM FULL, though, the toast table is
* automatically rebuilt by cluster_rel so we shouldn't recurse to it.
*/
- if (do_toast && !(vacstmt->options & VACOPT_FULL))
+ if (!(options & VACOPT_SKIPTOAST) && !(options & VACOPT_FULL))
toast_relid = onerel->rd_rel->reltoastrelid;
else
toast_relid = InvalidOid;
@@ -1305,7 +1348,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
/*
* Do the actual work --- either FULL or "lazy" vacuum
*/
- if (vacstmt->options & VACOPT_FULL)
+ if (options & VACOPT_FULL)
{
/* close relation before vacuuming, but hold lock until commit */
relation_close(onerel, NoLock);
@@ -1313,10 +1356,10 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
/* VACUUM FULL is now a variant of CLUSTER; see cluster.c */
cluster_rel(relid, InvalidOid, false,
- (vacstmt->options & VACOPT_VERBOSE) != 0);
+ (options & VACOPT_VERBOSE) != 0);
}
else
- lazy_vacuum_rel(onerel, vacstmt, vac_strategy);
+ lazy_vacuum_rel(onerel, options, params, vac_strategy);
/* Roll back any GUC changes executed by index functions */
AtEOXact_GUC(false, save_nestlevel);
@@ -1342,7 +1385,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound)
* totally unimportant for toast relations.
*/
if (toast_relid != InvalidOid)
- vacuum_rel(toast_relid, vacstmt, false, for_wraparound);
+ vacuum_rel(toast_relid, relation, options, params);
/*
* Now release the session-level lock on the master table.
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 7d9e49eb330..cd5ca4c2f97 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -169,7 +169,7 @@ static bool heap_page_is_all_visible(Relation rel, Buffer buf,
* and locked the relation.
*/
void
-lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
+lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
BufferAccessStrategy bstrategy)
{
LVRelStats *vacrelstats;
@@ -193,6 +193,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
TransactionId new_frozen_xid;
MultiXactId new_min_multi;
+ Assert(params != NULL);
+
/* measure elapsed time iff autovacuum logging requires it */
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
{
@@ -200,7 +202,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
starttime = GetCurrentTimestamp();
}
- if (vacstmt->options & VACOPT_VERBOSE)
+ if (options & VACOPT_VERBOSE)
elevel = INFO;
else
elevel = DEBUG2;
@@ -208,9 +210,10 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
vac_strategy = bstrategy;
vacuum_set_xid_limits(onerel,
- vacstmt->freeze_min_age, vacstmt->freeze_table_age,
- vacstmt->multixact_freeze_min_age,
- vacstmt->multixact_freeze_table_age,
+ params->freeze_min_age,
+ params->freeze_table_age,
+ params->multixact_freeze_min_age,
+ params->multixact_freeze_table_age,
&OldestXmin, &FreezeLimit, &xidFullScanLimit,
&MultiXactCutoff, &mxactFullScanLimit);
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 3c6a964a659..029761e74f8 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3300,10 +3300,6 @@ _copyVacuumStmt(const VacuumStmt *from)
VacuumStmt *newnode = makeNode(VacuumStmt);
COPY_SCALAR_FIELD(options);
- COPY_SCALAR_FIELD(freeze_min_age);
- COPY_SCALAR_FIELD(freeze_table_age);
- COPY_SCALAR_FIELD(multixact_freeze_min_age);
- COPY_SCALAR_FIELD(multixact_freeze_table_age);
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(va_cols);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index fcd58ada3d0..190e50ab8c6 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1503,10 +1503,6 @@ static bool
_equalVacuumStmt(const VacuumStmt *a, const VacuumStmt *b)
{
COMPARE_SCALAR_FIELD(options);
- COMPARE_SCALAR_FIELD(freeze_min_age);
- COMPARE_SCALAR_FIELD(freeze_table_age);
- COMPARE_SCALAR_FIELD(multixact_freeze_min_age);
- COMPARE_SCALAR_FIELD(multixact_freeze_table_age);
COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(va_cols);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 149962035dc..82405b9d26f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -9034,12 +9034,10 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->options = VACOPT_VACUUM;
if ($2)
n->options |= VACOPT_FULL;
+ if ($3)
+ n->options |= VACOPT_FREEZE;
if ($4)
n->options |= VACOPT_VERBOSE;
- n->freeze_min_age = $3 ? 0 : -1;
- n->freeze_table_age = $3 ? 0 : -1;
- n->multixact_freeze_min_age = $3 ? 0 : -1;
- n->multixact_freeze_table_age = $3 ? 0 : -1;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
@@ -9050,12 +9048,10 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->options = VACOPT_VACUUM;
if ($2)
n->options |= VACOPT_FULL;
+ if ($3)
+ n->options |= VACOPT_FREEZE;
if ($4)
n->options |= VACOPT_VERBOSE;
- n->freeze_min_age = $3 ? 0 : -1;
- n->freeze_table_age = $3 ? 0 : -1;
- n->multixact_freeze_min_age = $3 ? 0 : -1;
- n->multixact_freeze_table_age = $3 ? 0 : -1;
n->relation = $5;
n->va_cols = NIL;
$$ = (Node *)n;
@@ -9066,30 +9062,16 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
n->options |= VACOPT_VACUUM;
if ($2)
n->options |= VACOPT_FULL;
+ if ($3)
+ n->options |= VACOPT_FREEZE;
if ($4)
n->options |= VACOPT_VERBOSE;
- n->freeze_min_age = $3 ? 0 : -1;
- n->freeze_table_age = $3 ? 0 : -1;
- n->multixact_freeze_min_age = $3 ? 0 : -1;
- n->multixact_freeze_table_age = $3 ? 0 : -1;
$$ = (Node *)n;
}
| VACUUM '(' vacuum_option_list ')'
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_VACUUM | $3;
- if (n->options & VACOPT_FREEZE)
- {
- n->freeze_min_age = n->freeze_table_age = 0;
- n->multixact_freeze_min_age = 0;
- n->multixact_freeze_table_age = 0;
- }
- else
- {
- n->freeze_min_age = n->freeze_table_age = -1;
- n->multixact_freeze_min_age = -1;
- n->multixact_freeze_table_age = -1;
- }
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *) n;
@@ -9098,18 +9080,6 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_VACUUM | $3;
- if (n->options & VACOPT_FREEZE)
- {
- n->freeze_min_age = n->freeze_table_age = 0;
- n->multixact_freeze_min_age = 0;
- n->multixact_freeze_table_age = 0;
- }
- else
- {
- n->freeze_min_age = n->freeze_table_age = -1;
- n->multixact_freeze_min_age = -1;
- n->multixact_freeze_table_age = -1;
- }
n->relation = $5;
n->va_cols = $6;
if (n->va_cols != NIL) /* implies analyze */
@@ -9137,10 +9107,6 @@ AnalyzeStmt:
n->options = VACOPT_ANALYZE;
if ($2)
n->options |= VACOPT_VERBOSE;
- n->freeze_min_age = -1;
- n->freeze_table_age = -1;
- n->multixact_freeze_min_age = -1;
- n->multixact_freeze_table_age = -1;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
@@ -9151,10 +9117,6 @@ AnalyzeStmt:
n->options = VACOPT_ANALYZE;
if ($2)
n->options |= VACOPT_VERBOSE;
- n->freeze_min_age = -1;
- n->freeze_table_age = -1;
- n->multixact_freeze_min_age = -1;
- n->multixact_freeze_table_age = -1;
n->relation = $3;
n->va_cols = $4;
$$ = (Node *)n;
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index ee556f3600d..5ccae24b25c 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -184,16 +184,11 @@ typedef struct av_relation
typedef struct autovac_table
{
Oid at_relid;
- bool at_dovacuum;
- bool at_doanalyze;
- int at_freeze_min_age;
- int at_freeze_table_age;
- int at_multixact_freeze_min_age;
- int at_multixact_freeze_table_age;
+ int at_vacoptions; /* bitmask of VacuumOption */
+ VacuumParams at_params;
int at_vacuum_cost_delay;
int at_vacuum_cost_limit;
bool at_dobalance;
- bool at_wraparound;
char *at_relname;
char *at_nspname;
char *at_datname;
@@ -2301,7 +2296,7 @@ do_autovacuum(void)
* next table in our list.
*/
HOLD_INTERRUPTS();
- if (tab->at_dovacuum)
+ if (tab->at_vacoptions & VACOPT_VACUUM)
errcontext("automatic vacuum of table \"%s.%s.%s\"",
tab->at_datname, tab->at_nspname, tab->at_relname);
else
@@ -2528,15 +2523,17 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
tab = palloc(sizeof(autovac_table));
tab->at_relid = relid;
- tab->at_dovacuum = dovacuum;
- tab->at_doanalyze = doanalyze;
- tab->at_freeze_min_age = freeze_min_age;
- tab->at_freeze_table_age = freeze_table_age;
- tab->at_multixact_freeze_min_age = multixact_freeze_min_age;
- tab->at_multixact_freeze_table_age = multixact_freeze_table_age;
+ tab->at_vacoptions = VACOPT_SKIPTOAST |
+ (dovacuum ? VACOPT_VACUUM : 0) |
+ (doanalyze ? VACOPT_ANALYZE : 0) |
+ (wraparound ? VACOPT_NOWAIT : 0);
+ tab->at_params.freeze_min_age = freeze_min_age;
+ tab->at_params.freeze_table_age = freeze_table_age;
+ tab->at_params.multixact_freeze_min_age = multixact_freeze_min_age;
+ tab->at_params.multixact_freeze_table_age = multixact_freeze_table_age;
+ tab->at_params.is_wraparound = wraparound;
tab->at_vacuum_cost_limit = vac_cost_limit;
tab->at_vacuum_cost_delay = vac_cost_delay;
- tab->at_wraparound = wraparound;
tab->at_relname = NULL;
tab->at_nspname = NULL;
tab->at_datname = NULL;
@@ -2737,39 +2734,22 @@ relation_needs_vacanalyze(Oid relid,
* Vacuum and/or analyze the specified table
*/
static void
-autovacuum_do_vac_analyze(autovac_table *tab,
- BufferAccessStrategy bstrategy)
+autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy)
{
- VacuumStmt vacstmt;
- RangeVar rangevar;
+ RangeVar rangevar;
/* Set up command parameters --- use local variables instead of palloc */
- MemSet(&vacstmt, 0, sizeof(vacstmt));
MemSet(&rangevar, 0, sizeof(rangevar));
rangevar.schemaname = tab->at_nspname;
rangevar.relname = tab->at_relname;
rangevar.location = -1;
- vacstmt.type = T_VacuumStmt;
- if (!tab->at_wraparound)
- vacstmt.options = VACOPT_NOWAIT;
- if (tab->at_dovacuum)
- vacstmt.options |= VACOPT_VACUUM;
- if (tab->at_doanalyze)
- vacstmt.options |= VACOPT_ANALYZE;
- vacstmt.freeze_min_age = tab->at_freeze_min_age;
- vacstmt.freeze_table_age = tab->at_freeze_table_age;
- vacstmt.multixact_freeze_min_age = tab->at_multixact_freeze_min_age;
- vacstmt.multixact_freeze_table_age = tab->at_multixact_freeze_table_age;
- /* we pass the OID, but might need this anyway for an error message */
- vacstmt.relation = &rangevar;
- vacstmt.va_cols = NIL;
-
/* Let pgstat know what we're doing */
autovac_report_activity(tab);
- vacuum(&vacstmt, tab->at_relid, false, bstrategy, tab->at_wraparound, true);
+ vacuum(tab->at_vacoptions, &rangevar, tab->at_relid, &tab->at_params, NIL,
+ bstrategy, true);
}
/*
@@ -2791,10 +2771,10 @@ autovac_report_activity(autovac_table *tab)
int len;
/* Report the command and possible options */
- if (tab->at_dovacuum)
+ if (tab->at_vacoptions & VACOPT_VACUUM)
snprintf(activity, MAX_AUTOVAC_ACTIV_LEN,
"autovacuum: VACUUM%s",
- tab->at_doanalyze ? " ANALYZE" : "");
+ tab->at_vacoptions & VACOPT_ANALYZE ? " ANALYZE" : "");
else
snprintf(activity, MAX_AUTOVAC_ACTIV_LEN,
"autovacuum: ANALYZE");
@@ -2806,7 +2786,7 @@ autovac_report_activity(autovac_table *tab)
snprintf(activity + len, MAX_AUTOVAC_ACTIV_LEN - len,
" %s.%s%s", tab->at_nspname, tab->at_relname,
- tab->at_wraparound ? " (to prevent wraparound)" : "");
+ tab->at_params.is_wraparound ? " (to prevent wraparound)" : "");
/* Set statement_timestamp() to current time for pg_stat_activity */
SetCurrentStatementStartTimestamp();
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 065475dda2a..d9443b1496a 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -627,7 +627,7 @@ standard_ProcessUtility(Node *parsetree,
/* we choose to allow this during "read only" transactions */
PreventCommandDuringRecovery((stmt->options & VACOPT_VACUUM) ?
"VACUUM" : "ANALYZE");
- vacuum(stmt, InvalidOid, true, NULL, false, isTopLevel);
+ ExecVacuum(stmt, isTopLevel);
}
break;
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index 4275484349d..9fd25169230 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -130,6 +130,19 @@ typedef struct VacAttrStats
int rowstride;
} VacAttrStats;
+/*
+ * Parameters customizing behavior of VACUUM and ANALYZE.
+ */
+typedef struct VacuumParams
+{
+ int freeze_min_age; /* min freeze age, -1 to use default */
+ int freeze_table_age; /* age at which to scan whole table */
+ int multixact_freeze_min_age; /* min multixact freeze age,
+ * -1 to use default */
+ int multixact_freeze_table_age; /* multixact age at which to
+ * scan whole table */
+ bool is_wraparound; /* force a for-wraparound vacuum */
+} VacuumParams;
/* GUC parameters */
extern PGDLLIMPORT int default_statistics_target; /* PGDLLIMPORT for
@@ -141,8 +154,10 @@ extern int vacuum_multixact_freeze_table_age;
/* in commands/vacuum.c */
-extern void vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
- BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel);
+extern void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel);
+extern void vacuum(int options, RangeVar *relation, Oid relid,
+ VacuumParams *params, List *va_cols,
+ BufferAccessStrategy bstrategy, bool isTopLevel);
extern void vac_open_indexes(Relation relation, LOCKMODE lockmode,
int *nindexes, Relation **Irel);
extern void vac_close_indexes(int nindexes, Relation *Irel, LOCKMODE lockmode);
@@ -171,12 +186,13 @@ extern void vac_update_datfrozenxid(void);
extern void vacuum_delay_point(void);
/* in commands/vacuumlazy.c */
-extern void lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
- BufferAccessStrategy bstrategy);
+extern void lazy_vacuum_rel(Relation onerel, int options,
+ VacuumParams *params, BufferAccessStrategy bstrategy);
/* in commands/analyze.c */
-extern void analyze_rel(Oid relid, VacuumStmt *vacstmt,
- bool in_outer_xact, BufferAccessStrategy bstrategy);
+extern void analyze_rel(Oid relid, RangeVar *relation, int options,
+ List *va_cols, bool in_outer_xact,
+ BufferAccessStrategy bstrategy);
extern bool std_typanalyze(VacAttrStats *stats);
extern double anl_random_fract(void);
extern double anl_init_selection_state(int n);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index a5753539a30..ec0d0eaa4ac 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2608,9 +2608,7 @@ typedef struct ClusterStmt
*
* Even though these are nominally two statements, it's convenient to use
* just one node type for both. Note that at least one of VACOPT_VACUUM
- * and VACOPT_ANALYZE must be set in options. VACOPT_FREEZE is an internal
- * convenience for the grammar and is not examined at runtime --- the
- * freeze_min_age and freeze_table_age fields are what matter.
+ * and VACOPT_ANALYZE must be set in options.
* ----------------------
*/
typedef enum VacuumOption
@@ -2620,19 +2618,14 @@ typedef enum VacuumOption
VACOPT_VERBOSE = 1 << 2, /* print progress info */
VACOPT_FREEZE = 1 << 3, /* FREEZE option */
VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */
- VACOPT_NOWAIT = 1 << 5 /* don't wait to get lock (autovacuum only) */
+ VACOPT_NOWAIT = 1 << 5, /* don't wait to get lock (autovacuum only) */
+ VACOPT_SKIPTOAST = 1 << 6 /* don't process the TOAST table, if any */
} VacuumOption;
typedef struct VacuumStmt
{
NodeTag type;
int options; /* OR of VacuumOption flags */
- int freeze_min_age; /* min freeze age, or -1 to use default */
- int freeze_table_age; /* age at which to scan whole table */
- int multixact_freeze_min_age; /* min multixact freeze age,
- * or -1 to use default */
- int multixact_freeze_table_age; /* multixact age at which to
- * scan whole table */
RangeVar *relation; /* single table to process, or NULL */
List *va_cols; /* list of column names, or NIL for all */
} VacuumStmt;