1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-10 14:22:35 +03:00

vacuumdb: Add --dry-run.

This new option instructs vacuumdb to print, but not execute, the
VACUUM and ANALYZE commands that would've been sent to the server.

Author: Corey Huinker <corey.huinker@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Kirill Reshke <reshkekirill@gmail.com>
Reviewed-by: Álvaro Herrera <alvherre@kurilemu.de>
Discussion: https://postgr.es/m/CADkLM%3DckHkX7Of5SrK7g0LokPUwJ%3Dkk8JU1GXGF5pZ1eBVr0%3DQ%40mail.gmail.com
This commit is contained in:
Nathan Bossart
2025-12-09 13:34:22 -06:00
parent 750816971b
commit d107176d27
5 changed files with 52 additions and 10 deletions

View File

@@ -171,6 +171,16 @@ PostgreSQL documentation
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--dry-run</option></term>
<listitem>
<para>
Print, but do not execute, the vacuum and analyze commands that would
have been sent to the server.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>-e</option></term> <term><option>-e</option></term>
<term><option>--echo</option></term> <term><option>--echo</option></term>

View File

@@ -169,6 +169,10 @@ $node->issues_sql_like(
[ 'vacuumdb', '--schema' => '"Foo"', 'postgres' ], [ 'vacuumdb', '--schema' => '"Foo"', 'postgres' ],
qr/VACUUM \(SKIP_DATABASE_STATS\) "Foo".bar/, qr/VACUUM \(SKIP_DATABASE_STATS\) "Foo".bar/,
'vacuumdb --schema'); 'vacuumdb --schema');
$node->issues_sql_unlike(
[ 'vacuumdb', '--schema' => '"Foo"', 'postgres', '--dry-run' ],
qr/VACUUM \(SKIP_DATABASE_STATS\) "Foo".bar/,
'vacuumdb --dry-run');
$node->issues_sql_like( $node->issues_sql_like(
[ 'vacuumdb', '--schema' => '"Foo"', '--schema' => '"Bar"', 'postgres' ], [ 'vacuumdb', '--schema' => '"Foo"', '--schema' => '"Bar"', 'postgres' ],
qr/VACUUM\ \(SKIP_DATABASE_STATS\)\ "Foo".bar qr/VACUUM\ \(SKIP_DATABASE_STATS\)\ "Foo".bar
@@ -241,6 +245,14 @@ $node->safe_psql('postgres', q|
CREATE TABLE regression_vacuumdb_test AS select generate_series(1, 10) a, generate_series(2, 11) b; CREATE TABLE regression_vacuumdb_test AS select generate_series(1, 10) a, generate_series(2, 11) b;
ALTER TABLE regression_vacuumdb_test ADD COLUMN c INT GENERATED ALWAYS AS (a + b); ALTER TABLE regression_vacuumdb_test ADD COLUMN c INT GENERATED ALWAYS AS (a + b);
|); |);
$node->issues_sql_unlike(
[
'vacuumdb', '--analyze-only', '--dry-run',
'--missing-stats-only', '-t',
'regression_vacuumdb_test', 'postgres'
],
qr/statement:\ ANALYZE/sx,
'--missing-stats-only --dry-run');
$node->issues_sql_like( $node->issues_sql_like(
[ [
'vacuumdb', '--analyze-only', 'vacuumdb', '--analyze-only',

View File

@@ -59,6 +59,7 @@ main(int argc, char *argv[])
{"no-process-main", no_argument, NULL, 12}, {"no-process-main", no_argument, NULL, 12},
{"buffer-usage-limit", required_argument, NULL, 13}, {"buffer-usage-limit", required_argument, NULL, 13},
{"missing-stats-only", no_argument, NULL, 14}, {"missing-stats-only", no_argument, NULL, 14},
{"dry-run", no_argument, NULL, 15},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
@@ -207,6 +208,9 @@ main(int argc, char *argv[])
case 14: case 14:
vacopts.missing_stats_only = true; vacopts.missing_stats_only = true;
break; break;
case 15:
vacopts.dry_run = true;
break;
default: default:
/* getopt_long already emitted a complaint */ /* getopt_long already emitted a complaint */
pg_log_error_hint("Try \"%s --help\" for more information.", progname); pg_log_error_hint("Try \"%s --help\" for more information.", progname);
@@ -303,6 +307,10 @@ main(int argc, char *argv[])
pg_fatal("cannot use the \"%s\" option without \"%s\" or \"%s\"", pg_fatal("cannot use the \"%s\" option without \"%s\" or \"%s\"",
"missing-stats-only", "analyze-only", "analyze-in-stages"); "missing-stats-only", "analyze-only", "analyze-in-stages");
if (vacopts.dry_run && !vacopts.quiet)
pg_log_info("Executing in dry-run mode.\n"
"No commands will be sent to the server.");
ret = vacuuming_main(&cparams, dbname, maintenance_db, &vacopts, ret = vacuuming_main(&cparams, dbname, maintenance_db, &vacopts,
&objects, tbl_count, &objects, tbl_count,
concurrentCons, concurrentCons,
@@ -345,6 +353,7 @@ help(const char *progname)
printf(_(" --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n")); printf(_(" --buffer-usage-limit=SIZE size of ring buffer used for vacuum\n"));
printf(_(" -d, --dbname=DBNAME database to vacuum\n")); printf(_(" -d, --dbname=DBNAME database to vacuum\n"));
printf(_(" --disable-page-skipping disable all page-skipping behavior\n")); printf(_(" --disable-page-skipping disable all page-skipping behavior\n"));
printf(_(" --dry-run show the commands that would be sent to the server\n"));
printf(_(" -e, --echo show the commands being sent to the server\n")); printf(_(" -e, --echo show the commands being sent to the server\n"));
printf(_(" -f, --full do full vacuuming\n")); printf(_(" -f, --full do full vacuuming\n"));
printf(_(" -F, --freeze freeze row transaction information\n")); printf(_(" -F, --freeze freeze row transaction information\n"));

View File

@@ -42,8 +42,9 @@ static SimpleStringList *retrieve_objects(PGconn *conn,
static void free_retrieved_objects(SimpleStringList *list); static void free_retrieved_objects(SimpleStringList *list);
static void prepare_vacuum_command(PGconn *conn, PQExpBuffer sql, static void prepare_vacuum_command(PGconn *conn, PQExpBuffer sql,
vacuumingOptions *vacopts, const char *table); vacuumingOptions *vacopts, const char *table);
static void run_vacuum_command(PGconn *conn, vacuumingOptions *vacopts, static void run_vacuum_command(ParallelSlot *free_slot,
const char *sql, const char *table); vacuumingOptions *vacopts, const char *sql,
const char *table);
/* /*
* Executes vacuum/analyze as indicated. Returns 0 if the plan is carried * Executes vacuum/analyze as indicated. Returns 0 if the plan is carried
@@ -340,6 +341,10 @@ vacuum_one_database(ConnParams *cparams,
if (vacopts->mode == MODE_ANALYZE_IN_STAGES) if (vacopts->mode == MODE_ANALYZE_IN_STAGES)
{ {
initcmd = stage_commands[stage]; initcmd = stage_commands[stage];
if (vacopts->dry_run)
printf("%s\n", initcmd);
else
executeCommand(conn, initcmd, vacopts->echo); executeCommand(conn, initcmd, vacopts->echo);
} }
else else
@@ -383,7 +388,7 @@ vacuum_one_database(ConnParams *cparams,
* through ParallelSlotsGetIdle. * through ParallelSlotsGetIdle.
*/ */
ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL); ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL);
run_vacuum_command(free_slot->connection, vacopts, sql.data, tabname); run_vacuum_command(free_slot, vacopts, sql.data, tabname);
cell = cell->next; cell = cell->next;
} while (cell != NULL); } while (cell != NULL);
@@ -407,7 +412,7 @@ vacuum_one_database(ConnParams *cparams,
} }
ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL); ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL);
run_vacuum_command(free_slot->connection, vacopts, cmd, NULL); run_vacuum_command(free_slot, vacopts, cmd, NULL);
if (!ParallelSlotsWaitCompletion(sa)) if (!ParallelSlotsWaitCompletion(sa))
ret = EXIT_FAILURE; /* error already reported by handler */ ret = EXIT_FAILURE; /* error already reported by handler */
@@ -995,19 +1000,24 @@ prepare_vacuum_command(PGconn *conn, PQExpBuffer sql,
/* /*
* Send a vacuum/analyze command to the server, returning after sending the * Send a vacuum/analyze command to the server, returning after sending the
* command. * command. If dry_run is true, the command is printed but not sent to the
* server.
* *
* Any errors during command execution are reported to stderr. * Any errors during command execution are reported to stderr.
*/ */
static void static void
run_vacuum_command(PGconn *conn, vacuumingOptions *vacopts, run_vacuum_command(ParallelSlot *free_slot, vacuumingOptions *vacopts,
const char *sql, const char *table) const char *sql, const char *table)
{ {
bool status; bool status = true;
PGconn *conn = free_slot->connection;
if (vacopts->echo) if (vacopts->echo || vacopts->dry_run)
printf("%s\n", sql); printf("%s\n", sql);
if (vacopts->dry_run)
ParallelSlotSetIdle(free_slot);
else
status = PQsendQuery(conn, sql) == 1; status = PQsendQuery(conn, sql) == 1;
if (!status) if (!status)

View File

@@ -53,6 +53,7 @@ typedef struct vacuumingOptions
bool missing_stats_only; bool missing_stats_only;
bool echo; bool echo;
bool quiet; bool quiet;
bool dry_run;
} vacuumingOptions; } vacuumingOptions;
/* Valid values for vacuumingOptions->objfilter */ /* Valid values for vacuumingOptions->objfilter */