From 0f823675bb74d0b9ef4d6ab776432e6c83709f50 Mon Sep 17 00:00:00 2001 From: "okbob@github.com" Date: Sun, 3 Sep 2023 19:14:24 +0200 Subject: [PATCH 3/4] - allow to connect to server with major protocol version 3, minor version is ignored - allow to read minor protocol version --- doc/src/sgml/libpq.sgml | 33 +++++++++++++++++++++++++++++ src/include/libpq/pqcomm.h | 2 +- src/interfaces/libpq/exports.txt | 2 ++ src/interfaces/libpq/fe-connect.c | 19 ++++++++++++++++- src/interfaces/libpq/fe-protocol3.c | 21 ++++++++++++++---- src/interfaces/libpq/libpq-fe.h | 2 ++ 6 files changed, 73 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index a52baa27d5..6dc72622d6 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -2576,6 +2576,39 @@ int PQprotocolVersion(const PGconn *conn); + + PQprotocolVersionFullPQprotocolVersionFull + + + + Returns complete frontend/backend protocol number. + +int PQprotocolVersionFull(const PGconn *conn); + + The internal frontend/backend version protocol number is an value, that + composites major protocol number and minor protocol number. The returned + value is calculated as protocol version number major * 1000 + + protocol version number minor. + + + + + + + PQmakeProtocolVersionFullPQmakeProtocolVersionFull + + + + Calculates full protocol version number from entered major and minor numbers + +int PQmakeProtocolVersionFull(int pversion_major, int pversion_major); + + returns an number that is comparable with an number returned by function + . + + + + PQserverVersionPQserverVersion diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h index 46a0946b8b..4ea4538157 100644 --- a/src/include/libpq/pqcomm.h +++ b/src/include/libpq/pqcomm.h @@ -94,7 +94,7 @@ is_unixsock_path(const char *path) */ #define PG_PROTOCOL_EARLIEST PG_PROTOCOL(3,0) -#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,0) +#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,1) typedef uint32 ProtocolVersion; /* FE/BE protocol version number */ diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt index 7e101368d5..ab12d9b7cd 100644 --- a/src/interfaces/libpq/exports.txt +++ b/src/interfaces/libpq/exports.txt @@ -193,3 +193,5 @@ PQsendClosePrepared 190 PQsendClosePortal 191 PQlinkParameterStatus 192 PQunlinkParameterStatus 193 +PQprotocolVersionFull 194 +PQmakeProtocolVersionFull 195 diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index bf83a9b569..8a1fca1064 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -2777,7 +2777,7 @@ keep_going: /* We will come back to here until there is * must persist across individual connection attempts, but we must * reset them when we start to consider a new server. */ - conn->pversion = PG_PROTOCOL(3, 0); + conn->pversion = PG_PROTOCOL(3, 1); conn->send_appname = true; #ifdef USE_SSL /* initialize these values based on SSL mode */ @@ -7234,6 +7234,23 @@ PQprotocolVersion(const PGconn *conn) return PG_PROTOCOL_MAJOR(conn->pversion); } +int +PQmakeProtocolVersionFull(int pversion_major, int pversion_minor) +{ + return pversion_major * 1000 + pversion_minor; +} + +int +PQprotocolVersionFull(const PGconn *conn) +{ + if (!conn) + return 0; + if (conn->status == CONNECTION_BAD) + return 0; + return PQmakeProtocolVersionFull(PG_PROTOCOL_MAJOR(conn->pversion), + PG_PROTOCOL_MINOR(conn->pversion)); +} + int PQserverVersion(const PGconn *conn) { diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c index 90d4e17e6f..e9d4d2a1ca 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -1440,10 +1440,23 @@ pqGetNegotiateProtocolVersion3(PGconn *conn) appendPQExpBufferStr(&buf, conn->workBuffer.data); } - if (their_version < conn->pversion) - libpq_append_conn_error(conn, "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u", - PG_PROTOCOL_MAJOR(conn->pversion), PG_PROTOCOL_MINOR(conn->pversion), - PG_PROTOCOL_MAJOR(their_version), PG_PROTOCOL_MINOR(their_version)); + if (their_version != conn->pversion) + { + if ((PG_PROTOCOL_MAJOR(their_version) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST)) || + ((PG_PROTOCOL_MAJOR(their_version) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST)) && + (PG_PROTOCOL_MINOR(their_version) < PG_PROTOCOL_MINOR(PG_PROTOCOL_EARLIEST))) || + (PG_PROTOCOL_MAJOR(their_version) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST)) || + ((PG_PROTOCOL_MAJOR(their_version) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST)) && + (PG_PROTOCOL_MINOR(their_version) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))) + { + libpq_append_conn_error(conn, "protocol version not supported by server: client uses %u.%u, server supports up to %u.%u", + PG_PROTOCOL_MAJOR(conn->pversion), PG_PROTOCOL_MINOR(conn->pversion), + PG_PROTOCOL_MAJOR(their_version), PG_PROTOCOL_MINOR(their_version)); + } + else + conn->pversion = their_version; + } + if (num > 0) { appendPQExpBuffer(&conn->errorMessage, diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index ba3ad7e0aa..a64d7815ac 100644 --- a/src/interfaces/libpq/libpq-fe.h +++ b/src/interfaces/libpq/libpq-fe.h @@ -347,6 +347,8 @@ extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn); extern const char *PQparameterStatus(const PGconn *conn, const char *paramName); extern int PQprotocolVersion(const PGconn *conn); +extern int PQprotocolVersionFull(const PGconn *conn); +extern int PQmakeProtocolVersionFull(int protocol_major, int protocol_minor); extern int PQserverVersion(const PGconn *conn); extern char *PQerrorMessage(const PGconn *conn); extern int PQsocket(const PGconn *conn); -- 2.41.0