From 9a5054196a13165b9a2c752ee822b84babead275 Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 6 Jan 2021 14:07:58 -0800
Subject: [PATCH v3 7/9] Moving pg_dump functions to new file option_utils

Moving the recently refactored functions
expand_schema_name_patterns, expand_foreign_server_name_patterns,
and expand_table_name_patterns from pg_dump.c, along with the
function expand_dbname_patterns from pg_dumpall.c, into the new file
fe_utils/option_utils.c
---
 src/bin/pg_dump/pg_dump.c           | 170 +--------------------
 src/bin/pg_dump/pg_dumpall.c        |  46 +-----
 src/fe_utils/Makefile               |   1 +
 src/fe_utils/option_utils.c         | 225 ++++++++++++++++++++++++++++
 src/include/fe_utils/option_utils.h |  35 +++++
 5 files changed, 263 insertions(+), 214 deletions(-)
 create mode 100644 src/fe_utils/option_utils.c
 create mode 100644 src/include/fe_utils/option_utils.h

diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 41ce4b7866..c334b9e829 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -55,6 +55,7 @@
 #include "catalog/pg_type_d.h"
 #include "common/connect.h"
 #include "dumputils.h"
+#include "fe_utils/option_utils.h"
 #include "fe_utils/query_utils.h"
 #include "fe_utils/string_utils.h"
 #include "getopt_long.h"
@@ -148,17 +149,6 @@ static void setup_connection(Archive *AH,
 							 const char *dumpencoding, const char *dumpsnapshot,
 							 char *use_role);
 static ArchiveFormat parseArchiveFormat(const char *format, ArchiveMode *mode);
-static void expand_schema_name_patterns(PGconn *conn,
-										SimpleStringList *patterns,
-										SimpleOidList *oids,
-										bool strict_names);
-static void expand_foreign_server_name_patterns(PGconn *conn,
-												SimpleStringList *patterns,
-												SimpleOidList *oids);
-static void expand_table_name_patterns(PGconn *conn,
-									   SimpleStringList *patterns,
-									   SimpleOidList *oids,
-									   bool strict_names);
 static NamespaceInfo *findNamespace(Oid nsoid);
 static void dumpTableData(Archive *fout, TableDataInfo *tdinfo);
 static void refreshMatViewData(Archive *fout, TableDataInfo *tdinfo);
@@ -1318,164 +1308,6 @@ parseArchiveFormat(const char *format, ArchiveMode *mode)
 	return archiveFormat;
 }
 
