From 8fadc245dff6f71a420c1a13b9648b000600065f Mon Sep 17 00:00:00 2001
From: Mark Dilger <mark.dilger@enterprisedb.com>
Date: Wed, 6 Jan 2021 13:01:02 -0800
Subject: [PATCH v3 3/9] Creating query_utils frontend utility

Moving the ExecuteSqlQuery, ExecuteSqlQueryForSingleRow, and
ExecuteSqlStatement out of the pg_dump project into a new shared
location.
---
 src/bin/pg_dump/pg_backup_db.c     | 102 +-------------------------
 src/bin/pg_dump/pg_backup_db.h     |  17 -----
 src/fe_utils/Makefile              |   1 +
 src/fe_utils/query_utils.c         | 114 +++++++++++++++++++++++++++++
 src/include/fe_utils/query_utils.h |  34 +++++++++
 5 files changed, 150 insertions(+), 118 deletions(-)
 create mode 100644 src/fe_utils/query_utils.c
 create mode 100644 src/include/fe_utils/query_utils.h

diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index b55a968da2..38402d0831 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -20,6 +20,7 @@
 #include "common/connect.h"
 #include "common/string.h"
 #include "dumputils.h"
+#include "fe_utils/query_utils.h"
 #include "fe_utils/string_utils.h"
 #include "parallel.h"
 #include "pg_backup_archiver.h"
@@ -271,107 +272,6 @@ notice_processor(void *arg, const char *message)
 	pg_log_generic(PG_LOG_INFO, "%s", message);
 }
 
