From 5e66a51c2eebaad4c0d78e3f776d74b2c5a0d1bc Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Mon, 16 Nov 2009 21:32:07 +0000 Subject: [PATCH] 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 --- doc/src/sgml/maintenance.sgml | 7 +-- doc/src/sgml/ref/vacuum.sgml | 15 +++++- src/backend/commands/analyze.c | 12 ++--- src/backend/commands/vacuum.c | 41 ++++++++------ src/backend/commands/vacuumlazy.c | 7 +-- src/backend/nodes/copyfuncs.c | 7 +-- src/backend/nodes/equalfuncs.c | 7 +-- src/backend/parser/gram.y | 81 +++++++++++++++++++++------- src/backend/postmaster/autovacuum.c | 11 ++-- src/backend/tcop/utility.c | 4 +- src/include/nodes/parsenodes.h | 21 +++++--- src/test/regress/expected/vacuum.out | 3 +- src/test/regress/sql/vacuum.sql | 4 +- 13 files changed, 146 insertions(+), 74 deletions(-) diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 80b6365226b..686a4e9d56d 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -1,4 +1,4 @@ -<!-- $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"> <title>Routine Database Maintenance Tasks</title> @@ -502,8 +502,9 @@ SELECT datname, age(datfrozenxid) FROM pg_database; only scans pages that have been modified since the last vacuum, but <structfield>relfrozenxid</> can only be advanced when the whole table is scanned. The whole table is scanned when <structfield>relfrozenxid</> is - more than <varname>vacuum_freeze_table_age</> transactions old, when the - <command>VACUUM FREEZE</> command is used, or when all pages happen to + more than <varname>vacuum_freeze_table_age</> transactions old, when + <command>VACUUM</>'s <literal>FREEZE</> option is used, or when all pages + happen to require vacuuming to remove dead row versions. When <command>VACUUM</> scans the whole table, after it's finished <literal>age(relfrozenxid)</> should be a little more than the <varname>vacuum_freeze_min_age</> setting diff --git a/doc/src/sgml/ref/vacuum.sgml b/doc/src/sgml/ref/vacuum.sgml index 205165e7176..3b5d241703d 100644 --- a/doc/src/sgml/ref/vacuum.sgml +++ b/doc/src/sgml/ref/vacuum.sgml @@ -1,5 +1,5 @@ <!-- -$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 --> @@ -21,6 +21,7 @@ PostgreSQL documentation <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> @@ -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 table while it is being processed. </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> @@ -127,6 +137,7 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER"> <listitem> <para> The name of a specific column to analyze. Defaults to all columns. + If a column list is specified, <literal>ANALYZE</> is implied. </para> </listitem> </varlistentry> @@ -214,7 +225,7 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ <replaceable class="PARAMETER"> table in the regression database: <programlisting> -regression=# VACUUM VERBOSE ANALYZE onek; +regression=# VACUUM (VERBOSE, ANALYZE) onek; INFO: vacuuming "public.onek" INFO: index "onek_unique1" now contains 1000 tuples in 14 pages DETAIL: 3000 index tuples were removed. diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 38cf57aba08..ab1fe9bf0eb 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -8,7 +8,7 @@ * * * 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, Oid save_userid; bool save_secdefcxt; - if (vacstmt->verbose) + if (vacstmt->options & VACOPT_VERBOSE) elevel = INFO; else elevel = DEBUG2; @@ -173,7 +173,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->vacuum) + if (!(vacstmt->options & VACOPT_VACUUM)) { if (onerel->rd_rel->relisshared) ereport(WARNING, @@ -199,7 +199,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, if (onerel->rd_rel->relkind != RELKIND_RELATION) { /* No need for a WARNING if we already complained during VACUUM */ - if (!vacstmt->vacuum) + if (!(vacstmt->options & VACOPT_VACUUM)) ereport(WARNING, (errmsg("skipping \"%s\" --- cannot analyze indexes, views, or special system tables", RelationGetRelationName(onerel)))); @@ -475,7 +475,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, * VACUUM ANALYZE, don't overwrite the accurate count already inserted by * VACUUM. */ - if (!vacstmt->vacuum) + if (!(vacstmt->options & VACOPT_VACUUM)) { for (ind = 0; ind < nindexes; ind++) { @@ -493,7 +493,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt, 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++) { diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index bb1a2077ffa..eeee7654e0e 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * 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 vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, BufferAccessStrategy bstrategy, bool for_wraparound, bool isTopLevel) { - const char *stmttype = vacstmt->vacuum ? "VACUUM" : "ANALYZE"; + const char *stmttype; volatile MemoryContext anl_context = NULL; volatile bool all_rels, in_outer_xact, use_own_xacts; 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; else elevel = DEBUG2; @@ -315,7 +323,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, * * ANALYZE (without VACUUM) can run either way. */ - if (vacstmt->vacuum) + if (vacstmt->options & VACOPT_VACUUM) { PreventTransactionChain(isTopLevel, stmttype); in_outer_xact = false; @@ -327,7 +335,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->vacuum && !IsAutoVacuumWorkerProcess()) + if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess()) pgstat_vacuum_stat(); /* @@ -378,11 +386,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->vacuum) + if (vacstmt->options & VACOPT_VACUUM) use_own_xacts = true; else { - Assert(vacstmt->analyze); + Assert(vacstmt->options & VACOPT_ANALYZE); if (IsAutoVacuumWorkerProcess()) use_own_xacts = true; else if (in_outer_xact) @@ -438,11 +446,11 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, Oid relid = lfirst_oid(cur); bool scanned_all = false; - if (vacstmt->vacuum) + if (vacstmt->options & VACOPT_VACUUM) vacuum_rel(relid, vacstmt, do_toast, for_wraparound, &scanned_all); - if (vacstmt->analyze) + if (vacstmt->options & VACOPT_ANALYZE) { MemoryContext old_context = NULL; @@ -502,7 +510,7 @@ vacuum(VacuumStmt *vacstmt, Oid relid, bool do_toast, StartTransactionCommand(); } - if (vacstmt->vacuum && !IsAutoVacuumWorkerProcess()) + if ((vacstmt->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess()) { /* * 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, */ PushActiveSnapshot(GetTransactionSnapshot()); - if (!vacstmt->full) + if (!(vacstmt->options & VACOPT_FULL)) { /* * 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, * 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; + lmode = (vacstmt->options & VACOPT_FULL) ? AccessExclusiveLock : ShareUpdateExclusiveLock; /* * 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, /* * Do the actual work --- either FULL or "lazy" vacuum */ - if (vacstmt->full) + if (vacstmt->options & VACOPT_FULL) heldoff = full_vacuum_rel(onerel, vacstmt); else heldoff = lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all); @@ -1331,8 +1339,11 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt) vacrelstats->hasindex, FreezeLimit); /* report results to the stats collector, too */ - pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared, - true, vacstmt->analyze, vacrelstats->rel_tuples); + pgstat_report_vacuum(RelationGetRelid(onerel), + onerel->rd_rel->relisshared, + true, + (vacstmt->options & VACOPT_ANALYZE) != 0, + vacrelstats->rel_tuples); return heldoff; } diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 92fee334ff4..50c96e948ea 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -29,7 +29,7 @@ * * * 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, if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration > 0) starttime = GetCurrentTimestamp(); - if (vacstmt->verbose) + if (vacstmt->options & VACOPT_VERBOSE) elevel = INFO; else elevel = DEBUG2; @@ -236,7 +236,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt, pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared, vacrelstats->scanned_all, - vacstmt->analyze, vacrelstats->rel_tuples); + (vacstmt->options & VACOPT_ANALYZE) != 0, + vacrelstats->rel_tuples); /* and log the action if appropriate */ if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0) diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index a9efce40532..b48909a3c5a 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * 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) { VacuumStmt *newnode = makeNode(VacuumStmt); - COPY_SCALAR_FIELD(vacuum); - COPY_SCALAR_FIELD(full); - COPY_SCALAR_FIELD(analyze); - COPY_SCALAR_FIELD(verbose); + COPY_SCALAR_FIELD(options); COPY_SCALAR_FIELD(freeze_min_age); COPY_SCALAR_FIELD(freeze_table_age); COPY_NODE_FIELD(relation); diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index d60d238be93..c69468ae7aa 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * 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) 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(options); COMPARE_SCALAR_FIELD(freeze_min_age); COMPARE_SCALAR_FIELD(freeze_table_age); COMPARE_NODE_FIELD(relation); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index a61729135bd..e80fffd3bed 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * 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 * AUTHOR DATE MAJOR EVENT @@ -229,6 +229,7 @@ static TypeName *TableFuncTypeName(List *columns); 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 @@ -6625,12 +6626,13 @@ cluster_index_specification: VacuumStmt: VACUUM opt_full opt_freeze opt_verbose { VacuumStmt *n = makeNode(VacuumStmt); - n->vacuum = true; - n->analyze = false; - n->full = $2; + 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->verbose = $4; n->relation = NULL; n->va_cols = NIL; $$ = (Node *)n; @@ -6638,12 +6640,13 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose | VACUUM opt_full opt_freeze opt_verbose qualified_name { VacuumStmt *n = makeNode(VacuumStmt); - n->vacuum = true; - n->analyze = false; - n->full = $2; + 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->verbose = $4; n->relation = $5; n->va_cols = NIL; $$ = (Node *)n; @@ -6651,25 +6654,64 @@ VacuumStmt: VACUUM opt_full opt_freeze opt_verbose | VACUUM opt_full opt_freeze opt_verbose AnalyzeStmt { VacuumStmt *n = (VacuumStmt *) $5; - n->vacuum = true; - n->full = $2; + 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->verbose |= $4; $$ = (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->vacuum = false; - n->analyze = true; - n->full = false; + n->options = VACOPT_ANALYZE; + if ($2) + n->options |= VACOPT_VERBOSE; n->freeze_min_age = -1; n->freeze_table_age = -1; - n->verbose = $2; n->relation = NULL; n->va_cols = NIL; $$ = (Node *)n; @@ -6677,12 +6719,11 @@ AnalyzeStmt: | analyze_keyword opt_verbose qualified_name opt_name_list { VacuumStmt *n = makeNode(VacuumStmt); - n->vacuum = false; - n->analyze = true; - n->full = false; + n->options = VACOPT_ANALYZE; + if ($2) + n->options |= VACOPT_VERBOSE; n->freeze_min_age = -1; n->freeze_table_age = -1; - n->verbose = $2; n->relation = $3; n->va_cols = $4; $$ = (Node *)n; diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 41bd37d72a6..e4ab771b7f6 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -55,7 +55,7 @@ * * * 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, MemSet(&vacstmt, 0, sizeof(vacstmt)); vacstmt.type = T_VacuumStmt; - vacstmt.vacuum = tab->at_dovacuum; - vacstmt.full = false; - vacstmt.analyze = tab->at_doanalyze; + vacstmt.options = 0; + 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.verbose = false; vacstmt.relation = NULL; /* not used since we pass a relid */ vacstmt.va_cols = NIL; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 025a03f19a9..f0ef9d6406f 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * 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) break; case T_VacuumStmt: - if (((VacuumStmt *) parsetree)->vacuum) + if (((VacuumStmt *) parsetree)->options & VACOPT_VACUUM) tag = "VACUUM"; else tag = "ANALYZE"; diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 2384e38ab7d..b51f1d9892f 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * 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 * Vacuum and Analyze Statements * * 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 { 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 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 --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out index 1a578a0c9b5..1a139d03773 100644 --- a/src/test/regress/expected/vacuum.out +++ b/src/test/regress/expected/vacuum.out @@ -49,11 +49,12 @@ SELECT count(*) FROM vactst; (1 row) DELETE FROM vactst WHERE i != 0; -VACUUM FULL vactst; +VACUUM (FULL) vactst; DELETE FROM vactst; SELECT * FROM vactst; i --- (0 rows) +VACUUM (FULL, FREEZE) vactst; DROP TABLE vactst; diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql index 368499ac4c6..e1686971c96 100644 --- a/src/test/regress/sql/vacuum.sql +++ b/src/test/regress/sql/vacuum.sql @@ -35,8 +35,10 @@ INSERT INTO vactst SELECT * FROM vactst; INSERT INTO vactst VALUES (0); SELECT count(*) FROM vactst; DELETE FROM vactst WHERE i != 0; -VACUUM FULL vactst; +VACUUM (FULL) vactst; DELETE FROM vactst; SELECT * FROM vactst; +VACUUM (FULL, FREEZE) vactst; + DROP TABLE vactst; -- GitLab