Index: doc/src/sgml/catalogs.sgml
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/doc/src/sgml/catalogs.sgml,v
retrieving revision 2.191
diff -c -p -r2.191 catalogs.sgml
*** doc/src/sgml/catalogs.sgml	22 Jan 2009 20:15:59 -0000	2.191
--- doc/src/sgml/catalogs.sgml	23 Jan 2009 15:30:29 -0000
***************
*** 89,99 ****
       </row>
  
       <row>
-       <entry><link linkend="catalog-pg-autovacuum"><structname>pg_autovacuum</structname></link></entry>
-       <entry>per-relation autovacuum configuration parameters</entry>
-      </row>
- 
-      <row>
        <entry><link linkend="catalog-pg-cast"><structname>pg_cast</structname></link></entry>
        <entry>casts (data type conversions)</entry>
       </row>
--- 89,94 ----
***************
*** 1256,1433 ****
   </sect1>
  
  
-  <sect1 id="catalog-pg-autovacuum">
-   <title><structname>pg_autovacuum</structname></title>
- 
-   <indexterm zone="catalog-pg-autovacuum">
-    <primary>pg_autovacuum</primary>
-   </indexterm>
- 
-   <indexterm zone="catalog-pg-autovacuum">
-    <primary>autovacuum</primary>
-    <secondary>table-specific configuration</secondary>
-   </indexterm>
- 
-   <para>
-    The catalog <structname>pg_autovacuum</structname> stores optional
-    per-relation configuration parameters for the autovacuum daemon.
-    If there is an entry here for a particular relation, the given
-    parameters will be used for autovacuuming that table.  If no entry
-    is present, the system-wide defaults will be used. For more information
-    about the autovacuum daemon, see <xref linkend="autovacuum">.
-   </para>
- 
-   <note>
-    <para>
-     It is likely that <structname>pg_autovacuum</structname> will disappear
-     in a future release, with the information instead being kept in
-     <structname>pg_class</>.<structfield>reloptions</> entries.
-    </para>
-   </note>
- 
-   <table>
-    <title><structname>pg_autovacuum</> Columns</title>
- 
-    <tgroup cols=4>
-     <thead>
-      <row>
-       <entry>Name</entry>
-       <entry>Type</entry>
-       <entry>References</entry>
-       <entry>Description</entry>
-      </row>
-     </thead>
- 
-     <tbody>
-      <row>
-       <entry><structfield>vacrelid</structfield></entry>
-       <entry><type>oid</type></entry>
-       <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
-       <entry>The table this entry is for</entry>
-      </row>
- 
-      <row>
-       <entry><structfield>enabled</structfield></entry>
-       <entry><type>bool</type></entry>
-       <entry></entry>
-       <entry>If false, this table will not be autovacuumed, except
-        to prevent transaction ID wraparound</entry>
-      </row>
- 
-      <row>
-       <entry><structfield>vac_base_thresh</structfield></entry>
-       <entry><type>integer</type></entry>
-       <entry></entry>
-       <entry>Minimum number of modified tuples before vacuum</entry>
-      </row>
- 
-      <row>
-       <entry><structfield>vac_scale_factor</structfield></entry>
-       <entry><type>float4</type></entry>
-       <entry></entry>
-       <entry>Multiplier for <structfield>reltuples</> to add to
-        <structfield>vac_base_thresh</></entry>
-      </row>
- 
-      <row>
-       <entry><structfield>anl_base_thresh</structfield></entry>
-       <entry><type>integer</type></entry>
-       <entry></entry>
-       <entry>Minimum number of modified tuples before analyze</entry>
-      </row>
- 
-      <row>
-       <entry><structfield>anl_scale_factor</structfield></entry>
-       <entry><type>float4</type></entry>
-       <entry></entry>
-       <entry>Multiplier for <structfield>reltuples</> to add to
-        <structfield>anl_base_thresh</></entry>
-      </row>
- 
-      <row>
-       <entry><structfield>vac_cost_delay</structfield></entry>
-       <entry><type>integer</type></entry>
-       <entry></entry>
-       <entry>Custom <varname>vacuum_cost_delay</> parameter</entry>
-      </row>
- 
-      <row>
-       <entry><structfield>vac_cost_limit</structfield></entry>
-       <entry><type>integer</type></entry>
-       <entry></entry>
-       <entry>Custom <varname>vacuum_cost_limit</> parameter</entry>
-      </row>
- 
-      <row>
-       <entry><structfield>freeze_min_age</structfield></entry>
-       <entry><type>integer</type></entry>
-       <entry></entry>
-       <entry>Custom <varname>vacuum_freeze_min_age</> parameter</entry>
-      </row>
- 
-      <row>
-       <entry><structfield>freeze_max_age</structfield></entry>
-       <entry><type>integer</type></entry>
-       <entry></entry>
-       <entry>Custom <varname>autovacuum_freeze_max_age</> parameter</entry>
-      </row>
- 
-      <row>
-       <entry><structfield>freeze_table_age</structfield></entry>
-       <entry><type>integer</type></entry>
-       <entry></entry>
-       <entry>Custom <varname>vacuum_freeze_table_age</> parameter</entry>
-      </row>
-     </tbody>
-    </tgroup>
-   </table>
- 
-   <para>
-    The autovacuum daemon will initiate a <command>VACUUM</> operation
-    on a particular table when the number of updated or deleted tuples
-    exceeds <structfield>vac_base_thresh</structfield> plus
-    <structfield>vac_scale_factor</structfield> times the number of
-    live tuples currently estimated to be in the relation.
-    Similarly, it will initiate an <command>ANALYZE</> operation
-    when the number of inserted, updated or deleted tuples
-    exceeds <structfield>anl_base_thresh</structfield> plus
-    <structfield>anl_scale_factor</structfield> times the number of
-    live tuples currently estimated to be in the relation.
-   </para>
- 
-   <para>
-    Also, the autovacuum daemon will perform a <command>VACUUM</> operation
-    to prevent transaction ID wraparound if the table's
-    <structname>pg_class</>.<structfield>relfrozenxid</> field attains an age
-    of more than <structfield>freeze_max_age</> transactions, whether the table
-    has been changed or not, even if
-    <structname>pg_autovacuum</>.<structfield>enabled</> is set to
-    <literal>false</> for it.  The system will launch autovacuum to perform
-    such <command>VACUUM</>s even if autovacuum is otherwise disabled.
-    See <xref linkend="vacuum-for-wraparound"> for more about wraparound
-    prevention.
-   </para>
- 
-   <para>
-    Any of the numerical fields can contain <literal>-1</> (or indeed
-    any negative value) to indicate that the system-wide default should
-    be used for this particular value.  Observe that the
-    <structfield>vac_cost_delay</> variable inherits its default value from the
-    <xref linkend="guc-autovacuum-vacuum-cost-delay"> configuration parameter,
-    or from <xref linkend="guc-vacuum-cost-delay"> if the former is set to a
-    negative value.  The same applies to <structfield>vac_cost_limit</>.
-    Also, autovacuum will ignore attempts to set a per-table
-    <structfield>freeze_max_age</> larger than the system-wide setting (it can
-    only be set smaller), and the <structfield>freeze_min_age</> value will be
-    limited to half the system-wide <xref
-    linkend="guc-autovacuum-freeze-max-age"> setting.  Note that while you
-    can set <structfield>freeze_max_age</> very small, or even zero, this
-    is usually unwise since it will force frequent vacuuming.
-   </para>
- 
-  </sect1>
- 
- 
   <sect1 id="catalog-pg-cast">
    <title><structname>pg_cast</structname></title>
  
--- 1251,1256 ----
Index: doc/src/sgml/config.sgml
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/doc/src/sgml/config.sgml,v
retrieving revision 1.206
diff -c -p -r1.206 config.sgml
*** doc/src/sgml/config.sgml	16 Jan 2009 13:27:23 -0000	1.206
--- doc/src/sgml/config.sgml	16 Jan 2009 16:48:50 -0000
*************** COPY postgres_log FROM '/full/path/to/lo
*** 3548,3554 ****
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_autovacuum</>.
         </para>
        </listitem>
       </varlistentry>
--- 3548,3554 ----
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_class</>.<structfield>reloptions</>.
         </para>
        </listitem>
       </varlistentry>
*************** COPY postgres_log FROM '/full/path/to/lo
*** 3566,3572 ****
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_autovacuum</>.
         </para>
        </listitem>
       </varlistentry>
--- 3566,3572 ----
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_class</>.<structfield>reloptions</>.
         </para>
        </listitem>
       </varlistentry>
*************** COPY postgres_log FROM '/full/path/to/lo
*** 3585,3591 ****
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_autovacuum</>.
         </para>
        </listitem>
       </varlistentry>
--- 3585,3591 ----
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_class</>.<structfield>reloptions</>.
         </para>
        </listitem>
       </varlistentry>
*************** COPY postgres_log FROM '/full/path/to/lo
*** 3604,3610 ****
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_autovacuum</>.
         </para>
        </listitem>
       </varlistentry>
