From 5a6622d67c803490320dca067898023d7676dc26 Mon Sep 17 00:00:00 2001 From: Anthonin Bonnefoy Date: Mon, 24 Aug 2026 08:57:16 +0200 Subject: Add tracing for PqMsg_CompressedMessages Add protocol tracing for the new PqMsg_CompressedMessages message. Messages decompressed from PqMsg_CompressedMessages will be prefixed with 'B*' to indicate they were decompressed. --- src/interfaces/libpq/fe-auth.c | 10 ++++---- src/interfaces/libpq/fe-misc.c | 5 ++-- src/interfaces/libpq/fe-trace.c | 41 ++++++++++++++++++++++++-------- src/interfaces/libpq/libpq-int.h | 2 +- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c index 8df5bad92ab..6cd43929699 100644 --- a/src/interfaces/libpq/fe-auth.c +++ b/src/interfaces/libpq/fe-auth.c @@ -99,7 +99,7 @@ pg_GSS_continue(PGconn *conn, int payloadlen) /* finished parsing, trace server-to-client message */ if (conn->Pfdebug) - pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false); + pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false, false); /* Only try to acquire credentials if GSS delegation isn't disabled. */ if (!pg_GSS_have_cred_cache(&conn->gcred)) @@ -267,7 +267,7 @@ pg_SSPI_continue(PGconn *conn, int payloadlen) /* finished parsing, trace server-to-client message */ if (conn->Pfdebug) - pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false); + pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false, false); OutBuffers[0].pvBuffer = NULL; OutBuffers[0].BufferType = SECBUFFER_TOKEN; @@ -605,7 +605,7 @@ pg_SASL_init(PGconn *conn, int payloadlen, bool *async) /* finished parsing, trace server-to-client message */ if (conn->Pfdebug) - pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false); + pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false, false); Assert(conn->sasl); @@ -726,7 +726,7 @@ pg_SASL_continue(PGconn *conn, int payloadlen, bool final, bool *async) /* finished parsing, trace server-to-client message */ if (conn->Pfdebug) - pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false); + pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false, false); /* For safety and convenience, ensure the buffer is NULL-terminated. */ challenge[payloadlen] = '\0'; @@ -809,7 +809,7 @@ pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq) /* finished parsing, trace server-to-client message */ if (conn->Pfdebug) - pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false); + pqTraceOutputMessage(conn, conn->inBuffer.buffer + conn->inBuffer.start, false, false); /* Encrypt the password if needed. */ diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index e027cc84ebb..57de54b6ec0 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -446,7 +446,8 @@ pqParseDone(PGconn *conn, msg_buffer * msgBuf, int newInStart) { /* trace server-to-client message */ if (conn->Pfdebug) - pqTraceOutputMessage(conn, msgBuf->buffer + msgBuf->start, false); + pqTraceOutputMessage(conn, msgBuf->buffer + msgBuf->start, false, + msgBuf == &conn->decompressBuffer); /* Mark message as done */ msgBuf->start = newInStart; @@ -546,7 +547,7 @@ pqPutMsgEnd(PGconn *conn) if (conn->Pfdebug) { if (conn->outCount < conn->outMsgStart) - pqTraceOutputMessage(conn, conn->outBuffer + conn->outCount, true); + pqTraceOutputMessage(conn, conn->outBuffer + conn->outCount, true, false); else pqTraceOutputNoTypeByteMessage(conn, conn->outBuffer + conn->outMsgStart); diff --git a/src/interfaces/libpq/fe-trace.c b/src/interfaces/libpq/fe-trace.c index 383a924d5c5..41531007985 100644 --- a/src/interfaces/libpq/fe-trace.c +++ b/src/interfaces/libpq/fe-trace.c @@ -298,6 +298,16 @@ pqTraceOutput_Close(PQExpBuffer buf, const char *message, int *cursor) pqTraceOutputString(buf, message, cursor, false); } +static void +pqTraceOutput_CompressedMessages(PQExpBuffer buf, const char *message, int *cursor, int length, + bool suppress) +{ + appendPQExpBufferStr(buf, "CompressedMessages\t"); + pqTraceOutputByte1(buf, message, cursor); + pqTraceOutputString(buf, message, cursor, false); + pqTraceOutputNbyte(buf, length - *cursor + 1, message, cursor, suppress); +} + static void pqTraceOutput_CommandComplete(PQExpBuffer buf, const char *message, int *cursor) { @@ -646,11 +656,12 @@ pqTraceOutput_ReadyForQuery(PQExpBuffer buf, const char *message, int *cursor) * Print the given message to the trace output stream. */ void -pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer) +pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer, bool compressed) { char id; int length; char *prefix = toServer ? "F" : "B"; + char *compressedPrefix = compressed ? "*" : ""; int logCursor = 0; bool regress; PQExpBufferData buf; @@ -673,19 +684,26 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer) logCursor += 4; /* - * In regress mode, suppress the length of ErrorResponse, NoticeResponse - * and ParameterStatus. The F (file name), L (line number) and R (routine - * name) fields can change as server code is modified, and if their - * lengths differ from the originals, that would break tests. For - * ParameterStatus, the size changes depending on the parameters' value, - * whose values depend on the test environment. + * In regress mode, suppress the length of some messages. For + * ErrorResponse and NoticeResponse, the F (file name), L (line number) + * and R (routine name) fields can change as server code is modified, and + * if their lengths differ from the originals, that would break tests. + * + * For ParameterStatus, the size will change depending on the parameters' + * values, which is likely going to be different depending on the test + * environment. + * + * For CompressedMessages, the message's length will depend on the + * architecture (32-bit/64-bit) or other factors like the compression + * library's version. */ if (regress && !toServer && (id == PqMsg_ErrorResponse || id == PqMsg_NoticeResponse - || id == PqMsg_ParameterStatus)) - appendPQExpBuffer(&buf, "%s\tNN\t", prefix); + || id == PqMsg_ParameterStatus + || id == PqMsg_CompressedMessages)) + appendPQExpBuffer(&buf, "%s%s\tNN\t", prefix, compressedPrefix); else - appendPQExpBuffer(&buf, "%s\t%d\t", prefix, length); + appendPQExpBuffer(&buf, "%s%s\t%d\t", prefix, compressedPrefix, length); switch (id) { @@ -701,6 +719,9 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer) appendPQExpBufferStr(&buf, "CloseComplete"); /* No message content */ break; + case PqMsg_CompressedMessages: + pqTraceOutput_CompressedMessages(&buf, message, &logCursor, length, regress); + break; case PqMsg_NotificationResponse: pqTraceOutput_NotificationResponse(&buf, message, &logCursor, regress); break; diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 6e6d78d0f46..e724e2bc53d 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -959,7 +959,7 @@ extern ssize_t pg_GSS_bytes_pending(PGconn *conn); /* === in fe-trace.c === */ extern void pqTraceOutputMessage(PGconn *conn, const char *message, - bool toServer); + bool toServer, bool compressed); extern void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message); extern void pqTraceOutputCharResponse(PGconn *conn, const char *responseType, char response); -- 2.50.1 (Apple Git-155)