From 11e8ec72b78ed267016f9630882c40760af2ee3c Mon Sep 17 00:00:00 2001 From: "okbob@github.com" Date: Sun, 21 Jan 2024 14:26:08 +0100 Subject: [PATCH 3/4] allow to connect to server with major 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 173ab779a0..51ebbadca1 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 9ae469c86c..2e604bb759 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 1f588da191..cdfb81dd45 100644 --- a/src/interfaces/libpq/exports.txt +++ b/src/interfaces/libpq/exports.txt @@ -195,3 +195,5 @@ PQchangePassword 192 PQsendPipelineSync 193 PQlinkParameterStatus 194 PQunlinkParameterStatus 195 +PQprotocolVersionFull 196 +PQmakeProtocolVersionFull 197 diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 79e0b73d61..48695fb30f 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 a4f9754c2f..f9ced96277 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -1435,10 +1435,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 5c0f17ec2a..47b9534c86 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.43.0