--- 3604,3610 ----
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_class</>.<structfield>reloptions</>.
         </para>
        </listitem>
       </varlistentry>
*************** COPY postgres_log FROM '/full/path/to/lo
*** 3625,3631 ****
          The default is 200 million transactions.
          This parameter can only be set at server start, but the setting
          can be reduced for individual tables by entries in
!         <structname>pg_autovacuum</>.
          For more information see <xref linkend="vacuum-for-wraparound">.
         </para>
        </listitem>
--- 3625,3631 ----
          The default is 200 million transactions.
          This parameter can only be set at server start, but the setting
          can be reduced for individual tables by entries in
!         <structname>pg_class</>.<structfield>reloptions</>.
          For more information see <xref linkend="vacuum-for-wraparound">.
         </para>
        </listitem>
*************** COPY postgres_log FROM '/full/path/to/lo
*** 3646,3652 ****
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_autovacuum</>.
         </para>
        </listitem>
       </varlistentry>
--- 3646,3652 ----
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_class</>.<structfield>reloptions</>.
         </para>
        </listitem>
       </varlistentry>
*************** COPY postgres_log FROM '/full/path/to/lo
*** 3668,3674 ****
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_autovacuum</>.
         </para>
        </listitem>
       </varlistentry>
--- 3668,3674 ----
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by entries in
!         <structname>pg_class</>.<structfield>reloptions</>.
         </para>
        </listitem>
       </varlistentry>
Index: doc/src/sgml/maintenance.sgml
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/doc/src/sgml/maintenance.sgml,v
retrieving revision 1.89
diff -c -p -r1.89 maintenance.sgml
*** doc/src/sgml/maintenance.sgml	16 Jan 2009 13:27:23 -0000	1.89
--- doc/src/sgml/maintenance.sgml	16 Jan 2009 17:04:19 -0000
*************** analyze threshold = analyze base thresho
*** 604,668 ****
     <para>
      The default thresholds and scale factors are taken from
      <filename>postgresql.conf</filename>, but it is possible to override them
!     on a table-by-table basis by making entries in the system catalog
      <link
!     linkend="catalog-pg-autovacuum"><structname>pg_autovacuum</></link>.
!     If a <structname>pg_autovacuum</structname> row exists for a particular
!     table, the settings it specifies are applied; otherwise the global
!     settings are used.  See <xref linkend="runtime-config-autovacuum"> for
!     more details on the global settings.
     </para>
  
     <para>
!     Besides the base threshold values and scale factors, there are five
!     more parameters that can be set for each table in
!     <structname>pg_autovacuum</structname>.
!     The first, <structname>pg_autovacuum</>.<structfield>enabled</>,
      can be set to <literal>false</literal> to instruct the autovacuum daemon
      to skip that particular table entirely.  In this case
      autovacuum will only touch the table if it must do so
      to prevent transaction ID wraparound.
      The next two parameters, the vacuum cost delay
!     (<structname>pg_autovacuum</structname>.<structfield>vac_cost_delay</structfield>)
!     and the vacuum cost limit
!     (<structname>pg_autovacuum</structname>.<structfield>vac_cost_limit</structfield>),
!     are used to set table-specific values for the
      <xref linkend="runtime-config-resource-vacuum-cost" endterm="runtime-config-resource-vacuum-cost-title">
      feature.
!     The last two parameters,
!     (<structname>pg_autovacuum</structname>.<structfield>freeze_min_age</structfield>)
!     and
!     (<structname>pg_autovacuum</structname>.<structfield>freeze_max_age</structfield>),
!     are used to set table-specific values for
!     <xref linkend="guc-vacuum-freeze-min-age"> and
!     <xref linkend="guc-autovacuum-freeze-max-age"> respectively.
     </para>
  
     <para>
!     If any of the values in <structname>pg_autovacuum</structname>
!     are set to a negative number, or if a row is not present at all in
!     <structname>pg_autovacuum</structname> for any particular table, the
!     corresponding values from <filename>postgresql.conf</filename> are used.
     </para>
  
     <para>
!     There is not currently any support for making
!     <structname>pg_autovacuum</structname> entries, except by doing
!     manual <command>INSERT</>s into the catalog.  This feature will be
!     improved in future releases, and it is likely that the catalog
!     definition will change.
     </para>
  
-    <caution>
-     <para>
-      The contents of the <structname>pg_autovacuum</structname> system
-      catalog are currently not saved in database dumps created by the
-      tools <application>pg_dump</> and <application>pg_dumpall</>.  If
-      you want to preserve them across a dump/reload cycle, make sure
-      you dump the catalog manually.
-     </para>
-    </caution>
- 
     <para>
      When multiple workers are running, the cost limit is
      <quote>balanced</quote> among all the running workers, so that the
--- 604,657 ----
     <para>
      The default thresholds and scale factors are taken from
      <filename>postgresql.conf</filename>, but it is possible to override them
!     on a table-by-table basis by specifying options in the system catalog column
      <link
!     linkend="catalog-pg-class"><structname>pg_class</>.<structfield>reloptions</></link>.
! 	If there is options in <structname>pg_class</>.<structfield>reloptions</>
! 	for a particular table, the settings it specifies are applied; otherwise the
! 	global settings are used. See <xref linkend="runtime-config-autovacuum"> for
! 	more details on the global settings.
     </para>
  
     <para>
!     Besides the base threshold values and scale factors, there are six
!     more autovacuum parameters that can be set for each table in
!     <structname>pg_class</structname>.<structfield>reloptions</>.
!     The first, <literal>autovacuum_enabled</>,
      can be set to <literal>false</literal> to instruct the autovacuum daemon
      to skip that particular table entirely.  In this case
      autovacuum will only touch the table if it must do so
      to prevent transaction ID wraparound.
      The next two parameters, the vacuum cost delay
!     (<literal>autovacuum_vac_cost_delay</literal>) and the vacuum cost limit
! 	(<literal>autovacuum_vac_cost_limit</literal>), are used to set
! 	table-specific values for the
      <xref linkend="runtime-config-resource-vacuum-cost" endterm="runtime-config-resource-vacuum-cost-title">
      feature.
!     The last three parameters, (<literal>autovacuum_freeze_min_age</literal>),
! 	(<literal>autovacuum_freeze_max_age</literal> and
!     <literal>autovacuum_freeze_table_age</literal>), are used to set
! 	table-specific values for <xref linkend="guc-vacuum-freeze-min-age">,
!     <xref linkend="guc-autovacuum-freeze-max-age"> and
!     <xref linkend="guc-vacuum-freeze-table-age"> respectively.
     </para>
  
     <para>
!     If any of the autovacuum-specific values in
! 	<structname>pg_class</structname>.<structfield>reloptions</>
!     are not set, the corresponding values from 
! 	<filename>postgresql.conf</filename> are used.
     </para>
  
     <para>
!    The <literal>WITH</> clause can specify autovacuum-specific parameters for
!    tables while creating them. Similarly, <literal>RESET</> can be used to reset
!    autovacuum parameters to their defaults and <literal>SET</> can be used to
!    add new autovacuum parameters. These parameters are documented in <xref
!    linkend="SQL-CREATETABLE-relation-parameters"
!    endterm="SQL-CREATETABLE-relation-parameters-title">.
     </para>
  
     <para>
      When multiple workers are running, the cost limit is
      <quote>balanced</quote> among all the running workers, so that the
Index: doc/src/sgml/ref/alter_index.sgml
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/doc/src/sgml/ref/alter_index.sgml,v
retrieving revision 1.14
diff -c -p -r1.14 alter_index.sgml
*** doc/src/sgml/ref/alter_index.sgml	14 Nov 2008 10:22:45 -0000	1.14
--- doc/src/sgml/ref/alter_index.sgml	19 Dec 2008 23:50:39 -0000
*************** ALTER INDEX <replaceable class="PARAMETE
*** 75,80 ****
--- 75,90 ----
      </listitem>
     </varlistentry>
  
+      <varlistentry>
+       <term><replaceable class="PARAMETER">value</replaceable></term>
+       <listitem>
+        <para>
+         The new value for a storage parameter.
+         This might be a number or a word depending on the parameter.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
     <varlistentry>
      <term><literal>RESET ( <replaceable class="PARAMETER">storage_parameter</replaceable> [, ... ] )</literal></term>
      <listitem>
Index: doc/src/sgml/ref/create_index.sgml
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/doc/src/sgml/ref/create_index.sgml,v
retrieving revision 1.69
diff -c -p -r1.69 create_index.sgml
*** doc/src/sgml/ref/create_index.sgml	14 Nov 2008 10:22:46 -0000	1.69
--- doc/src/sgml/ref/create_index.sgml	19 Dec 2008 23:50:39 -0000
*************** CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ]
*** 231,237 ****
        <listitem>
         <para>
          The name of an index-method-specific storage parameter.  See
!         below for details.
         </para>
        </listitem>
       </varlistentry>
--- 231,248 ----
        <listitem>
         <para>
          The name of an index-method-specific storage parameter.  See
