From ed6aedd7d95942f299fba7acfab9a3e363a96b31 Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Fri, 16 Aug 2024 11:28:39 +0500 Subject: [PATCH] Improved PShandleRowData function --- deps/postgresql/handle_row_data.patch | 147 ++++++++++++++++++-------- 1 file changed, 104 insertions(+), 43 deletions(-) diff --git a/deps/postgresql/handle_row_data.patch b/deps/postgresql/handle_row_data.patch index 4d8742c21..316e100d3 100644 --- a/deps/postgresql/handle_row_data.patch +++ b/deps/postgresql/handle_row_data.patch @@ -12,8 +12,52 @@ index 2265ab5..56883ec 100644 + return psHandleRowData(conn, result); +} + +diff --git src/interfaces/libpq/fe-misc.c src/interfaces/libpq/fe-misc.c +index 488f7d6..65beb87 100644 +--- src/interfaces/libpq/fe-misc.c ++++ src/interfaces/libpq/fe-misc.c +@@ -1344,3 +1344,39 @@ libpq_append_conn_error(PGconn *conn, const char *fmt,...) + + appendPQExpBufferChar(&conn->errorMessage, '\n'); + } ++ ++/* ++ * psGetInt16 ++ * read 2 byte integer and convert from network byte order ++ * to local byte order ++ */ ++int ++psGetInt16(int *result, PGconn *conn) ++{ ++ uint16 tmp2; ++ ++ if (conn->inCursor + 2 > conn->inEnd) ++ return EOF; ++ memcpy(&tmp2, conn->inBuffer + conn->inCursor, 2); ++ conn->inCursor += 2; ++ *result = (int) pg_ntoh16(tmp2); ++ return 0; ++} ++ ++/* ++ * psGetInt32 ++ * read 4 byte integer and convert from network byte order ++ * to local byte order ++ */ ++int ++psGetInt32(int *result, PGconn *conn) ++{ ++ uint32 tmp4; ++ ++ if (conn->inCursor + 4 > conn->inEnd) ++ return EOF; ++ memcpy(&tmp4, conn->inBuffer + conn->inCursor, 4); ++ conn->inCursor += 4; ++ *result = (int) pg_ntoh32(tmp4); ++ return 0; ++} diff --git src/interfaces/libpq/fe-protocol3.c src/interfaces/libpq/fe-protocol3.c -index 9c4aa7e..eb08983 100644 +index 9c4aa7e..de0746c 100644 --- src/interfaces/libpq/fe-protocol3.c +++ src/interfaces/libpq/fe-protocol3.c @@ -2299,3 +2299,102 @@ build_startup_packet(const PGconn *conn, char *packet, @@ -40,6 +84,8 @@ index 9c4aa7e..eb08983 100644 + int msgLength; + int avail; + ++ if (conn->asyncStatus != PGASYNC_BUSY) ++ return 1; + /* + * Try to read a message. First get the type code and length. Return + * if not enough data. @@ -47,7 +93,11 @@ index 9c4aa7e..eb08983 100644 + conn->inCursor = conn->inStart; + if (pqGetc(&id, conn)) + return EOF; -+ if (pqGetInt(&msgLength, 4, conn)) ++ ++ if (id != 'D') ++ return 1; ++ ++ if (psGetInt32(&msgLength, conn)) + return EOF; + + /* @@ -69,52 +119,46 @@ index 9c4aa7e..eb08983 100644 + if (avail < msgLength) + return EOF; + -+ if (conn->asyncStatus != PGASYNC_BUSY) -+ return 1; ++ if (conn->result != NULL && ++ conn->result->resultStatus == PGRES_TUPLES_OK) ++ { ++ PGresult *res = conn->result; ++ int nfields = res->numAttributes; ++ int tupnfields; /* # fields from tuple */ ++ int vlen; /* length of the current field value */ ++ int i; + -+ if (id == 'D') -+ { -+ if (conn->result != NULL && -+ conn->result->resultStatus == PGRES_TUPLES_OK) -+ { -+ PGresult *res = conn->result; -+ int nfields = res->numAttributes; -+ int tupnfields; /* # fields from tuple */ -+ int vlen; /* length of the current field value */ -+ int i; + ++ /* Get the field count and make sure it's what we expect */ ++ if (psGetInt16(&tupnfields, conn)) ++ return 1; + -+ /* Get the field count and make sure it's what we expect */ -+ if (pqGetInt(&tupnfields, 2, conn)) -+ return 1; ++ if (tupnfields != nfields) ++ return 1; + -+ if (tupnfields != nfields) ++ /* Scan the fields */ ++ for (i = 0; i < nfields; i++) ++ { ++ /* get the value length */ ++ if (psGetInt32(&vlen, conn)) + return 1; + -+ /* Scan the fields */ -+ for (i = 0; i < nfields; i++) ++ /* Skip over the data value */ ++ if (vlen > 0) + { -+ /* get the value length */ -+ if (pqGetInt(&vlen, 4, conn)) ++ if (pqSkipnchar(vlen, conn)) + return 1; -+ -+ /* Skip over the data value */ -+ if (vlen > 0) -+ { -+ if (pqSkipnchar(vlen, conn)) -+ return 1; -+ } + } -+ -+ result->id = 'D'; -+ result->len = msgLength + 5; -+ result->data = conn->inBuffer + conn->inStart; -+ conn->asyncStatus = PGASYNC_BUSY; -+ /* trust the specified message length as what to skip */ -+ conn->inStart += 5 + msgLength; -+ conn->inCursor = conn->inStart; -+ return 0; + } ++ ++ result->id = 'D'; ++ result->len = msgLength + 5; ++ result->data = conn->inBuffer + conn->inStart; ++ conn->asyncStatus = PGASYNC_BUSY; ++ /* trust the specified message length as what to skip */ ++ conn->inStart += 5 + msgLength; ++ conn->inCursor = conn->inStart; ++ return 0; + } + return 1; +} @@ -153,15 +197,32 @@ index c5170d1..3e3cc34 100644 } #endif diff --git src/interfaces/libpq/libpq-int.h src/interfaces/libpq/libpq-int.h -index a951f49..210fbc9 100644 +index a951f49..e1df8b5 100644 --- src/interfaces/libpq/libpq-int.h +++ src/interfaces/libpq/libpq-int.h -@@ -755,7 +755,7 @@ extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn, - time_t finish_time); +@@ -727,6 +727,11 @@ extern PGresult *pqFunctionCall3(PGconn *conn, Oid fnid, + int result_is_int, + const PQArgBlock *args, int nargs); + ++ /* ++ * ProxySQL light weight routines ++ */ ++extern int psHandleRowData(PGconn *conn, PSresult* result); ++ + /* === in fe-misc.c === */ + + /* +@@ -756,6 +761,13 @@ extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn, extern int pqReadReady(PGconn *conn); extern int pqWriteReady(PGconn *conn); -- -+extern int psHandleRowData(PGconn *conn, PSresult* result); + ++ /* ++ * ProxySQL light weight routines ++ */ ++extern int psGetInt16(int *result, PGconn *conn); ++extern int psGetInt32(int *result, PGconn *conn); ++ ++ /* === in fe-secure.c === */ extern int pqsecure_initialize(PGconn *, bool, bool);