v2-0001-libpq-fe.h-Don-t-claim-SOCKTYPE-in-the-global-nam.patch

application/octet-stream

Filename: v2-0001-libpq-fe.h-Don-t-claim-SOCKTYPE-in-the-global-nam.patch
Type: application/octet-stream
Part: 1
Message: Re: [oauth] Stabilize the libpq-oauth ABI (and allow alternative implementations?)
From 8312bf3072601f03eecf55d31fba3584d214854f Mon Sep 17 00:00:00 2001
From: Jacob Champion <jacob.champion@enterprisedb.com>
Date: Mon, 1 Dec 2025 10:50:42 -0800
Subject: [PATCH v2 1/7] libpq-fe.h: Don't claim SOCKTYPE in the global
 namespace

The definition of PGoauthBearerRequest uses a temporary SOCKTYPE macro
to hide the difference between Windows and Berkeley socket handles,
since we don't surface pgsocket in our public API. This macro doesn't
need to escape the header, because implementers will choose the correct
socket type based on their platform, so I #undef'd it immediately after
use.

I didn't namespace that helper, though, so if anyone else needs a
SOCKTYPE macro, libpq-fe.h will now unhelpfully get rid of it. This
doesn't seem too far-fetched, given its proximity to existing POSIX
macro names.

Add a PQ_ prefix to avoid collisions, update and improve the surrounding
documentation, and backpatch.

Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://postgr.es/m/CAOYmi%2BmrGg%2Bn_X2MOLgeWcj3v_M00gR8uz_D7mM8z%3DdX1JYVbg%40mail.gmail.com
Backpatch-through: 18
---
 doc/src/sgml/libpq.sgml         | 10 +++++++---
 src/interfaces/libpq/libpq-fe.h | 17 ++++++++++++-----
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 7ab679a765d..7d05938feda 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -10422,10 +10422,14 @@ typedef struct PGoauthBearerRequest
 
     /* Hook outputs */
 
-    /* Callback implementing a custom asynchronous OAuth flow. */
+    /*
+     * Callback implementing a custom asynchronous OAuth flow. The signature is
+     * platform-dependent: PQ_SOCKTYPE is SOCKET on Windows, and int everywhere
+     * else.
+     */
     PostgresPollingStatusType (*async) (PGconn *conn,
                                         struct PGoauthBearerRequest *request,
-                                        SOCKTYPE *altsock);
+                                        PQ_SOCKTYPE *altsock);
 
     /* Callback to clean up custom allocations. */
     void        (*cleanup) (PGconn *conn, struct PGoauthBearerRequest *request);
@@ -10482,7 +10486,7 @@ typedef struct PGoauthBearerRequest
          hook. When the callback cannot make further progress without blocking,
          it should return either <symbol>PGRES_POLLING_READING</symbol> or
          <symbol>PGRES_POLLING_WRITING</symbol> after setting
-         <literal>*pgsocket</literal> to the file descriptor that will be marked
+         <literal>*altsock</literal> to the file descriptor that will be marked
          ready to read/write when progress can be made again. (This descriptor
          is then provided to the top-level polling loop via
          <function>PQsocket()</function>.) Return <symbol>PGRES_POLLING_OK</symbol>
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 0852584edae..877a6483b34 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -738,11 +738,15 @@ typedef struct _PGpromptOAuthDevice
 	int			expires_in;		/* seconds until user code expires */
 } PGpromptOAuthDevice;
 
-/* for PGoauthBearerRequest.async() */
+/*
+ * For PGoauthBearerRequest.async(). This macro just allows clients to avoid
+ * depending on libpq-int.h or Winsock for the "socket" type; it's undefined
+ * immediately below.
+ */
 #ifdef _WIN32
-#define SOCKTYPE uintptr_t		/* avoids depending on winsock2.h for SOCKET */
+#define PQ_SOCKTYPE uintptr_t	/* avoids depending on winsock2.h for SOCKET */
 #else
-#define SOCKTYPE int
+#define PQ_SOCKTYPE int
 #endif
 
 typedef struct PGoauthBearerRequest
@@ -768,10 +772,13 @@ typedef struct PGoauthBearerRequest
 	 * blocking during the original call to the PQAUTHDATA_OAUTH_BEARER_TOKEN
 	 * hook, it may be returned directly, but one of request->async or
 	 * request->token must be set by the hook.
+	 *
+	 * The (PQ_SOCKTYPE *) in the signature is a placeholder for the platform's
+	 * native socket type: (SOCKET *) on Windows, and (int *) everywhere else.
 	 */
 	PostgresPollingStatusType (*async) (PGconn *conn,
 										struct PGoauthBearerRequest *request,
-										SOCKTYPE * altsock);
+										PQ_SOCKTYPE * altsock);
 
 	/*
 	 * Callback to clean up custom allocations. A hook implementation may use
@@ -798,7 +805,7 @@ typedef struct PGoauthBearerRequest
 	void	   *user;
 } PGoauthBearerRequest;
 
-#undef SOCKTYPE
+#undef PQ_SOCKTYPE
 
 extern char *PQencryptPassword(const char *passwd, const char *user);
 extern char *PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm);
-- 
2.34.1