-/*
- * Find the OIDs of all schemas matching the given list of patterns,
- * and append them to the given OID list.
- */
-static void
-expand_schema_name_patterns(PGconn *conn,
-							SimpleStringList *patterns,
-							SimpleOidList *oids,
-							bool strict_names)
-{
-	PQExpBuffer query;
-	PGresult   *res;
-	SimpleStringListCell *cell;
-	int			i;
-
-	if (patterns->head == NULL)
-		return;					/* nothing to do */
-
-	query = createPQExpBuffer();
-
-	/*
-	 * The loop below runs multiple SELECTs might sometimes result in
-	 * duplicate entries in the OID list, but we don't care.
-	 */
-
-	for (cell = patterns->head; cell; cell = cell->next)
-	{
-		appendPQExpBufferStr(query,
-							 "SELECT oid FROM pg_catalog.pg_namespace n\n");
-		processSQLNamePattern(conn, query, cell->val, false,
-							  false, NULL, "n.nspname", NULL, NULL);
-
-		res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
-		if (strict_names && PQntuples(res) == 0)
-			fatal("no matching schemas were found for pattern \"%s\"", cell->val);
-
-		for (i = 0; i < PQntuples(res); i++)
-		{
-			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
-		}
-
-		PQclear(res);
-		resetPQExpBuffer(query);
-	}
-
-	destroyPQExpBuffer(query);
-}
-
-/*
- * Find the OIDs of all foreign servers matching the given list of patterns,
- * and append them to the given OID list.
- */
-static void
-expand_foreign_server_name_patterns(PGconn *conn,
-									SimpleStringList *patterns,
-									SimpleOidList *oids)
-{
-	PQExpBuffer query;
-	PGresult   *res;
-	SimpleStringListCell *cell;
-	int			i;
-
-	if (patterns->head == NULL)
-		return;					/* nothing to do */
-
-	query = createPQExpBuffer();
-
-	/*
-	 * The loop below runs multiple SELECTs might sometimes result in
-	 * duplicate entries in the OID list, but we don't care.
-	 */
-
-	for (cell = patterns->head; cell; cell = cell->next)
-	{
-		appendPQExpBufferStr(query,
-							 "SELECT oid FROM pg_catalog.pg_foreign_server s\n");
-		processSQLNamePattern(conn, query, cell->val, false,
-							  false, NULL, "s.srvname", NULL, NULL);
-
-		res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
-		if (PQntuples(res) == 0)
-			fatal("no matching foreign servers were found for pattern \"%s\"", cell->val);
-
-		for (i = 0; i < PQntuples(res); i++)
-			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
-
-		PQclear(res);
-		resetPQExpBuffer(query);
-	}
-
-	destroyPQExpBuffer(query);
-}
-
-/*
- * Find the OIDs of all tables matching the given list of patterns,
- * and append them to the given OID list. See also expand_dbname_patterns()
- * in pg_dumpall.c
- */
-static void
-expand_table_name_patterns(PGconn *conn,
-						   SimpleStringList *patterns, SimpleOidList *oids,
-						   bool strict_names)
-{
-	PQExpBuffer query;
-	PGresult   *res;
-	SimpleStringListCell *cell;
-	int			i;
-
-	if (patterns->head == NULL)
-		return;					/* nothing to do */
-
-	query = createPQExpBuffer();
-
-	/*
-	 * this might sometimes result in duplicate entries in the OID list, but
-	 * we don't care.
-	 */
-
-	for (cell = patterns->head; cell; cell = cell->next)
-	{
-		/*
-		 * Query must remain ABSOLUTELY devoid of unqualified names.  This
-		 * would be unnecessary given a pg_table_is_visible() variant taking a
-		 * search_path argument.
-		 */
-		appendPQExpBuffer(query,
-						  "SELECT c.oid"
-						  "\nFROM pg_catalog.pg_class c"
-						  "\n     LEFT JOIN pg_catalog.pg_namespace n"
-						  "\n     ON n.oid OPERATOR(pg_catalog.=) c.relnamespace"
-						  "\nWHERE c.relkind OPERATOR(pg_catalog.=) ANY"
-						  "\n    (array['%c', '%c', '%c', '%c', '%c', '%c'])\n",
-						  RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
-						  RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
-						  RELKIND_PARTITIONED_TABLE);
-		processSQLNamePattern(conn, query, cell->val, true,
-							  false, "n.nspname", "c.relname", NULL,
-							  "pg_catalog.pg_table_is_visible(c.oid)");
-
-		ExecuteSqlStatement(conn, "RESET search_path");
-		res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
-		PQclear(ExecuteSqlQueryForSingleRow(conn,
-											ALWAYS_SECURE_SEARCH_PATH_SQL));
-		if (strict_names && PQntuples(res) == 0)
-			fatal("no matching tables were found for pattern \"%s\"", cell->val);
-
-		for (i = 0; i < PQntuples(res); i++)
-		{
-			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
-		}
-
-		PQclear(res);
-		resetPQExpBuffer(query);
-	}
-
-	destroyPQExpBuffer(query);
-}
-
 /*
  * checkExtensionMembership
  *		Determine whether object is an extension member, and if so,
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 807226537a..01db15dfda 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -23,6 +23,7 @@
 #include "common/logging.h"
 #include "common/string.h"
 #include "dumputils.h"
+#include "fe_utils/option_utils.h"
 #include "fe_utils/query_utils.h"
 #include "fe_utils/string_utils.h"
 #include "getopt_long.h"
@@ -54,8 +55,6 @@ static PGconn *connectDatabase(const char *dbname, const char *connstr, const ch
 static char *constructConnStr(const char **keywords, const char **values);
 static PGresult *executeQuery(PGconn *conn, const char *query);
 static void executeCommand(PGconn *conn, const char *query);
-static void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns,
-								   SimpleStringList *names);
 
 static char pg_dump_bin[MAXPGPATH];
 static const char *progname;
@@ -1409,49 +1408,6 @@ dumpUserConfig(PGconn *conn, const char *username)
 	destroyPQExpBuffer(buf);
 }
 
-/*
- * Find a list of database names that match the given patterns.
- * See also expand_table_name_patterns() in pg_dump.c
- */
-static void
-expand_dbname_patterns(PGconn *conn,
-					   SimpleStringList *patterns,
-					   SimpleStringList *names)
-{
-	PQExpBuffer query;
-	PGresult   *res;
-
-	if (patterns->head == NULL)
-		return;					/* nothing to do */
-
-	query = createPQExpBuffer();
-
-	/*
-	 * The loop below runs multiple SELECTs, which might sometimes result in
-	 * duplicate entries in the name list, but we don't care, since all we're
-	 * going to do is test membership of the list.
-	 */
-
-	for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next)
-	{
-		appendPQExpBufferStr(query,
-							 "SELECT datname FROM pg_catalog.pg_database n\n");
-		processSQLNamePattern(conn, query, cell->val, false,
-							  false, NULL, "datname", NULL, NULL);
-
-		res = executeQuery(conn, query->data);
-		for (int i = 0; i < PQntuples(res); i++)
-		{
-			simple_string_list_append(names, PQgetvalue(res, i, 0));
-		}
-
-		PQclear(res);
-		resetPQExpBuffer(query);
-	}
-
-	destroyPQExpBuffer(query);
-}
-
 /*
  * Dump contents of databases.
  */
diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile
index 7fdbe08e11..eb937e4648 100644
--- a/src/fe_utils/Makefile
+++ b/src/fe_utils/Makefile
@@ -25,6 +25,7 @@ OBJS = \
 	conditional.o \
 	exit_utils.o \
 	mbprint.o \
+	option_utils.o \
 	print.o \
 	psqlscan.o \
 	query_utils.o \
diff --git a/src/fe_utils/option_utils.c b/src/fe_utils/option_utils.c
new file mode 100644
index 0000000000..7893df77aa
--- /dev/null
+++ b/src/fe_utils/option_utils.c
@@ -0,0 +1,225 @@
+/*-------------------------------------------------------------------------
+ *
+ * Command-line option facilities for frontend code
+ *
+ * Functions for converting shell-style patterns into simple lists of Oids for
+ * database objects that match the patterns.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/fe_utils/option_utils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres_fe.h"
+
+#include "catalog/pg_class.h"
+#include "common/connect.h"
+#include "fe_utils/exit_utils.h"
+#include "fe_utils/option_utils.h"
+#include "fe_utils/query_utils.h"
+#include "fe_utils/simple_list.h"
+#include "fe_utils/string_utils.h"
+#include "libpq-fe.h"
+#include "pqexpbuffer.h"
+
+/*
+ * Find the OIDs of all schemas matching the given list of patterns,
+ * and append them to the given OID list.
+ */
+void
+expand_schema_name_patterns(PGconn *conn,
+							SimpleStringList *patterns,
+							SimpleOidList *oids,
+							bool strict_names)
+{
+	PQExpBuffer query;
+	PGresult   *res;
+	SimpleStringListCell *cell;
+	int			i;
+
+	if (patterns->head == NULL)
+		return;					/* nothing to do */
+
+	query = createPQExpBuffer();
+
+	/*
+	 * The loop below runs multiple SELECTs might sometimes result in
+	 * duplicate entries in the OID list, but we don't care.
+	 */
+
+	for (cell = patterns->head; cell; cell = cell->next)
+	{
+		appendPQExpBufferStr(query,
+							 "SELECT oid FROM pg_catalog.pg_namespace n\n");
+		processSQLNamePattern(conn, query, cell->val, false,
+							  false, NULL, "n.nspname", NULL, NULL);
+
+		res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
+		if (strict_names && PQntuples(res) == 0)
+			fatal("no matching schemas were found for pattern \"%s\"", cell->val);
+
+		for (i = 0; i < PQntuples(res); i++)
+		{
+			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+		}
+
+		PQclear(res);
+		resetPQExpBuffer(query);
+	}
+
+	destroyPQExpBuffer(query);
+}
+
+/*
+ * Find the OIDs of all foreign servers matching the given list of patterns,
+ * and append them to the given OID list.
+ */
+void
+expand_foreign_server_name_patterns(PGconn *conn,
+									SimpleStringList *patterns,
+									SimpleOidList *oids)
+{
+	PQExpBuffer query;
+	PGresult   *res;
+	SimpleStringListCell *cell;
+	int			i;
+
+	if (patterns->head == NULL)
+		return;					/* nothing to do */
+
+	query = createPQExpBuffer();
+
+	/*
+	 * The loop below runs multiple SELECTs might sometimes result in
+	 * duplicate entries in the OID list, but we don't care.
+	 */
+
+	for (cell = patterns->head; cell; cell = cell->next)
+	{
+		appendPQExpBufferStr(query,
+							 "SELECT oid FROM pg_catalog.pg_foreign_server s\n");
+		processSQLNamePattern(conn, query, cell->val, false,
+							  false, NULL, "s.srvname", NULL, NULL);
+
+		res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
+		if (PQntuples(res) == 0)
+			fatal("no matching foreign servers were found for pattern \"%s\"", cell->val);
+
+		for (i = 0; i < PQntuples(res); i++)
+			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+
+		PQclear(res);
+		resetPQExpBuffer(query);
+	}
+
+	destroyPQExpBuffer(query);
+}
+
+/*
+ * Find the OIDs of all tables matching the given list of patterns,
+ * and append them to the given OID list.
+ */
+void
+expand_table_name_patterns(PGconn *conn,
+						   SimpleStringList *patterns, SimpleOidList *oids,
+						   bool strict_names)
+{
+	PQExpBuffer query;
+	PGresult   *res;
+	SimpleStringListCell *cell;
+	int			i;
+
+	if (patterns->head == NULL)
+		return;					/* nothing to do */
+
+	query = createPQExpBuffer();
+
+	/*
+	 * this might sometimes result in duplicate entries in the OID list, but
+	 * we don't care.
+	 */
+
+	for (cell = patterns->head; cell; cell = cell->next)
+	{
+		/*
+		 * Query must remain ABSOLUTELY devoid of unqualified names.  This
+		 * would be unnecessary given a pg_table_is_visible() variant taking a
+		 * search_path argument.
+		 */
+		appendPQExpBuffer(query,
+						  "SELECT c.oid"
+						  "\nFROM pg_catalog.pg_class c"
+						  "\n     LEFT JOIN pg_catalog.pg_namespace n"
+						  "\n     ON n.oid OPERATOR(pg_catalog.=) c.relnamespace"
+						  "\nWHERE c.relkind OPERATOR(pg_catalog.=) ANY"
+						  "\n    (array['%c', '%c', '%c', '%c', '%c', '%c'])\n",
+						  RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW,
+						  RELKIND_MATVIEW, RELKIND_FOREIGN_TABLE,
+						  RELKIND_PARTITIONED_TABLE);
+		processSQLNamePattern(conn, query, cell->val, true,
+							  false, "n.nspname", "c.relname", NULL,
+							  "pg_catalog.pg_table_is_visible(c.oid)");
+
+		ExecuteSqlStatement(conn, "RESET search_path");
+		res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
+		PQclear(ExecuteSqlQueryForSingleRow(conn,
+											ALWAYS_SECURE_SEARCH_PATH_SQL));
+		if (strict_names && PQntuples(res) == 0)
+			fatal("no matching tables were found for pattern \"%s\"", cell->val);
+
+		for (i = 0; i < PQntuples(res); i++)
+		{
+			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+		}
+
+		PQclear(res);
+		resetPQExpBuffer(query);
+	}
+
+	destroyPQExpBuffer(query);
+}
+
+/*
+ * Find a list of database names that match the given patterns.
+ */
+void
+expand_dbname_patterns(PGconn *conn,
+					   SimpleStringList *patterns,
+					   SimpleStringList *names)
+{
+	PQExpBuffer query;
+	PGresult   *res;
+
+	if (patterns->head == NULL)
+		return;					/* nothing to do */
+
+	query = createPQExpBuffer();
+
+	/*
+	 * The loop below runs multiple SELECTs, which might sometimes result in
+	 * duplicate entries in the name list, but we don't care, since all we're
+	 * going to do is test membership of the list.
+	 */
+
+	for (SimpleStringListCell *cell = patterns->head; cell; cell = cell->next)
+	{
+		appendPQExpBufferStr(query,
+							 "SELECT datname FROM pg_catalog.pg_database n\n");
+		processSQLNamePattern(conn, query, cell->val, false,
+							  false, NULL, "datname", NULL, NULL);
+
+		pg_log_info("executing %s", query->data);
+		res = ExecuteSqlQuery(conn, query->data, PGRES_TUPLES_OK);
+		for (int i = 0; i < PQntuples(res); i++)
+		{
+			simple_string_list_append(names, PQgetvalue(res, i, 0));
+		}
+
+		PQclear(res);
+		resetPQExpBuffer(query);
+	}
+
+	destroyPQExpBuffer(query);
+}
diff --git a/src/include/fe_utils/option_utils.h b/src/include/fe_utils/option_utils.h
new file mode 100644
index 0000000000..d626a0bbc9
--- /dev/null
+++ b/src/include/fe_utils/option_utils.h
@@ -0,0 +1,35 @@
+/*-------------------------------------------------------------------------
+ *
+ * Command-line option facilities for frontend code
+ *
+ * Functions for converting shell-style patterns into simple lists of Oids for
+ * database objects that match the patterns.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/option_utils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef OPTION_UTILS_H
+#define OPTION_UTILS_H
+
+#include "fe_utils/simple_list.h"
+#include "libpq-fe.h"
+
+extern void expand_schema_name_patterns(PGconn *conn,
+										SimpleStringList *patterns,
+										SimpleOidList *oids,
+										bool strict_names);
+extern void expand_foreign_server_name_patterns(PGconn *conn,
+												SimpleStringList *patterns,
+												SimpleOidList *oids);
+extern void expand_table_name_patterns(PGconn *conn,
+									   SimpleStringList *patterns,
+									   SimpleOidList *oids,
+									   bool strict_names);
+extern void expand_dbname_patterns(PGconn *conn, SimpleStringList *patterns,
+								   SimpleStringList *names);
+
+#endif							/* OPTION_UTILS_H */
-- 
2.21.1 (Apple Git-122.3)

