Skip to content

Commit aa2cca3

Browse files
vnepogodinrobot-piglet
authored andcommitted
fix postgres: support libpq patch with pq >= 18
ref breaking change for cancel keys postgres/postgres@a460251 --- Pull Request resolved: #1051 commit_hash:335ac9ff8e90ab94cb9530ccef9faa5ab218fac3
1 parent ea9e6d0 commit aa2cca3

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

postgresql/pq-extra/pq_workaround.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ static int getNotify(PGconn* conn);
6060
static int getCopyStart(PGconn* conn, ExecStatusType copytype);
6161
static int getReadyForQuery(PGconn* conn);
6262

63+
#if PG_VERSION_NUM >= 180000
64+
static int getBackendKeyData(PGconn *conn, int msgLength);
65+
#endif
66+
6367
/* Glue to simplify working with error reporting between versions */
6468
#if PG_VERSION_NUM >= 140000
6569
#define updatePQXExpBuffer appendPQExpBuffer
@@ -394,8 +398,12 @@ static void pqxParseInput3(PGconn* conn, const PGresult* description) {
394398
* just as easy to handle it as part of the main loop.
395399
* Save the data and continue processing.
396400
*/
401+
#if PG_VERSION_NUM >= 180000
402+
if (getBackendKeyData(conn, msgLength)) return;
403+
#else
397404
if (pqGetInt(&(conn->be_pid), 4, conn)) return;
398405
if (pqGetInt(&(conn->be_key), 4, conn)) return;
406+
#endif
399407
break;
400408
case 'T': /* Row Description */
401409
if (conn->result != NULL &&
@@ -909,6 +917,78 @@ static int getReadyForQuery(PGconn* conn) {
909917
return 0;
910918
}
911919

920+
#if PG_VERSION_NUM >= 180000
921+
/*
922+
* This is copy-paste of getNotify from fe-protocol3.c
923+
*
924+
* parseInput subroutine to read a BackendKeyData message.
925+
* Entry: 'v' message type and length have already been consumed.
926+
* Exit: returns 0 if successfully consumed message.
927+
* returns EOF if not enough data.
928+
*/
929+
static int
930+
getBackendKeyData(PGconn *conn, int msgLength)
931+
{
932+
int cancel_key_len;
933+
934+
if (conn->be_cancel_key)
935+
{
936+
free(conn->be_cancel_key);
937+
conn->be_cancel_key = NULL;
938+
conn->be_cancel_key_len = 0;
939+
}
940+
941+
if (pqGetInt(&(conn->be_pid), 4, conn))
942+
return EOF;
943+
944+
cancel_key_len = 5 + msgLength - (conn->inCursor - conn->inStart);
945+
946+
if (cancel_key_len != 4 && conn->pversion == PG_PROTOCOL(3, 0))
947+
{
948+
updatePQXExpBuffer(&conn->errorMessage,
949+
libpq_gettext("received invalid BackendKeyData message: cancel key with length %d not allowed in protocol version 3.0 (must be 4 bytes)"),
950+
cancel_key_len);
951+
pqSaveErrorResult(conn);
952+
return 0;
953+
}
954+
955+
if (cancel_key_len < 4)
956+
{
957+
updatePQXExpBuffer(&conn->errorMessage,
958+
libpq_gettext("received invalid BackendKeyData message: cancel key with length %d is too short (minimum 4 bytes)"),
959+
cancel_key_len);
960+
pqSaveErrorResult(conn);
961+
return 0;
962+
}
963+
964+
if (cancel_key_len > 256)
965+
{
966+
updatePQXExpBuffer(&conn->errorMessage,
967+
libpq_gettext("received invalid BackendKeyData message: cancel key with length %d is too long (maximum 256 bytes)"),
968+
cancel_key_len);
969+
pqSaveErrorResult(conn);
970+
return 0;
971+
}
972+
973+
conn->be_cancel_key = malloc(cancel_key_len);
974+
if (conn->be_cancel_key == NULL)
975+
{
976+
updatePQXExpBufferStr(&conn->errorMessage,
977+
libpq_gettext("out of memory"));
978+
pqSaveErrorResult(conn);
979+
return 0;
980+
}
981+
if (pqGetnchar(conn->be_cancel_key, cancel_key_len, conn))
982+
{
983+
free(conn->be_cancel_key);
984+
conn->be_cancel_key = NULL;
985+
return EOF;
986+
}
987+
conn->be_cancel_key_len = cancel_key_len;
988+
return 0;
989+
}
990+
#endif
991+
912992
/*
913993
* This is copy-paste of getNotify from fe-protocol3.c
914994
*

0 commit comments

Comments
 (0)