From da24813c2079c67363d5333bab5cfb3fcf969713 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Thu, 11 Sep 2014 21:08:59 -0400
Subject: [PATCH] Fix vacuumdb --analyze-in-stages --all order

When running vacuumdb --analyze-in-stages --all, it needs to run the
first stage across all databases before the second one, instead of
running all stages in a database before processing the next one.

Also respect the --quiet option with --analyze-in-stages.
---
 src/bin/scripts/t/102_vacuumdb_stages.pl | 19 +++++-
 src/bin/scripts/vacuumdb.c               | 77 +++++++++++++++++-------
 2 files changed, 72 insertions(+), 24 deletions(-)

diff --git a/src/bin/scripts/t/102_vacuumdb_stages.pl b/src/bin/scripts/t/102_vacuumdb_stages.pl
index 4b032d3abac..18d596ea548 100644
--- a/src/bin/scripts/t/102_vacuumdb_stages.pl
+++ b/src/bin/scripts/t/102_vacuumdb_stages.pl
@@ -1,7 +1,7 @@
 use strict;
 use warnings;
 use TestLib;
-use Test::More tests => 1;
+use Test::More tests => 2;
 
 my $tempdir = tempdir;
 start_test_server $tempdir;
@@ -15,3 +15,20 @@ qr/.*statement:\ SET\ default_statistics_target=1;\ SET\ vacuum_cost_delay=0;
                    .*statement:\ RESET\ default_statistics_target;
                    .*statement:\ ANALYZE/sx,
 	'analyze three times');
+
+
+issues_sql_like(
+	[ 'vacuumdb', '--analyze-in-stages', '--all' ],
+                qr/.*statement:\ SET\ default_statistics_target=1;\ SET\ vacuum_cost_delay=0;
+                   .*statement:\ ANALYZE.*
+                   .*statement:\ SET\ default_statistics_target=1;\ SET\ vacuum_cost_delay=0;
+                   .*statement:\ ANALYZE.*
+                   .*statement:\ SET\ default_statistics_target=10;\ RESET\ vacuum_cost_delay;
+                   .*statement:\ ANALYZE.*
+                   .*statement:\ SET\ default_statistics_target=10;\ RESET\ vacuum_cost_delay;
+                   .*statement:\ ANALYZE.*
+                   .*statement:\ RESET\ default_statistics_target;
+                   .*statement:\ ANALYZE.*
+                   .*statement:\ RESET\ default_statistics_target;
+                   .*statement:\ ANALYZE/sx,
+	'analyze more than one database in stages');
diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c
index 0cfe5b0bc95..86e6ab359fa 100644
--- a/src/bin/scripts/vacuumdb.c
+++ b/src/bin/scripts/vacuumdb.c
@@ -16,10 +16,10 @@
 
 
 static void vacuum_one_database(const char *dbname, bool full, bool verbose,
-	bool and_analyze, bool analyze_only, bool analyze_in_stages, bool freeze,
+	bool and_analyze, bool analyze_only, bool analyze_in_stages, int stage, bool freeze,
 					const char *table, const char *host, const char *port,
 					const char *username, enum trivalue prompt_password,
-					const char *progname, bool echo);
+					const char *progname, bool echo, bool quiet);
 static void vacuum_all_databases(bool full, bool verbose, bool and_analyze,
 					 bool analyze_only, bool analyze_in_stages, bool freeze,
 					 const char *maintenance_db,
@@ -217,18 +217,18 @@ main(int argc, char *argv[])
 			for (cell = tables.head; cell; cell = cell->next)
 			{
 				vacuum_one_database(dbname, full, verbose, and_analyze,
-									analyze_only, analyze_in_stages,
+									analyze_only, analyze_in_stages, -1,
 									freeze, cell->val,
 									host, port, username, prompt_password,
-									progname, echo);
+									progname, echo, quiet);
 			}
 		}
 		else
 			vacuum_one_database(dbname, full, verbose, and_analyze,
-								analyze_only, analyze_in_stages,
+								analyze_only, analyze_in_stages, -1,
 								freeze, NULL,
 								host, port, username, prompt_password,
-								progname, echo);
+								progname, echo, quiet);
 	}
 
 	exit(0);
