The documentation of PQport says that the function will never return
NULL, unless the connection is null:
https://www.postgresql.org/docs/17/libpq-status.html#LIBPQ-PQPORT

However this is not the case: it seems to return null when the port
specified is an empty string:

    $ PSYCOPG_IMPL=python python3
    >>> import psycopg
    >>> conn = psycopg.connect("port=")
    >>> from psycopg.pq import _pq_ctypes as libpq
    >>> print(libpq.PQport(conn.pgconn._pgconn_ptr))
    None

I have prepared a patch, which is attached, to fix the issue. However
the patch returns the default port in case of no info in
'conn->connhost'. Re-reading the docs, I find the behaviour confusing.

    if there is an error producing the port information (perhaps if
the connection
    has not been fully established or there was an error), it returns
an empty string.

If we have a successful connection but no port information I believe
that returning the default port would be the right answer from this
function (it's the port where the connection was established).

If the connection is unsuccessful, the documentation says that this
function will return an empty string. Is this useful info? If that's
the case, maybe we should finish with an if instead?

    if (conn->status == CONNECTION_OK)
        return DEF_PGPORT_STR;
    else
        return "";

Or, alternatively, maybe a better implementation would be to copy the
default port on 'conn->connhost[conn->whichhost].port' if the
connection is successful (or even before attempting connection, as to
be able to return the port we tried)?

Cheers

-- Daniele
From be3a051e8f39ad504cd22e22e80178d57949b7d9 Mon Sep 17 00:00:00 2001
From: Daniele Varrazzo <daniele.varra...@gmail.com>
Date: Thu, 8 May 2025 18:34:56 +0200
Subject: [PATCH] Fix PQport to never return NULL unless the connection is NULL

This is the documented behaviour, but, at the moment, if the port is an
empty string, the port is returned null.

Return the default port instead of an empty string if the port is not
set.
---
 src/interfaces/libpq/fe-connect.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 2f87961a71e..7f746aef94e 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -7074,10 +7074,12 @@ PQport(const PGconn *conn)
 	if (!conn)
 		return NULL;
 
-	if (conn->connhost != NULL)
+	if (conn->connhost != NULL &&
+		conn->connhost[conn->whichhost].port != NULL &&
+		conn->connhost[conn->whichhost].port[0] != '\0')
 		return conn->connhost[conn->whichhost].port;
 
-	return "";
+	return DEF_PGPORT_STR;
 }
 
 /*
-- 
2.34.1

Reply via email to