From 3d76fe73c7adf182c0989dc197e38394c8f50f57 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Wed, 24 Jul 2024 14:01:17 +0900
Subject: psql: Refactor status of extended protocol commands

Rather than three separate boolean flags, this groups the commands to be
handled with a single enum, able to control which libpq API to call.
---
 src/bin/psql/command.c  |  8 ++--
 src/bin/psql/common.c   | 89 ++++++++++++++++++++++-------------------
 src/bin/psql/settings.h | 17 +++++---
 3 files changed, 62 insertions(+), 52 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index f1731e527c2..42eb6756404 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -498,7 +498,7 @@ exec_command_bind(PsqlScanState scan_state, bool active_branch)
 		}
 
 		pset.bind_nparams = nparams;
-		pset.bind_flag = true;
+		pset.send_mode = PSQL_SEND_EXTENDED_QUERY_PARAMS;
 	}
 	else
 		ignore_slash_options(scan_state);
@@ -534,7 +534,7 @@ exec_command_bind_named(PsqlScanState scan_state, bool active_branch,
 		else
 		{
 			pset.stmtName = opt;
-			pset.bind_flag = true;
+			pset.send_mode = PSQL_SEND_EXTENDED_QUERY_PREPARED;
 
 			/* set of parameters */
 			while ((opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false)))
@@ -728,7 +728,7 @@ exec_command_close(PsqlScanState scan_state, bool active_branch, const char *cmd
 		else
 		{
 			pset.stmtName = opt;
-			pset.close_flag = true;
+			pset.send_mode = PSQL_SEND_EXTENDED_CLOSE;
 			status = PSQL_CMD_SEND;
 		}
 	}
@@ -2214,7 +2214,7 @@ exec_command_parse(PsqlScanState scan_state, bool active_branch,
 		else
 		{
 			pset.stmtName = opt;
-			pset.parse_flag = true;
+			pset.send_mode = PSQL_SEND_EXTENDED_PARSE;
 			status = PSQL_CMD_SEND;
 		}
 	}
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index e6e57c63dbe..6b359871fe6 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -1274,33 +1274,28 @@ sendquery_cleanup:
 		pset.gsavepopt = NULL;
 	}
 
-	/* clean up after \bind or \bind_named */
-	if (pset.bind_flag)
+	/* clean up after extended protocol queries */
+	switch (pset.send_mode)
 	{
-		for (i = 0; i < pset.bind_nparams; i++)
-			free(pset.bind_params[i]);
-		free(pset.bind_params);
-		free(pset.stmtName);
-		pset.bind_params = NULL;
-		pset.stmtName = NULL;
-		pset.bind_flag = false;
-	}
-
-	/* clean up after \parse */
-	if (pset.parse_flag)
-	{
-		free(pset.stmtName);
-		pset.stmtName = NULL;
-		pset.parse_flag = false;
-	}
-
-	/* clean up after \close */
-	if (pset.close_flag)
-	{
-		free(pset.stmtName);
-		pset.stmtName = NULL;
-		pset.close_flag = false;
+		case PSQL_SEND_EXTENDED_CLOSE:	/* \close */
+			free(pset.stmtName);
+			break;
+		case PSQL_SEND_EXTENDED_PARSE:	/* \parse */
+			free(pset.stmtName);
+			break;
+		case PSQL_SEND_EXTENDED_QUERY_PARAMS:	/* \bind */
+		case PSQL_SEND_EXTENDED_QUERY_PREPARED:	/* \bind_named */
+			for (i = 0; i < pset.bind_nparams; i++)
+				free(pset.bind_params[i]);
+			free(pset.bind_params);
+			free(pset.stmtName);
+			pset.bind_params = NULL;
+			break;
+		case PSQL_SEND_QUERY:
+			break;
 	}
+	pset.stmtName = NULL;
+	pset.send_mode = PSQL_SEND_QUERY;
 
 	/* reset \gset trigger */
 	if (pset.gset_prefix)