!         <xref linkend="SQL-CREATEINDEX-storage-parameters" endterm="SQL-CREATEINDEX-storage-parameters-title">
!         for details.
!        </para>
!       </listitem>
!      </varlistentry>
! 
!      <varlistentry>
!       <term><replaceable class="PARAMETER">value</replaceable></term>
!       <listitem>
!        <para>
!         The new value for a storage parameter.
!         This might be a number or a word depending on the parameter.
         </para>
        </listitem>
       </varlistentry>
Index: doc/src/sgml/ref/create_table.sgml
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/doc/src/sgml/ref/create_table.sgml,v
retrieving revision 1.111
diff -c -p -r1.111 create_table.sgml
*** doc/src/sgml/ref/create_table.sgml	14 Nov 2008 10:22:46 -0000	1.111
--- doc/src/sgml/ref/create_table.sgml	19 Dec 2008 23:50:39 -0000
*************** and <replaceable class="PARAMETER">table
*** 690,703 ****
      for tables, and for indexes associated with a <literal>UNIQUE</literal> or
      <literal>PRIMARY KEY</literal> constraint.  Storage parameters for
      indexes are documented in <xref linkend="SQL-CREATEINDEX"
!     endterm="sql-createindex-title">.  The only storage parameter currently
!     available for tables is:
     </para>
  
     <variablelist>
  
     <varlistentry>
!     <term><literal>FILLFACTOR</></term>
      <listitem>
       <para>
        The fillfactor for a table is a percentage between 10 and 100.
--- 690,703 ----
      for tables, and for indexes associated with a <literal>UNIQUE</literal> or
      <literal>PRIMARY KEY</literal> constraint.  Storage parameters for
      indexes are documented in <xref linkend="SQL-CREATEINDEX"
!     endterm="sql-createindex-title">.  The storage parameters currently
!     available for tables are:
     </para>
  
     <variablelist>
  
     <varlistentry>
!     <term><literal>FILLFACTOR</> (<type>integer</>)</term>
      <listitem>
       <para>
        The fillfactor for a table is a percentage between 10 and 100.
*************** and <replaceable class="PARAMETER">table
*** 714,719 ****
--- 714,833 ----
      </listitem>
     </varlistentry>
  
+    <varlistentry>
+     <term><literal>AUTOVACUUM_ENABLED</> (<type>boolean</>)</term>
+     <listitem>
+      <para>
+ 	 Enables or disables the autovacuum daemon on a particular table.
+ 	 If true, the autovacuum daemon will initiate a <command>VACUUM</> operation
+ 	 on a particular table when the number of updated or deleted tuples exceeds 
+ 	 <literal>autovacuum_vac_threshold</> plus 
+ 	 <literal>autovacuum_vac_scale_factor</> times the number of live tuples 
+ 	 currently estimated to be in the relation.
+ 	 Similarly, it will initiate an <command>ANALYZE</> operation when the
+ 	 number of inserted, updated or deleted tuples exceeds
+ 	 <literal>autovacuum_anl_threshold</> plus 
+ 	 <literal>autovacuum_anl_scale_factor</> times the number of live tuples 
+ 	 currently estimated to be in the relation.
+ 	 If false, this table will not be autovacuumed, except to prevent
+ 	 transaction Id wraparound. See <xref linkend="vacuum-for-wraparound"> for
+ 	 more about wraparound prevention.
+ 	 Observe that this variable inherits its value from the <xref
+ 	 linkend="guc-autovacuum">.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
+     <term><literal>AUTOVACUUM_VACUUM_THRESHOLD</> (<type>integer</>)</term>
+     <listitem>
+      <para>
+ 	 Minimum number of updated or deleted tuples before initiate a
+ 	 <command>VACUUM</> operation on a particular table. 
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
+     <term><literal>AUTOVACUUM_VACUUM_SCALE_FACTOR</> (<type>float4</>)</term>
+     <listitem>
+      <para>
+ 	 Multiplier for <structfield>reltuples</> to add to
+ 	 <literal>autovacuum_vac_threshold</>.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
+     <term><literal>AUTOVACUUM_ANALYZE_THRESHOLD</> (<type>integer</>)</term>
+     <listitem>
+      <para>
+ 	 Minimum number of inserted, updated, or deleted tuples before initiate an
+ 	 <command>ANALYZE</> operation on a particular table.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
+     <term><literal>AUTOVACUUM_ANALYZE_SCALE_FACTOR</> (<type>float4</>)</term>
+     <listitem>
+      <para>
+ 	 Multiplier for <structfield>reltuples</> to add to
+ 	 <literal>autovacuum_anl_threshold</>.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
+     <term><literal>AUTOVACUUM_VACUUM_COST_DELAY</> (<type>integer</>)</term>
+     <listitem>
+      <para>
+ 	 Custom <xref linkend="guc-autovacuum-vacuum-cost-delay"> parameter. A
+ 	 <literal>-1</> (or indeed any negative value) indicates that the
+ 	 system-wide default (<varname>autovacuum_vacuum_cost_delay</>) should be 
+ 	 used for this particular value.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
+     <term><literal>AUTOVACUUM_VACUUM_COST_LIMIT</> (<type>integer</>)</term>
+     <listitem>
+      <para>
+ 	 Custom <xref linkend="guc-autovacuum-vacuum-cost-limit"> parameter. A
+ 	 <literal>-1</> (or indeed any negative value) indicates that the
+ 	 system-wide default (<varname>autovacuum_vacuum_cost_limit</>) should be 
+ 	 used for this particular value.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
+     <term><literal>AUTOVACUUM_FREEZE_MIN_AGE</> (<type>integer</>)</term>
+     <listitem>
+      <para>
+ 	 Custom <xref linkend="guc-vacuum-freeze-min-age"> parameter. Also, 
+ 	 autovacuum will ignore attempts to set a per-table
+ 	 <literal>autovacuum_freeze_min_age</> larger than the half system-wide 
+ 	 <xref linkend="guc-autovacuum-freeze-max-age"> setting.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
+    <varlistentry>
+     <term><literal>AUTOVACUUM_FREEZE_MAX_AGE</> (<type>integer</>)</term>
+     <listitem>
+      <para>
+ 	 Custom <xref linkend="guc-autovacuum-freeze-max-age"> parameter. Also,
+ 	 autovacuum will ignore attempts to set a per-table
+ 	 <literal>autovacuum_freeze_max_age</> larger than the system-wide setting
+ 	 (it can only be set smaller). Note that while you can set
+ 	 <literal>autovacuum_freeze_max_age</> very small, or even zero, this is
+ 	 usually unwise since it will force frequent vacuuming.
+      </para>
+     </listitem>
+    </varlistentry>
+ 
     </variablelist>
  
    </refsect2>
Index: src/backend/access/common/reloptions.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/access/common/reloptions.c,v
retrieving revision 1.18
diff -c -p -r1.18 reloptions.c
*** src/backend/access/common/reloptions.c	12 Jan 2009 21:02:14 -0000	1.18
--- src/backend/access/common/reloptions.c	23 Jan 2009 00:07:43 -0000
***************
*** 48,53 ****
--- 48,61 ----
  
  static relopt_bool boolRelOpts[] =
  {
+ 	{
+ 		{
+ 			"autovacuum_enabled",
+ 			"Enables autovacuum in this relation",
+ 			RELOPT_KIND_HEAP
+ 		},
+ 		true
+ 	},
  	/* list terminator */
  	{ { NULL } }
  };
*************** static relopt_int intRelOpts[] =
*** 86,97 ****
--- 94,169 ----
  		},
  		GIST_DEFAULT_FILLFACTOR, GIST_MIN_FILLFACTOR, 100
  	},
+ 	{
+ 		{
+ 			"autovacuum_vacuum_threshold",
+ 			"Minimum number of tuple updates or deletes prior to vacuum",
+ 			RELOPT_KIND_HEAP
+ 		},
+ 		50, 0, INT_MAX
+ 	},
+ 	{
+ 		{
+ 			"autovacuum_analyze_threshold",
+ 			"Minimum number of tuple inserts, updates or deletes prior to analyze",
+ 			RELOPT_KIND_HEAP
+ 		},
+ 		50, 0, INT_MAX
+ 	},
+ 	{
+ 		{
+ 			"autovacuum_vacuum_cost_delay",
+ 			"Vacuum cost delay in milliseconds, for autovacuum",
+ 			RELOPT_KIND_HEAP
+ 		},
+ 		20, 0, 1000
+ 	},
+ 	{
+ 		{
+ 			"autovacuum_vacuum_cost_limit",
+ 			"Vacuum cost amount available before napping, for autovacuum",
+ 			RELOPT_KIND_HEAP
+ 		},
+ 		200, 1, 10000
+ 	},
+ 	{
+ 		{
+ 			"autovacuum_freeze_min_age",
+ 			"Minimum age at which VACUUM should freeze a table row, for autovacuum",
+ 			RELOPT_KIND_HEAP
+ 		},
+ 		100000000, 0, 1000000000
+ 	},
+ 	{
+ 		{
+ 			"autovacuum_freeze_max_age",
+ 			"Age at which to autovacuum a table to prevent transaction ID wraparound",
+ 			RELOPT_KIND_HEAP
+ 		},
+ 		200000000, 100000000, 2000000000
+ 	},
  	/* list terminator */
  	{ { NULL } }
  };
  
  static relopt_real realRelOpts[] =
  {
+ 	{
+ 		{
+ 			"autovacuum_vacuum_scale_factor",
+ 			"Number of tuple updates or deletes prior to vacuum as a fraction of reltuples",
+ 			RELOPT_KIND_HEAP
+ 		},
+ 		0.2, 0.0, 100.0
+ 	},
+ 	{
+ 		{
+ 			"autovacuum_analyze_scale_factor",
+ 			"Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
+ 			RELOPT_KIND_HEAP
+ 		},
+ 		0.1, 0.0, 100.0
+ 	},
  	/* list terminator */
  	{ { NULL } }
  };
