This is a small patch to add a new option to vacuumdb to answer the
question "what commands will actually be run by this combination of
command-line switches against this database?" without actually running the
commands.

Including Nathan because we had previously discussed the utility of just
such a thing.
From e64b1795a6a41827b8152e62c05bbbba1dac7dc4 Mon Sep 17 00:00:00 2001
From: Corey Huinker <[email protected]>
Date: Mon, 10 Nov 2025 14:33:41 -0500
Subject: [PATCH v1] Add --dry-run to vacuumdb.

This option answers the question "what tables would be affected if I ran
a command using these options" without actually initiating those
actions.
---
 src/bin/scripts/vacuumdb.c     |  6 ++++++
 src/bin/scripts/vacuuming.c    |  7 +++++--
 src/bin/scripts/vacuuming.h    |  1 +
 doc/src/sgml/ref/vacuumdb.sgml | 11 +++++++++++
 4 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c
index e117dac2242..aa0dc366eb0 100644
--- a/src/bin/scripts/vacuumdb.c
+++ b/src/bin/scripts/vacuumdb.c
@@ -59,6 +59,7 @@ main(int argc, char *argv[])
 		{"no-process-main", no_argument, NULL, 12},
 		{"buffer-usage-limit", required_argument, NULL, 13},
 		{"missing-stats-only", no_argument, NULL, 14},
+		{"dry-run", no_argument, NULL, 15},
 		{NULL, 0, NULL, 0}
 	};
 
@@ -86,6 +87,7 @@ main(int argc, char *argv[])
 	vacopts.do_truncate = true;
 	vacopts.process_main = true;
 	vacopts.process_toast = true;
+	vacopts.dry_run = false;
 
 	/* the same for connection parameters */
 	memset(&cparams, 0, sizeof(cparams));
@@ -213,6 +215,9 @@ main(int argc, char *argv[])
 			case 14:
 				vacopts.missing_stats_only = true;
 				break;
+			case 15:
+				vacopts.dry_run = true;
+				break;
 			default:
 				/* getopt_long already emitted a complaint */
 				pg_log_error_hint("Try \"%s --help\" for more information.", progname);
@@ -375,6 +380,7 @@ help(const char *progname)
 	printf(_("  -Z, --analyze-only              only update optimizer statistics; no vacuum\n"));
 	printf(_("      --analyze-in-stages         only update optimizer statistics, in multiple\n"
 			 "                                  stages for faster results; no vacuum\n"));
+	printf(_("      --dry-run                   do not vacuum/analyze the selected tables, only print\n"));
 	printf(_("  -?, --help                      show this help, then exit\n"));
 	printf(_("\nConnection options:\n"));
 	printf(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));
diff --git a/src/bin/scripts/vacuuming.c b/src/bin/scripts/vacuuming.c
index f836f21fb03..6255d2bac47 100644
--- a/src/bin/scripts/vacuuming.c
+++ b/src/bin/scripts/vacuuming.c
@@ -383,8 +383,11 @@ vacuum_one_database(ConnParams *cparams,
 		 * through ParallelSlotsGetIdle.
 		 */
 		ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL);
-		run_vacuum_command(free_slot->connection, sql.data,
-						   echo, tabname);
+		if (vacopts->dry_run)
+			printf("%s (not executed)\n", sql.data);
+		else
+			run_vacuum_command(free_slot->connection, sql.data,
+							   echo, tabname);
 
 		cell = cell->next;
 	} while (cell != NULL);
diff --git a/src/bin/scripts/vacuuming.h b/src/bin/scripts/vacuuming.h
index 49f968b32e5..50155239e7e 100644
--- a/src/bin/scripts/vacuuming.h
+++ b/src/bin/scripts/vacuuming.h
@@ -51,6 +51,7 @@ typedef struct vacuumingOptions
 	bool		skip_database_stats;
 	char	   *buffer_usage_limit;
 	bool		missing_stats_only;
+	bool		dry_run;
 } vacuumingOptions;
 
 /* Valid values for vacuumingOptions->objfilter */
diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml
index 84c76d7350c..100691b579a 100644
--- a/doc/src/sgml/ref/vacuumdb.sgml
+++ b/doc/src/sgml/ref/vacuumdb.sgml
@@ -171,6 +171,17 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>--dry-run</option></term>
+      <listitem>
+       <para>
+        Print but do not execute the vacuum or analyze commands generated.
+        This is useful for testing the effects of various command-line options
+        before actually running the commands.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-e</option></term>
       <term><option>--echo</option></term>

base-commit: e510378358540703a13b77090a0021853bae0745
-- 
2.51.1

Reply via email to