Provide a parenthesized-options syntax for VACUUM, analogous to that recently
authorTom Lane
Mon, 16 Nov 2009 21:32:07 +0000 (21:32 +0000)
committerTom Lane
Mon, 16 Nov 2009 21:32:07 +0000 (21:32 +0000)
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

13 files changed:
doc/src/sgml/maintenance.sgml
doc/src/sgml/ref/vacuum.sgml
src/backend/commands/analyze.c
src/backend/commands/vacuum.c
src/backend/commands/vacuumlazy.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/postmaster/autovacuum.c
src/backend/tcop/utility.c
src/include/nodes/parsenodes.h
src/test/regress/expected/vacuum.out
src/test/regress/sql/vacuum.sql

index 80b6365226b8377b4678f924f9ad8fc921751958..686a4e9d56d9c445746518c8173d23c348439183 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
  Routine Database Maintenance Tasks
@@ -502,8 +502,9 @@ SELECT datname, age(datfrozenxid) FROM pg_database;
     only scans pages that have been modified since the last vacuum, but
     relfrozenxid can only be advanced when the whole table is
     scanned. The whole table is scanned when relfrozenxid is
-    more than vacuum_freeze_table_age transactions old, when the
-    VACUUM FREEZE command is used, or when all pages happen to
+    more than vacuum_freeze_table_age transactions old, when
+    VACUUM's FREEZE option is used, or when all pages
+    happen to
     require vacuuming to remove dead row versions. When VACUUM
     scans the whole table, after it's finished age(relfrozenxid)
     should be a little more than the vacuum_freeze_min_age setting
index 205165e7176338053558a00a266d4f3a7c05a287..3b5d241703da75a9ee232ca6172cc5b020d4a857 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -21,6 +21,7 @@ PostgreSQL documentation
 
  
 
+VACUUM [ ( { FULL | FREEZE | VERBOSE | ANALYZE } [, ...] ) ] [ table [ (column [, ...] ) ] ]
 VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ table ]
 VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
 
@@ -63,6 +64,15 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ 
    blocks.  This form is much slower and requires an exclusive lock on each
    table while it is being processed.
   
+
+  
+   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 PostgreSQL 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.
+  
  
 
  
@@ -127,6 +137,7 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ 
     
      
       The name of a specific column to analyze. Defaults to all columns.
+      If a column list is specified, ANALYZE is implied.
      
     
    
@@ -214,7 +225,7 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ 
    table in the regression database:
 
 
-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.
index 38cf57aba08a022f8623b9d1ca7594d7c04f94c6..ab1fe9bf0eba9d73a2ee4ca60101c628158e1b65 100644 (file)
@@ -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++)
        {
index bb1a2077ffa9aed063d50d3ad2966216d64feb73..eeee7654e0e47aad0594f1850dad4265dcdf465c 100644 (file)
@@ -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;
 }
index 92fee334ff4030c91461567cb2ca7193814023bf..50c96e948ead142b8a7ebe200559d9ec909943e2 100644 (file)
@@ -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)
index a9efce40532a8a92ba5ef9c7a91be932ad8f60c3..b48909a3c5ad783f5157d2bdc5ed0aa237cd5853 100644 (file)
@@ -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);
index d60d238be93e2f33ea8a078922a3472da3d7be3b..c69468ae7aab9bea04e0be884794c3d364029234 100644 (file)
@@ -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);
index a61729135bd70dd40309ed1361b7b6242cb80c61..e80fffd3bed105b19b20058dcba1e828de2958be 100644 (file)
@@ -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    opt_lock lock_type cast_context
+%type    vacuum_option_list vacuum_option_elem
 %type     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;
index 41bd37d72a655fdd062f428cd1e8ca5c45563e9b..e4ab771b7f6ccebf88d0997587c1641d279c8a62 100644 (file)
@@ -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;
 
index 025a03f19a931a5e1e9736626bd670675c0cf4eb..f0ef9d6406fc6f35435aab0179eb4dad58f63389 100644 (file)
@@ -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";
index 2384e38ab7db90cb628c409947edff9c1a47ddaf..b51f1d9892f6c51f222cc9e30e0dc5ad6547e749 100644 (file)
@@ -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 */
index 1a578a0c9b5c1c42dcd6298ad5f489401eb554e1..1a139d03773e920f0889fa72459888a978729db3 100644 (file)
@@ -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;
index 368499ac4c676c2acd6cd2c82eccb03b00f6b914..e1686971c967427971cb5382f2b6a2b3b7c119f8 100644 (file)
@@ -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;