*************** untransformRelOptions(Datum options)
*** 558,563 ****
--- 630,681 ----
  	return result;
  }
  
+ /*
+  * Extract reloptions from a pg_class tuple.
+  *
+  * This is a very low-level routine, expected to be used by relcache code only.
+  * For other uses, consider grabbing the pointer from the relcache entry
+  * instead.
+  *
+  * tupdesc is pg_class' tuple descriptor.  amoptions is the amoptions regproc
+  * in the case of the tuple corresponding to an index, or InvalidOid otherwise.
+  */
+ bytea *
+ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc, Oid amoptions)
+ {
+ 	bytea  *options;
+ 	bool	isnull;
+ 	Datum	datum;
+ 	Form_pg_class	classForm;
+ 
+ 	datum = fastgetattr(tuple,
+ 						Anum_pg_class_reloptions,
+ 						tupdesc,
+ 						&isnull);
+ 	if (isnull)
+ 		return NULL;
+ 
+ 	classForm = (Form_pg_class) GETSTRUCT(tuple);
+ 
+ 	/* Parse into appropriate format; don't error out here */
+ 	switch (classForm->relkind)
+ 	{
+ 		case RELKIND_RELATION:
+ 		case RELKIND_TOASTVALUE:
+ 		case RELKIND_UNCATALOGED:
+ 			options = heap_reloptions(classForm->relkind, datum, false);
+ 			break;
+ 		case RELKIND_INDEX:
+ 			options = index_reloptions(amoptions, datum, false);
+ 			break;
+ 		default:
+ 			Assert(false);		/* can't get here */
+ 			options = NULL;		/* keep compiler quiet */
+ 			break;
+ 	}
+ 	
+ 	return options;
+ }
  
  /*
   * Interpret reloptions that are given in text-array format.
*************** fillRelOptions(void *rdopts, Size basesi
*** 868,874 ****
  
  
  /*
!  * Option parser for anything that uses StdRdOptions (i.e. fillfactor only)
   */
  bytea *
  default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
--- 986,993 ----
  
  
  /*
!  * Option parser for anything that uses StdRdOptions (i.e. fillfactor and
!  * autovacuum)
   */
  bytea *
  default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
*************** default_reloptions(Datum reloptions, boo
*** 877,883 ****
  	StdRdOptions   *rdopts;
  	int				numoptions;
  	relopt_parse_elt tab[] = {
! 		{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)}
  	};
  
  	options = parseRelOptions(reloptions, validate, kind, &numoptions);
--- 996,1020 ----
  	StdRdOptions   *rdopts;
  	int				numoptions;
  	relopt_parse_elt tab[] = {
! 		{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
! 		{"autovacuum_enabled", RELOPT_TYPE_BOOL,
! 			offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
! 		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
! 			offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)},
! 		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
! 			offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)},
! 		{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_INT,
! 			offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_delay)},
! 		{"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,
! 			offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit)},
! 		{"autovacuum_freeze_min_age", RELOPT_TYPE_INT,
! 			offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_min_age)},
! 		{"autovacuum_freeze_max_age", RELOPT_TYPE_INT,
! 			offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_max_age)},
! 		{"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL,
! 			offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_scale_factor)},
! 		{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,
! 			offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_scale_factor)}
  	};
  
  	options = parseRelOptions(reloptions, validate, kind, &numoptions);
Index: src/backend/catalog/Makefile
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/catalog/Makefile,v
retrieving revision 1.68
diff -c -p -r1.68 Makefile
*** src/backend/catalog/Makefile	19 Dec 2008 16:25:16 -0000	1.68
--- src/backend/catalog/Makefile	29 Dec 2008 15:03:11 -0000
*************** all: $(BKIFILES)
*** 26,32 ****
  # indexing.h had better be last, and toasting.h just before it.
  
  POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
! 	pg_proc.h pg_type.h pg_attribute.h pg_class.h pg_autovacuum.h \
  	pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h pg_operator.h \
  	pg_opfamily.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
  	pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
--- 26,32 ----
  # indexing.h had better be last, and toasting.h just before it.
  
  POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
! 	pg_proc.h pg_type.h pg_attribute.h pg_class.h \
  	pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h pg_operator.h \
  	pg_opfamily.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
  	pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
Index: src/backend/postmaster/autovacuum.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/postmaster/autovacuum.c,v
retrieving revision 1.92
diff -c -p -r1.92 autovacuum.c
*** src/backend/postmaster/autovacuum.c	16 Jan 2009 13:27:24 -0000	1.92
--- src/backend/postmaster/autovacuum.c	23 Jan 2009 15:56:56 -0000
***************
*** 69,80 ****
  
  #include "access/genam.h"
  #include "access/heapam.h"
  #include "access/transam.h"
  #include "access/xact.h"
  #include "catalog/dependency.h"
  #include "catalog/indexing.h"
  #include "catalog/namespace.h"
- #include "catalog/pg_autovacuum.h"
  #include "catalog/pg_database.h"
  #include "commands/dbcommands.h"
  #include "commands/vacuum.h"
--- 69,80 ----
  
  #include "access/genam.h"
  #include "access/heapam.h"
+ #include "access/reloptions.h"
  #include "access/transam.h"
  #include "access/xact.h"
  #include "catalog/dependency.h"
  #include "catalog/indexing.h"
  #include "catalog/namespace.h"
  #include "catalog/pg_database.h"
  #include "commands/dbcommands.h"
  #include "commands/vacuum.h"
***************
*** 88,93 ****
--- 88,94 ----
  #include "storage/bufmgr.h"
  #include "storage/fd.h"
  #include "storage/ipc.h"
+ #include "storage/lmgr.h"
  #include "storage/pmsignal.h"
  #include "storage/proc.h"
  #include "storage/procarray.h"
*************** typedef struct av_relation
*** 165,177 ****
  {
  	Oid			ar_toastrelid;	/* hash key - must be first */
  	Oid			ar_relid;
  } av_relation;
  
  /* struct to keep track of tables to vacuum and/or analyze, after rechecking */
  typedef struct autovac_table
  {
  	Oid			at_relid;
- 	Oid			at_toastrelid;
  	bool		at_dovacuum;
  	bool		at_doanalyze;
  	int			at_freeze_min_age;
--- 166,179 ----
  {
  	Oid			ar_toastrelid;	/* hash key - must be first */
  	Oid			ar_relid;
+ 	AutoVacOpts *ar_reloptions;	/* copy of AutoVacOpts from the main table's
+ 								   reloptions, or NULL if none */
  } av_relation;
  
  /* struct to keep track of tables to vacuum and/or analyze, after rechecking */
  typedef struct autovac_table
  {
  	Oid			at_relid;
  	bool		at_dovacuum;
  	bool		at_doanalyze;
  	int			at_freeze_min_age;
*************** static void autovac_balance_cost(void);
*** 282,297 ****
  static void do_autovacuum(void);
  static void FreeWorkerInfo(int code, Datum arg);
  
! static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map);
! static void relation_needs_vacanalyze(Oid relid, Form_pg_autovacuum avForm,
  						  Form_pg_class classForm,
! 						  PgStat_StatTabEntry *tabentry, bool *dovacuum,
! 						  bool *doanalyze, bool *wraparound);
  
  static void autovacuum_do_vac_analyze(autovac_table *tab,
  						  BufferAccessStrategy bstrategy);
! static HeapTuple get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid,
! 											   HTAB *table_toast_map);
  static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared,
  						  PgStat_StatDBEntry *shared,
  						  PgStat_StatDBEntry *dbentry);
--- 284,300 ----
  static void do_autovacuum(void);
  static void FreeWorkerInfo(int code, Datum arg);
  
! static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map,
! 					  TupleDesc pg_class_desc);
! static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts,
  						  Form_pg_class classForm,
! 						  PgStat_StatTabEntry *tabentry,
! 						  bool *dovacuum, bool *doanalyze, bool *wraparound);
  
  static void autovacuum_do_vac_analyze(autovac_table *tab,
  						  BufferAccessStrategy bstrategy);
