From a89571fae6e91077050fc2ee6f0997376f1708fb Mon Sep 17 00:00:00 2001
From: Jelte Fennema-Nio <jelte.fennema@microsoft.com>
Date: Thu, 14 Mar 2024 10:45:51 +0100
Subject: [PATCH v38 1/3] Use simple query protocol for cancel test

The new cancel test was randomly failing on the build farm. It turns out
that using the extended query protocol was the cause of this, because
it was possible for the cancel to arrive in between the Bind and Execute
messages. This fixes that by using the simple query protocol to send the
query that should be cancelled.

Reported-By: Jacob Champion
---
 .../modules/libpq_pipeline/libpq_pipeline.c     | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c
index e730ad37698..83f9caca726 100644
--- a/src/test/modules/libpq_pipeline/libpq_pipeline.c
+++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c
@@ -165,7 +165,7 @@ static void
 send_cancellable_query_impl(int line, PGconn *conn, PGconn *monitorConn)
 {
 	const char *env_wait;
-	const Oid	paramTypes[1] = {INT4OID};
+	char	   *query;
 
 	/*
 	 * Wait for the connection to be idle, so that our check for an active
@@ -178,10 +178,21 @@ send_cancellable_query_impl(int line, PGconn *conn, PGconn *monitorConn)
 	if (env_wait == NULL)
 		env_wait = "180";
 
-	if (PQsendQueryParams(conn, "SELECT pg_sleep($1)", 1, paramTypes,
-						  &env_wait, NULL, NULL, 0) != 1)
+	/*
+	 * We cannot use PQsendQueryParams here because it uses the extended
+	 * protocol to send the query. And it turns out there exists a race
+	 * condition where would send the cancel request in between the Bind and
+	 * Execute messages, resulting in the cancel request being ignored. So
+	 * instead we build the query string client side and send it using
+	 * PQsendQuery so there is only a single Query message.
+	 */
+	query = psprintf("SELECT pg_sleep(%d)", atoi(env_wait));
+
+	if (PQsendQuery(conn, query) != 1)
 		pg_fatal_impl(line, "failed to send query: %s", PQerrorMessage(conn));
 
+	pfree(query);
+
 	/*
 	 * Wait for the query to start, because if the query is not running yet
 	 * the cancel request that we send won't have any effect.

base-commit: cc6e64afda530576d83e331365d36c758495a7cd
-- 
2.34.1

