From 10b12c50cf784741c763b3a0b6635e8d07b9c713 Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Wed, 6 Nov 2024 16:15:16 -0500
Subject: [PATCH v35 09/12] split out generate_catalog_list

---
 src/bin/scripts/vacuumdb.c | 176 +++++++++++++++++++++----------------
 1 file changed, 99 insertions(+), 77 deletions(-)

diff --git a/src/bin/scripts/vacuumdb.c b/src/bin/scripts/vacuumdb.c
index e9946f79b2..36f4796db0 100644
--- a/src/bin/scripts/vacuumdb.c
+++ b/src/bin/scripts/vacuumdb.c
@@ -560,67 +560,38 @@ print_processing_notice(PGconn *conn, int stage, const char *progname, bool quie
 }
 
 /*
- * vacuum_one_database
- *
- * Process tables in the given database.  If the 'tables' list is empty,
- * process all tables in the database.
- *
- * Note that this function is only concerned with running exactly one stage
- * when in analyze-in-stages mode; caller must iterate on us if necessary.
- *
- * If concurrentCons is > 1, multiple connections are used to vacuum tables
- * in parallel.  In this case and if the table list is empty, we first obtain
- * a list of tables from the database.
- */
-static void
-vacuum_one_database(ConnParams *cparams,
-					vacuumingOptions *vacopts,
-					int stage,
-					SimpleStringList *objects,
-					int concurrentCons,
-					const char *progname, bool echo, bool quiet)
+	* Prepare the list of tables to process by querying the catalogs.
+	*
+	* Since we execute the constructed query with the default search_path
+	* (which could be unsafe), everything in this query MUST be fully
+	* qualified.
+	*
+	* First, build a WITH clause for the catalog query if any tables were
+	* specified, with a set of values made of relation names and their
+	* optional set of columns.  This is used to match any provided column
+	* lists with the generated qualified identifiers and to filter for the
+	* tables provided via --table.  If a listed table does not exist, the
+	* catalog query will fail.
+	*/
+static SimpleStringList *
+generate_catalog_list(PGconn *conn,
+					  vacuumingOptions *vacopts,
+					  SimpleStringList *objects,
+					  bool echo,
+					  int *ntups)
 {
-	PQExpBufferData sql;
-	PQExpBufferData buf;
 	PQExpBufferData catalog_query;
-	PGresult   *res;
-	PGconn	   *conn;
+	PQExpBufferData buf;
+	SimpleStringList *dbtables;
 	SimpleStringListCell *cell;
-	ParallelSlotArray *sa;
-	SimpleStringList dbtables = {NULL, NULL};
-	int			i;
-	int			ntups;
-	bool		failed = false;
 	bool		objects_listed = false;
-	const char *initcmd;
-	const char *stage_commands[] = {
-		"SET default_statistics_target=1; SET vacuum_cost_delay=0;",
-		"SET default_statistics_target=10; RESET vacuum_cost_delay;",
-		"RESET default_statistics_target;"
-	};
+	PGresult   *res;
+	int			i;
 
-	Assert(stage == ANALYZE_NO_STAGE ||
-		   (stage >= 0 && stage < ANALYZE_NUM_STAGES));
+	dbtables = palloc(sizeof(SimpleStringList));
+	dbtables->head = NULL;
+	dbtables->tail = NULL;
 
-	conn = connectDatabase(cparams, progname, echo, false, true);
-
-	check_conn_options(conn, vacopts);
-	print_processing_notice(conn, stage, progname, quiet);
-
-	/*
-	 * Prepare the list of tables to process by querying the catalogs.
-	 *
-	 * Since we execute the constructed query with the default search_path
-	 * (which could be unsafe), everything in this query MUST be fully
-	 * qualified.
-	 *
-	 * First, build a WITH clause for the catalog query if any tables were
-	 * specified, with a set of values made of relation names and their
-	 * optional set of columns.  This is used to match any provided column
-	 * lists with the generated qualified identifiers and to filter for the
-	 * tables provided via --table.  If a listed table does not exist, the
-	 * catalog query will fail.
-	 */
 	initPQExpBuffer(&catalog_query);
 	for (cell = objects ? objects->head : NULL; cell; cell = cell->next)
 	{
@@ -771,40 +742,91 @@ vacuum_one_database(ConnParams *cparams,
 	appendPQExpBufferStr(&catalog_query, " ORDER BY c.relpages DESC;");
 	executeCommand(conn, "RESET search_path;", echo);
 	res = executeQuery(conn, catalog_query.data, echo);
+	*ntups = PQntuples(res);
 	termPQExpBuffer(&catalog_query);
 	PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo));
 
-	/*
-	 * If no rows are returned, there are no matching tables, so we are done.
-	 */
-	ntups = PQntuples(res);
-	if (ntups == 0)
-	{
-		PQclear(res);
-		PQfinish(conn);
-		return;
-	}
-
 	/*
 	 * Build qualified identifiers for each table, including the column list
 	 * if given.
 	 */
-	initPQExpBuffer(&buf);
-	for (i = 0; i < ntups; i++)
+	if (*ntups > 0)
 	{
-		appendPQExpBufferStr(&buf,
-							 fmtQualifiedId(PQgetvalue(res, i, 1),
-											PQgetvalue(res, i, 0)));
+		initPQExpBuffer(&buf);
+		for (i = 0; i < *ntups; i++)
+		{
+			appendPQExpBufferStr(&buf,
+								fmtQualifiedId(PQgetvalue(res, i, 1),
+												PQgetvalue(res, i, 0)));
 
-		if (objects_listed && !PQgetisnull(res, i, 2))
-			appendPQExpBufferStr(&buf, PQgetvalue(res, i, 2));
+			if (objects_listed && !PQgetisnull(res, i, 2))
+				appendPQExpBufferStr(&buf, PQgetvalue(res, i, 2));
 
-		simple_string_list_append(&dbtables, buf.data);
-		resetPQExpBuffer(&buf);
+			simple_string_list_append(dbtables, buf.data);
+			resetPQExpBuffer(&buf);
+		}
+		termPQExpBuffer(&buf);
 	}
-	termPQExpBuffer(&buf);
 	PQclear(res);
 
+	return dbtables;
+}
+
+/*
+ * vacuum_one_database
+ *
+ * Process tables in the given database.  If the 'tables' list is empty,
+ * process all tables in the database.
+ *
+ * Note that this function is only concerned with running exactly one stage
+ * when in analyze-in-stages mode; caller must iterate on us if necessary.
+ *
+ * If concurrentCons is > 1, multiple connections are used to vacuum tables
+ * in parallel.  In this case and if the table list is empty, we first obtain
+ * a list of tables from the database.
+ */
+static void
+vacuum_one_database(ConnParams *cparams,
+					vacuumingOptions *vacopts,
+					int stage,
+					SimpleStringList *objects,
+					int concurrentCons,
+					const char *progname, bool echo, bool quiet)
+{
+	PQExpBufferData sql;
+	PGconn	   *conn;
+	SimpleStringListCell *cell;
+	ParallelSlotArray *sa;
+	int			ntups;
+	bool		failed = false;
+	const char *initcmd;
+	SimpleStringList *dbtables;
+	const char *stage_commands[] = {
+		"SET default_statistics_target=1; SET vacuum_cost_delay=0;",
+		"SET default_statistics_target=10; RESET vacuum_cost_delay;",
+		"RESET default_statistics_target;"
+	};
+
+	Assert(stage == ANALYZE_NO_STAGE ||
+		   (stage >= 0 && stage < ANALYZE_NUM_STAGES));
+
+	conn = connectDatabase(cparams, progname, echo, false, true);
+
+	check_conn_options(conn, vacopts);
+	print_processing_notice(conn, stage, progname, quiet);
+
+	dbtables = generate_catalog_list(conn, vacopts, objects, echo, &ntups);
+
+	/*
+	 * If no rows are returned, there are no matching tables, so we are done.
+	 */
+	if (ntups == 0)
+	{
+		PQfinish(conn);
+		return;
+	}
+
+
 	/*
 	 * Ensure concurrentCons is sane.  If there are more connections than
 	 * vacuumable relations, we don't need to use them all.
@@ -837,7 +859,7 @@ vacuum_one_database(ConnParams *cparams,
 
 	initPQExpBuffer(&sql);
 
-	cell = dbtables.head;
+	cell = dbtables->head;
 	do
 	{
 		const char *tabname = cell->val;
-- 
2.47.1