! static AutoVacOpts *extract_autovac_opts(HeapTuple tup,
! 					 TupleDesc pg_class_desc);
  static PgStat_StatTabEntry *get_pgstat_tabentry_relid(Oid relid, bool isshared,
  						  PgStat_StatDBEntry *shared,
  						  PgStat_StatDBEntry *dbentry);
*************** get_database_list(void)
*** 1816,1823 ****
  static void
  do_autovacuum(void)
  {
! 	Relation	classRel,
! 				avRel;
  	HeapTuple	tuple;
  	HeapScanDesc relScan;
  	Form_pg_database dbForm;
--- 1819,1825 ----
  static void
  do_autovacuum(void)
  {
! 	Relation	classRel;
  	HeapTuple	tuple;
  	HeapScanDesc relScan;
  	Form_pg_database dbForm;
*************** do_autovacuum(void)
*** 1829,1834 ****
--- 1831,1837 ----
  	PgStat_StatDBEntry *dbentry;
  	BufferAccessStrategy bstrategy;
  	ScanKeyData	key;
+ 	TupleDesc	pg_class_desc;
  
  	/*
  	 * StartTransactionCommand and CommitTransactionCommand will automatically
*************** do_autovacuum(void)
*** 1890,1896 ****
  	shared = pgstat_fetch_stat_dbentry(InvalidOid);
  
  	classRel = heap_open(RelationRelationId, AccessShareLock);
! 	avRel = heap_open(AutovacuumRelationId, AccessShareLock);
  
  	/* create hash table for toast <-> main relid mapping */
  	MemSet(&ctl, 0, sizeof(ctl));
--- 1893,1901 ----
  	shared = pgstat_fetch_stat_dbentry(InvalidOid);
  
  	classRel = heap_open(RelationRelationId, AccessShareLock);
! 
! 	/* create a copy so we can use it after closing pg_class */
! 	pg_class_desc = CreateTupleDescCopy(RelationGetDescr(classRel));
  
  	/* create hash table for toast <-> main relid mapping */
  	MemSet(&ctl, 0, sizeof(ctl));
*************** do_autovacuum(void)
*** 1909,1917 ****
  	 * We do this in two passes: on the first one we collect the list of
  	 * plain relations, and on the second one we collect TOAST tables.
  	 * The reason for doing the second pass is that during it we want to use
! 	 * the main relation's pg_autovacuum entry if the TOAST table does not have
! 	 * any, and we cannot obtain it unless we know beforehand what's the main
! 	 * table OID.
  	 *
  	 * We need to check TOAST tables separately because in cases with short,
  	 * wide tables there might be proportionally much more activity in the
--- 1914,1922 ----
  	 * We do this in two passes: on the first one we collect the list of
  	 * plain relations, and on the second one we collect TOAST tables.
  	 * The reason for doing the second pass is that during it we want to use
! 	 * the main relation's pg_class.reloptions entry if the TOAST table does
! 	 * not have any, and we cannot obtain it unless we know beforehand what's
! 	 * the main table OID.
  	 *
  	 * We need to check TOAST tables separately because in cases with short,
  	 * wide tables there might be proportionally much more activity in the
*************** do_autovacuum(void)
*** 1931,1939 ****
  	while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
  	{
  		Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
- 		Form_pg_autovacuum avForm = NULL;
  		PgStat_StatTabEntry *tabentry;
! 		HeapTuple	avTup;
  		Oid			relid;
  		bool		dovacuum;
  		bool		doanalyze;
--- 1936,1943 ----
  	while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
  	{
  		Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
  		PgStat_StatTabEntry *tabentry;
! 		AutoVacOpts *relopts;
  		Oid			relid;
  		bool		dovacuum;
  		bool		doanalyze;
*************** do_autovacuum(void)
*** 1942,1958 ****
  
  		relid = HeapTupleGetOid(tuple);
  
! 		/* Fetch the pg_autovacuum tuple for the relation, if any */
! 		avTup = get_pg_autovacuum_tuple_relid(avRel, relid, NULL);
! 		if (HeapTupleIsValid(avTup))
! 			avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
! 
! 		/* Fetch the pgstat entry for this table */
  		tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
  											 shared, dbentry);
  
  		/* Check if it needs vacuum or analyze */
! 		relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
  								  &dovacuum, &doanalyze, &wraparound);
  
  		/*
--- 1946,1958 ----
  
  		relid = HeapTupleGetOid(tuple);
  
! 		/* Fetch reloptions and the pgstat entry for this table */
! 		relopts = extract_autovac_opts(tuple, pg_class_desc);
  		tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
  											 shared, dbentry);
  
  		/* Check if it needs vacuum or analyze */
! 		relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
  								  &dovacuum, &doanalyze, &wraparound);
  
  		/*
*************** do_autovacuum(void)
*** 1998,2004 ****
  		}
  		else
  		{
! 			/* Plain relations that need work are added to table_oids */
  			if (dovacuum || doanalyze)
  				table_oids = lappend_oid(table_oids, relid);
  
--- 1998,2004 ----
  		}
  		else
  		{
! 			/* relations that need work are added to table_oids */
  			if (dovacuum || doanalyze)
  				table_oids = lappend_oid(table_oids, relid);
  
*************** do_autovacuum(void)
*** 2020,2031 ****
  				{
  					/* hash_search already filled in the key */
  					hentry->ar_relid = relid;
  				}
  			}
  		}
- 
- 		if (HeapTupleIsValid(avTup))
- 			heap_freetuple(avTup);
  	}
  
  	heap_endscan(relScan);
--- 2020,2035 ----
  				{
  					/* hash_search already filled in the key */
  					hentry->ar_relid = relid;
+ 					hentry->ar_reloptions = NULL;
+ 					if (relopts != NULL)
+ 					{
+ 						hentry->ar_reloptions = palloc(sizeof(AutoVacOpts));
+ 						memcpy(hentry->ar_reloptions, relopts,
+ 							   sizeof(AutoVacOpts));
+ 					}
  				}
  			}
  		}
  	}
  
  	heap_endscan(relScan);
*************** do_autovacuum(void)
*** 2040,2049 ****
  	while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
  	{
  		Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
- 		Form_pg_autovacuum avForm = NULL;
  		PgStat_StatTabEntry *tabentry;
- 		HeapTuple   avTup;
  		Oid         relid;
  		bool		dovacuum;
  		bool		doanalyze;
  		bool		wraparound;
--- 2044,2052 ----
  	while ((tuple = heap_getnext(relScan, ForwardScanDirection)) != NULL)
  	{
  		Form_pg_class classForm = (Form_pg_class) GETSTRUCT(tuple);
  		PgStat_StatTabEntry *tabentry;
  		Oid         relid;
+ 		AutoVacOpts *relopts = NULL;
  		bool		dovacuum;
  		bool		doanalyze;
  		bool		wraparound;
*************** do_autovacuum(void)
*** 2057,2073 ****
  
  		relid = HeapTupleGetOid(tuple);
  
! 		/* Fetch the pg_autovacuum tuple for this rel */
! 		avTup = get_pg_autovacuum_tuple_relid(avRel, relid, table_toast_map);
  
! 		if (HeapTupleIsValid(avTup))
! 			avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
  
  		/* Fetch the pgstat entry for this table */
  		tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
  											 shared, dbentry);
  
! 		relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
  								  &dovacuum, &doanalyze, &wraparound);
  
  		/* ignore analyze for toast tables */
--- 2060,2085 ----
  
  		relid = HeapTupleGetOid(tuple);
  
! 		/*
! 		 * fetch reloptions -- if this toast table does not have them,
! 		 * try the main rel
! 		 */
! 		relopts = extract_autovac_opts(tuple, pg_class_desc);
! 		if (relopts == NULL)
! 		{
! 			av_relation		*hentry;
! 			bool			found;
  
! 			hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
! 			if (found)
! 				relopts = hentry->ar_reloptions;
! 		}
  
  		/* Fetch the pgstat entry for this table */
  		tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
  											 shared, dbentry);
  
! 		relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
  								  &dovacuum, &doanalyze, &wraparound);
  
  		/* ignore analyze for toast tables */
*************** do_autovacuum(void)
*** 2076,2082 ****
  	}
  
  	heap_endscan(relScan);
- 	heap_close(avRel, AccessShareLock);
  	heap_close(classRel, AccessShareLock);
  
  	/*
--- 2088,2093 ----
*************** do_autovacuum(void)
*** 2163,2172 ****
  		 * condition is not closed but it is very small.
  		 */
  		MemoryContextSwitchTo(AutovacMemCxt);
! 		tab = table_recheck_autovac(relid, table_toast_map);
  		if (tab == NULL)
  		{
! 			/* someone else vacuumed the table */
  			LWLockRelease(AutovacuumScheduleLock);
  			continue;
  		}
--- 2174,2183 ----
  		 * condition is not closed but it is very small.
  		 */
  		MemoryContextSwitchTo(AutovacMemCxt);