-/*
- * The exiting query result handler embeds the historical pg_dump behavior
- * under query error conditions, including exiting nicely.  The 'conn' object
- * is unused here, but is included in the interface for alternate query result
- * handler implementations.
- *
- * Whether the query was successful is determined by comparing the returned
- * status code against the expected status code, and by comparing the number of
- * tuples returned from the query against expected_ntups.  Special negative
- * values of expected_ntups can be used to require at least one row or to
- * disables ntup checking.
- *
- * Exits on failure.  On successful query completion, returns the 'res'
- * argument as a notational convenience.
- */
-PGresult *
-exiting_handler(PGresult *res, PGconn *conn, ExecStatusType expected_status,
-				  int expected_ntups, const char *query)
-{
-	if (PQresultStatus(res) != expected_status)
-	{
-		pg_log_error("query failed: %s", PQerrorMessage(conn));
-		pg_log_error("query was: %s", query);
-		PQfinish(conn);
-		exit_nicely(1);
-	}
-	if (expected_ntups == POSITIVE_NTUPS || expected_ntups >= 0)
-	{
-		int ntups = PQntuples(res);
-
-		if (expected_ntups == POSITIVE_NTUPS)
-		{
-			if (ntups == 0)
-				fatal("query returned no rows: %s", query);
-		}
-		else if (ntups != expected_ntups)
-		{
-			/*
-			 * Preserve historical message behavior of spelling "one" as the
-			 * expected row count.
-			 */
-			if (expected_ntups == 1)
-				fatal(ngettext("query returned %d row instead of one: %s",
-							   "query returned %d rows instead of one: %s",
-							   ntups),
-					ntups, query);
-			fatal(ngettext("query returned %d row instead of %d: %s",
-						   "query returned %d rows instead of %d: %s",
-						   ntups),
-				ntups, expected_ntups, query);
-		}
-	}
-	return res;
-}
-
-/*
- * Executes the given SQL query statement.
- *
- * Invokes the exiting handler for any but PGRES_COMMAND_OK status.
- */
-void
-ExecuteSqlStatement(PGconn *conn, const char *query)
-{
-	PQclear(exiting_handler(PQexec(conn, query),
-							conn,
-							PGRES_COMMAND_OK,
-							ANY_NTUPS,
-							query));
-}
-
-/*
- * Executes the given SQL query.
- *
- * Invokes the exiting handler unless the given 'status' results.
- *
- * If successful, returns the query result.
- */
-PGresult *
-ExecuteSqlQuery(PGconn *conn, const char *query, ExecStatusType status)
-{
-	return exiting_handler(PQexec(conn, query),
-						   conn,
-						   status,
-						   ANY_NTUPS,
-						   query);
-}
-
-/*
- * Like ExecuteSqlQuery, but requires PGRES_TUPLES_OK status and
- * requires that exactly one row be returned.
- */
-PGresult *
-ExecuteSqlQueryForSingleRow(PGconn *conn, const char *query)
-{
-	return exiting_handler(PQexec(conn, query),
-						   conn,
-						   PGRES_TUPLES_OK,
-						   1,
-						   query);
-}
-
 void
 ExecuteSqlStatementAH(Archive *AHX, const char *query)
 {
diff --git a/src/bin/pg_dump/pg_backup_db.h b/src/bin/pg_dump/pg_backup_db.h
index 1aac600ece..018a28908e 100644
--- a/src/bin/pg_dump/pg_backup_db.h
+++ b/src/bin/pg_dump/pg_backup_db.h
@@ -13,23 +13,6 @@
 
 extern int	ExecuteSqlCommandBuf(Archive *AHX, const char *buf, size_t bufLen);
 
-#define POSITIVE_NTUPS (-1)
-#define ANY_NTUPS (-2)
-typedef PGresult *(*PGresultHandler) (PGresult *res,
-									  PGconn *conn,
-									  ExecStatusType expected_status,
-									  int expected_ntups,
-									  const char *query);
-
-extern PGresult *exiting_handler(PGresult *res, PGconn *conn,
-								 ExecStatusType expected_status,
-								 int expected_ntups, const char *query);
-
-extern void ExecuteSqlStatement(PGconn *conn, const char *query);
-extern PGresult *ExecuteSqlQuery(PGconn *conn, const char *query,
-								 ExecStatusType expected_status);
-extern PGresult *ExecuteSqlQueryForSingleRow(PGconn *conn, const char *query);
-
 extern void ExecuteSqlStatementAH(Archive *AHX, const char *query);
 extern PGresult *ExecuteSqlQueryAH(Archive *AHX, const char *query,
 								   ExecStatusType status);
diff --git a/src/fe_utils/Makefile b/src/fe_utils/Makefile
index d6c328faf1..7fdbe08e11 100644
--- a/src/fe_utils/Makefile
+++ b/src/fe_utils/Makefile
@@ -27,6 +27,7 @@ OBJS = \
 	mbprint.o \
 	print.o \
 	psqlscan.o \
+	query_utils.o \
 	recovery_gen.o \
 	simple_list.o \
 	string_utils.o
diff --git a/src/fe_utils/query_utils.c b/src/fe_utils/query_utils.c
new file mode 100644
index 0000000000..b28750f4b2
--- /dev/null
+++ b/src/fe_utils/query_utils.c
@@ -0,0 +1,114 @@
+/*-------------------------------------------------------------------------
+ *
+ * Query executing routines with facilities for modular error handling.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/fe_utils/query_utils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "fe_utils/exit_utils.h"
+#include "fe_utils/query_utils.h"
+
+/*
+ * The exiting query result handler embeds the historical pg_dump behavior
+ * under query error conditions, including exiting nicely.  The 'conn' object
+ * is unused here, but is included in the interface for alternate query result
+ * handler implementations.
+ *
+ * Whether the query was successful is determined by comparing the returned
+ * status code against the expected status code, and by comparing the number of
+ * tuples returned from the query against expected_ntups.  Special negative
+ * values of expected_ntups can be used to require at least one row or to
+ * disables ntup checking.
+ *
+ * Exits on failure.  On successful query completion, returns the 'res'
+ * argument as a notational convenience.
+ */
+PGresult *
+exiting_handler(PGresult *res, PGconn *conn, ExecStatusType expected_status,
+				  int expected_ntups, const char *query)
+{
+	if (PQresultStatus(res) != expected_status)
+	{
+		pg_log_error("query failed: %s", PQerrorMessage(conn));
+		pg_log_error("query was: %s", query);
+		PQfinish(conn);
+		exit_nicely(1);
+	}
+	if (expected_ntups == POSITIVE_NTUPS || expected_ntups >= 0)
+	{
+		int ntups = PQntuples(res);
+
+		if (expected_ntups == POSITIVE_NTUPS)
+		{
+			if (ntups == 0)
+				fatal("query returned no rows: %s", query);
+		}
+		else if (ntups != expected_ntups)
+		{
+			/*
+			 * Preserve historical message behavior of spelling "one" as the
+			 * expected row count.
+			 */
+			if (expected_ntups == 1)
+				fatal(ngettext("query returned %d row instead of one: %s",
+							   "query returned %d rows instead of one: %s",
+							   ntups),
+					ntups, query);
+			fatal(ngettext("query returned %d row instead of %d: %s",
+						   "query returned %d rows instead of %d: %s",
+						   ntups),
+				ntups, expected_ntups, query);
+		}
+	}
+	return res;
+}
+
+/*
+ * Executes the given SQL query statement.
+ *
+ * Invokes the exiting handler for any but PGRES_COMMAND_OK status.
+ */
+void
+ExecuteSqlStatement(PGconn *conn, const char *query)
+{
+	PQclear(exiting_handler(PQexec(conn, query),
+							conn,
+							PGRES_COMMAND_OK,
+							ANY_NTUPS,
+							query));
+}
+
+/*
+ * Executes the given SQL query.
+ *
+ * Invokes the exiting handler unless the given 'status' results.
+ *
+ * If successful, returns the query result.
+ */
+PGresult *
+ExecuteSqlQuery(PGconn *conn, const char *query, ExecStatusType status)
+{
+	return exiting_handler(PQexec(conn, query),
+						   conn,
+						   status,
+						   ANY_NTUPS,
+						   query);
+}
+
+/*
+ * Like ExecuteSqlQuery, but requires PGRES_TUPLES_OK status and
+ * requires that exactly one row be returned.
+ */
+PGresult *
+ExecuteSqlQueryForSingleRow(PGconn *conn, const char *query)
+{
+	return exiting_handler(PQexec(conn, query),
+						   conn,
+						   PGRES_TUPLES_OK,
+						   1,
+						   query);
+}
diff --git a/src/include/fe_utils/query_utils.h b/src/include/fe_utils/query_utils.h
new file mode 100644
index 0000000000..f03d17b1ed
--- /dev/null
+++ b/src/include/fe_utils/query_utils.h
@@ -0,0 +1,34 @@
+/*-------------------------------------------------------------------------
+ *
+ * Query executing routines with facilities for modular error handling.
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/fe_utils/query_utils.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef QUERY_UTILS_H
+#define QUERY_UTILS_H
+
+#include "libpq-fe.h"
+
+#define POSITIVE_NTUPS (-1)
+#define ANY_NTUPS (-2)
+typedef PGresult *(*PGresultHandler) (PGresult *res,
+									  PGconn *conn,
+									  ExecStatusType expected_status,
+									  int expected_ntups,
+									  const char *query);
+
+extern PGresult *exiting_handler(PGresult *res, PGconn *conn,
+								 ExecStatusType expected_status,
+								 int expected_ntups, const char *query);
+
+extern void ExecuteSqlStatement(PGconn *conn, const char *query);
+extern PGresult *ExecuteSqlQuery(PGconn *conn, const char *query,
+								 ExecStatusType expected_status);
+extern PGresult *ExecuteSqlQueryForSingleRow(PGconn *conn, const char *query);
+
+#endif							/* QUERY_UTILS_H */
-- 
2.21.1 (Apple Git-122.3)