@@ -1474,7 +1469,7 @@ ExecQueryAndProcessResults(const char *query,
 						   const printQueryOpt *opt, FILE *printQueryFout)
 {
 	bool		timing = pset.timing;
-	bool		success;
+	bool		success = false;
 	bool		return_early = false;
 	instr_time	before,
 				after;
@@ -1487,22 +1482,32 @@ ExecQueryAndProcessResults(const char *query,
 	else
 		INSTR_TIME_SET_ZERO(before);
 
-	if (pset.bind_flag && pset.stmtName == NULL)	/* \bind */
-		success = PQsendQueryParams(pset.db, query,
-									pset.bind_nparams, NULL,
-									(const char *const *) pset.bind_params,
-									NULL, NULL, 0);
-	else if (pset.bind_flag && pset.stmtName != NULL)	/* \bind_named */
-		success = PQsendQueryPrepared(pset.db, pset.stmtName,
-									  pset.bind_nparams,
-									  (const char *const *) pset.bind_params,
-									  NULL, NULL, 0);
-	else if (pset.close_flag)	/* \close */
-		success = PQsendClosePrepared(pset.db, pset.stmtName);
-	else if (pset.parse_flag)	/* \parse */
-		success = PQsendPrepare(pset.db, pset.stmtName, query, 0, NULL);
-	else
-		success = PQsendQuery(pset.db, query);
+	switch (pset.send_mode)
+	{
+		case PSQL_SEND_EXTENDED_CLOSE:
+			success = PQsendClosePrepared(pset.db, pset.stmtName);
+			break;
+		case PSQL_SEND_EXTENDED_PARSE:
+			success = PQsendPrepare(pset.db, pset.stmtName, query, 0, NULL);
+			break;
+		case PSQL_SEND_EXTENDED_QUERY_PARAMS:
+			Assert(pset.stmtName == NULL);
+			success = PQsendQueryParams(pset.db, query,
+										pset.bind_nparams, NULL,
+										(const char *const *) pset.bind_params,
+										NULL, NULL, 0);
+			break;
+		case PSQL_SEND_EXTENDED_QUERY_PREPARED:
+			Assert(pset.stmtName != NULL);
+			success = PQsendQueryPrepared(pset.db, pset.stmtName,
+										  pset.bind_nparams,
+										  (const char *const *) pset.bind_params,
+										  NULL, NULL, 0);
+			break;
+		case PSQL_SEND_QUERY:
+			success = PQsendQuery(pset.db, query);
+			break;
+	}
 
 	if (!success)
 	{
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index 485fca871c4..a22de8ef78e 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -62,6 +62,15 @@ typedef enum
 	PSQL_COMP_CASE_LOWER,
 } PSQL_COMP_CASE;
 
+typedef enum
+{
+	PSQL_SEND_QUERY,
+	PSQL_SEND_EXTENDED_CLOSE,
+	PSQL_SEND_EXTENDED_PARSE,
+	PSQL_SEND_EXTENDED_QUERY_PARAMS,
+	PSQL_SEND_EXTENDED_QUERY_PREPARED,
+} PSQL_SEND_MODE;
+
 typedef enum
 {
 	hctl_none = 0,
@@ -96,14 +105,10 @@ typedef struct _psqlSettings
 	char	   *gset_prefix;	/* one-shot prefix argument for \gset */
 	bool		gdesc_flag;		/* one-shot request to describe query result */
 	bool		gexec_flag;		/* one-shot request to execute query result */
-	bool		bind_flag;		/* one-shot request to use extended query
-								 * protocol */
+	PSQL_SEND_MODE send_mode;	/* one-shot request to send query with normal
+								 * or extended query protocol */
 	int			bind_nparams;	/* number of parameters */
 	char	  **bind_params;	/* parameters for extended query protocol call */
-	bool		close_flag;		/* one-shot request to close a prepared
-								 * statement using extended query protocol */
-	bool		parse_flag;		/* one-shot request to parse query using
-								 * extended query protocol */
 	char	   *stmtName;		/* prepared statement name used for extended
 								 * query protocol commands */
 	bool		crosstab_flag;	/* one-shot request to crosstab result */
-- 
2.39.3 (Apple Git-146)

