提交 5e66a51c 编写于 作者: T Tom Lane

Provide a parenthesized-options syntax for VACUUM, analogous to that recently

adopted for EXPLAIN.  This will allow additional options to be implemented
in future without having to make them fully-reserved keywords.  The old syntax
remains available for existing options, however.

Itagaki Takahiro
上级 49ed392c
<!-- $PostgreSQL: pgsql/doc/src/sgml/maintenance.sgml,v 1.96 2009/08/07 20:54:31 alvherre Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/maintenance.sgml,v 1.97 2009/11/16 21:32:06 tgl Exp $ -->
<chapter id="maintenance"> <chapter id="maintenance">
<title>Routine Database Maintenance Tasks</title> <title>Routine Database Maintenance Tasks</title>
...@@ -502,8 +502,9 @@ SELECT datname, age(datfrozenxid) FROM pg_database; ...@@ -502,8 +502,9 @@ SELECT datname, age(datfrozenxid) FROM pg_database;
only scans pages that have been modified since the last vacuum, but only scans pages that have been modified since the last vacuum, but
<structfield>relfrozenxid</> can only be advanced when the whole table is <structfield>relfrozenxid</> can only be advanced when the whole table is
scanned. The whole table is scanned when <structfield>relfrozenxid</> is scanned. The whole table is scanned when <structfield>relfrozenxid</> is
more than <varname>vacuum_freeze_table_age</> transactions old, when the more than <varname>vacuum_freeze_table_age</> transactions old, when
<command>VACUUM FREEZE</> command is used, or when all pages happen to <command>VACUUM</>'s <literal>FREEZE</> option is used, or when all pages
happen to
require vacuuming to remove dead row versions. When <command>VACUUM</> require vacuuming to remove dead row versions. When <command>VACUUM</>
scans the whole table, after it's finished <literal>age(relfrozenxid)</> scans the whole table, after it's finished <literal>age(relfrozenxid)</>
should be a little more than the <varname>vacuum_freeze_min_age</> setting should be a little more than the <varname>vacuum_freeze_min_age</> setting
......
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/vacuum.sgml,v 1.55 2009/03/24 20:17:08 tgl Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/vacuum.sgml,v 1.56 2009/11/16 21:32:06 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -21,6 +21,7 @@ PostgreSQL documentation ...@@ -21,6 +21,7 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
VACUUM [ ( { FULL | FREEZE | VERBOSE | ANALYZE } [, ...] ) ] [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> ] VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ <replaceable class="PARAMETER">table</replaceable> ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ] VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ]
</synopsis> </synopsis>
...@@ -63,6 +64,15 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER"> ...@@ -63,6 +64,15 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">
blocks. This form is much slower and requires an exclusive lock on each blocks. This form is much slower and requires an exclusive lock on each
table while it is being processed. table while it is being processed.
</para> </para>
<para>
When the option list is surrounded by parentheses, the options can be
written in any order. Without parentheses, options must be specified
in exactly the order shown above.
Prior to <productname>PostgreSQL</productname> 8.5, the unparenthesized
syntax was the only one supported. It is expected that all new options
will be supported only in the parenthesized syntax.
</para>
</refsect1> </refsect1>
<refsect1> <refsect1>
...@@ -127,6 +137,7 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER"> ...@@ -127,6 +137,7 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">
<listitem> <listitem>
<para> <para>
The name of a specific column to analyze. Defaults to all columns. The name of a specific column to analyze. Defaults to all columns.
If a column list is specified, <literal>ANALYZE</> is implied.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
...@@ -214,7 +225,7 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER"> ...@@ -214,7 +225,7 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER">
table in the regression database: table in the regression database:
<programlisting> <programlisting>
regression=# VACUUM VERBOSE ANALYZE onek; regression=# VACUUM (VERBOSE, ANALYZE) onek;
INFO: vacuuming "public.onek" INFO: vacuuming "public.onek"
INFO: index "onek_unique1" now contains 1000 tuples in 14 pages INFO: index "onek_unique1" now contains 1000 tuples in 14 pages
DETAIL: 3000 index tuples were removed. DETAIL: 3000 index tuples were removed.
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.141 2009/08/12 18:23:49 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.142 2009/11/16 21:32:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -135,7 +135,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -135,7 +135,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
Oid save_userid; Oid save_userid;
bool save_secdefcxt; bool save_secdefcxt;
if (vacstmt->verbose) if (vacstmt->options & VACOPT_VERBOSE)
elevel = INFO; elevel = INFO;
else else
elevel = DEBUG2; elevel = DEBUG2;
...@@ -173,7 +173,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -173,7 +173,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
(pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared))) (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
{ {
/* No need for a WARNING if we already complained during VACUUM */ /* No need for a WARNING if we already complained during VACUUM */
if (!vacstmt->vacuum) if (!(vacstmt->options & VACOPT_VACUUM))
{ {
if (onerel->rd_rel->relisshared) if (onerel->rd_rel->relisshared)
ereport(WARNING, ereport(WARNING,
...@@ -199,7 +199,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -199,7 +199,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
if (onerel->rd_rel->relkind != RELKIND_RELATION) if (onerel->rd_rel->relkind != RELKIND_RELATION)
{ {
/* No need for a WARNING if we already complained during VACUUM */ /* No need for a WARNING if we already complained during VACUUM */
if (!vacstmt->vacuum) if (!(vacstmt->options & VACOPT_VACUUM))
ereport(WARNING, ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot analyze indexes, views, or special system tables", (errmsg("skipping \"%s\" --- cannot analyze indexes, views, or special system tables",
RelationGetRelationName(onerel)))); RelationGetRelationName(onerel))));
...@@ -475,7 +475,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -475,7 +475,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by * VACUUM ANALYZE, don't overwrite the accurate count already inserted by
* VACUUM. * VACUUM.
*/ */
if (!vacstmt->vacuum) if (!(vacstmt->options & VACOPT_VACUUM))
{ {
for (ind = 0; ind < nindexes; ind++) for (ind = 0; ind < nindexes; ind++)
{ {
...@@ -493,7 +493,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, ...@@ -493,7 +493,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
cleanup: cleanup:
/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */ /* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
if (!vacstmt->vacuum) if (!(vacstmt->options & VACOPT_VACUUM))
{ {
for (ind = 0; ind < nindexes; ind++) for (ind = 0; ind < nindexes; ind++)
{ {
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.395 2009/11/10 18:00:06 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.396 2009/11/16 21:32:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -289,14 +289,22 @@ void ...@@ -289,14 +289,22 @@ void
vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel) BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
{ {
const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE"; const char *stmttype;
volatile MemoryContext anl_context = NULL; volatile MemoryContext anl_context = NULL;
volatile bool all_rels, volatile bool all_rels,
in_outer_xact, in_outer_xact,
use_own_xacts; use_own_xacts;
List *relations; List *relations;
if (vacstmt->verbose) /* 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);
stmttype = (vacstmt->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
if (vacstmt->options & VACOPT_VERBOSE)
elevel = INFO; elevel = INFO;
else else
elevel = DEBUG2; elevel = DEBUG2;
...@@ -315,7 +323,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, ...@@ -315,7 +323,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
* *
* ANALYZE (without VACUUM) can run either way. * ANALYZE (without VACUUM) can run either way.
*/ */
if (vacstmt->vacuum) if (vacstmt->options & VACOPT_VACUUM)
{ {
PreventTransactionChain(isTopLevel, stmttype); PreventTransactionChain(isTopLevel, stmttype);
in_outer_xact = false; in_outer_xact = false;
...@@ -327,7 +335,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, ...@@ -327,7 +335,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
* Send info about dead objects to the statistics collector, unless we are * Send info about dead objects to the statistics collector, unless we are
* in autovacuum --- autovacuum.c does this for itself. * in autovacuum --- autovacuum.c does this for itself.
*/ */
if (vacstmt->vacuum && !IsAutoVacuumWorkerProcess()) if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
pgstat_vacuum_stat(); pgstat_vacuum_stat();
/* /*
...@@ -378,11 +386,11 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, ...@@ -378,11 +386,11 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
* transaction block, and also in an autovacuum worker, use own * transaction block, and also in an autovacuum worker, use own
* transactions so we can release locks sooner. * transactions so we can release locks sooner.
*/ */
if (vacstmt->vacuum) if (vacstmt->options & VACOPT_VACUUM)
use_own_xacts = true; use_own_xacts = true;
else else
{ {
Assert(vacstmt->analyze); Assert(vacstmt->options & VACOPT_ANALYZE);
if (IsAutoVacuumWorkerProcess()) if (IsAutoVacuumWorkerProcess())
use_own_xacts = true; use_own_xacts = true;
else if (in_outer_xact) else if (in_outer_xact)
...@@ -438,11 +446,11 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, ...@@ -438,11 +446,11 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
Oid relid = lfirst_oid(cur); Oid relid = lfirst_oid(cur);
bool scanned_all = false; bool scanned_all = false;
if (vacstmt->vacuum) if (vacstmt->options & VACOPT_VACUUM)
vacuum_rel(relid, vacstmt, do_toast, for_wraparound, vacuum_rel(relid, vacstmt, do_toast, for_wraparound,
&scanned_all); &scanned_all);
if (vacstmt->analyze) if (vacstmt->options & VACOPT_ANALYZE)
{ {
MemoryContext old_context = NULL; MemoryContext old_context = NULL;
...@@ -502,7 +510,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, ...@@ -502,7 +510,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
StartTransactionCommand(); StartTransactionCommand();
} }
if (vacstmt->vacuum && !IsAutoVacuumWorkerProcess()) if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
{ {
/* /*
* Update pg_database.datfrozenxid, and truncate pg_clog if possible. * Update pg_database.datfrozenxid, and truncate pg_clog if possible.
...@@ -1034,7 +1042,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound, ...@@ -1034,7 +1042,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
*/ */
PushActiveSnapshot(GetTransactionSnapshot()); PushActiveSnapshot(GetTransactionSnapshot());
if (!vacstmt->full) if (!(vacstmt->options & VACOPT_FULL))
{ {
/* /*
* In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets * In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
...@@ -1074,7 +1082,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound, ...@@ -1074,7 +1082,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
* vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either * vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
* way, we can be sure that no other backend is vacuuming the same table. * way, we can be sure that no other backend is vacuuming the same table.
*/ */
lmode = vacstmt->full ? AccessExclusiveLock : ShareUpdateExclusiveLock; lmode = (vacstmt->options & VACOPT_FULL) ? AccessExclusiveLock : ShareUpdateExclusiveLock;
/* /*
* Open the relation and get the appropriate lock on it. * Open the relation and get the appropriate lock on it.
...@@ -1186,7 +1194,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound, ...@@ -1186,7 +1194,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
/* /*
* Do the actual work --- either FULL or "lazy" vacuum * Do the actual work --- either FULL or "lazy" vacuum
*/ */
if (vacstmt->full) if (vacstmt->options & VACOPT_FULL)
heldoff = full_vacuum_rel(onerel, vacstmt); heldoff = full_vacuum_rel(onerel, vacstmt);
else else
heldoff = lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all); heldoff = lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all);
...@@ -1331,8 +1339,11 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) ...@@ -1331,8 +1339,11 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
vacrelstats->hasindex, FreezeLimit); vacrelstats->hasindex, FreezeLimit);
/* report results to the stats collector, too */ /* report results to the stats collector, too */
pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared, pgstat_report_vacuum(RelationGetRelid(onerel),
true, vacstmt->analyze, vacrelstats->rel_tuples); onerel->rd_rel->relisshared,
true,
(vacstmt->options & VACOPT_ANALYZE) != 0,
vacrelstats->rel_tuples);
return heldoff; return heldoff;
} }
......
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.123 2009/11/10 18:00:06 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.124 2009/11/16 21:32:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -164,7 +164,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, ...@@ -164,7 +164,7 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration > 0) if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration > 0)
starttime = GetCurrentTimestamp(); starttime = GetCurrentTimestamp();
if (vacstmt->verbose) if (vacstmt->options & VACOPT_VERBOSE)
elevel = INFO; elevel = INFO;
else else
elevel = DEBUG2; elevel = DEBUG2;
...@@ -236,7 +236,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, ...@@ -236,7 +236,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
pgstat_report_vacuum(RelationGetRelid(onerel), pgstat_report_vacuum(RelationGetRelid(onerel),
onerel->rd_rel->relisshared, onerel->rd_rel->relisshared,
vacrelstats->scanned_all, vacrelstats->scanned_all,
vacstmt->analyze, vacrelstats->rel_tuples); (vacstmt->options & VACOPT_ANALYZE) != 0,
vacrelstats->rel_tuples);
/* and log the action if appropriate */ /* and log the action if appropriate */
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0) if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.450 2009/10/28 14:55:38 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.451 2009/11/16 21:32:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2957,10 +2957,7 @@ _copyVacuumStmt(VacuumStmt *from) ...@@ -2957,10 +2957,7 @@ _copyVacuumStmt(VacuumStmt *from)
{ {
VacuumStmt *newnode = makeNode(VacuumStmt); VacuumStmt *newnode = makeNode(VacuumStmt);
COPY_SCALAR_FIELD(vacuum); COPY_SCALAR_FIELD(options);
COPY_SCALAR_FIELD(full);
COPY_SCALAR_FIELD(analyze);
COPY_SCALAR_FIELD(verbose);
COPY_SCALAR_FIELD(freeze_min_age); COPY_SCALAR_FIELD(freeze_min_age);
COPY_SCALAR_FIELD(freeze_table_age); COPY_SCALAR_FIELD(freeze_table_age);
COPY_NODE_FIELD(relation); COPY_NODE_FIELD(relation);
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.372 2009/10/28 14:55:38 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.373 2009/11/16 21:32:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1483,10 +1483,7 @@ _equalDropdbStmt(DropdbStmt *a, DropdbStmt *b) ...@@ -1483,10 +1483,7 @@ _equalDropdbStmt(DropdbStmt *a, DropdbStmt *b)
static bool static bool
_equalVacuumStmt(VacuumStmt *a, VacuumStmt *b) _equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
{ {
COMPARE_SCALAR_FIELD(vacuum); COMPARE_SCALAR_FIELD(options);
COMPARE_SCALAR_FIELD(full);
COMPARE_SCALAR_FIELD(analyze);
COMPARE_SCALAR_FIELD(verbose);
COMPARE_SCALAR_FIELD(freeze_min_age); COMPARE_SCALAR_FIELD(freeze_min_age);
COMPARE_SCALAR_FIELD(freeze_table_age); COMPARE_SCALAR_FIELD(freeze_table_age);
COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(relation);
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.692 2009/11/11 20:31:26 alvherre Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.693 2009/11/16 21:32:06 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -229,6 +229,7 @@ static TypeName *TableFuncTypeName(List *columns); ...@@ -229,6 +229,7 @@ static TypeName *TableFuncTypeName(List *columns);
transaction_mode_item transaction_mode_item
%type <ival> opt_lock lock_type cast_context %type <ival> opt_lock lock_type cast_context
%type <ival> vacuum_option_list vacuum_option_elem
%type <boolean> opt_force opt_or_replace %type <boolean> opt_force opt_or_replace
opt_grant_grant_option opt_grant_admin_option opt_grant_grant_option opt_grant_admin_option
opt_nowait opt_if_exists opt_with_data opt_nowait opt_if_exists opt_with_data
...@@ -6625,12 +6626,13 @@ cluster_index_specification: ...@@ -6625,12 +6626,13 @@ cluster_index_specification:
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{ {
VacuumStmt *n = makeNode(VacuumStmt); VacuumStmt *n = makeNode(VacuumStmt);
n->vacuum = true; n->options = VACOPT_VACUUM;
n->analyze = false; if ($2)
n->full = $2; n->options |= VACOPT_FULL;
if ($4)
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1; n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1; n->freeze_table_age = $3 ? 0 : -1;
n->verbose = $4;
n->relation = NULL; n->relation = NULL;
n->va_cols = NIL; n->va_cols = NIL;
$$ = (Node *)n; $$ = (Node *)n;
...@@ -6638,12 +6640,13 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose ...@@ -6638,12 +6640,13 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
| VACUUM opt_full opt_freeze opt_verbose qualified_name | VACUUM opt_full opt_freeze opt_verbose qualified_name
{ {
VacuumStmt *n = makeNode(VacuumStmt); VacuumStmt *n = makeNode(VacuumStmt);
n->vacuum = true; n->options = VACOPT_VACUUM;
n->analyze = false; if ($2)
n->full = $2; n->options |= VACOPT_FULL;
if ($4)
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1; n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1; n->freeze_table_age = $3 ? 0 : -1;
n->verbose = $4;
n->relation = $5; n->relation = $5;
n->va_cols = NIL; n->va_cols = NIL;
$$ = (Node *)n; $$ = (Node *)n;
...@@ -6651,25 +6654,64 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose ...@@ -6651,25 +6654,64 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt | VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
{ {
VacuumStmt *n = (VacuumStmt *) $5; VacuumStmt *n = (VacuumStmt *) $5;
n->vacuum = true; n->options |= VACOPT_VACUUM;
n->full = $2; if ($2)
n->options |= VACOPT_FULL;
if ($4)
n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1; n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1; n->freeze_table_age = $3 ? 0 : -1;
n->verbose |= $4;
$$ = (Node *)n; $$ = (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;
else
n->freeze_min_age = n->freeze_table_age = -1;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *) n;
}
| VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
n->options = VACOPT_VACUUM | $3;
if (n->options & VACOPT_FREEZE)
n->freeze_min_age = n->freeze_table_age = 0;
else
n->freeze_min_age = n->freeze_table_age = -1;
n->relation = $5;
n->va_cols = $6;
if (n->va_cols != NIL) /* implies analyze */
n->options |= VACOPT_ANALYZE;
$$ = (Node *) n;
}
;
vacuum_option_list:
vacuum_option_elem { $$ = $1; }
| vacuum_option_list ',' vacuum_option_elem { $$ = $1 | $3; }
;
vacuum_option_elem:
analyze_keyword { $$ = VACOPT_ANALYZE; }
| VERBOSE { $$ = VACOPT_VERBOSE; }
| FREEZE { $$ = VACOPT_FREEZE; }
| FULL { $$ = VACOPT_FULL; }
; ;
AnalyzeStmt: AnalyzeStmt:
analyze_keyword opt_verbose analyze_keyword opt_verbose
{ {
VacuumStmt *n = makeNode(VacuumStmt); VacuumStmt *n = makeNode(VacuumStmt);
n->vacuum = false; n->options = VACOPT_ANALYZE;
n->analyze = true; if ($2)
n->full = false; n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1; n->freeze_min_age = -1;
n->freeze_table_age = -1; n->freeze_table_age = -1;
n->verbose = $2;
n->relation = NULL; n->relation = NULL;
n->va_cols = NIL; n->va_cols = NIL;
$$ = (Node *)n; $$ = (Node *)n;
...@@ -6677,12 +6719,11 @@ AnalyzeStmt: ...@@ -6677,12 +6719,11 @@ AnalyzeStmt:
| analyze_keyword opt_verbose qualified_name opt_name_list | analyze_keyword opt_verbose qualified_name opt_name_list
{ {
VacuumStmt *n = makeNode(VacuumStmt); VacuumStmt *n = makeNode(VacuumStmt);
n->vacuum = false; n->options = VACOPT_ANALYZE;
n->analyze = true; if ($2)
n->full = false; n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1; n->freeze_min_age = -1;
n->freeze_table_age = -1; n->freeze_table_age = -1;
n->verbose = $2;
n->relation = $3; n->relation = $3;
n->va_cols = $4; n->va_cols = $4;
$$ = (Node *)n; $$ = (Node *)n;
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.104 2009/08/31 19:40:59 tgl Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.105 2009/11/16 21:32:06 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2640,12 +2640,13 @@ autovacuum_do_vac_analyze(autovac_table *tab, ...@@ -2640,12 +2640,13 @@ autovacuum_do_vac_analyze(autovac_table *tab,
MemSet(&vacstmt, 0, sizeof(vacstmt)); MemSet(&vacstmt, 0, sizeof(vacstmt));
vacstmt.type = T_VacuumStmt; vacstmt.type = T_VacuumStmt;
vacstmt.vacuum = tab->at_dovacuum; vacstmt.options = 0;
vacstmt.full = false; if (tab->at_dovacuum)
vacstmt.analyze = tab->at_doanalyze; vacstmt.options |= VACOPT_VACUUM;
if (tab->at_doanalyze)
vacstmt.options |= VACOPT_ANALYZE;
vacstmt.freeze_min_age = tab->at_freeze_min_age; vacstmt.freeze_min_age = tab->at_freeze_min_age;
vacstmt.freeze_table_age = tab->at_freeze_table_age; vacstmt.freeze_table_age = tab->at_freeze_table_age;
vacstmt.verbose = false;
vacstmt.relation = NULL; /* not used since we pass a relid */ vacstmt.relation = NULL; /* not used since we pass a relid */
vacstmt.va_cols = NIL; vacstmt.va_cols = NIL;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.316 2009/10/26 02:26:40 tgl Exp $ * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.317 2009/11/16 21:32:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1815,7 +1815,7 @@ CreateCommandTag(Node *parsetree) ...@@ -1815,7 +1815,7 @@ CreateCommandTag(Node *parsetree)
break; break;
case T_VacuumStmt: case T_VacuumStmt:
if (((VacuumStmt *) parsetree)->vacuum) if (((VacuumStmt *) parsetree)->options & VACOPT_VACUUM)
tag = "VACUUM"; tag = "VACUUM";
else else
tag = "ANALYZE"; tag = "ANALYZE";
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.414 2009/11/13 23:44:19 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.415 2009/11/16 21:32:07 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2209,16 +2209,25 @@ typedef struct ClusterStmt ...@@ -2209,16 +2209,25 @@ typedef struct ClusterStmt
* Vacuum and Analyze Statements * Vacuum and Analyze Statements
* *
* Even though these are nominally two statements, it's convenient to use * Even though these are nominally two statements, it's convenient to use
* just one node type for both. * 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.
* ---------------------- * ----------------------
*/ */
typedef enum VacuumOption
{
VACOPT_VACUUM = 1 << 0, /* do VACUUM */
VACOPT_ANALYZE = 1 << 1, /* do ANALYZE */
VACOPT_VERBOSE = 1 << 2, /* print progress info */
VACOPT_FREEZE = 1 << 3, /* FREEZE option */
VACOPT_FULL = 1 << 4 /* FULL (non-concurrent) vacuum */
} VacuumOption;
typedef struct VacuumStmt typedef struct VacuumStmt
{ {
NodeTag type; NodeTag type;
bool vacuum; /* do VACUUM step */ int options; /* OR of VacuumOption flags */
bool full; /* do FULL (non-concurrent) vacuum */
bool analyze; /* do ANALYZE step */
bool verbose; /* print progress info */
int freeze_min_age; /* min freeze age, or -1 to use default */ int freeze_min_age; /* min freeze age, or -1 to use default */
int freeze_table_age; /* age at which to scan whole table */ int freeze_table_age; /* age at which to scan whole table */
RangeVar *relation; /* single table to process, or NULL */ RangeVar *relation; /* single table to process, or NULL */
......
...@@ -49,11 +49,12 @@ SELECT count(*) FROM vactst; ...@@ -49,11 +49,12 @@ SELECT count(*) FROM vactst;
(1 row) (1 row)
DELETE FROM vactst WHERE i != 0; DELETE FROM vactst WHERE i != 0;
VACUUM FULL vactst; VACUUM (FULL) vactst;
DELETE FROM vactst; DELETE FROM vactst;
SELECT * FROM vactst; SELECT * FROM vactst;
i i
--- ---
(0 rows) (0 rows)
VACUUM (FULL, FREEZE) vactst;
DROP TABLE vactst; DROP TABLE vactst;
...@@ -35,8 +35,10 @@ INSERT INTO vactst SELECT * FROM vactst; ...@@ -35,8 +35,10 @@ INSERT INTO vactst SELECT * FROM vactst;
INSERT INTO vactst VALUES (0); INSERT INTO vactst VALUES (0);
SELECT count(*) FROM vactst; SELECT count(*) FROM vactst;
DELETE FROM vactst WHERE i != 0; DELETE FROM vactst WHERE i != 0;
VACUUM FULL vactst; VACUUM (FULL) vactst;
DELETE FROM vactst; DELETE FROM vactst;
SELECT * FROM vactst; SELECT * FROM vactst;
VACUUM (FULL, FREEZE) vactst;
DROP TABLE vactst; DROP TABLE vactst;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册