@@ -254,10 +254,10 @@ run_vacuum_command(PGconn *conn, const char *sql, bool echo, const char *dbname,
 
 static void
 vacuum_one_database(const char *dbname, bool full, bool verbose, bool and_analyze,
-   bool analyze_only, bool analyze_in_stages, bool freeze, const char *table,
+	bool analyze_only, bool analyze_in_stages, int stage, bool freeze, const char *table,
 					const char *host, const char *port,
 					const char *username, enum trivalue prompt_password,
-					const char *progname, bool echo)
+					const char *progname, bool echo, bool quiet)
 {
 	PQExpBufferData sql;
 
@@ -334,14 +334,36 @@ vacuum_one_database(const char *dbname, bool full, bool verbose, bool and_analyz
 			gettext_noop("Generating medium optimizer statistics (10 targets)"),
 			gettext_noop("Generating default (full) optimizer statistics")
 		};
-		int			i;
 
-		for (i = 0; i < 3; i++)
+		if (stage == -1)
+		{
+			int		i;
+
+			/* Run all stages. */
+			for (i = 0; i < 3; i++)
+			{
+				if (!quiet)
+				{
+					puts(gettext(stage_messages[i]));
+					fflush(stdout);
+				}
+				executeCommand(conn, stage_commands[i], progname, echo);
+				run_vacuum_command(conn, sql.data, echo, dbname, table, progname);
+			}
+		}
+		else
 		{
-			puts(gettext(stage_messages[i]));
-			executeCommand(conn, stage_commands[i], progname, echo);
+			/* Otherwise, we got a stage from vacuum_all_databases(), so run
+			 * only that one. */
+			if (!quiet)
+			{
+				puts(gettext(stage_messages[stage]));
+				fflush(stdout);
+			}
+			executeCommand(conn, stage_commands[stage], progname, echo);
 			run_vacuum_command(conn, sql.data, echo, dbname, table, progname);
 		}
+
 	}
 	else
 		run_vacuum_command(conn, sql.data, echo, dbname, NULL, progname);
@@ -360,27 +382,36 @@ vacuum_all_databases(bool full, bool verbose, bool and_analyze, bool analyze_onl
 {
 	PGconn	   *conn;
 	PGresult   *result;
-	int			i;
+	int			stage;
 
 	conn = connectMaintenanceDatabase(maintenance_db, host, port,
 									  username, prompt_password, progname);
 	result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
 	PQfinish(conn);
 
-	for (i = 0; i < PQntuples(result); i++)
+	/* If analyzing in stages, then run through all stages.  Otherwise just
+	 * run once, passing -1 as the stage. */
+	for (stage = (analyze_in_stages ? 0 : -1);
+		 stage < (analyze_in_stages ? 3 : 0);
+		 stage++)
 	{
-		char	   *dbname = PQgetvalue(result, i, 0);
+		int			i;
 
-		if (!quiet)
+		for (i = 0; i < PQntuples(result); i++)
 		{
-			printf(_("%s: vacuuming database \"%s\"\n"), progname, dbname);
-			fflush(stdout);
-		}
+			char	   *dbname = PQgetvalue(result, i, 0);
 
-		vacuum_one_database(dbname, full, verbose, and_analyze, analyze_only,
-							analyze_in_stages,
-						 freeze, NULL, host, port, username, prompt_password,
-							progname, echo);
+			if (!quiet)
+			{
+				printf(_("%s: vacuuming database \"%s\"\n"), progname, dbname);
+				fflush(stdout);
+			}
+
+			vacuum_one_database(dbname, full, verbose, and_analyze, analyze_only,
+								analyze_in_stages, stage,
+							freeze, NULL, host, port, username, prompt_password,
+								progname, echo, quiet);
+		}
 	}
 
 	PQclear(result);
-- 
GitLab