! 		tab = table_recheck_autovac(relid, table_toast_map, pg_class_desc);
  		if (tab == NULL)
  		{
! 			/* someone else vacuumed the table, or it went away */
  			LWLockRelease(AutovacuumScheduleLock);
  			continue;
  		}
*************** deleted:
*** 2292,2343 ****
  }
  
  /*
-  * Returns a copy of the pg_autovacuum tuple for the given relid, or NULL if
-  * there isn't any.  avRel is pg_autovacuum, already open and suitably locked.
-  *
-  * If table_toast_map is not null, use it to find an alternative OID with which
-  * to search a pg_autovacuum entry, if the passed relid does not yield one
-  * directly.
-  */
- static HeapTuple
- get_pg_autovacuum_tuple_relid(Relation avRel, Oid relid,
- 							  HTAB *table_toast_map)
- {
- 	ScanKeyData entry[1];
- 	SysScanDesc avScan;
- 	HeapTuple	avTup;
- 
- 	ScanKeyInit(&entry[0],
- 				Anum_pg_autovacuum_vacrelid,
- 				BTEqualStrategyNumber, F_OIDEQ,
- 				ObjectIdGetDatum(relid));
- 
- 	avScan = systable_beginscan(avRel, AutovacuumRelidIndexId, true,
- 								SnapshotNow, 1, entry);
- 
- 	avTup = systable_getnext(avScan);
- 
- 	if (HeapTupleIsValid(avTup))
- 		avTup = heap_copytuple(avTup);
- 
- 	systable_endscan(avScan);
- 
- 	if (!HeapTupleIsValid(avTup) && table_toast_map != NULL)
- 	{
- 		av_relation		*hentry;
- 		bool		found;
- 
- 		hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
- 		if (found)
- 			/* avoid second recursion */
- 			avTup = get_pg_autovacuum_tuple_relid(avRel, hentry->ar_relid,
- 												  NULL);
- 	}
- 
- 	return avTup;
- }
- 
- /*
   * get_pgstat_tabentry_relid
   *
   * Fetch the pgstat entry of a table, either local to a database or shared.
--- 2303,2308 ----
*************** get_pgstat_tabentry_relid(Oid relid, boo
*** 2362,2367 ****
--- 2327,2358 ----
  }
  
  /*
+  * extract_autovac_opts
+  *
+  * Given a relation's pg_class tuple, return the AutoVacOpts portion of
+  * reloptions, if set; otherwise, return NULL.
+  */
+ AutoVacOpts *
+ extract_autovac_opts(HeapTuple tup, TupleDesc pg_class_desc)
+ {
+ 	bytea	   *relopts;
+ 	AutoVacOpts *av;
+ 
+ 	Assert(((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_RELATION ||
+ 		   ((Form_pg_class) GETSTRUCT(tup))->relkind == RELKIND_TOASTVALUE);
+ 
+ 	relopts = extractRelOptions(tup, pg_class_desc, InvalidOid);
+ 	if (relopts == NULL)
+ 		return NULL;
+ 	
+ 	av = palloc(sizeof(AutoVacOpts));
+ 	memcpy(av, &(((StdRdOptions *) relopts)->autovacuum), sizeof(AutoVacOpts));
+ 	pfree(relopts);
+ 
+ 	return av;
+ }
+ 
+ /*
   * table_recheck_autovac
   *
   * Recheck whether a table still needs vacuum or analyze.  Return value is a
*************** get_pgstat_tabentry_relid(Oid relid, boo
*** 2370,2382 ****
   * Note that the returned autovac_table does not have the name fields set.
   */
  static autovac_table *
! table_recheck_autovac(Oid relid, HTAB *table_toast_map)
  {
- 	Form_pg_autovacuum avForm = NULL;
  	Form_pg_class classForm;
  	HeapTuple	classTup;
- 	HeapTuple	avTup;
- 	Relation	avRel;
  	bool		dovacuum;
  	bool		doanalyze;
  	autovac_table *tab = NULL;
--- 2361,2371 ----
   * Note that the returned autovac_table does not have the name fields set.
   */
  static autovac_table *
! table_recheck_autovac(Oid relid, HTAB *table_toast_map,
! 					  TupleDesc pg_class_desc)
  {
  	Form_pg_class classForm;
  	HeapTuple	classTup;
  	bool		dovacuum;
  	bool		doanalyze;
  	autovac_table *tab = NULL;
*************** table_recheck_autovac(Oid relid, HTAB *t
*** 2384,2389 ****
--- 2373,2379 ----
  	PgStat_StatDBEntry *shared;
  	PgStat_StatDBEntry *dbentry;
  	bool		wraparound;
+ 	AutoVacOpts	*avopts;
  
  	/* use fresh stats */
  	autovac_refresh_stats();
*************** table_recheck_autovac(Oid relid, HTAB *t
*** 2399,2421 ****
  		return NULL;
  	classForm = (Form_pg_class) GETSTRUCT(classTup);
  
! 	/*
! 	 * Fetch the pg_autovacuum entry, if any.  For a toast table, also try the
! 	 * main rel's pg_autovacuum entry if there isn't one for the TOAST table
! 	 * itself.
! 	 */
! 	avRel = heap_open(AutovacuumRelationId, AccessShareLock);
! 	avTup = get_pg_autovacuum_tuple_relid(avRel, relid,
! 			classForm->relkind == RELKIND_TOASTVALUE ? table_toast_map : NULL);
  
! 	if (HeapTupleIsValid(avTup))
! 		avForm = (Form_pg_autovacuum) GETSTRUCT(avTup);
  
  	/* fetch the pgstat table entry */
  	tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
  										 shared, dbentry);
  
! 	relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
  							  &dovacuum, &doanalyze, &wraparound);
  
  	/* ignore ANALYZE for toast tables */
--- 2389,2415 ----
  		return NULL;
  	classForm = (Form_pg_class) GETSTRUCT(classTup);
  
! 	/* 
! 	 * Get the applicable reloptions.  If it is a TOAST table, try to get the
! 	 * main table reloptions if the toast table itself doesn't have.
! 	 */
! 	avopts = extract_autovac_opts(classTup, pg_class_desc);
! 	if (classForm->relkind == RELKIND_TOASTVALUE && 
! 		avopts == NULL && table_toast_map != NULL)
! 	{
! 		av_relation		*hentry;
! 		bool			found;
  
! 		hentry = hash_search(table_toast_map, &relid, HASH_FIND, &found);
! 		if (found)
! 			avopts = hentry->ar_reloptions;
! 	}
  
  	/* fetch the pgstat table entry */
  	tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
  										 shared, dbentry);
  
! 	relation_needs_vacanalyze(relid, avopts, classForm, tabentry,
  							  &dovacuum, &doanalyze, &wraparound);
  
  	/* ignore ANALYZE for toast tables */
*************** table_recheck_autovac(Oid relid, HTAB *t
*** 2432,2476 ****
  
  		/*
  		 * Calculate the vacuum cost parameters and the minimum freeze age. If
! 		 * there is a tuple in pg_autovacuum, use it; else, use the GUC
! 		 * defaults.  Note that the fields may contain "-1" (or indeed any
! 		 * negative value), which means use the GUC defaults for each setting.
! 		 * In cost_limit, the value 0 also means to use the value from
! 		 * elsewhere.
! 		 */
! 		if (avForm != NULL)
! 		{
! 			vac_cost_limit = (avForm->vac_cost_limit > 0) ?
! 				avForm->vac_cost_limit :
! 				((autovacuum_vac_cost_limit > 0) ?
! 				 autovacuum_vac_cost_limit : VacuumCostLimit);
! 
! 			vac_cost_delay = (avForm->vac_cost_delay >= 0) ?
! 				avForm->vac_cost_delay :
! 				((autovacuum_vac_cost_delay >= 0) ?
! 				 autovacuum_vac_cost_delay : VacuumCostDelay);
! 
! 			freeze_min_age = (avForm->freeze_min_age >= 0) ?
! 				avForm->freeze_min_age : default_freeze_min_age;
! 
! 			freeze_table_age = (avForm->freeze_table_age >= 0) ?
! 				avForm->freeze_table_age : default_freeze_table_age;
  		}
  		else
  		{
! 			vac_cost_limit = (autovacuum_vac_cost_limit > 0) ?
! 				autovacuum_vac_cost_limit : VacuumCostLimit;
! 
! 			vac_cost_delay = (autovacuum_vac_cost_delay >= 0) ?
  				autovacuum_vac_cost_delay : VacuumCostDelay;
! 
  			freeze_min_age = default_freeze_min_age;
- 
  			freeze_table_age = default_freeze_table_age;
  		}
  
  		tab = palloc(sizeof(autovac_table));
- 		tab->at_relid = relid;
  		tab->at_dovacuum = dovacuum;
  		tab->at_doanalyze = doanalyze;
  		tab->at_freeze_min_age = freeze_min_age;
--- 2426,2455 ----
  
  		/*
  		 * Calculate the vacuum cost parameters and the minimum freeze age. If
! 		 * there is an option in pg_class.reloptions, use it; in the case of a
! 		 * toast table, try the main table too.  Otherwise use the GUC
! 		 * defaults, autovacuum's own first and plain vacuum second.
! 		 */
! 		if (avopts)
! 		{
! 			vac_cost_delay = avopts->vacuum_cost_delay;
! 			vac_cost_limit = avopts->vacuum_cost_limit;
! 			freeze_min_age = avopts->freeze_min_age;
! 			freeze_table_age = avopts->freeze_table_age;
  		}
  		else
  		{
! 			/* -1 in autovac setting means use plain vacuum_cost_delay */
! 			vac_cost_delay = autovacuum_vac_cost_delay >= 0 ?
  				autovacuum_vac_cost_delay : VacuumCostDelay;
! 			/* 0 or -1 in autovac setting means use plain vacuum_cost_limit */
! 			vac_cost_limit = autovacuum_vac_cost_limit > 0 ?
! 				autovacuum_vac_cost_limit : VacuumCostLimit;
  			freeze_min_age = default_freeze_min_age;
  			freeze_table_age = default_freeze_table_age;
  		}
  
  		tab = palloc(sizeof(autovac_table));
  		tab->at_dovacuum = dovacuum;
  		tab->at_doanalyze = doanalyze;
  		tab->at_freeze_min_age = freeze_min_age;
*************** table_recheck_autovac(Oid relid, HTAB *t
*** 2478,2491 ****
  		tab->at_vacuum_cost_limit = vac_cost_limit;
  		tab->at_vacuum_cost_delay = vac_cost_delay;
  		tab->at_wraparound = wraparound;
- 		tab->at_relname = NULL;
  		tab->at_nspname = NULL;
  		tab->at_datname = NULL;
  	}
  
- 	heap_close(avRel, AccessShareLock);
- 	if (HeapTupleIsValid(avTup))
- 		heap_freetuple(avTup);
  	heap_freetuple(classTup);
  
  	return tab;
--- 2457,2466 ----
*************** table_recheck_autovac(Oid relid, HTAB *t
*** 2496,2503 ****
   *
   * Check whether a relation needs to be vacuumed or analyzed; return each into
   * "dovacuum" and "doanalyze", respectively.  Also return whether the vacuum is
!  * being forced because of Xid wraparound.	avForm and tabentry can be NULL,
!  * classForm shouldn't.
   *
   * A table needs to be vacuumed if the number of dead tuples exceeds a
   * threshold.  This threshold is calculated as
--- 2471,2482 ----
   *
   * Check whether a relation needs to be vacuumed or analyzed; return each into
   * "dovacuum" and "doanalyze", respectively.  Also return whether the vacuum is
!  * being forced because of Xid wraparound.
!  *
!  * "rel" is the relation to be checked, already opened and AccessShare-locked;
!  * relopts is NULL when the relation is a regular table, and the AutoVacOpts
!  * options from the main table in the case of a toast table (NULL if it doesn't
!  * have any); tabentry is the pgstats entry, which can be NULL.
   *
   * A table needs to be vacuumed if the number of dead tuples exceeds a
   * threshold.  This threshold is calculated as
*************** table_recheck_autovac(Oid relid, HTAB *t
*** 2513,2531 ****
   * We also force vacuum if the table's relfrozenxid is more than freeze_max_age
   * transactions back.
   *
!  * A table whose pg_autovacuum.enabled value is false, is automatically
!  * skipped (unless we have to vacuum it due to freeze_max_age).  Thus
!  * autovacuum can be disabled for specific tables.	Also, when the stats
   * collector does not have data about a table, it will be skipped.
   *
!  * A table whose vac_base_thresh value is <0 takes the base value from the
   * autovacuum_vacuum_threshold GUC variable.  Similarly, a vac_scale_factor
!  * value <0 is substituted with the value of
   * autovacuum_vacuum_scale_factor GUC variable.  Ditto for analyze.
   */
  static void
  relation_needs_vacanalyze(Oid relid,
! 						  Form_pg_autovacuum avForm,
  						  Form_pg_class classForm,
  						  PgStat_StatTabEntry *tabentry,
   /* output params below */
--- 2492,2510 ----
   * We also force vacuum if the table's relfrozenxid is more than freeze_max_age
   * transactions back.
   *
!  * A table whose autovacuum_enabled option is false, is
!  * automatically skipped (unless we have to vacuum it due to freeze_max_age).
!  * Thus autovacuum can be disabled for specific tables.	Also, when the stats
   * collector does not have data about a table, it will be skipped.
   *
!  * A table whose vac_base_thresh value is < 0 takes the base value from the
   * autovacuum_vacuum_threshold GUC variable.  Similarly, a vac_scale_factor
!  * value < 0 is substituted with the value of
   * autovacuum_vacuum_scale_factor GUC variable.  Ditto for analyze.
   */
  static void
  relation_needs_vacanalyze(Oid relid,
! 						  AutoVacOpts *relopts,
  						  Form_pg_class classForm,
  						  PgStat_StatTabEntry *tabentry,
   /* output params below */
*************** relation_needs_vacanalyze(Oid relid,
*** 2534,2542 ****
  						  bool *wraparound)
  {
  	bool		force_vacuum;
  	float4		reltuples;		/* pg_class.reltuples */
  
! 	/* constants from pg_autovacuum or GUC variables */
  	int			vac_base_thresh,
  				anl_base_thresh;
  	float4		vac_scale_factor,
--- 2513,2522 ----
  						  bool *wraparound)
  {
  	bool		force_vacuum;
+ 	bool		av_enabled;
  	float4		reltuples;		/* pg_class.reltuples */
  
! 	/* constants from reloptions or GUC variables */
  	int			vac_base_thresh,
  				anl_base_thresh;
  	float4		vac_scale_factor,
*************** relation_needs_vacanalyze(Oid relid,
*** 2554,2593 ****
  	int			freeze_max_age;
  	TransactionId xidForceLimit;
  
- 	AssertArg(classForm != NULL);
- 	AssertArg(OidIsValid(relid));
- 
  	/*
! 	 * Determine vacuum/analyze equation parameters.  If there is a tuple in
! 	 * pg_autovacuum, use it; else, use the GUC defaults.  Note that the
! 	 * fields may contain "-1" (or indeed any negative value), which means use
! 	 * the GUC defaults for each setting.
! 	 */
! 	if (avForm != NULL)
! 	{
! 		vac_scale_factor = (avForm->vac_scale_factor >= 0) ?
! 			avForm->vac_scale_factor : autovacuum_vac_scale;
! 		vac_base_thresh = (avForm->vac_base_thresh >= 0) ?
! 			avForm->vac_base_thresh : autovacuum_vac_thresh;
! 
! 		anl_scale_factor = (avForm->anl_scale_factor >= 0) ?
! 			avForm->anl_scale_factor : autovacuum_anl_scale;
! 		anl_base_thresh = (avForm->anl_base_thresh >= 0) ?
! 			avForm->anl_base_thresh : autovacuum_anl_thresh;
! 
! 		freeze_max_age = (avForm->freeze_max_age >= 0) ?
! 			Min(avForm->freeze_max_age, autovacuum_freeze_max_age) :
! 			autovacuum_freeze_max_age;
  	}
  	else
  	{
  		vac_scale_factor = autovacuum_vac_scale;
  		vac_base_thresh = autovacuum_vac_thresh;
- 
  		anl_scale_factor = autovacuum_anl_scale;
  		anl_base_thresh = autovacuum_anl_thresh;
- 
  		freeze_max_age = autovacuum_freeze_max_age;
  	}
  
  	/* Force vacuum if table is at risk of wraparound */
--- 2534,2562 ----
  	int			freeze_max_age;
  	TransactionId xidForceLimit;
  
  	/*
! 	 * Determine vacuum/analyze equation parameters.  We have two possible
! 	 * sources: the passed reloptions (which could be a main table or a toast
! 	 * table), or the autovacuum GUC variables.
! 	 */
! 	if (relopts)
! 	{
! 		vac_scale_factor = relopts->vacuum_scale_factor;
! 		vac_base_thresh = relopts->vacuum_threshold;
! 		anl_scale_factor = relopts->analyze_scale_factor;
! 		anl_base_thresh = relopts->analyze_threshold;
! 		freeze_max_age = Min(relopts->freeze_max_age,
! 							 autovacuum_freeze_max_age);
! 		av_enabled = relopts->enabled;
  	}
  	else
  	{
  		vac_scale_factor = autovacuum_vac_scale;
  		vac_base_thresh = autovacuum_vac_thresh;
  		anl_scale_factor = autovacuum_anl_scale;
  		anl_base_thresh = autovacuum_anl_thresh;
  		freeze_max_age = autovacuum_freeze_max_age;
+ 		av_enabled = true;
  	}
  
  	/* Force vacuum if table is at risk of wraparound */
*************** relation_needs_vacanalyze(Oid relid,
*** 2599,2609 ****
  										  xidForceLimit));
  	*wraparound = force_vacuum;
  
! 	/* User disabled it in pg_autovacuum?  (But ignore if at risk) */
! 	if (avForm && !avForm->enabled && !force_vacuum)
  	{
  		*doanalyze = false;
  		*dovacuum = false;
  		return;
  	}
  
--- 2568,2579 ----
  										  xidForceLimit));
  	*wraparound = force_vacuum;
  
! 	/* User disabled it in pg_class.reloptions?  (But ignore if at risk) */
! 	if (!force_vacuum && !av_enabled)
  	{
  		*doanalyze = false;
  		*dovacuum = false;
+ 
  		return;
  	}
  
*************** relation_needs_vacanalyze(Oid relid,
*** 2644,2649 ****
--- 2614,2633 ----
  	/* ANALYZE refuses to work with pg_statistics */
  	if (relid == StatisticRelationId)
  		*doanalyze = false;
+ 
+ 	if (*doanalyze || *dovacuum)
+ 	{
+ 		elog(LOG, "parameters used for %s (%s) -- freeze max age: %d\n"
+ 			 "vac scale: %f, thresh: %d; do it: %s\n"
+ 			 "anl scale: %f, thresh: %d; do it: %s",
+ 			 NameStr(classForm->relname),
+ 			 relopts ? "relopts" : "defaults",
+ 			 freeze_max_age,
+ 			 vac_scale_factor, vac_base_thresh,
+ 			 *dovacuum ? "yes" : "no",
+ 			 anl_scale_factor, anl_base_thresh,
+ 			 *doanalyze ? "yes" : "no");
+ 	}
  }
  
  /*
*************** autovacuum_do_vac_analyze(autovac_table 
*** 2672,2678 ****
  	/* Let pgstat know what we're doing */
  	autovac_report_activity(tab);
  
! 	vacuum(&vacstmt, tab->at_relid, false, bstrategy, tab->at_wraparound, true);
  }
  
  /*
--- 2656,2663 ----
  	/* Let pgstat know what we're doing */
  	autovac_report_activity(tab);
  
! 	vacuum(&vacstmt, tab->at_relid, false, bstrategy,
! 		   tab->at_wraparound, true);
  }
  
  /*
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.282
diff -c -p -r1.282 relcache.c
*** src/backend/utils/cache/relcache.c	22 Jan 2009 20:16:06 -0000	1.282
--- src/backend/utils/cache/relcache.c	23 Jan 2009 15:30:30 -0000
*************** AllocateRelationDesc(Relation relation, 
*** 351,358 ****
  static void
  RelationParseRelOptions(Relation relation, HeapTuple tuple)
  {
- 	Datum		datum;
- 	bool		isnull;
  	bytea	   *options;
  
  	relation->rd_options = NULL;
--- 351,356 ----
*************** RelationParseRelOptions(Relation relatio
*** 374,404 ****
  	 * we might not have any other for pg_class yet (consider executing this
  	 * code for pg_class itself)
  	 */
! 	datum = fastgetattr(tuple,
! 						Anum_pg_class_reloptions,
! 						GetPgClassDescriptor(),
! 						&isnull);
! 	if (isnull)
! 		return;
! 
! 	/* Parse into appropriate format; don't error out here */
! 	switch (relation->rd_rel->relkind)
! 	{
! 		case RELKIND_RELATION:
! 		case RELKIND_TOASTVALUE:
! 		case RELKIND_UNCATALOGED:
! 			options = heap_reloptions(relation->rd_rel->relkind, datum,
! 									  false);
! 			break;
! 		case RELKIND_INDEX:
! 			options = index_reloptions(relation->rd_am->amoptions, datum,
! 									   false);
! 			break;
! 		default:
! 			Assert(false);		/* can't get here */
! 			options = NULL;		/* keep compiler quiet */
! 			break;
! 	}
  
  	/* Copy parsed data into CacheMemoryContext */
  	if (options)
--- 372,381 ----
  	 * we might not have any other for pg_class yet (consider executing this
  	 * code for pg_class itself)
  	 */
! 	options = extractRelOptions(tuple,
! 								GetPgClassDescriptor(),
! 								relation->rd_rel->relkind == RELKIND_INDEX ?
! 								relation->rd_am->amoptions : InvalidOid);
  
  	/* Copy parsed data into CacheMemoryContext */
  	if (options)
Index: src/include/access/reloptions.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/access/reloptions.h,v
retrieving revision 1.10
diff -c -p -r1.10 reloptions.h
*** src/include/access/reloptions.h	12 Jan 2009 21:02:15 -0000	1.10
--- src/include/access/reloptions.h	23 Jan 2009 00:07:44 -0000
***************
*** 18,23 ****
--- 18,24 ----
  #ifndef RELOPTIONS_H
  #define RELOPTIONS_H
  
+ #include "access/htup.h"
  #include "nodes/pg_list.h"
  
  /* types supported by reloptions */
*************** extern void add_string_reloption(int kin
*** 241,246 ****
--- 242,249 ----
  extern Datum transformRelOptions(Datum oldOptions, List *defList,
  					bool ignoreOids, bool isReset);
  extern List *untransformRelOptions(Datum options);
+ extern bytea *extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
+ 				  Oid amoptions);
  extern relopt_value *parseRelOptions(Datum options, bool validate,
  				relopt_kind kind, int *numrelopts);
  extern void *allocateReloptStruct(Size base, relopt_value *options,
Index: src/include/catalog/indexing.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/catalog/indexing.h,v
retrieving revision 1.106
diff -c -p -r1.106 indexing.h
*** src/include/catalog/indexing.h	22 Jan 2009 20:16:08 -0000	1.106
--- src/include/catalog/indexing.h	23 Jan 2009 15:30:30 -0000
*************** DECLARE_UNIQUE_INDEX(pg_auth_members_rol
*** 97,105 ****
  DECLARE_UNIQUE_INDEX(pg_auth_members_member_role_index, 2695, on pg_auth_members using btree(member oid_ops, roleid oid_ops));
  #define AuthMemMemRoleIndexId	2695
  
- DECLARE_UNIQUE_INDEX(pg_autovacuum_vacrelid_index, 1250, on pg_autovacuum using btree(vacrelid oid_ops));
- #define AutovacuumRelidIndexId	1250
- 
  DECLARE_UNIQUE_INDEX(pg_cast_oid_index, 2660, on pg_cast using btree(oid oid_ops));
  #define CastOidIndexId	2660
  DECLARE_UNIQUE_INDEX(pg_cast_source_target_index, 2661, on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
--- 97,102 ----
Index: src/include/utils/rel.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/utils/rel.h,v
retrieving revision 1.111
diff -c -p -r1.111 rel.h
*** src/include/utils/rel.h	1 Jan 2009 17:24:02 -0000	1.111
--- src/include/utils/rel.h	23 Jan 2009 00:46:56 -0000
*************** typedef struct RelationData
*** 214,223 ****
--- 214,239 ----
   * be applied to relations that use this format or a superset for
   * private options data.
   */
+  /* autovacuum-related reloptions. */
+ typedef struct AutoVacOpts
+ {
+ 	bool    enabled;
+ 	int     vacuum_threshold;
+ 	int     analyze_threshold;
+ 	int     vacuum_cost_delay;
+ 	int     vacuum_cost_limit;
+ 	int     freeze_min_age;
+ 	int     freeze_max_age;
+ 	int		freeze_table_age;
+ 	float8  vacuum_scale_factor;
+ 	float8  analyze_scale_factor;
+ } AutoVacOpts;
+ 
  typedef struct StdRdOptions
  {
  	int32		vl_len_;		/* varlena header (do not touch directly!) */
  	int			fillfactor;		/* page fill factor in percent (0..100) */
+ 	AutoVacOpts autovacuum;     /* autovacuum-related options */
  } StdRdOptions;
  
  #define HEAP_MIN_FILLFACTOR			10
Index: src/test/regress/expected/sanity_check.out
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/test/regress/expected/sanity_check.out,v
retrieving revision 1.38
diff -c -p -r1.38 sanity_check.out
*** src/test/regress/expected/sanity_check.out	19 Dec 2008 16:25:19 -0000	1.38
--- src/test/regress/expected/sanity_check.out	29 Dec 2008 15:04:14 -0000
*************** SELECT relname, relhasindex
*** 90,96 ****
   pg_attribute            | t
   pg_auth_members         | t
   pg_authid               | t
-  pg_autovacuum           | t
   pg_cast                 | t
   pg_class                | t
   pg_constraint           | t
--- 90,95 ----
*************** SELECT relname, relhasindex
*** 152,158 ****
   timetz_tbl              | f
   tinterval_tbl           | f
   varchar_tbl             | f
! (141 rows)
  
  --
  -- another sanity check: every system catalog that has OIDs should have
--- 151,157 ----
   timetz_tbl              | f
   tinterval_tbl           | f
   varchar_tbl             | f
! (140 rows)
  
  --
  -- another sanity check: every system catalog that has OIDs should have
