Thread

  1. Fix regression in vacuumdb --analyze-in-stages for partitioned tables

    Chao Li <li.evan.chao@gmail.com> — 2026-05-29T08:40:56Z

    Hi,
    
    While testing "vacuumdb: Make vacuumdb --analyze-only process partitioned tables”, I found a regression from later commit c4067383cb2.
    
    The original feature commit 6429e5b77 made "--analyze-in-stages" work for partitioned tables, as the doc change states:
    ```
    --- a/doc/src/sgml/ref/vacuumdb.sgml
    +++ b/doc/src/sgml/ref/vacuumdb.sgml
    @@ -397,6 +397,15 @@ PostgreSQL documentation
             Multiple tables can be vacuumed by writing multiple
             <option>-t</option> switches.
            </para>
    +       <para>
    +        If no tables are specified with the <option>--table</option> option,
    +        <application>vacuumdb</application> will clean all regular tables
    +        and materialized views in the connected database.
    +        If <option>--analyze-only</option> or
    +        <option>--analyze-in-stages</option> is also specified,
    +        it will analyze all regular tables, partitioned tables,
    +        and materialized views (but not foreign tables).
    +       </para>
    ```
    
    The corresponding code was:
    ```
    +               /*
    +                * vacuumdb should generally follow the behavior of the underlying
    +                * VACUUM and ANALYZE commands. If analyze_only is true, process
    +                * regular tables, materialized views, and partitioned tables, just
    +                * like ANALYZE (with no specific target tables) does. Otherwise,
    +                * process only regular tables and materialized views, since VACUUM
    +                * skips partitioned tables when no target tables are specified.
    +                */
    +               if (vacopts->analyze_only)
    +                       appendPQExpBufferStr(&catalog_query,
    +                                                                " AND c.relkind OPERATOR(pg_catalog.=) ANY (array["
    +                                                                CppAsString2(RELKIND_RELATION) ", "
    +                                                                CppAsString2(RELKIND_MATVIEW) ", "
    +                                                                CppAsString2(RELKIND_PARTITIONED_TABLE) "])\n");
    ```
    
    However, the refactoring commit c4067383cb2 removed the `analyze_only` field from `vacuumingOptions` and switched to a new `mode` field. The new code is:
    ```
    +               /*
    +                * vacuumdb should generally follow the behavior of the underlying
    +                * VACUUM and ANALYZE commands.  In MODE_ANALYZE mode, process regular
    +                * tables, materialized views, and partitioned tables, just like
    +                * ANALYZE (with no specific target tables) does. Otherwise, process
    +                * only regular tables and materialized views, since VACUUM skips
    +                * partitioned tables when no target tables are specified.
    +                */
    +               if (vacopts->mode == MODE_ANALYZE)
    +                       appendPQExpBufferStr(&catalog_query,
    +                                                                " AND c.relkind OPERATOR(pg_catalog.=) ANY (array["
    +                                                                CppAsString2(RELKIND_RELATION) ", "
    +                                                                CppAsString2(RELKIND_MATVIEW) ", "
    +                                                                CppAsString2(RELKIND_PARTITIONED_TABLE) "])\n");
    ```
    
    analyze_only used to be true when "--analyze-in-stages" was specified, but that meaning was lost in c4067383cb2:
    ```
                            case 3:
    -                               analyze_in_stages = vacopts.analyze_only = true;
    +                               vacopts.mode = MODE_ANALYZE_IN_STAGES;
                                    break;
    ```
    
    The fix is very straightforward, just add check for vacopts->mode == MODE_ANALYZE_IN_STAGES. I also added a test. If we had had this test earlier, the regression should have been caught.
    
    Best regards,
    --
    Chao Li (Evan)
    HighGo Software Co., Ltd.
    https://www.highgo.com/