vacuum-options_20091113.patch
application/octet-stream
Filename: vacuum-options_20091113.patch
Type: application/octet-stream
Part: 0
Message:
Re: New VACUUM FULL
Patch
Format: context
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/vacuum.sgml | 1 | 0 |
| src/backend/commands/analyze.c | 5 | 5 |
| src/backend/commands/vacuum.c | 29 | 19 |
| src/backend/commands/vacuumlazy.c | 3 | 2 |
| src/backend/nodes/copyfuncs.c | 1 | 4 |
| src/backend/nodes/equalfuncs.c | 1 | 4 |
| src/backend/parser/gram.y | 61 | 20 |
| src/backend/postmaster/autovacuum.c | 4 | 4 |
| src/backend/tcop/utility.c | 1 | 1 |
| src/include/nodes/parsenodes.h | 11 | 4 |
| src/test/regress/expected/vacuum.out | 3 | 0 |
| src/test/regress/sql/vacuum.sql | 4 | 0 |
diff -cprN head/doc/src/sgml/ref/vacuum.sgml work/doc/src/sgml/ref/vacuum.sgml
*** head/doc/src/sgml/ref/vacuum.sgml 2009-03-25 05:17:08.000000000 +0900
--- work/doc/src/sgml/ref/vacuum.sgml 2009-11-13 10:17:39.141536000 +0900
*************** PostgreSQL documentation
*** 21,26 ****
--- 21,27 ----
<refsynopsisdiv>
<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 ] ANALYZE [ <replaceable class="PARAMETER">table</replaceable> [ (<replaceable class="PARAMETER">column</replaceable> [, ...] ) ] ]
</synopsis>
diff -cprN head/src/backend/commands/analyze.c work/src/backend/commands/analyze.c
*** head/src/backend/commands/analyze.c 2009-08-13 03:23:49.000000000 +0900
--- work/src/backend/commands/analyze.c 2009-11-13 10:00:02.275841676 +0900
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 135,141 ****
Oid save_userid;
bool save_secdefcxt;
! if (vacstmt->verbose)
elevel = INFO;
else
elevel = DEBUG2;
--- 135,141 ----
Oid save_userid;
bool save_secdefcxt;
! if (vacstmt->options & VACOPT_VERBOSE)
elevel = INFO;
else
elevel = DEBUG2;
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 173,179 ****
(pg_database_ownercheck(MyDatabaseId, GetUserId()) && !onerel->rd_rel->relisshared)))
{
/* No need for a WARNING if we already complained during VACUUM */
! if (!vacstmt->vacuum)
{
if (onerel->rd_rel->relisshared)
ereport(WARNING,
--- 173,179 ----
(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 (onerel->rd_rel->relisshared)
ereport(WARNING,
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 199,205 ****
if (onerel->rd_rel->relkind != RELKIND_RELATION)
{
/* No need for a WARNING if we already complained during VACUUM */
! if (!vacstmt->vacuum)
ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot analyze indexes, views, or special system tables",
RelationGetRelationName(onerel))));
--- 199,205 ----
if (onerel->rd_rel->relkind != RELKIND_RELATION)
{
/* No need for a WARNING if we already complained during VACUUM */
! if (!(vacstmt->options & VACOPT_VACUUM))
ereport(WARNING,
(errmsg("skipping \"%s\" --- cannot analyze indexes, views, or special system tables",
RelationGetRelationName(onerel))));
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 475,481 ****
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by
* VACUUM.
*/
! if (!vacstmt->vacuum)
{
for (ind = 0; ind < nindexes; ind++)
{
--- 475,481 ----
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by
* VACUUM.
*/
! if (!(vacstmt->options & VACOPT_VACUUM))
{
for (ind = 0; ind < nindexes; ind++)
{
*************** analyze_rel(Oid relid, VacuumStmt *vacst
*** 493,499 ****
cleanup:
/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
! if (!vacstmt->vacuum)
{
for (ind = 0; ind < nindexes; ind++)
{
--- 493,499 ----
cleanup:
/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
! if (!(vacstmt->options & VACOPT_VACUUM))
{
for (ind = 0; ind < nindexes; ind++)
{
diff -cprN head/src/backend/commands/vacuum.c work/src/backend/commands/vacuum.c
*** head/src/backend/commands/vacuum.c 2009-11-11 03:00:06.000000000 +0900
--- work/src/backend/commands/vacuum.c 2009-11-13 10:33:33.200912128 +0900
*************** void
*** 289,302 ****
vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
{
! const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE";
volatile MemoryContext anl_context = NULL;
volatile bool all_rels,
in_outer_xact,
use_own_xacts;
List *relations;
! if (vacstmt->verbose)
elevel = INFO;
else
elevel = DEBUG2;
--- 289,310 ----
vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast,
BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel)
{
! const char *stmttype;
volatile MemoryContext anl_context = NULL;
volatile bool all_rels,
in_outer_xact,
use_own_xacts;
List *relations;
! /* sanity checks */
! Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE));
! Assert(!(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE)) ||
! (vacstmt->options & VACOPT_VACUUM));
! Assert(vacstmt->va_cols == NIL || (vacstmt->options & VACOPT_ANALYZE));
!
! stmttype = (vacstmt->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
!
! if (vacstmt->options & VACOPT_VERBOSE)
elevel = INFO;
else
elevel = DEBUG2;
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 315,336 ****
*
* ANALYZE (without VACUUM) can run either way.
*/
! if (vacstmt->vacuum)
{
PreventTransactionChain(isTopLevel, stmttype);
in_outer_xact = false;
}
else
in_outer_xact = IsInTransactionChain(isTopLevel);
/*
- * Send info about dead objects to the statistics collector, unless we are
- * in autovacuum --- autovacuum.c does this for itself.
- */
- if (vacstmt->vacuum && !IsAutoVacuumWorkerProcess())
- pgstat_vacuum_stat();
-
- /*
* Create special memory context for cross-transaction storage.
*
* Since it is a child of PortalContext, it will go away eventually even
--- 323,344 ----
*
* ANALYZE (without VACUUM) can run either way.
*/
! if (vacstmt->options & VACOPT_VACUUM)
{
PreventTransactionChain(isTopLevel, stmttype);
in_outer_xact = false;
+
+ /*
+ * Send info about dead objects to the statistics collector, unless
+ * we are in autovacuum --- autovacuum.c does this for itself.
+ */
+ if (!IsAutoVacuumWorkerProcess())
+ pgstat_vacuum_stat();
}
else
in_outer_xact = IsInTransactionChain(isTopLevel);
/*
* Create special memory context for cross-transaction storage.
*
* Since it is a child of PortalContext, it will go away eventually even
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 378,388 ****
* transaction block, and also in an autovacuum worker, use own
* transactions so we can release locks sooner.
*/
! if (vacstmt->vacuum)
use_own_xacts = true;
else
{
! Assert(vacstmt->analyze);
if (IsAutoVacuumWorkerProcess())
use_own_xacts = true;
else if (in_outer_xact)
--- 386,396 ----
* transaction block, and also in an autovacuum worker, use own
* transactions so we can release locks sooner.
*/
! if (vacstmt->options & VACOPT_VACUUM)
use_own_xacts = true;
else
{
! Assert(vacstmt->options & VACOPT_ANALYZE);
if (IsAutoVacuumWorkerProcess())
use_own_xacts = true;
else if (in_outer_xact)
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 438,448 ****
Oid relid = lfirst_oid(cur);
bool scanned_all = false;
! if (vacstmt->vacuum)
vacuum_rel(relid, vacstmt, do_toast, for_wraparound,
&scanned_all);
! if (vacstmt->analyze)
{
MemoryContext old_context = NULL;
--- 446,456 ----
Oid relid = lfirst_oid(cur);
bool scanned_all = false;
! if (vacstmt->options & VACOPT_VACUUM)
vacuum_rel(relid, vacstmt, do_toast, for_wraparound,
&scanned_all);
! if (vacstmt->options & VACOPT_ANALYZE)
{
MemoryContext old_context = NULL;
*************** vacuum(VacuumStmt *vacstmt, Oid relid, b
*** 502,508 ****
StartTransactionCommand();
}
! if (vacstmt->vacuum && !IsAutoVacuumWorkerProcess())
{
/*
* Update pg_database.datfrozenxid, and truncate pg_clog if possible.
--- 510,516 ----
StartTransactionCommand();
}
! if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
{
/*
* Update pg_database.datfrozenxid, and truncate pg_clog if possible.
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 1034,1040 ****
*/
PushActiveSnapshot(GetTransactionSnapshot());
! if (!vacstmt->full)
{
/*
* In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
--- 1042,1048 ----
*/
PushActiveSnapshot(GetTransactionSnapshot());
! if (!(vacstmt->options & VACOPT_FULL))
{
/*
* In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 1074,1080 ****
* vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either
* way, we can be sure that no other backend is vacuuming the same table.
*/
! lmode = vacstmt->full ? AccessExclusiveLock : ShareUpdateExclusiveLock;
/*
* Open the relation and get the appropriate lock on it.
--- 1082,1090 ----
* 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;
/*
* Open the relation and get the appropriate lock on it.
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 1186,1192 ****
/*
* Do the actual work --- either FULL or "lazy" vacuum
*/
! if (vacstmt->full)
heldoff = full_vacuum_rel(onerel, vacstmt);
else
heldoff = lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all);
--- 1196,1202 ----
/*
* Do the actual work --- either FULL or "lazy" vacuum
*/
! if (vacstmt->options & VACOPT_FULL)
heldoff = full_vacuum_rel(onerel, vacstmt);
else
heldoff = lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all);
*************** full_vacuum_rel(Relation onerel, VacuumS
*** 1332,1338 ****
/* report results to the stats collector, too */
pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared,
! true, vacstmt->analyze, vacrelstats->rel_tuples);
return heldoff;
}
--- 1342,1348 ----
/* report results to the stats collector, too */
pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared,
! true, (vacstmt->options & VACOPT_ANALYZE) != 0, vacrelstats->rel_tuples);
return heldoff;
}
diff -cprN head/src/backend/commands/vacuumlazy.c work/src/backend/commands/vacuumlazy.c
*** head/src/backend/commands/vacuumlazy.c 2009-11-11 03:00:06.000000000 +0900
--- work/src/backend/commands/vacuumlazy.c 2009-11-13 10:00:02.277828910 +0900
*************** lazy_vacuum_rel(Relation onerel, VacuumS
*** 164,170 ****
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration > 0)
starttime = GetCurrentTimestamp();
! if (vacstmt->verbose)
elevel = INFO;
else
elevel = DEBUG2;
--- 164,170 ----
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration > 0)
starttime = GetCurrentTimestamp();
! if (vacstmt->options & VACOPT_VERBOSE)
elevel = INFO;
else
elevel = DEBUG2;
*************** lazy_vacuum_rel(Relation onerel, VacuumS
*** 236,242 ****
pgstat_report_vacuum(RelationGetRelid(onerel),
onerel->rd_rel->relisshared,
vacrelstats->scanned_all,
! vacstmt->analyze, vacrelstats->rel_tuples);
/* and log the action if appropriate */
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
--- 236,243 ----
pgstat_report_vacuum(RelationGetRelid(onerel),
onerel->rd_rel->relisshared,
vacrelstats->scanned_all,
! (vacstmt->options & VACOPT_ANALYZE) != 0,
! vacrelstats->rel_tuples);
/* and log the action if appropriate */
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
diff -cprN head/src/backend/nodes/copyfuncs.c work/src/backend/nodes/copyfuncs.c
*** head/src/backend/nodes/copyfuncs.c 2009-10-28 23:55:38.000000000 +0900
--- work/src/backend/nodes/copyfuncs.c 2009-11-13 10:00:02.278845497 +0900
*************** _copyVacuumStmt(VacuumStmt *from)
*** 2957,2966 ****
{
VacuumStmt *newnode = makeNode(VacuumStmt);
! COPY_SCALAR_FIELD(vacuum);
! COPY_SCALAR_FIELD(full);
! COPY_SCALAR_FIELD(analyze);
! COPY_SCALAR_FIELD(verbose);
COPY_SCALAR_FIELD(freeze_min_age);
COPY_SCALAR_FIELD(freeze_table_age);
COPY_NODE_FIELD(relation);
--- 2957,2963 ----
{
VacuumStmt *newnode = makeNode(VacuumStmt);
! COPY_SCALAR_FIELD(options);
COPY_SCALAR_FIELD(freeze_min_age);
COPY_SCALAR_FIELD(freeze_table_age);
COPY_NODE_FIELD(relation);
diff -cprN head/src/backend/nodes/equalfuncs.c work/src/backend/nodes/equalfuncs.c
*** head/src/backend/nodes/equalfuncs.c 2009-10-28 23:55:38.000000000 +0900
--- work/src/backend/nodes/equalfuncs.c 2009-11-13 10:00:02.279860288 +0900
*************** _equalDropdbStmt(DropdbStmt *a, DropdbSt
*** 1483,1492 ****
static bool
_equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
{
! COMPARE_SCALAR_FIELD(vacuum);
! COMPARE_SCALAR_FIELD(full);
! COMPARE_SCALAR_FIELD(analyze);
! COMPARE_SCALAR_FIELD(verbose);
COMPARE_SCALAR_FIELD(freeze_min_age);
COMPARE_SCALAR_FIELD(freeze_table_age);
COMPARE_NODE_FIELD(relation);
--- 1483,1489 ----
static bool
_equalVacuumStmt(VacuumStmt *a, VacuumStmt *b)
{
! COMPARE_SCALAR_FIELD(options);
COMPARE_SCALAR_FIELD(freeze_min_age);
COMPARE_SCALAR_FIELD(freeze_table_age);
COMPARE_NODE_FIELD(relation);
diff -cprN head/src/backend/parser/gram.y work/src/backend/parser/gram.y
*** head/src/backend/parser/gram.y 2009-11-12 05:31:26.000000000 +0900
--- work/src/backend/parser/gram.y 2009-11-13 10:29:38.737883224 +0900
*************** static TypeName *TableFuncTypeName(List
*** 229,234 ****
--- 229,235 ----
transaction_mode_item
%type <ival> opt_lock lock_type cast_context
+ %type <ival> vacuum_option_list vacuum_option_elem
%type <boolean> opt_force opt_or_replace
opt_grant_grant_option opt_grant_admin_option
opt_nowait opt_if_exists opt_with_data
*************** static TypeName *TableFuncTypeName(List
*** 484,490 ****
IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P
INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P
! INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
JOIN
--- 485,491 ----
IDENTITY_P IF_P ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P
INCLUDING INCREMENT INDEX INDEXES INHERIT INHERITS INITIALLY INLINE_P
! INNER_P INOUT INPLACE INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
JOIN
*************** cluster_index_specification:
*** 6625,6636 ****
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->vacuum = true;
! n->analyze = false;
! n->full = $2;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose = $4;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
--- 6626,6638 ----
VacuumStmt: VACUUM opt_full opt_freeze opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->options = VACOPT_VACUUM;
! if ($2)
! n->options |= VACOPT_FULL;
! if ($4)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
*************** VacuumStmt: VACUUM opt_full opt_freeze o
*** 6638,6649 ****
| VACUUM opt_full opt_freeze opt_verbose qualified_name
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->vacuum = true;
! n->analyze = false;
! n->full = $2;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose = $4;
n->relation = $5;
n->va_cols = NIL;
$$ = (Node *)n;
--- 6640,6652 ----
| VACUUM opt_full opt_freeze opt_verbose qualified_name
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->options = VACOPT_VACUUM;
! if ($2)
! n->options |= VACOPT_FULL;
! if ($4)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
n->relation = $5;
n->va_cols = NIL;
$$ = (Node *)n;
*************** VacuumStmt: VACUUM opt_full opt_freeze o
*** 6651,6675 ****
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
{
VacuumStmt *n = (VacuumStmt *) $5;
! n->vacuum = true;
! n->full = $2;
n->freeze_min_age = $3 ? 0 : -1;
n->freeze_table_age = $3 ? 0 : -1;
- n->verbose |= $4;
$$ = (Node *)n;
}
;
AnalyzeStmt:
analyze_keyword opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->vacuum = false;
! n->analyze = true;
! n->full = false;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
- n->verbose = $2;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
--- 6654,6717 ----
| VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt
{
VacuumStmt *n = (VacuumStmt *) $5;
! n->options |= VACOPT_VACUUM;
! if ($2)
! n->options |= VACOPT_FULL;
! if ($4)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = $3 ? 0 : -1;
n->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;
+ 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:
analyze_keyword opt_verbose
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->options = VACOPT_ANALYZE;
! if ($2)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
n->relation = NULL;
n->va_cols = NIL;
$$ = (Node *)n;
*************** AnalyzeStmt:
*** 6677,6688 ****
| analyze_keyword opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->vacuum = false;
! n->analyze = true;
! n->full = false;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
- n->verbose = $2;
n->relation = $3;
n->va_cols = $4;
$$ = (Node *)n;
--- 6719,6729 ----
| analyze_keyword opt_verbose qualified_name opt_name_list
{
VacuumStmt *n = makeNode(VacuumStmt);
! n->options = VACOPT_ANALYZE;
! if ($2)
! n->options |= VACOPT_VERBOSE;
n->freeze_min_age = -1;
n->freeze_table_age = -1;
n->relation = $3;
n->va_cols = $4;
$$ = (Node *)n;
diff -cprN head/src/backend/postmaster/autovacuum.c work/src/backend/postmaster/autovacuum.c
*** head/src/backend/postmaster/autovacuum.c 2009-09-01 04:40:59.000000000 +0900
--- work/src/backend/postmaster/autovacuum.c 2009-11-13 10:00:02.283848658 +0900
*************** autovacuum_do_vac_analyze(autovac_table
*** 2640,2651 ****
MemSet(&vacstmt, 0, sizeof(vacstmt));
vacstmt.type = T_VacuumStmt;
! vacstmt.vacuum = tab->at_dovacuum;
! vacstmt.full = false;
! vacstmt.analyze = tab->at_doanalyze;
vacstmt.freeze_min_age = tab->at_freeze_min_age;
vacstmt.freeze_table_age = tab->at_freeze_table_age;
- vacstmt.verbose = false;
vacstmt.relation = NULL; /* not used since we pass a relid */
vacstmt.va_cols = NIL;
--- 2640,2651 ----
MemSet(&vacstmt, 0, sizeof(vacstmt));
vacstmt.type = T_VacuumStmt;
! 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.relation = NULL; /* not used since we pass a relid */
vacstmt.va_cols = NIL;
diff -cprN head/src/backend/tcop/utility.c work/src/backend/tcop/utility.c
*** head/src/backend/tcop/utility.c 2009-10-26 11:26:40.000000000 +0900
--- work/src/backend/tcop/utility.c 2009-11-13 10:00:02.284847777 +0900
*************** CreateCommandTag(Node *parsetree)
*** 1815,1821 ****
break;
case T_VacuumStmt:
! if (((VacuumStmt *) parsetree)->vacuum)
tag = "VACUUM";
else
tag = "ANALYZE";
--- 1815,1821 ----
break;
case T_VacuumStmt:
! if (((VacuumStmt *) parsetree)->options & VACOPT_VACUUM)
tag = "VACUUM";
else
tag = "ANALYZE";
diff -cprN head/src/include/nodes/parsenodes.h work/src/include/nodes/parsenodes.h
*** head/src/include/nodes/parsenodes.h 2009-11-07 06:57:57.000000000 +0900
--- work/src/include/nodes/parsenodes.h 2009-11-13 10:04:59.222848463 +0900
*************** typedef struct ClusterStmt
*** 2212,2224 ****
* just one node type for both.
* ----------------------
*/
typedef struct VacuumStmt
{
NodeTag type;
! bool vacuum; /* do VACUUM step */
! 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_table_age; /* age at which to scan whole table */
RangeVar *relation; /* single table to process, or NULL */
--- 2212,2231 ----
* just one node type for both.
* ----------------------
*/
+
+ typedef enum VacuumOption
+ {
+ VACOPT_VACUUM = 1 << 0, /* do VACUUM */
+ VACOPT_ANALYZE = 1 << 1, /* do ANALYZE */
+ VACOPT_VERBOSE = 1 << 2, /* VERBOSE option */
+ VACOPT_FREEZE = 1 << 3, /* FREEZE option */
+ VACOPT_FULL = 1 << 4 /* FULL option */
+ } VacuumOption;
+
typedef struct VacuumStmt
{
NodeTag type;
! bits32 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 */
RangeVar *relation; /* single table to process, or NULL */
diff -cprN head/src/test/regress/expected/vacuum.out work/src/test/regress/expected/vacuum.out
*** head/src/test/regress/expected/vacuum.out 2002-07-20 13:58:14.000000000 +0900
--- work/src/test/regress/expected/vacuum.out 2009-11-13 10:15:10.348824551 +0900
*************** SELECT * FROM vactst;
*** 56,59 ****
--- 56,62 ----
---
(0 rows)
+ VACUUM (FULL) vactst;
+ VACUUM (FREEZE) vactst;
+ VACUUM (FULL, FREEZE) vactst;
DROP TABLE vactst;
diff -cprN head/src/test/regress/sql/vacuum.sql work/src/test/regress/sql/vacuum.sql
*** head/src/test/regress/sql/vacuum.sql 2002-07-20 13:58:14.000000000 +0900
--- work/src/test/regress/sql/vacuum.sql 2009-11-13 10:14:15.709830767 +0900
*************** VACUUM FULL vactst;
*** 39,42 ****
--- 39,46 ----
DELETE FROM vactst;
SELECT * FROM vactst;
+ VACUUM (FULL) vactst;
+ VACUUM (FREEZE) vactst;
+ VACUUM (FULL, FREEZE) vactst;
+
DROP TABLE vactst;