v2-0001-libpq-PQtrace-output_one_line.patch
application/octet-stream
Filename: v2-0001-libpq-PQtrace-output_one_line.patch
Type: application/octet-stream
Part: 0
Message:
RE: libpq debug log
Patch
Format: unified
Series: patch v2-0001
| File | + | − |
|---|---|---|
| src/interfaces/libpq/fe-misc.c | 515 | 27 |
| src/interfaces/libpq/fe-protocol3.c | 8 | 0 |
| src/interfaces/libpq/libpq-int.h | 44 | 0 |
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index ea4c9d2..20cfef3 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -35,6 +35,7 @@
#ifdef WIN32
#include "win32.h"
+#include <windows.h>
#else
#include <unistd.h>
#include <sys/time.h>
@@ -45,6 +46,7 @@
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
+#include <sys/timeb.h>
#endif
#include "libpq-fe.h"
@@ -53,12 +55,377 @@
#include "port/pg_bswap.h"
#include "pg_config_paths.h"
+/* protocol message name */
+static char *command_text_b[] = {
+ /* 0 */ 0,
+ /* 1 */ "ParseComplete",
+ /* 2 */ "BindComplete",
+ /* 3 */ "CloseComplete",
+ /* \x04 - \x0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x10 - \x1f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x20 - \x2f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x30 - \x3f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* @ */ 0,
+ /* A */ "NotificationResponse",
+ /* B */ 0,
+ /* C */ "CommandComplete",
+ /* D */ "DataRow",
+ /* E */ "ErrorResponse",
+ /* F */ 0,
+ /* G */ "CopyInResponse",
+ /* H */ "CopyOutResponse",
+ /* I */ "EmptyQueryResponse",
+ /* J */ 0,
+ /* K */ "BackendKeyData",
+ /* L */ 0,
+ /* M */ 0,
+ /* N */ "NoticeResponse",
+ /* O */ 0,
+ /* P */ 0,
+ /* Q */ 0,
+ /* R */ "Authentication",
+ /* S */ "ParameterStatus",
+ /* T */ "RowDescription",
+ /* U */ 0,
+ /* V */ "FunctionCallResponse",
+ /* W */ "CopyBothResponse",
+ /* X */ 0,
+ /* Y */ 0,
+ /* Z */ "ReadyForQuery",
+ /* \x5b - \x5f*/ 0, 0, 0, 0, 0,
+ /* \x60 - \x6d*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* n */ "NoData",
+ /* o */ 0,
+ /* p */ 0,
+ /* q */ 0,
+ /* r */ 0,
+ /* s */ "PortalSuspended",
+ /* t */ "ParameterDescription",
+ /* u */ 0,
+ /* v */ "NegotiateProtocolVersion",
+ /* w */ 0,
+ /* x */ 0,
+ /* y */ 0,
+ /* z */ 0
+};
+#define COMMAND_B_MAX (sizeof(command_text_b) / sizeof(*command_text_b))
+
+static char *command_text_f[] = {
+ /* \0 - \x0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x10 - \x1f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x20 - \x2f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x30 - \x3f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* @ */ 0,
+ /* A */ 0,
+ /* B */ "Bind",
+ /* C */ "Close",
+ /* D */ "Describe",
+ /* E */ "Execute",
+ /* F */ "FunctionCall",
+ /* G */ 0,
+ /* H */ "Flush",
+ /* I */ 0,
+ /* J */ 0,
+ /* K */ 0,
+ /* L */ 0,
+ /* M */ 0,
+ /* N */ 0,
+ /* O */ 0,
+ /* P */ "Parse",
+ /* Q */ "Query",
+ /* R */ 0,
+ /* S */ "Sync",
+ /* T */ 0,
+ /* U */ 0,
+ /* V */ 0,
+ /* W */ 0,
+ /* X */ "Terminate",
+ /* Y */ 0,
+ /* Z */ 0,
+ /* \x5b - \x5f*/ 0, 0, 0, 0, 0,
+ /* ` */ 0,
+ /* a */ 0,
+ /* b */ 0,
+ /* c */ 0,
+ /* d */ 0,
+ /* e */ 0,
+ /* f */ "CopyFail",
+ /* g */ 0,
+ /* h */ 0,
+ /* i */ 0,
+ /* j */ 0,
+ /* k */ 0,
+ /* l */ 0,
+ /* m */ 0,
+ /* n */ 0,
+ /* o */ 0,
+ /* p */ "AuthnenticationResponse",
+ /* q */ 0,
+ /* r */ 0,
+ /* s */ 0,
+ /* t */ 0,
+ /* u */ 0,
+ /* v */ 0,
+ /* w */ 0,
+ /* x */ 0,
+ /* y */ 0,
+ /* z */ 0
+};
+#define COMMAND_F_MAX (sizeof(command_text_f) / sizeof(*command_text_f))
+
+static char *command_text_bf[] = {
+ /* \0 - \x0f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x10 - \x1f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x20 - \x2f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x30 - \x3f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x40 - \x4f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* \x50 - \x5f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* ` */ 0,
+ /* a */ 0,
+ /* b */ 0,
+ /* c */ "CopyDone",
+ /* d */ "CopyData",
+ /* e */ 0,
+ /* f */ 0,
+ /* g */ 0,
+ /* h */ 0,
+ /* i */ 0,
+ /* j */ 0,
+ /* k */ 0,
+ /* l */ 0,
+ /* m */ 0,
+ /* n */ 0,
+ /* o */ 0,
+ /* p */ 0,
+ /* q */ 0,
+ /* r */ 0,
+ /* s */ 0,
+ /* t */ 0,
+ /* u */ 0,
+ /* v */ 0,
+ /* w */ 0,
+ /* x */ 0,
+ /* y */ 0,
+ /* z */ 0
+};
+#define COMMAND_BF_MAX (sizeof(command_text_bf) / sizeof(*command_text_bf))
+
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn);
static int pqSendSome(PGconn *conn, int len);
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite,
time_t end_time);
static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time);
+static void fputnbytes(FILE *f, const char *str, size_t n);
+static void message_Byte1(PGconn *conn, char v, CommunicationDirection direction);
+static void message_String(PGconn *conn, const char *v, int length,
+ CommunicationDirection direction);
+static void message_nchar(PGconn *conn, const char *v, int length,
+ CommunicationDirection direction);
+static void message_Int(PGconn *conn, int v, int length, CommunicationDirection direct);
+static void getCurrentTime(char* currenttime);
+#define TRACELOG_TIME_SIZE 33
+
+/*
+ * message_get_command_text:
+ * Get Protocol message text from byte1 identifier
+ */
+static char *
+message_get_command_text(unsigned char c, CommunicationDirection direction)
+{
+ char *text = 0;
+
+ if (c >= 0 && c < COMMAND_BF_MAX)
+ {
+ text = command_text_bf[c];
+ if (text)
+ return text;
+ }
+
+ if (direction == FROM_BACKEND && c >= 0 && c < COMMAND_B_MAX)
+ {
+ text = command_text_b[c];
+ if (text)
+ return text;
+ }
+
+ if (direction == FROM_FRONTEND && c >= 0 && c < COMMAND_F_MAX)
+ {
+ text = command_text_f[c];
+ if (text)
+ return text;
+ }
+
+ return "UnknownCommand";
+}
+
+/* initialize_message_log: Initializing logging message */
+static void
+initialize_message_log(PGconn *conn) {
+ conn->logging_message.state = LOG_COMMAND;
+ conn->logging_message.length = 0;
+}
+
+/* message_invalid_protocol: Output a message the protocol is invalid */
+static void
+message_invalid_protocol(PGconn *conn)
+{
+ fprintf(conn->Pfdebug, ":::Invalid Protocol\n");
+ conn->logging_message.state = LOG_COMMAND;
+}
+
+/*
+ * message_state_transaction:
+ * Check whether message formats is complete. If so,
+ * break the line.
+ */
+void
+message_state_transaction(int size, PGconn *conn)
+{
+ conn->logging_message.length -= size;
+ if (conn->logging_message.length <= 0)
+ {
+ fprintf(conn->Pfdebug, "\n");
+ initialize_message_log(conn);
+ }
+}
+
+/*
+ * message_entry: Remember messages that frontend sends.
+ */
+static void message_entry(PGconn *conn, Type type, int length)
+{
+ char message;
+ uint16 result16 = 0;
+ uint32 result32 = 0;
+ int result = 0;
+
+ if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
+ {
+ conn->frontend_entry[conn->entry].type = type;
+ conn->frontend_entry[conn->entry].message_addr = conn->outMsgEnd - length;
+ conn->frontend_entry[conn->entry].message_length = length;
+ conn->entry++;
+ }
+ else
+ {
+ /* In older protocols output one contents per one line */
+ switch (type)
+ {
+ case BYTE1:
+ memcpy(&message, conn->outBuffer + conn->outMsgEnd - length, length);
+ fprintf(conn->Pfdebug, "To backend> %c\n", message);
+ break;
+
+ case STRING:
+ memcpy(&message, conn->outBuffer + conn->outMsgEnd - length, length);
+ fprintf(conn->Pfdebug, "To backend> \"%c\"\n", message);
+ break;
+
+ case NCHAR:
+ fprintf(conn->Pfdebug, "To backend (%d)> ", length);
+ fputnbytes(conn->Pfdebug, conn->outBuffer + conn->outMsgEnd - length, length);
+ fprintf(conn->Pfdebug, "\n");
+ break;
+
+ case INT16:
+ memcpy(&result16, conn->outBuffer + conn->outMsgEnd - length, length);
+ result = (int) pg_ntoh16(result16);
+ fprintf(conn->Pfdebug, "To backend (#%d)> %c\n", length, result);
+ break;
+
+ case INT32:
+ memcpy(&result32, conn->outBuffer + conn->outMsgEnd - length, length);
+ result = (int) pg_ntoh32(result32);
+ fprintf(conn->Pfdebug, "To backend (#%d)> %c\n", length, result);
+ break;
+ }
+ }
+}
+
+/*
+ * put_frontend_entry:
+ * After output frontend message length, output organized frontend message.
+ */
+static void put_frontend_entry(PGconn *conn)
+{
+ int i;
+ int message_addr;
+ int length;
+
+ char message;
+ uint16 result16 = 0;
+ uint32 result32 = 0;
+ int result = 0;
+
+ for (i = 0; i < conn->entry; i++)
+ {
+ message_addr = conn->frontend_entry[i].message_addr;
+ length = conn->frontend_entry[i].message_length;
+
+ switch (conn->frontend_entry[i].type)
+ {
+ case BYTE1:
+ memcpy(&message, conn->outBuffer + message_addr, length);
+ message_Byte1(conn, message, FROM_FRONTEND);
+ break;
+
+ case STRING:
+ message_String(conn, conn->outBuffer + message_addr,
+ length, FROM_FRONTEND);
+ break;
+
+ case NCHAR:
+ message_nchar(conn, conn->outBuffer + message_addr,
+ length, FROM_FRONTEND);
+ break;
+
+ case INT16:
+ memcpy(&result16, conn->outBuffer + message_addr, length);
+ result = (int) pg_ntoh16(result16);
+ message_Int(conn, result, length, FROM_FRONTEND);
+ break;
+
+ case INT32:
+ memcpy(&result32, conn->outBuffer + message_addr, length);
+ result = (int) pg_ntoh32(result32);
+ message_Int(conn, result, length, FROM_FRONTEND);
+ break;
+ }
+ }
+ conn->entry = 0;
+ initialize_message_log(conn);
+}
+
+/*
+ * getCurrentTime: get current time for trace log output
+ */
+static void
+getCurrentTime(char* currenttime)
+{
+#ifdef WIN32
+ SYSTEMTIME localTime;
+ TIME_ZONE_INFORMATION TimezoneInfo;
+ GetLocalTime(&localTime);
+
+ GetTimeZoneInformation(&TimezoneInfo);
+ snprintf(currenttime, TRACELOG_TIME_SIZE, "%4d-%02d-%02d %02d:%02d:%02d.%03d %s ",
+ localTime.wYear, localTime.wMonth, localTime.wDay,
+ localTime.wHour, localTime.wMinute, localTime.wSecond,
+ localTime.wMilliseconds, TimezoneInfo.Bias);
+#else
+ struct timeb localTime;
+ struct tm *tm;
+ char timezone[100];
+ ftime(&localTime);
+ tm = localtime(&localTime.time);
+
+ strftime(timezone, sizeof(timezone), "%Z", tm);
+ snprintf(currenttime, TRACELOG_TIME_SIZE, "%4d-%02d-%02d %02d:%02d:%02d.%03d %s ",
+ 1900+ tm->tm_year, 1 + tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec, localTime.millitm, timezone);
+#endif
+}
/*
* PQlibVersion: return the libpq version number
@@ -99,12 +466,11 @@ pqGetc(char *result, PGconn *conn)
*result = conn->inBuffer[conn->inCursor++];
if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "From backend> %c\n", *result);
+ message_Byte1(conn, *result, FROM_BACKEND);
return 0;
}
-
/*
* pqPutc: write 1 char to the current message
*/
@@ -115,11 +481,49 @@ pqPutc(char c, PGconn *conn)
return EOF;
if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> %c\n", c);
+ message_entry(conn, BYTE1, 1);
return 0;
}
+/*
+ * message_Byte1: output 1 char message to the log
+ */
+static void
+message_Byte1(PGconn *conn, char v, CommunicationDirection direction)
+{
+ char *command_text;
+ char *direction_text = direction == FROM_BACKEND ? "<" : ">";
+ char current_time[TRACELOG_TIME_SIZE];
+
+ if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
+ {
+ switch (conn->logging_message.state) {
+ case LOG_COMMAND:
+ command_text = message_get_command_text((unsigned char) v, direction);
+ getCurrentTime(current_time);
+ fprintf(conn->Pfdebug, "%s %s %s ", current_time, direction_text, command_text);
+ conn->logging_message.state = LOG_LENGTH;
+ conn->logging_message.command = v;
+ conn->entry = 0;
+ break;
+
+ case LOG_BODY:
+ fprintf(conn->Pfdebug, "%c ", v);
+ message_state_transaction(sizeof(v), conn);
+ break;
+
+ default:
+ message_invalid_protocol(conn);
+ break;
+ }
+ }
+ else
+ fprintf(conn->Pfdebug, "FROM backend> %c\n", v);
+
+ return;
+}
+
/*
* pqGets[_append]:
@@ -153,8 +557,7 @@ pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
conn->inCursor = ++inCursor;
if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "From backend> \"%s\"\n",
- buf->data);
+ message_String(conn, buf->data, buf->len + 1, FROM_BACKEND);
return 0;
}
@@ -182,12 +585,39 @@ pqPuts(const char *s, PGconn *conn)
return EOF;
if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> \"%s\"\n", s);
+ message_entry(conn, STRING, strlen(s) + 1);
return 0;
}
/*
+ * message_String: output a a null-terminated string to the log
+ */
+static void
+message_String(PGconn *conn, const char *v, int length, CommunicationDirection direction)
+{
+ if(length < 0)
+ length = strlen(v) + 1;
+
+ if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
+ {
+ switch (conn->logging_message.state)
+ {
+ case LOG_BODY:
+ fprintf(conn->Pfdebug, "\"%s\" ", v);
+ message_state_transaction(length, conn);
+ break;
+
+ default:
+ message_invalid_protocol(conn);
+ break;
+ }
+ }
+ else
+ fprintf(conn->Pfdebug, "To backend> \"%s\"\n", v);
+}
+
+/*
* pqGetnchar:
* get a string of exactly len bytes in buffer s, no null termination
*/
@@ -203,11 +633,7 @@ pqGetnchar(char *s, size_t len, PGconn *conn)
conn->inCursor += len;
if (conn->Pfdebug)
- {
- fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
- fputnbytes(conn->Pfdebug, s, len);
- fprintf(conn->Pfdebug, "\n");
- }
+ message_nchar(conn, s, len, FROM_BACKEND);
return 0;
}
@@ -227,11 +653,7 @@ pqSkipnchar(size_t len, PGconn *conn)
return EOF;
if (conn->Pfdebug)
- {
- fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
- fputnbytes(conn->Pfdebug, conn->inBuffer + conn->inCursor, len);
- fprintf(conn->Pfdebug, "\n");
- }
+ message_nchar(conn, conn->inBuffer + conn->inCursor, len, FROM_BACKEND);
conn->inCursor += len;
@@ -249,13 +671,39 @@ pqPutnchar(const char *s, size_t len, PGconn *conn)
return EOF;
if (conn->Pfdebug)
+ message_entry(conn, NCHAR, len);
+
+ return 0;
+}
+
+/*
+ * message_nchar: output a string of exactly len bytes message to the log
+ */
+static void
+message_nchar(PGconn *conn, const char *v, int length, CommunicationDirection direction)
+{
+ if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
{
- fprintf(conn->Pfdebug, "To backend> ");
- fputnbytes(conn->Pfdebug, s, len);
+ switch (conn->logging_message.state)
+ {
+ case LOG_BODY:
+ fprintf(conn->Pfdebug, "\'");
+ fputnbytes(conn->Pfdebug, v, length);
+ fprintf(conn->Pfdebug, "\' ");
+ message_state_transaction(length, conn);
+ break;
+
+ default:
+ message_invalid_protocol(conn);
+ break;
+ }
+ }
+ else
+ {
+ fprintf(conn->Pfdebug, "From backend (%d)> ", length);
+ fputnbytes(conn->Pfdebug, v, length);
fprintf(conn->Pfdebug, "\n");
}
-
- return 0;
}
/*
@@ -293,7 +741,7 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
}
if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
+ message_Int(conn, *result, (unsigned int) bytes, FROM_BACKEND);
return 0;
}
@@ -315,11 +763,15 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
tmp2 = pg_hton16((uint16) value);
if (pqPutMsgBytes((const char *) &tmp2, 2, conn))
return EOF;
+ if (conn->Pfdebug)
+ message_entry(conn, INT16, 2);
break;
case 4:
tmp4 = pg_hton32((uint32) value);
if (pqPutMsgBytes((const char *) &tmp4, 4, conn))
return EOF;
+ if (conn->Pfdebug)
+ message_entry(conn, INT32, 4);
break;
default:
pqInternalNotice(&conn->noticeHooks,
@@ -327,11 +779,40 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
(unsigned long) bytes);
return EOF;
}
+ return 0;
+}
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
+/*
+ * message_Int: output a 2 or 4 bytes integer message to the log
+ */
+static void
+message_Int(PGconn *conn, int v, int length, CommunicationDirection direct)
+{
+ char *prefix = length == 4 ? "" : "#";
- return 0;
+ if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
+ {
+ switch (conn->logging_message.state)
+ {
+ case LOG_LENGTH:
+ fprintf(conn->Pfdebug, "%d ", v);
+ conn->logging_message.length = v - length;
+ conn->logging_message.state = LOG_BODY;
+ message_state_transaction(0, conn);
+ break;
+
+ case LOG_BODY:
+ fprintf(conn->Pfdebug, "%s%d ", prefix, v);
+ message_state_transaction(length, conn);
+ break;
+
+ default:
+ message_invalid_protocol(conn);
+ break;
+ }
+ }
+ else
+ fprintf(conn->Pfdebug, "To backend (#%d)> %d\n", length, v);
}
/*
@@ -549,8 +1030,7 @@ pqPutMsgStart(char msg_type, bool force_len, PGconn *conn)
/* length word, if needed, will be filled in by pqPutMsgEnd */
if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> Msg %c\n",
- msg_type ? msg_type : ' ');
+ message_Byte1(conn, msg_type ? msg_type : ' ', FROM_FRONTEND);
return 0;
}
@@ -586,15 +1066,23 @@ pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
int
pqPutMsgEnd(PGconn *conn)
{
- if (conn->Pfdebug)
+ if (conn->Pfdebug && PG_PROTOCOL_MAJOR(conn->pversion) < 3)
+ {
fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
conn->outMsgEnd - conn->outCount);
+ }
/* Fill in length word if needed */
if (conn->outMsgStart >= 0)
{
uint32 msgLen = conn->outMsgEnd - conn->outMsgStart;
+ if (conn->Pfdebug)
+ {
+ message_Int(conn, (int) msgLen, 4, FROM_FRONTEND);
+ put_frontend_entry(conn);
+ }
+
msgLen = pg_hton32(msgLen);
memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
}
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index d582cfd..6013c6a 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -125,6 +125,9 @@ pqParseInput3(PGconn *conn)
*/
handleSyncLoss(conn, id, msgLength);
}
+ /* Terminate a harf-finished logging message */
+ if (conn->Pfdebug)
+ message_state_transaction(msgLength, conn);
return;
}
@@ -158,7 +161,12 @@ pqParseInput3(PGconn *conn)
{
/* If not IDLE state, just wait ... */
if (conn->asyncStatus != PGASYNC_IDLE)
+ {
+ /* Terminate a harf-finished logging message */
+ if (conn->Pfdebug)
+ message_state_transaction(msgLength, conn);
return;
+ }
/*
* Unexpected message in IDLE state; need to recover somehow.
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 1221ea9..c5bc9d4 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -155,6 +155,44 @@ typedef struct
void *noticeProcArg;
} PGNoticeHooks;
+/* Logging message */
+typedef enum CommunicationDirection
+{
+ FROM_BACKEND,
+ FROM_FRONTEND
+} CommunicationDirection;
+
+typedef enum State
+{
+ LOG_COMMAND,
+ LOG_LENGTH,
+ LOG_BODY
+} State;
+
+typedef struct _LoggingMsg
+{
+ State state;
+ int length;
+ char command;
+} LoggingMsg;
+
+/* Organizing frontend message. */
+typedef enum Type
+{
+ BYTE1,
+ STRING,
+ NCHAR,
+ INT16,
+ INT32
+} Type;
+
+typedef struct _Frontend_Entry
+{
+ Type type;
+ int message_addr;
+ int message_length;
+} Frontend_Entry;
+
typedef struct PGEvent
{
PGEventProc proc; /* the function to call on events */
@@ -370,6 +408,11 @@ struct pg_conn
/* Optional file to write trace info to */
FILE *Pfdebug;
+ /* Organize trace info to output one line */
+ LoggingMsg logging_message;
+ Frontend_Entry frontend_entry[MAXPGPATH];
+ int entry;
+
/* Callback procedures for notice message processing */
PGNoticeHooks noticeHooks;
@@ -656,6 +699,7 @@ extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn,
time_t finish_time);
extern int pqReadReady(PGconn *conn);
extern int pqWriteReady(PGconn *conn);
+extern void message_state_transaction(int size, PGconn *conn);
/* === in fe-secure.c === */