pg.ddx.io pgsql-hackers@postgresql.org mailing list archive
help / color / mirror / Atom feed From: alvherre@alvh.no-ip.org <alvherre@alvh.no-ip.org>
To: tsunakawa.takay@fujitsu.com <tsunakawa.takay@fujitsu.com>
Cc: iwata.aya@fujitsu.com <iwata.aya@fujitsu.com>
Cc: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Cc: tgl@sss.pgh.pa.us <tgl@sss.pgh.pa.us>
Cc: k.jamison@fujitsu.com <k.jamison@fujitsu.com>
Cc: pgsql-hackers@lists.postgresql.org <pgsql-hackers@lists.postgresql.org>
Subject: Re: libpq debug log
Date: Sat, 27 Mar 2021 16:28:12 -0300
Message-ID: <20210327192812.GA25115@alvherre.pgsql> (raw )
In-Reply-To: <20210327003320.GA7965@alvherre.pgsql >
On 2021-Mar-26, alvherre@alvh.no-ip.org wrote:
> Proposed changes on top of v29.
This last one uses libpq_pipeline -t and verifies the output against an
expected trace file. Applies on top of all the previous patches. I
attach the whole lot, so that the CF bot has a chance to run it.
I did notice another problem for comparison of expected trace files,
which is that RowDescription includes table OIDs for some columns. I
think we would need to have a flag to suppress that too, somehow,
although the answer to what should we do is not as clear as for the
other two cases.
I dodged the issue by just using -t for the pipeline cases that don't
have OIDs in their output. This leaves us with no coverage for the
ErrorResponse message, which I think is a shortcoming. If we fixed the
OID problem and the ErrorResponse problem, we could add an expected
trace for pipeline_abort. I think we should do that.
Maybe the easiest way is to have a new flag PQTRACE_REGRESS_MODE.
--
Álvaro Herrera 39°49'30"S 73°17'W
Essentially, you're proposing Kevlar shoes as a solution for the problem
that you want to walk around carrying a loaded gun aimed at your foot.
(Tom Lane)
Attachments:
[text/x-diff] v30-0001-libpq-trace-v29.patch (27.7K, ../20210327192812.GA25115@alvherre.pgsql/2-v30-0001-libpq-trace-v29.patch)
download | inline diff:
From f239da90f069b19e1c2fa6b69bc7c6fd4be826b9 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 26 Mar 2021 11:10:52 -0300
Subject: [PATCH v30 1/7] libpq trace v29
---
doc/src/sgml/libpq.sgml | 39 +-
src/interfaces/libpq/Makefile | 1 +
src/interfaces/libpq/exports.txt | 1 +
src/interfaces/libpq/fe-connect.c | 21 -
src/interfaces/libpq/fe-exec.c | 4 -
src/interfaces/libpq/fe-misc.c | 66 +--
src/interfaces/libpq/fe-protocol3.c | 8 +
src/interfaces/libpq/libpq-fe.h | 2 +
src/interfaces/libpq/libpq-int.h | 7 +
src/interfaces/libpq/libpq-trace.c | 717 ++++++++++++++++++++++++++++
10 files changed, 789 insertions(+), 77 deletions(-)
create mode 100644 src/interfaces/libpq/libpq-trace.c
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index be674fbaa9..838e394d54 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -6459,12 +6459,27 @@ PGContextVisibility PQsetErrorContextVisibility(PGconn *conn, PGContextVisibilit
<listitem>
<para>
- Enables tracing of the client/server communication to a debugging file stream.
+ Enables tracing of the client/server communication to a debugging file
+ stream.
<synopsis>
void PQtrace(PGconn *conn, FILE *stream);
</synopsis>
</para>
+ <para>
+ Each line consists of: an optional timestamp, a direction indicator
+ (<literal>></literal> for messages from client to server
+ or <literal><</literal> for messages from server to client),
+ message length, message type, and message contents.
+ Non-message contents fields (timestamp, direction, length and message type)
+ are separated by a tab. Message contents are separated by a space.
+ Protocol strings are enclosed in double quotes, while strings used as data
+ values are enclosed in single quotes. Non-printable chars are printed as
+ hexadecimal escapes.
+ Further message-type-specific detail can be found in
+ <xref linkend="protocol-message-formats"/>.
+ </para>
+
<note>
<para>
On Windows, if the <application>libpq</application> library and an application are
@@ -6479,6 +6494,28 @@ void PQtrace(PGconn *conn, FILE *stream);
</listitem>
</varlistentry>
+ <varlistentry id="libpq-PQtraceSetFlags">
+ <term><function>PQtraceSetFlags</function><indexterm><primary>PQtraceSetFlags</primary></indexterm></term>
+
+ <listitem>
+ <para>
+ Controls the tracing behavior of client/server communication.
+<synopsis>
+void PQtraceSetFlags(PGconn *conn, int flags);
+</synopsis>
+ </para>
+
+ <para>
+ <literal>flags</literal> contains flag bits describing the operating mode
+ of tracing.
+ If <literal>flags</literal> contains <literal>PQTRACE_SUPPRESS_TIMESTAMPS</literal>,
+ then the timestamp is not included when printing each message.
+ This function must be called after calling <function>PQtrace</function>.
+ </para>
+
+ </listitem>
+ </varlistentry>
+
<varlistentry id="libpq-PQuntrace">
<term><function>PQuntrace</function><indexterm><primary>PQuntrace</primary></indexterm></term>
diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 2aca882a2b..0424523492 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -41,6 +41,7 @@ OBJS = \
fe-secure.o \
legacy-pqsignal.o \
libpq-events.o \
+ libpq-trace.o \
pqexpbuffer.o \
fe-auth.o
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index 5c48c14191..a00701f2c5 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -183,3 +183,4 @@ PQenterPipelineMode 180
PQexitPipelineMode 181
PQpipelineSync 182
PQpipelineStatus 183
+PQtraceSetFlags 184
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 53b354abb2..a90bdb8ab6 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -6859,27 +6859,6 @@ PQsetErrorContextVisibility(PGconn *conn, PGContextVisibility show_context)
return old;
}
-void
-PQtrace(PGconn *conn, FILE *debug_port)
-{
- if (conn == NULL)
- return;
- PQuntrace(conn);
- conn->Pfdebug = debug_port;
-}
-
-void
-PQuntrace(PGconn *conn)
-{
- if (conn == NULL)
- return;
- if (conn->Pfdebug)
- {
- fflush(conn->Pfdebug);
- conn->Pfdebug = NULL;
- }
-}
-
PQnoticeReceiver
PQsetNoticeReceiver(PGconn *conn, PQnoticeReceiver proc, void *arg)
{
diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index f143b8b7fb..03592bdce9 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -970,10 +970,6 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
pgParameterStatus *pstatus;
pgParameterStatus *prev;
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "pqSaveParameterStatus: '%s' = '%s'\n",
- name, value);
-
/*
* Forget any old information about the parameter
*/
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index ce2d24b91f..54d6a76246 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -84,9 +84,6 @@ pqGetc(char *result, PGconn *conn)
*result = conn->inBuffer[conn->inCursor++];
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "From backend> %c\n", *result);
-
return 0;
}
@@ -100,9 +97,6 @@ pqPutc(char c, PGconn *conn)
if (pqPutMsgBytes(&c, 1, conn))
return EOF;
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> %c\n", c);
-
return 0;
}
@@ -138,10 +132,6 @@ pqGets_internal(PQExpBuffer buf, PGconn *conn, bool resetbuffer)
conn->inCursor = ++inCursor;
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "From backend> \"%s\"\n",
- buf->data);
-
return 0;
}
@@ -167,9 +157,6 @@ pqPuts(const char *s, PGconn *conn)
if (pqPutMsgBytes(s, strlen(s) + 1, conn))
return EOF;
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> \"%s\"\n", s);
-
return 0;
}
@@ -188,13 +175,6 @@ pqGetnchar(char *s, size_t len, PGconn *conn)
conn->inCursor += len;
- if (conn->Pfdebug)
- {
- fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
- fwrite(s, 1, len, conn->Pfdebug);
- fprintf(conn->Pfdebug, "\n");
- }
-
return 0;
}
@@ -212,13 +192,6 @@ pqSkipnchar(size_t len, PGconn *conn)
if (len > (size_t) (conn->inEnd - conn->inCursor))
return EOF;
- if (conn->Pfdebug)
- {
- fprintf(conn->Pfdebug, "From backend (%lu)> ", (unsigned long) len);
- fwrite(conn->inBuffer + conn->inCursor, 1, len, conn->Pfdebug);
- fprintf(conn->Pfdebug, "\n");
- }
-
conn->inCursor += len;
return 0;
@@ -234,13 +207,6 @@ pqPutnchar(const char *s, size_t len, PGconn *conn)
if (pqPutMsgBytes(s, len, conn))
return EOF;
- if (conn->Pfdebug)
- {
- fprintf(conn->Pfdebug, "To backend> ");
- fwrite(s, 1, len, conn->Pfdebug);
- fprintf(conn->Pfdebug, "\n");
- }
-
return 0;
}
@@ -278,9 +244,6 @@ pqGetInt(int *result, size_t bytes, PGconn *conn)
return EOF;
}
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "From backend (#%lu)> %d\n", (unsigned long) bytes, *result);
-
return 0;
}
@@ -314,9 +277,6 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
return EOF;
}
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend (%lu#)> %d\n", (unsigned long) bytes, value);
-
return 0;
}
@@ -525,10 +485,6 @@ pqPutMsgStart(char msg_type, PGconn *conn)
conn->outMsgEnd = endPos;
/* 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 : ' ');
-
return 0;
}
@@ -563,10 +519,6 @@ pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
int
pqPutMsgEnd(PGconn *conn)
{
- if (conn->Pfdebug)
- fprintf(conn->Pfdebug, "To backend> Msg complete, length %u\n",
- conn->outMsgEnd - conn->outCount);
-
/* Fill in length word if needed */
if (conn->outMsgStart >= 0)
{
@@ -576,6 +528,16 @@ pqPutMsgEnd(PGconn *conn)
memcpy(conn->outBuffer + conn->outMsgStart, &msgLen, 4);
}
+ /* Trace message only when there is first 1 byte */
+ if (conn->Pfdebug)
+ {
+ if (conn->outCount < conn->outMsgStart)
+ pqTraceOutputMessage(conn, conn->outBuffer + conn->outCount, true);
+ else
+ pqTraceOutputNoTypeByteMessage(conn,
+ conn->outBuffer + conn->outMsgStart);
+ }
+
/* Make message eligible to send */
conn->outCount = conn->outMsgEnd;
@@ -1002,11 +964,13 @@ pqSendSome(PGconn *conn, int len)
int
pqFlush(PGconn *conn)
{
- if (conn->Pfdebug)
- fflush(conn->Pfdebug);
-
if (conn->outCount > 0)
+ {
+ if (conn->Pfdebug)
+ fflush(conn->Pfdebug);
+
return pqSendSome(conn, conn->outCount);
+ }
return 0;
}
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index 306e89acfd..de77c06874 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -457,6 +457,9 @@ pqParseInput3(PGconn *conn)
/* Successfully consumed this message */
if (conn->inCursor == conn->inStart + 5 + msgLength)
{
+ if(conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
/* Normal case: parsing agrees with specified length */
conn->inStart = conn->inCursor;
}
@@ -1660,6 +1663,9 @@ getCopyDataMessage(PGconn *conn)
return -1;
}
+ if(conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
+
/* Drop the processed message and loop around for another */
conn->inStart = conn->inCursor;
}
@@ -2121,6 +2127,8 @@ pqFunctionCall3(PGconn *conn, Oid fnid,
}
/* Completed this message, keep going */
/* trust the specified message length as what to skip */
+ if(conn->Pfdebug)
+ pqTraceOutputMessage(conn, conn->inBuffer + conn->inStart, false);
conn->inStart += 5 + msgLength;
needInput = false;
}
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index cee42d4843..d0decde2da 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -376,7 +376,9 @@ extern PGContextVisibility PQsetErrorContextVisibility(PGconn *conn,
PGContextVisibility show_context);
/* Enable/disable tracing */
+#define PQTRACE_SUPPRESS_TIMESTAMPS 1
extern void PQtrace(PGconn *conn, FILE *debug_port);
+extern void PQtraceSetFlags(PGconn *conn, int flags);
extern void PQuntrace(PGconn *conn);
/* Override default notice handling routines */
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 6374ec657a..1a1d0e1414 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -394,6 +394,7 @@ struct pg_conn
/* Optional file to write trace info to */
FILE *Pfdebug;
+ int traceFlags;
/* Callback procedures for notice message processing */
PGNoticeHooks noticeHooks;
@@ -818,6 +819,12 @@ extern ssize_t pg_GSS_write(PGconn *conn, const void *ptr, size_t len);
extern ssize_t pg_GSS_read(PGconn *conn, void *ptr, size_t len);
#endif
+/* === in libpq-trace.c === */
+
+extern void pqTraceOutputMessage(PGconn *conn, const char *message,
+ bool toServer);
+extern void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message);
+
/* === miscellaneous macros === */
/*
diff --git a/src/interfaces/libpq/libpq-trace.c b/src/interfaces/libpq/libpq-trace.c
new file mode 100644
index 0000000000..bacb7903b9
--- /dev/null
+++ b/src/interfaces/libpq/libpq-trace.c
@@ -0,0 +1,717 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq-trace.c
+ * functions for libpq protocol tracing
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/interfaces/libpq/libpq-trace.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres_fe.h"
+
+#include <limits.h>
+#include <time.h>
+
+#ifdef WIN32
+#include "win32.h"
+#else
+#include <unistd.h>
+#include <sys/time.h>
+#endif
+
+#include "libpq-fe.h"
+#include "libpq-int.h"
+#include "pgtime.h"
+#include "port/pg_bswap.h"
+
+void
+PQtrace(PGconn *conn, FILE *debug_port)
+{
+ if (conn == NULL)
+ return;
+ PQuntrace(conn);
+ if (debug_port == NULL)
+ return;
+
+ setvbuf(debug_port, NULL, _IOLBF, 0);
+ conn->Pfdebug = debug_port;
+ conn->traceFlags = 0;
+}
+
+void
+PQuntrace(PGconn *conn)
+{
+ if (conn == NULL)
+ return;
+ if (conn->Pfdebug)
+ {
+ fflush(conn->Pfdebug);
+ conn->Pfdebug = NULL;
+ }
+
+ conn->traceFlags = 0;
+}
+
+void
+PQtraceSetFlags(PGconn *conn, int flags)
+{
+ if (conn == NULL)
+ return;
+ /* If PQtrace() failed, do nothing. */
+ if (conn->Pfdebug == NULL)
+ return;
+ conn->traceFlags = flags;
+}
+
+/*
+ * Print the current time, with microseconds, into a caller-supplied
+ * buffer.
+ * Cribbed from setup_formatted_log_time, but much simpler.
+ */
+static void
+pqTraceFormatTimestamp(char *timestr, size_t ts_len)
+{
+ struct timeval tval;
+ pg_time_t stamp_time;
+
+ gettimeofday(&tval, NULL);
+ stamp_time = (pg_time_t) tval.tv_sec;
+
+ strftime(timestr, ts_len,
+ "%Y-%m-%d %H:%M:%S",
+ localtime(&stamp_time));
+ /* append microseconds */
+ sprintf(timestr + strlen(timestr), ".%06d", (int) (tval.tv_usec));
+}
+
+/*
+ * pqTraceOutputByte1: output 1 char message to the log
+ */
+static void
+pqTraceOutputByte1(const char *data, int *cursor, FILE *pfdebug)
+{
+ const char *v = data + *cursor;
+
+ /*
+ * Show non-printable data in hex format, including the
+ * terminating \0 that completes ErrorResponse and NoticeResponse
+ * messages.
+ */
+ if (!isprint(*v))
+ fprintf(pfdebug, " \\x%02x", *v);
+ else
+ fprintf(pfdebug, " %c", *v);
+ ++*cursor;
+}
+
+/*
+ * pqTraceOutputInt16: output a 2-byte integer message to the log
+ */
+static int
+pqTraceOutputInt16(const char *data, int *cursor, FILE *pfdebug)
+{
+ uint16 tmp;
+ int result;
+
+ memcpy(&tmp, data + *cursor , 2);
+ *cursor += 2;
+ result = (int) pg_ntoh16(tmp);
+ fprintf(pfdebug, " %d", result);
+
+ return result;
+}
+
+/*
+ * pqTraceOutputInt32: output a 4-byte integer message to the log
+ */
+static int
+pqTraceOutputInt32(const char *data, int *cursor, FILE *pfdebug)
+{
+ int result;
+
+ memcpy(&result, data + *cursor, 4);
+ *cursor += 4;
+ result = (int) pg_ntoh32(result);
+ fprintf(pfdebug, " %d", result);
+
+ return result;
+}
+
+/*
+ * pqTraceOutputString: output a string message to the log
+ */
+static void
+pqTraceOutputString(const char *data, int *cursor, FILE *pfdebug)
+{
+ int len;
+
+ len = fprintf(pfdebug, " \"%s\"", data + *cursor);
+
+ /*
+ * This is null-terminated string. So add 1 after subtracting 3
+ * which is the double quotes and space length from len.
+ */
+ *cursor += (len - 3 + 1);
+}
+
+/*
+ * pqTraceOutputNchar: output a string of exactly len bytes message to the log
+ */
+static void
+pqTraceOutputNchar(const char *data, int *cursor, FILE *pfdebug, int len)
+{
+ int i,
+ next; /* first char not yet printed */
+ const char *v = data + *cursor;
+
+ fprintf(pfdebug, " \'");
+
+ for (next = i = 0; i < len; ++i)
+ {
+ if (isprint(v[i]))
+ continue;
+ else
+ {
+ fwrite(v + next, 1, i - next, pfdebug);
+ fprintf(pfdebug, "\\x%02x", v[i]);
+ next = i + 1;
+ }
+ }
+ if (next < len)
+ fwrite(v + next, 1, len - next, pfdebug);
+
+ fprintf(pfdebug, "\'");
+ *cursor += len;
+}
+
+/*
+ * Output functions by protocol message type
+ */
+
+/* Authentication */
+static void
+pqTraceOutputR(const char *message, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "Authentication\t");
+ pqTraceOutputInt32(message, &cursor, f);
+}
+
+/* BackendKeyData */
+static void
+pqTraceOutputK(const char *message, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "BackendKeyData\t");
+ pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt32(message, &cursor, f);
+}
+
+/* Bind */
+static void
+pqTraceOutputB(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+ int nparams;
+ int nbytes;
+ int i;
+
+ fprintf(f, "Bind\t");
+ pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(message, &cursor, f);
+ nparams = pqTraceOutputInt16(message, &cursor, f);
+
+ for (i = 0; i < nparams; i++)
+ pqTraceOutputInt16(message, &cursor, f);
+
+ nparams = pqTraceOutputInt16(message, &cursor, f);
+
+ for (i = 0; i < nparams; i++)
+ {
+ nbytes = pqTraceOutputInt32(message, &cursor, f);
+ if (nbytes == -1)
+ continue;
+ pqTraceOutputNchar(message, &cursor, f, nbytes);
+ }
+
+ nparams = pqTraceOutputInt16(message, &cursor, f);
+ for (i = 0; i < nparams; i++)
+ pqTraceOutputInt16(message, &cursor, f);
+}
+
+/* Close(F) or CommandComplete(B) */
+static void
+pqTraceOutputC(const char *message, int end, FILE *f, bool toServer)
+{
+ int cursor = 0;
+
+ if (toServer)
+ {
+ fprintf(f, "Close\t");
+ pqTraceOutputByte1(message, &cursor, f);
+ pqTraceOutputString(message, &cursor, f);
+ }
+ else
+ {
+ fprintf(f, "CommandComplete\t");
+ pqTraceOutputString(message, &cursor, f);
+ }
+}
+
+/* CopyFail */
+static void
+pqTraceOutputf(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "CopyFail\t");
+ pqTraceOutputString(message, &cursor, f);
+}
+
+/* CopyInResponse */
+static void
+pqTraceOutputG(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+ int nfields;
+ int i;
+
+ fprintf(f, "CopyInResponse\t");
+ pqTraceOutputByte1(message, &cursor, f);
+ nfields = pqTraceOutputInt16(message, &cursor, f);
+
+ for (i = 0; i < nfields; i++)
+ pqTraceOutputInt16(message, &cursor, f);
+}
+
+/* CopyOutResponse */
+static void
+pqTraceOutputH(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+ int nfields;
+ int i;
+
+ fprintf(f, "CopyOutResponse\t");
+ pqTraceOutputByte1(message, &cursor, f);
+ nfields = pqTraceOutputInt16(message, &cursor, f);
+
+ for (i = 0; i < nfields; i++)
+ pqTraceOutputInt16(message, &cursor, f);
+}
+
+/* CopyBothResponse */
+static void
+pqTraceOutputW(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "CopyBothResponse\t");
+ pqTraceOutputByte1(message, &cursor, f);
+
+ while (end > cursor)
+ pqTraceOutputInt16(message, &cursor, f);
+}
+
+/* Describe(F) or DataRow(B) */
+static void
+pqTraceOutputD(const char *message, int end, FILE *f, bool toServer)
+{
+ int cursor = 0;
+
+ if (toServer)
+ {
+ fprintf(f, "Describe\t");
+ pqTraceOutputByte1(message, &cursor, f);
+ pqTraceOutputString(message, &cursor, f);
+ }
+ else
+ {
+ int nfields;
+ int len;
+ int i;
+
+ fprintf(f, "DataRow\t");
+ nfields = pqTraceOutputInt16(message, &cursor, f);
+ for (i = 0; i < nfields; i++)
+ {
+ len = pqTraceOutputInt32(message, &cursor, f);
+ if (len == -1)
+ continue;
+ pqTraceOutputNchar(message, &cursor, f, len);
+ }
+ }
+}
+
+/* Execute(F) or ErrorResponse(B) */
+static void
+pqTraceOutputE(const char *message, int end, FILE *f, bool toServer)
+{
+ int cursor = 0;
+
+ if (toServer)
+ {
+ fprintf(f, "Execute\t");
+ pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputInt32(message, &cursor, f);
+ }
+ else
+ {
+ fprintf(f, "ErrorResponse\t");
+ while (end > cursor)
+ {
+ pqTraceOutputByte1(message, &cursor, f);
+ if (message[cursor] == '\0')
+ continue;
+ pqTraceOutputString(message, &cursor, f);
+ }
+ }
+}
+
+/* FunctionCall */
+static void
+pqTraceOutputF(const char *message, FILE *f)
+{
+ int cursor = 0;
+ int nfields;
+ int nbytes;
+ int i;
+
+ fprintf(f, "FunctionCall\t");
+ pqTraceOutputInt32(message, &cursor, f);
+ nfields = pqTraceOutputInt16(message, &cursor, f);
+
+ for (i = 0; i < nfields; i++)
+ pqTraceOutputInt16(message, &cursor, f);
+
+ nfields = pqTraceOutputInt16(message, &cursor, f);
+
+ for (i = 0; i < nfields; i++)
+ {
+ nbytes = pqTraceOutputInt32(message, &cursor, f);
+ if (nbytes == -1)
+ continue;
+ pqTraceOutputNchar(message, &cursor, f, nbytes);
+ }
+
+ pqTraceOutputInt16(message, &cursor, f);
+}
+
+/* FunctionCallResponse */
+static void
+pqTraceOutputV(const char *message, FILE *f)
+{
+ int cursor = 0;
+ int len;
+
+ fprintf(f, "FunctionCallResponse\t");
+ len = pqTraceOutputInt32(message, &cursor, f);
+ if (len != -1)
+ pqTraceOutputNchar(message, &cursor, f, len);
+}
+
+/* NegotiateProtocolVersion */
+static void
+pqTraceOutputv(const char *message, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "NegotiateProtocolVersion\t");
+ pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt32(message, &cursor, f);
+}
+
+/* NoticeResponse */
+static void
+pqTraceOutputN(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "NoticeResponse\t");
+ while (end > cursor)
+ {
+ pqTraceOutputByte1(message, &cursor, f);
+ if (message[cursor] == '\0')
+ continue;
+ pqTraceOutputString(message, &cursor, f);
+ }
+}
+
+/* NotificationResponse */
+static void
+pqTraceOutputA(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "NotificationResponse\t");
+ pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(message, &cursor, f);
+}
+
+/* ParameterDescription */
+static void
+pqTraceOutputt(const char *message, FILE *f)
+{
+ int cursor = 0;
+ int nfields;
+ int i;
+
+ fprintf(f, "ParameterDescription\t");
+ nfields = pqTraceOutputInt16(message, &cursor, f);
+
+ for (i = 0; i < nfields; i++)
+ pqTraceOutputInt32(message, &cursor, f);
+}
+
+/* ParameterStatus */
+static void
+pqTraceOutputS(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "ParameterStatus\t");
+ pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(message, &cursor, f);
+}
+
+/* Parse */
+static void
+pqTraceOutputP(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+ int nparams;
+ int i;
+
+ fprintf(f, "Parse\t");
+ pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(message, &cursor, f);
+ nparams = pqTraceOutputInt16(message, &cursor, f);
+
+ for (i = 0; i < nparams; i++)
+ pqTraceOutputInt32(message, &cursor, f);
+}
+
+/* Query */
+static void
+pqTraceOutputQ(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "Query\t");
+ pqTraceOutputString(message, &cursor, f);
+}
+
+/* ReadyForQuery */
+static void
+pqTraceOutputZ(const char *message, FILE *f)
+{
+ int cursor = 0;
+
+ fprintf(f, "ReadyForQuery\t");
+ pqTraceOutputByte1(message, &cursor, f);
+}
+
+/* RowDescription */
+static void
+pqTraceOutputT(const char *message, int end, FILE *f)
+{
+ int cursor = 0;
+ int nfields;
+ int i;
+
+ fprintf(f, "RowDescription\t");
+ nfields = pqTraceOutputInt16(message, &cursor, f);
+
+ for (i = 0; i < nfields; i++)
+ {
+ pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt16(message, &cursor, f);
+ }
+}
+
+void
+pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
+{
+ char timestr[128];
+ char id;
+ int length;
+ char *prefix = toServer ? ">" : "<";
+ int LogCursor = 0;
+ int LogEnd;
+
+ if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0)
+ pqTraceFormatTimestamp(timestr, sizeof(timestr));
+ else
+ timestr[0] = '\0';
+
+ id = message[LogCursor++];
+
+ memcpy(&length, message + LogCursor , 4);
+ length = (int) pg_ntoh32(length);
+ LogCursor += 4;
+ LogEnd = length - 4;
+
+ fprintf(conn->Pfdebug, "%s\t%s\t%d\t", timestr, prefix, length);
+
+ switch(id)
+ {
+ case 'R': /* Authentication */
+ pqTraceOutputR(message + LogCursor, conn->Pfdebug);
+ break;
+ case 'K': /* secret key data from the backend */
+ pqTraceOutputK(message + LogCursor, conn->Pfdebug);
+ break;
+ case 'B': /* Bind */
+ pqTraceOutputB(message + LogCursor, LogEnd, conn->Pfdebug);
+ break;
+ case 'C': /* Close(F) or Command Complete(B) */
+ pqTraceOutputC(message + LogCursor, LogEnd, conn->Pfdebug, toServer);
+ break;
+ case 'd': /* Copy Data */
+ /* Drop COPY data to reduce the overhead of logging. */
+ break;
+ case 'f': /* Copy Fail */
+ pqTraceOutputf(message + LogCursor, LogEnd, conn->Pfdebug);
+ break;
+ case 'G': /* Start Copy In */
+ pqTraceOutputG(message + LogCursor, LogEnd, conn->Pfdebug);
+ break;
+ case 'H': /* Flush(F) or Start Copy Out(B) */
+ if (!toServer)
+ pqTraceOutputH(message + LogCursor, LogEnd, conn->Pfdebug);
+ else
+ fprintf(conn->Pfdebug, "Flush");
+ break;
+ case 'W': /* Start Copy Both */
+ pqTraceOutputW(message + LogCursor, LogEnd, conn->Pfdebug);
+ break;
+ case 'D': /* Describe(F) or Data Row(B) */
+ pqTraceOutputD(message + LogCursor, LogEnd, conn->Pfdebug, toServer);
+ break;
+ case 'E': /* Execute(F) or Error Response(B) */
+ pqTraceOutputE(message + LogCursor, LogEnd, conn->Pfdebug, toServer);
+ break;
+ case 'F': /* Function Call */
+ pqTraceOutputF(message + LogCursor, conn->Pfdebug);
+ break;
+ case 'V': /* Function Call response */
+ pqTraceOutputV(message + LogCursor, conn->Pfdebug);
+ break;
+ case 'v': /* Negotiate Protocol Version */
+ pqTraceOutputv(message + LogCursor, conn->Pfdebug);
+ break;
+ case 'N': /* Notice Response */
+ pqTraceOutputN(message + LogCursor, LogEnd, conn->Pfdebug);
+ break;
+ case 'A': /* Notification Response */
+ pqTraceOutputA(message + LogCursor, LogEnd, conn->Pfdebug);
+ break;
+ case 't': /* Parameter Description */
+ pqTraceOutputt(message + LogCursor, conn->Pfdebug);
+ break;
+ case 'S': /* Parameter Status(B) or Sync(F) */
+ if (!toServer)
+ pqTraceOutputS(message + LogCursor, LogEnd, conn->Pfdebug);
+ else
+ fprintf(conn->Pfdebug, "Sync");
+ break;
+ case 'P': /* Parse */
+ pqTraceOutputP(message + LogCursor, LogEnd, conn->Pfdebug);
+ break;
+ case 'Q': /* Query */
+ pqTraceOutputQ(message + LogCursor, LogEnd, conn->Pfdebug);
+ break;
+ case 'Z': /* Ready For Query */
+ pqTraceOutputZ(message + LogCursor, conn->Pfdebug);
+ break;
+ case 'T': /* Row Description */
+ pqTraceOutputT(message + LogCursor, LogEnd, conn->Pfdebug);
+ break;
+ case '2': /* Bind Complete */
+ fprintf(conn->Pfdebug, "BindComplete");
+ /* No message content */
+ break;
+ case '3': /* Close Complete */
+ fprintf(conn->Pfdebug, "CloseComplete");
+ /* No message content */
+ break;
+ case 'c': /* Copy Done */
+ fprintf(conn->Pfdebug, "CopyDone");
+ /* No message content */
+ break;
+ case 'I': /* Empty Query Response */
+ fprintf(conn->Pfdebug, "EmptyQueryResponse");
+ /* No message content */
+ break;
+ case 'n': /* No Data */
+ fprintf(conn->Pfdebug, "NoData");
+ /* No message content */
+ break;
+ case '1': /* Parse Complete */
+ fprintf(conn->Pfdebug, "ParseComplete");
+ /* No message content */
+ break;
+ case 's': /* Portal Suspended */
+ fprintf(conn->Pfdebug, "PortalSuspended");
+ /* No message content */
+ break;
+ case 'X': /* Terminate */
+ fprintf(conn->Pfdebug, "Terminate");
+ /* No message content */
+ break;
+ default:
+ fprintf(conn->Pfdebug, "Unknown message: %02x", id);
+ break;
+ }
+
+ fputc('\n', conn->Pfdebug);
+}
+
+void
+pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
+{
+ char timestr[128];
+ int length;
+ int LogCursor = 0;
+
+ if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0)
+ pqTraceFormatTimestamp(timestr, sizeof(timestr));
+ else
+ timestr[0] = '\0';
+
+ memcpy(&length, message + LogCursor , 4);
+ length = (int) pg_ntoh32(length);
+ LogCursor += 4;
+
+ fprintf(conn->Pfdebug, "%s\t>\t%d\t", timestr, length);
+
+ switch(length)
+ {
+ case 16: /* CancelRequest */
+ fprintf(conn->Pfdebug, "CancelRequest\t");
+ pqTraceOutputInt32(message, &LogCursor, conn->Pfdebug);
+ pqTraceOutputInt32(message, &LogCursor, conn->Pfdebug);
+ pqTraceOutputInt32(message, &LogCursor, conn->Pfdebug);
+ break;
+ case 8 : /* GSSENCRequest or SSLRequest */
+ /* These messages do not reach here. */
+ default:
+ fprintf(conn->Pfdebug, "Unknown message: length is %d", length);
+ break;
+ }
+
+ fputc('\n', conn->Pfdebug);
+}
--
2.20.1
[text/x-diff] v30-0002-libpq_pipeline-add-t-support-for-PQtrace.patch (4.6K, ../20210327192812.GA25115@alvherre.pgsql/3-v30-0002-libpq_pipeline-add-t-support-for-PQtrace.patch)
download | inline diff:
From b32ae3805bb28553c0a1cf308c6ed27f58576f3c Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 26 Mar 2021 19:12:12 -0300
Subject: [PATCH v30 2/7] libpq_pipeline: add -t support for PQtrace
---
.../modules/libpq_pipeline/libpq_pipeline.c | 84 +++++++++++++------
1 file changed, 59 insertions(+), 25 deletions(-)
diff --git a/src/test/modules/libpq_pipeline/libpq_pipeline.c b/src/test/modules/libpq_pipeline/libpq_pipeline.c
index 846ee9f5ab..34d085035b 100644
--- a/src/test/modules/libpq_pipeline/libpq_pipeline.c
+++ b/src/test/modules/libpq_pipeline/libpq_pipeline.c
@@ -23,6 +23,7 @@
#include "catalog/pg_type_d.h"
#include "common/fe_memutils.h"
#include "libpq-fe.h"
+#include "pg_getopt.h"
#include "portability/instr_time.h"
@@ -30,6 +31,9 @@ static void exit_nicely(PGconn *conn);
const char *const progname = "libpq_pipeline";
+/* Options and defaults */
+char *tracefile = NULL; /* path to PQtrace() file */
+
#define DEBUG
#ifdef DEBUG
@@ -1209,8 +1213,10 @@ usage(const char *progname)
{
fprintf(stderr, "%s tests libpq's pipeline mode.\n\n", progname);
fprintf(stderr, "Usage:\n");
- fprintf(stderr, " %s tests", progname);
- fprintf(stderr, " %s testname [conninfo [number_of_rows]]\n", progname);
+ fprintf(stderr, " %s [OPTION] tests\n", progname);
+ fprintf(stderr, " %s [OPTION] TESTNAME [CONNINFO [NUMBER_OF_ROWS]\n", progname);
+ fprintf(stderr, "\nOptions:\n");
+ fprintf(stderr, " -t TRACEFILE generate a libpq trace to TRACEFILE\n");
}
static void
@@ -1231,37 +1237,54 @@ main(int argc, char **argv)
{
const char *conninfo = "";
PGconn *conn;
+ FILE *trace;
+ char *testname;
int numrows = 10000;
PGresult *res;
+ int c;
- if (strcmp(argv[1], "tests") == 0)
+ while ((c = getopt(argc, argv, "t:")) != -1)
{
- print_test_list();
- exit(0);
+ switch (c)
+ {
+ case 't': /* trace file */
+ tracefile = pg_strdup(optarg);
+ break;
+ }
}
- /*
- * The testname parameter is mandatory; it can be followed by a conninfo
- * string and number of rows.
- */
- if (argc < 2 || argc > 4)
+ if (optind < argc)
+ {
+ testname = argv[optind];
+ optind++;
+ }
+ else
{
usage(argv[0]);
exit(1);
}
- if (argc >= 3)
- conninfo = pg_strdup(argv[2]);
+ if (strcmp(testname, "tests") == 0)
+ {
+ print_test_list();
+ exit(0);
+ }
- if (argc >= 4)
+ if (optind < argc)
+ {
+ conninfo = argv[optind];
+ optind++;
+ }
+ if (optind < argc)
{
errno = 0;
- numrows = strtol(argv[3], NULL, 10);
+ numrows = strtol(argv[optind], NULL, 10);
if (errno != 0 || numrows <= 0)
{
- fprintf(stderr, "couldn't parse \"%s\" as a positive integer\n", argv[3]);
+ fprintf(stderr, "couldn't parse \"%s\" as a positive integer\n", argv[optind]);
exit(1);
}
+ optind++;
}
/* Make a connection to the database */
@@ -1272,30 +1295,41 @@ main(int argc, char **argv)
PQerrorMessage(conn));
exit_nicely(conn);
}
+
+ /* Set the trace file, if requested */
+ if (tracefile != NULL)
+ {
+ trace = fopen(tracefile, "w+");
+
+ if (trace == NULL)
+ pg_fatal("could not open file \"%s\": %m", tracefile);
+ PQtrace(conn, trace);
+ PQtraceSetFlags(conn, PQTRACE_SUPPRESS_TIMESTAMPS);
+ }
+
res = PQexec(conn, "SET lc_messages TO \"C\"");
if (PQresultStatus(res) != PGRES_COMMAND_OK)
pg_fatal("failed to set lc_messages: %s", PQerrorMessage(conn));
- if (strcmp(argv[1], "disallowed_in_pipeline") == 0)
+ if (strcmp(testname, "disallowed_in_pipeline") == 0)
test_disallowed_in_pipeline(conn);
- else if (strcmp(argv[1], "multi_pipelines") == 0)
+ else if (strcmp(testname, "multi_pipelines") == 0)
test_multi_pipelines(conn);
- else if (strcmp(argv[1], "pipeline_abort") == 0)
+ else if (strcmp(testname, "pipeline_abort") == 0)
test_pipeline_abort(conn);
- else if (strcmp(argv[1], "pipelined_insert") == 0)
+ else if (strcmp(testname, "pipelined_insert") == 0)
test_pipelined_insert(conn, numrows);
- else if (strcmp(argv[1], "prepared") == 0)
+ else if (strcmp(testname, "prepared") == 0)
test_prepared(conn);
- else if (strcmp(argv[1], "simple_pipeline") == 0)
+ else if (strcmp(testname, "simple_pipeline") == 0)
test_simple_pipeline(conn);
- else if (strcmp(argv[1], "singlerow") == 0)
+ else if (strcmp(testname, "singlerow") == 0)
test_singlerowmode(conn);
- else if (strcmp(argv[1], "transaction") == 0)
+ else if (strcmp(testname, "transaction") == 0)
test_transaction(conn);
else
{
- fprintf(stderr, "\"%s\" is not a recognized test name\n", argv[1]);
- usage(argv[0]);
+ fprintf(stderr, "\"%s\" is not a recognized test name\n", testname);
exit(1);
}
--
2.20.1
[text/x-diff] v30-0003-put-FILE-arg-always-first.patch (18.5K, ../20210327192812.GA25115@alvherre.pgsql/4-v30-0003-put-FILE-arg-always-first.patch)
download | inline diff:
From 4b62c3159fe3aa8445317a5d65b7e81d91c7fba6 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 26 Mar 2021 19:13:04 -0300
Subject: [PATCH v30 3/7] put FILE * arg always first
---
src/interfaces/libpq/libpq-trace.c | 234 ++++++++++++++---------------
1 file changed, 117 insertions(+), 117 deletions(-)
diff --git a/src/interfaces/libpq/libpq-trace.c b/src/interfaces/libpq/libpq-trace.c
index bacb7903b9..bff542cada 100644
--- a/src/interfaces/libpq/libpq-trace.c
+++ b/src/interfaces/libpq/libpq-trace.c
@@ -93,7 +93,7 @@ pqTraceFormatTimestamp(char *timestr, size_t ts_len)
* pqTraceOutputByte1: output 1 char message to the log
*/
static void
-pqTraceOutputByte1(const char *data, int *cursor, FILE *pfdebug)
+pqTraceOutputByte1(FILE *pfdebug, const char *data, int *cursor)
{
const char *v = data + *cursor;
@@ -113,7 +113,7 @@ pqTraceOutputByte1(const char *data, int *cursor, FILE *pfdebug)
* pqTraceOutputInt16: output a 2-byte integer message to the log
*/
static int
-pqTraceOutputInt16(const char *data, int *cursor, FILE *pfdebug)
+pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
{
uint16 tmp;
int result;
@@ -130,7 +130,7 @@ pqTraceOutputInt16(const char *data, int *cursor, FILE *pfdebug)
* pqTraceOutputInt32: output a 4-byte integer message to the log
*/
static int
-pqTraceOutputInt32(const char *data, int *cursor, FILE *pfdebug)
+pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor)
{
int result;
@@ -146,7 +146,7 @@ pqTraceOutputInt32(const char *data, int *cursor, FILE *pfdebug)
* pqTraceOutputString: output a string message to the log
*/
static void
-pqTraceOutputString(const char *data, int *cursor, FILE *pfdebug)
+pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor)
{
int len;
@@ -163,7 +163,7 @@ pqTraceOutputString(const char *data, int *cursor, FILE *pfdebug)
* pqTraceOutputNchar: output a string of exactly len bytes message to the log
*/
static void
-pqTraceOutputNchar(const char *data, int *cursor, FILE *pfdebug, int len)
+pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor)
{
int i,
next; /* first char not yet printed */
@@ -195,28 +195,28 @@ pqTraceOutputNchar(const char *data, int *cursor, FILE *pfdebug, int len)
/* Authentication */
static void
-pqTraceOutputR(const char *message, FILE *f)
+pqTraceOutputR(FILE *f, const char *message)
{
int cursor = 0;
fprintf(f, "Authentication\t");
- pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt32(f, message, &cursor);
}
/* BackendKeyData */
static void
-pqTraceOutputK(const char *message, FILE *f)
+pqTraceOutputK(FILE *f, const char *message)
{
int cursor = 0;
fprintf(f, "BackendKeyData\t");
- pqTraceOutputInt32(message, &cursor, f);
- pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputInt32(f, message, &cursor);
}
/* Bind */
static void
-pqTraceOutputB(const char *message, int end, FILE *f)
+pqTraceOutputB(FILE *f, const char *message, int end)
{
int cursor = 0;
int nparams;
@@ -224,113 +224,113 @@ pqTraceOutputB(const char *message, int end, FILE *f)
int i;
fprintf(f, "Bind\t");
- pqTraceOutputString(message, &cursor, f);
- pqTraceOutputString(message, &cursor, f);
- nparams = pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputString(f, message, &cursor);
+ nparams = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nparams; i++)
- pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt16(f, message, &cursor);
- nparams = pqTraceOutputInt16(message, &cursor, f);
+ nparams = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nparams; i++)
{
- nbytes = pqTraceOutputInt32(message, &cursor, f);
+ nbytes = pqTraceOutputInt32(f, message, &cursor);
if (nbytes == -1)
continue;
- pqTraceOutputNchar(message, &cursor, f, nbytes);
+ pqTraceOutputNchar(f, nbytes, message, &cursor);
}
- nparams = pqTraceOutputInt16(message, &cursor, f);
+ nparams = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nparams; i++)
- pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt16(f, message, &cursor);
}
/* Close(F) or CommandComplete(B) */
static void
-pqTraceOutputC(const char *message, int end, FILE *f, bool toServer)
+pqTraceOutputC(FILE *f, bool toServer, const char *message, int end)
{
int cursor = 0;
if (toServer)
{
fprintf(f, "Close\t");
- pqTraceOutputByte1(message, &cursor, f);
- pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputByte1(f, message, &cursor);
+ pqTraceOutputString(f, message, &cursor);
}
else
{
fprintf(f, "CommandComplete\t");
- pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
}
}
/* CopyFail */
static void
-pqTraceOutputf(const char *message, int end, FILE *f)
+pqTraceOutputf(FILE *f, const char *message, int end)
{
int cursor = 0;
fprintf(f, "CopyFail\t");
- pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
}
/* CopyInResponse */
static void
-pqTraceOutputG(const char *message, int end, FILE *f)
+pqTraceOutputG(FILE *f, const char *message, int end)
{
int cursor = 0;
int nfields;
int i;
fprintf(f, "CopyInResponse\t");
- pqTraceOutputByte1(message, &cursor, f);
- nfields = pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputByte1(f, message, &cursor);
+ nfields = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nfields; i++)
- pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt16(f, message, &cursor);
}
/* CopyOutResponse */
static void
-pqTraceOutputH(const char *message, int end, FILE *f)
+pqTraceOutputH(FILE *f, const char *message, int end)
{
int cursor = 0;
int nfields;
int i;
fprintf(f, "CopyOutResponse\t");
- pqTraceOutputByte1(message, &cursor, f);
- nfields = pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputByte1(f, message, &cursor);
+ nfields = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nfields; i++)
- pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt16(f, message, &cursor);
}
/* CopyBothResponse */
static void
-pqTraceOutputW(const char *message, int end, FILE *f)
+pqTraceOutputW(FILE *f, const char *message, int end)
{
int cursor = 0;
fprintf(f, "CopyBothResponse\t");
- pqTraceOutputByte1(message, &cursor, f);
+ pqTraceOutputByte1(f, message, &cursor);
while (end > cursor)
- pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt16(f, message, &cursor);
}
/* Describe(F) or DataRow(B) */
static void
-pqTraceOutputD(const char *message, int end, FILE *f, bool toServer)
+pqTraceOutputD(FILE *f, bool toServer, const char *message, int end)
{
int cursor = 0;
if (toServer)
{
fprintf(f, "Describe\t");
- pqTraceOutputByte1(message, &cursor, f);
- pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputByte1(f, message, &cursor);
+ pqTraceOutputString(f, message, &cursor);
}
else
{
@@ -339,45 +339,45 @@ pqTraceOutputD(const char *message, int end, FILE *f, bool toServer)
int i;
fprintf(f, "DataRow\t");
- nfields = pqTraceOutputInt16(message, &cursor, f);
+ nfields = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nfields; i++)
{
- len = pqTraceOutputInt32(message, &cursor, f);
+ len = pqTraceOutputInt32(f, message, &cursor);
if (len == -1)
continue;
- pqTraceOutputNchar(message, &cursor, f, len);
+ pqTraceOutputNchar(f, len, message, &cursor);
}
}
}
/* Execute(F) or ErrorResponse(B) */
static void
-pqTraceOutputE(const char *message, int end, FILE *f, bool toServer)
+pqTraceOutputE(FILE *f, bool toServer, const char *message, int end)
{
int cursor = 0;
if (toServer)
{
fprintf(f, "Execute\t");
- pqTraceOutputString(message, &cursor, f);
- pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputInt32(f, message, &cursor);
}
else
{
fprintf(f, "ErrorResponse\t");
while (end > cursor)
{
- pqTraceOutputByte1(message, &cursor, f);
+ pqTraceOutputByte1(f, message, &cursor);
if (message[cursor] == '\0')
continue;
- pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
}
}
}
/* FunctionCall */
static void
-pqTraceOutputF(const char *message, FILE *f)
+pqTraceOutputF(FILE *f, const char *message)
{
int cursor = 0;
int nfields;
@@ -385,160 +385,160 @@ pqTraceOutputF(const char *message, FILE *f)
int i;
fprintf(f, "FunctionCall\t");
- pqTraceOutputInt32(message, &cursor, f);
- nfields = pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt32(f, message, &cursor);
+ nfields = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nfields; i++)
- pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt16(f, message, &cursor);
- nfields = pqTraceOutputInt16(message, &cursor, f);
+ nfields = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nfields; i++)
{
- nbytes = pqTraceOutputInt32(message, &cursor, f);
+ nbytes = pqTraceOutputInt32(f, message, &cursor);
if (nbytes == -1)
continue;
- pqTraceOutputNchar(message, &cursor, f, nbytes);
+ pqTraceOutputNchar(f, nbytes, message, &cursor);
}
- pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputInt16(f, message, &cursor);
}
/* FunctionCallResponse */
static void
-pqTraceOutputV(const char *message, FILE *f)
+pqTraceOutputV(FILE *f, const char *message)
{
int cursor = 0;
int len;
fprintf(f, "FunctionCallResponse\t");
- len = pqTraceOutputInt32(message, &cursor, f);
+ len = pqTraceOutputInt32(f, message, &cursor);
if (len != -1)
- pqTraceOutputNchar(message, &cursor, f, len);
+ pqTraceOutputNchar(f, len, message, &cursor);
}
/* NegotiateProtocolVersion */
static void
-pqTraceOutputv(const char *message, FILE *f)
+pqTraceOutputv(FILE *f, const char *message)
{
int cursor = 0;
fprintf(f, "NegotiateProtocolVersion\t");
- pqTraceOutputInt32(message, &cursor, f);
- pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputInt32(f, message, &cursor);
}
/* NoticeResponse */
static void
-pqTraceOutputN(const char *message, int end, FILE *f)
+pqTraceOutputN(FILE *f, const char *message, int end)
{
int cursor = 0;
fprintf(f, "NoticeResponse\t");
while (end > cursor)
{
- pqTraceOutputByte1(message, &cursor, f);
+ pqTraceOutputByte1(f, message, &cursor);
if (message[cursor] == '\0')
continue;
- pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
}
}
/* NotificationResponse */
static void
-pqTraceOutputA(const char *message, int end, FILE *f)
+pqTraceOutputA(FILE *f, const char *message, int end)
{
int cursor = 0;
fprintf(f, "NotificationResponse\t");
- pqTraceOutputInt32(message, &cursor, f);
- pqTraceOutputString(message, &cursor, f);
- pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputString(f, message, &cursor);
}
/* ParameterDescription */
static void
-pqTraceOutputt(const char *message, FILE *f)
+pqTraceOutputt(FILE *f, const char *message)
{
int cursor = 0;
int nfields;
int i;
fprintf(f, "ParameterDescription\t");
- nfields = pqTraceOutputInt16(message, &cursor, f);
+ nfields = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nfields; i++)
- pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt32(f, message, &cursor);
}
/* ParameterStatus */
static void
-pqTraceOutputS(const char *message, int end, FILE *f)
+pqTraceOutputS(FILE *f, const char *message, int end)
{
int cursor = 0;
fprintf(f, "ParameterStatus\t");
- pqTraceOutputString(message, &cursor, f);
- pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputString(f, message, &cursor);
}
/* Parse */
static void
-pqTraceOutputP(const char *message, int end, FILE *f)
+pqTraceOutputP(FILE *f, const char *message, int end)
{
int cursor = 0;
int nparams;
int i;
fprintf(f, "Parse\t");
- pqTraceOutputString(message, &cursor, f);
- pqTraceOutputString(message, &cursor, f);
- nparams = pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputString(f, message, &cursor);
+ nparams = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nparams; i++)
- pqTraceOutputInt32(message, &cursor, f);
+ pqTraceOutputInt32(f, message, &cursor);
}
/* Query */
static void
-pqTraceOutputQ(const char *message, int end, FILE *f)
+pqTraceOutputQ(FILE *f, const char *message, int end)
{
int cursor = 0;
fprintf(f, "Query\t");
- pqTraceOutputString(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
}
/* ReadyForQuery */
static void
-pqTraceOutputZ(const char *message, FILE *f)
+pqTraceOutputZ(FILE *f, const char *message)
{
int cursor = 0;
fprintf(f, "ReadyForQuery\t");
- pqTraceOutputByte1(message, &cursor, f);
+ pqTraceOutputByte1(f, message, &cursor);
}
/* RowDescription */
static void
-pqTraceOutputT(const char *message, int end, FILE *f)
+pqTraceOutputT(FILE *f, const char *message, int end)
{
int cursor = 0;
int nfields;
int i;
fprintf(f, "RowDescription\t");
- nfields = pqTraceOutputInt16(message, &cursor, f);
+ nfields = pqTraceOutputInt16(f, message, &cursor);
for (i = 0; i < nfields; i++)
{
- pqTraceOutputString(message, &cursor, f);
- pqTraceOutputInt32(message, &cursor, f);
- pqTraceOutputInt16(message, &cursor, f);
- pqTraceOutputInt32(message, &cursor, f);
- pqTraceOutputInt16(message, &cursor, f);
- pqTraceOutputInt32(message, &cursor, f);
- pqTraceOutputInt16(message, &cursor, f);
+ pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputInt16(f, message, &cursor);
+ pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputInt16(f, message, &cursor);
+ pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputInt16(f, message, &cursor);
}
}
@@ -569,76 +569,76 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
switch(id)
{
case 'R': /* Authentication */
- pqTraceOutputR(message + LogCursor, conn->Pfdebug);
+ pqTraceOutputR(conn->Pfdebug, message + LogCursor);
break;
case 'K': /* secret key data from the backend */
- pqTraceOutputK(message + LogCursor, conn->Pfdebug);
+ pqTraceOutputK(conn->Pfdebug, message + LogCursor);
break;
case 'B': /* Bind */
- pqTraceOutputB(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputB(conn->Pfdebug, message + LogCursor, LogEnd);
break;
case 'C': /* Close(F) or Command Complete(B) */
- pqTraceOutputC(message + LogCursor, LogEnd, conn->Pfdebug, toServer);
+ pqTraceOutputC(conn->Pfdebug, toServer, message + LogCursor, LogEnd);
break;
case 'd': /* Copy Data */
/* Drop COPY data to reduce the overhead of logging. */
break;
case 'f': /* Copy Fail */
- pqTraceOutputf(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputf(conn->Pfdebug, message + LogCursor, LogEnd);
break;
case 'G': /* Start Copy In */
- pqTraceOutputG(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputG(conn->Pfdebug, message + LogCursor, LogEnd);
break;
case 'H': /* Flush(F) or Start Copy Out(B) */
if (!toServer)
- pqTraceOutputH(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputH(conn->Pfdebug, message + LogCursor, LogEnd);
else
fprintf(conn->Pfdebug, "Flush");
break;
case 'W': /* Start Copy Both */
- pqTraceOutputW(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputW(conn->Pfdebug, message + LogCursor, LogEnd);
break;
case 'D': /* Describe(F) or Data Row(B) */
- pqTraceOutputD(message + LogCursor, LogEnd, conn->Pfdebug, toServer);
+ pqTraceOutputD(conn->Pfdebug, toServer, message + LogCursor, LogEnd);
break;
case 'E': /* Execute(F) or Error Response(B) */
- pqTraceOutputE(message + LogCursor, LogEnd, conn->Pfdebug, toServer);
+ pqTraceOutputE(conn->Pfdebug, toServer, message + LogCursor, LogEnd);
break;
case 'F': /* Function Call */
- pqTraceOutputF(message + LogCursor, conn->Pfdebug);
+ pqTraceOutputF(conn->Pfdebug, message + LogCursor);
break;
case 'V': /* Function Call response */
- pqTraceOutputV(message + LogCursor, conn->Pfdebug);
+ pqTraceOutputV(conn->Pfdebug, message + LogCursor);
break;
case 'v': /* Negotiate Protocol Version */
- pqTraceOutputv(message + LogCursor, conn->Pfdebug);
+ pqTraceOutputv(conn->Pfdebug, message + LogCursor);
break;
case 'N': /* Notice Response */
- pqTraceOutputN(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputN(conn->Pfdebug, message + LogCursor, LogEnd);
break;
case 'A': /* Notification Response */
- pqTraceOutputA(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputA(conn->Pfdebug, message + LogCursor, LogEnd);
break;
case 't': /* Parameter Description */
- pqTraceOutputt(message + LogCursor, conn->Pfdebug);
+ pqTraceOutputt(conn->Pfdebug, message + LogCursor);
break;
case 'S': /* Parameter Status(B) or Sync(F) */
if (!toServer)
- pqTraceOutputS(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputS(conn->Pfdebug, message + LogCursor, LogEnd);
else
fprintf(conn->Pfdebug, "Sync");
break;
case 'P': /* Parse */
- pqTraceOutputP(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputP(conn->Pfdebug, message + LogCursor, LogEnd);
break;
case 'Q': /* Query */
- pqTraceOutputQ(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputQ(conn->Pfdebug, message + LogCursor, LogEnd);
break;
case 'Z': /* Ready For Query */
- pqTraceOutputZ(message + LogCursor, conn->Pfdebug);
+ pqTraceOutputZ(conn->Pfdebug, message + LogCursor);
break;
case 'T': /* Row Description */
- pqTraceOutputT(message + LogCursor, LogEnd, conn->Pfdebug);
+ pqTraceOutputT(conn->Pfdebug, message + LogCursor, LogEnd);
break;
case '2': /* Bind Complete */
fprintf(conn->Pfdebug, "BindComplete");
@@ -702,9 +702,9 @@ pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
{
case 16: /* CancelRequest */
fprintf(conn->Pfdebug, "CancelRequest\t");
- pqTraceOutputInt32(message, &LogCursor, conn->Pfdebug);
- pqTraceOutputInt32(message, &LogCursor, conn->Pfdebug);
- pqTraceOutputInt32(message, &LogCursor, conn->Pfdebug);
+ pqTraceOutputInt32(conn->Pfdebug, message, &LogCursor);
+ pqTraceOutputInt32(conn->Pfdebug, message, &LogCursor);
+ pqTraceOutputInt32(conn->Pfdebug, message, &LogCursor);
break;
case 8 : /* GSSENCRequest or SSLRequest */
/* These messages do not reach here. */
--
2.20.1
[text/x-diff] v30-0004-use-F-B-instead-of.patch (780B, ../20210327192812.GA25115@alvherre.pgsql/5-v30-0004-use-F-B-instead-of.patch)
download | inline diff:
From d44009a25de3af549dfa528a4fa44c9ebf785c42 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 26 Mar 2021 19:13:16 -0300
Subject: [PATCH v30 4/7] use F/B instead of </>
---
src/interfaces/libpq/libpq-trace.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/interfaces/libpq/libpq-trace.c b/src/interfaces/libpq/libpq-trace.c
index bff542cada..94f28f04a8 100644
--- a/src/interfaces/libpq/libpq-trace.c
+++ b/src/interfaces/libpq/libpq-trace.c
@@ -548,7 +548,7 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
char timestr[128];
char id;
int length;
- char *prefix = toServer ? ">" : "<";
+ char *prefix = toServer ? "F" : "B";
int LogCursor = 0;
int LogEnd;
--
2.20.1
[text/x-diff] v30-0005-pass-cursor-to-printing-routines.patch (17.5K, ../20210327192812.GA25115@alvherre.pgsql/6-v30-0005-pass-cursor-to-printing-routines.patch)
download | inline diff:
From 39a5e0c6b5559a0fb9a6c376e493e4ee4bc980fb Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 26 Mar 2021 20:04:53 -0300
Subject: [PATCH v30 5/7] pass *cursor to printing routines
---
src/interfaces/libpq/libpq-trace.c | 309 +++++++++++++----------------
1 file changed, 134 insertions(+), 175 deletions(-)
diff --git a/src/interfaces/libpq/libpq-trace.c b/src/interfaces/libpq/libpq-trace.c
index 94f28f04a8..06d8d981a3 100644
--- a/src/interfaces/libpq/libpq-trace.c
+++ b/src/interfaces/libpq/libpq-trace.c
@@ -106,7 +106,7 @@ pqTraceOutputByte1(FILE *pfdebug, const char *data, int *cursor)
fprintf(pfdebug, " \\x%02x", *v);
else
fprintf(pfdebug, " %c", *v);
- ++*cursor;
+ *cursor += 1;
}
/*
@@ -195,142 +195,125 @@ pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor)
/* Authentication */
static void
-pqTraceOutputR(FILE *f, const char *message)
+pqTraceOutputR(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
-
fprintf(f, "Authentication\t");
- pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputInt32(f, message, cursor);
}
/* BackendKeyData */
static void
-pqTraceOutputK(FILE *f, const char *message)
+pqTraceOutputK(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
-
fprintf(f, "BackendKeyData\t");
- pqTraceOutputInt32(f, message, &cursor);
- pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputInt32(f, message, cursor);
+ pqTraceOutputInt32(f, message, cursor);
}
/* Bind */
static void
-pqTraceOutputB(FILE *f, const char *message, int end)
+pqTraceOutputB(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
int nparams;
- int nbytes;
- int i;
fprintf(f, "Bind\t");
- pqTraceOutputString(f, message, &cursor);
- pqTraceOutputString(f, message, &cursor);
- nparams = pqTraceOutputInt16(f, message, &cursor);
+ pqTraceOutputString(f, message, cursor);
+ pqTraceOutputString(f, message, cursor);
+ nparams = pqTraceOutputInt16(f, message, cursor);
- for (i = 0; i < nparams; i++)
- pqTraceOutputInt16(f, message, &cursor);
+ for (int i = 0; i < nparams; i++)
+ pqTraceOutputInt16(f, message, cursor);
- nparams = pqTraceOutputInt16(f, message, &cursor);
+ nparams = pqTraceOutputInt16(f, message, cursor);
- for (i = 0; i < nparams; i++)
+ for (int i = 0; i < nparams; i++)
{
- nbytes = pqTraceOutputInt32(f, message, &cursor);
+ int nbytes;
+
+ nbytes = pqTraceOutputInt32(f, message, cursor);
if (nbytes == -1)
continue;
- pqTraceOutputNchar(f, nbytes, message, &cursor);
+ pqTraceOutputNchar(f, nbytes, message, cursor);
}
- nparams = pqTraceOutputInt16(f, message, &cursor);
- for (i = 0; i < nparams; i++)
- pqTraceOutputInt16(f, message, &cursor);
+ nparams = pqTraceOutputInt16(f, message, cursor);
+ for (int i = 0; i < nparams; i++)
+ pqTraceOutputInt16(f, message, cursor);
}
/* Close(F) or CommandComplete(B) */
static void
-pqTraceOutputC(FILE *f, bool toServer, const char *message, int end)
+pqTraceOutputC(FILE *f, bool toServer, const char *message, int *cursor)
{
- int cursor = 0;
-
if (toServer)
{
fprintf(f, "Close\t");
- pqTraceOutputByte1(f, message, &cursor);
- pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputByte1(f, message, cursor);
+ pqTraceOutputString(f, message, cursor);
}
else
{
fprintf(f, "CommandComplete\t");
- pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputString(f, message, cursor);
}
}
/* CopyFail */
static void
-pqTraceOutputf(FILE *f, const char *message, int end)
+pqTraceOutputf(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
-
fprintf(f, "CopyFail\t");
- pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputString(f, message, cursor);
}
/* CopyInResponse */
static void
-pqTraceOutputG(FILE *f, const char *message, int end)
+pqTraceOutputG(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
int nfields;
- int i;
fprintf(f, "CopyInResponse\t");
- pqTraceOutputByte1(f, message, &cursor);
- nfields = pqTraceOutputInt16(f, message, &cursor);
+ pqTraceOutputByte1(f, message, cursor);
+ nfields = pqTraceOutputInt16(f, message, cursor);
- for (i = 0; i < nfields; i++)
- pqTraceOutputInt16(f, message, &cursor);
+ for (int i = 0; i < nfields; i++)
+ pqTraceOutputInt16(f, message, cursor);
}
/* CopyOutResponse */
static void
-pqTraceOutputH(FILE *f, const char *message, int end)
+pqTraceOutputH(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
int nfields;
- int i;
fprintf(f, "CopyOutResponse\t");
- pqTraceOutputByte1(f, message, &cursor);
- nfields = pqTraceOutputInt16(f, message, &cursor);
+ pqTraceOutputByte1(f, message, cursor);
+ nfields = pqTraceOutputInt16(f, message, cursor);
- for (i = 0; i < nfields; i++)
- pqTraceOutputInt16(f, message, &cursor);
+ for (int i = 0; i < nfields; i++)
+ pqTraceOutputInt16(f, message, cursor);
}
/* CopyBothResponse */
static void
-pqTraceOutputW(FILE *f, const char *message, int end)
+pqTraceOutputW(FILE *f, const char *message, int *cursor, int length)
{
- int cursor = 0;
-
fprintf(f, "CopyBothResponse\t");
- pqTraceOutputByte1(f, message, &cursor);
+ pqTraceOutputByte1(f, message, cursor);
- while (end > cursor)
- pqTraceOutputInt16(f, message, &cursor);
+ while (length > *cursor)
+ pqTraceOutputInt16(f, message, cursor);
}
/* Describe(F) or DataRow(B) */
static void
-pqTraceOutputD(FILE *f, bool toServer, const char *message, int end)
+pqTraceOutputD(FILE *f, bool toServer, const char *message, int *cursor)
{
- int cursor = 0;
-
if (toServer)
{
fprintf(f, "Describe\t");
- pqTraceOutputByte1(f, message, &cursor);
- pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputByte1(f, message, cursor);
+ pqTraceOutputString(f, message, cursor);
}
else
{
@@ -339,206 +322,183 @@ pqTraceOutputD(FILE *f, bool toServer, const char *message, int end)
int i;
fprintf(f, "DataRow\t");
- nfields = pqTraceOutputInt16(f, message, &cursor);
+ nfields = pqTraceOutputInt16(f, message, cursor);
for (i = 0; i < nfields; i++)
{
- len = pqTraceOutputInt32(f, message, &cursor);
+ len = pqTraceOutputInt32(f, message, cursor);
if (len == -1)
continue;
- pqTraceOutputNchar(f, len, message, &cursor);
+ pqTraceOutputNchar(f, len, message, cursor);
}
}
}
/* Execute(F) or ErrorResponse(B) */
static void
-pqTraceOutputE(FILE *f, bool toServer, const char *message, int end)
+pqTraceOutputE(FILE *f, bool toServer, const char *message, int *cursor, int length)
{
- int cursor = 0;
-
if (toServer)
{
fprintf(f, "Execute\t");
- pqTraceOutputString(f, message, &cursor);
- pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputString(f, message, cursor);
+ pqTraceOutputInt32(f, message, cursor);
}
else
{
fprintf(f, "ErrorResponse\t");
- while (end > cursor)
+ for (;;)
{
- pqTraceOutputByte1(f, message, &cursor);
- if (message[cursor] == '\0')
- continue;
- pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputByte1(f, message, cursor);
+ if (message[*cursor - 1] == '\0')
+ break;
+ pqTraceOutputString(f, message, cursor);
}
}
}
/* FunctionCall */
static void
-pqTraceOutputF(FILE *f, const char *message)
+pqTraceOutputF(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
int nfields;
int nbytes;
- int i;
fprintf(f, "FunctionCall\t");
- pqTraceOutputInt32(f, message, &cursor);
- nfields = pqTraceOutputInt16(f, message, &cursor);
+ pqTraceOutputInt32(f, message, cursor);
+ nfields = pqTraceOutputInt16(f, message, cursor);
- for (i = 0; i < nfields; i++)
- pqTraceOutputInt16(f, message, &cursor);
+ for (int i = 0; i < nfields; i++)
+ pqTraceOutputInt16(f, message, cursor);
- nfields = pqTraceOutputInt16(f, message, &cursor);
+ nfields = pqTraceOutputInt16(f, message, cursor);
- for (i = 0; i < nfields; i++)
+ for (int i = 0; i < nfields; i++)
{
- nbytes = pqTraceOutputInt32(f, message, &cursor);
+ nbytes = pqTraceOutputInt32(f, message, cursor);
if (nbytes == -1)
continue;
- pqTraceOutputNchar(f, nbytes, message, &cursor);
+ pqTraceOutputNchar(f, nbytes, message, cursor);
}
- pqTraceOutputInt16(f, message, &cursor);
+ pqTraceOutputInt16(f, message, cursor);
}
/* FunctionCallResponse */
static void
-pqTraceOutputV(FILE *f, const char *message)
+pqTraceOutputV(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
int len;
fprintf(f, "FunctionCallResponse\t");
- len = pqTraceOutputInt32(f, message, &cursor);
+ len = pqTraceOutputInt32(f, message, cursor);
if (len != -1)
- pqTraceOutputNchar(f, len, message, &cursor);
+ pqTraceOutputNchar(f, len, message, cursor);
}
/* NegotiateProtocolVersion */
static void
-pqTraceOutputv(FILE *f, const char *message)
+pqTraceOutputv(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
-
fprintf(f, "NegotiateProtocolVersion\t");
- pqTraceOutputInt32(f, message, &cursor);
- pqTraceOutputInt32(f, message, &cursor);
+ pqTraceOutputInt32(f, message, cursor);
+ pqTraceOutputInt32(f, message, cursor);
}
/* NoticeResponse */
static void
-pqTraceOutputN(FILE *f, const char *message, int end)
+pqTraceOutputN(FILE *f, const char *message, int *cursor, int length)
{
- int cursor = 0;
-
fprintf(f, "NoticeResponse\t");
- while (end > cursor)
+ for (;;)
{
- pqTraceOutputByte1(f, message, &cursor);
- if (message[cursor] == '\0')
- continue;
- pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputByte1(f, message, cursor);
+ if (message[*cursor - 1] == '\0')
+ break;
+ pqTraceOutputString(f, message, cursor);
}
}
/* NotificationResponse */
static void
-pqTraceOutputA(FILE *f, const char *message, int end)
+pqTraceOutputA(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
-
fprintf(f, "NotificationResponse\t");
- pqTraceOutputInt32(f, message, &cursor);
- pqTraceOutputString(f, message, &cursor);
- pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputInt32(f, message, cursor);
+ pqTraceOutputString(f, message, cursor);
+ pqTraceOutputString(f, message, cursor);
}
/* ParameterDescription */
static void
-pqTraceOutputt(FILE *f, const char *message)
+pqTraceOutputt(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
int nfields;
- int i;
fprintf(f, "ParameterDescription\t");
- nfields = pqTraceOutputInt16(f, message, &cursor);
+ nfields = pqTraceOutputInt16(f, message, cursor);
- for (i = 0; i < nfields; i++)
- pqTraceOutputInt32(f, message, &cursor);
+ for (int i = 0; i < nfields; i++)
+ pqTraceOutputInt32(f, message, cursor);
}
/* ParameterStatus */
static void
-pqTraceOutputS(FILE *f, const char *message, int end)
+pqTraceOutputS(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
-
fprintf(f, "ParameterStatus\t");
- pqTraceOutputString(f, message, &cursor);
- pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputString(f, message, cursor);
+ pqTraceOutputString(f, message, cursor);
}
/* Parse */
static void
-pqTraceOutputP(FILE *f, const char *message, int end)
+pqTraceOutputP(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
int nparams;
- int i;
fprintf(f, "Parse\t");
- pqTraceOutputString(f, message, &cursor);
- pqTraceOutputString(f, message, &cursor);
- nparams = pqTraceOutputInt16(f, message, &cursor);
+ pqTraceOutputString(f, message, cursor);
+ pqTraceOutputString(f, message, cursor);
+ nparams = pqTraceOutputInt16(f, message, cursor);
- for (i = 0; i < nparams; i++)
- pqTraceOutputInt32(f, message, &cursor);
+ for (int i = 0; i < nparams; i++)
+ pqTraceOutputInt32(f, message, cursor);
}
/* Query */
static void
-pqTraceOutputQ(FILE *f, const char *message, int end)
+pqTraceOutputQ(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
-
fprintf(f, "Query\t");
- pqTraceOutputString(f, message, &cursor);
+ pqTraceOutputString(f, message, cursor);
}
/* ReadyForQuery */
static void
-pqTraceOutputZ(FILE *f, const char *message)
+pqTraceOutputZ(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
-
fprintf(f, "ReadyForQuery\t");
- pqTraceOutputByte1(f, message, &cursor);
+ pqTraceOutputByte1(f, message, cursor);
}
/* RowDescription */
static void
-pqTraceOutputT(FILE *f, const char *message, int end)
+pqTraceOutputT(FILE *f, const char *message, int *cursor)
{
- int cursor = 0;
int nfields;
- int i;
fprintf(f, "RowDescription\t");
- nfields = pqTraceOutputInt16(f, message, &cursor);
+ nfields = pqTraceOutputInt16(f, message, cursor);
- for (i = 0; i < nfields; i++)
+ for (int i = 0; i < nfields; i++)
{
- pqTraceOutputString(f, message, &cursor);
- pqTraceOutputInt32(f, message, &cursor);
- pqTraceOutputInt16(f, message, &cursor);
- pqTraceOutputInt32(f, message, &cursor);
- pqTraceOutputInt16(f, message, &cursor);
- pqTraceOutputInt32(f, message, &cursor);
- pqTraceOutputInt16(f, message, &cursor);
+ pqTraceOutputString(f, message, cursor);
+ pqTraceOutputInt32(f, message, cursor);
+ pqTraceOutputInt16(f, message, cursor);
+ pqTraceOutputInt32(f, message, cursor);
+ pqTraceOutputInt16(f, message, cursor);
+ pqTraceOutputInt32(f, message, cursor);
+ pqTraceOutputInt16(f, message, cursor);
}
}
@@ -550,95 +510,94 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
int length;
char *prefix = toServer ? "F" : "B";
int LogCursor = 0;
- int LogEnd;
if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0)
+ {
pqTraceFormatTimestamp(timestr, sizeof(timestr));
- else
- timestr[0] = '\0';
+ fprintf(conn->Pfdebug, "%s\t", timestr);
+ }
id = message[LogCursor++];
- memcpy(&length, message + LogCursor , 4);
+ memcpy(&length, message + LogCursor, 4);
length = (int) pg_ntoh32(length);
LogCursor += 4;
- LogEnd = length - 4;
- fprintf(conn->Pfdebug, "%s\t%s\t%d\t", timestr, prefix, length);
+ fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
switch(id)
{
case 'R': /* Authentication */
- pqTraceOutputR(conn->Pfdebug, message + LogCursor);
+ pqTraceOutputR(conn->Pfdebug, message, &LogCursor);
break;
case 'K': /* secret key data from the backend */
- pqTraceOutputK(conn->Pfdebug, message + LogCursor);
+ pqTraceOutputK(conn->Pfdebug, message, &LogCursor);
break;
case 'B': /* Bind */
- pqTraceOutputB(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputB(conn->Pfdebug, message, &LogCursor);
break;
case 'C': /* Close(F) or Command Complete(B) */
- pqTraceOutputC(conn->Pfdebug, toServer, message + LogCursor, LogEnd);
+ pqTraceOutputC(conn->Pfdebug, toServer, message, &LogCursor);
break;
case 'd': /* Copy Data */
/* Drop COPY data to reduce the overhead of logging. */
break;
case 'f': /* Copy Fail */
- pqTraceOutputf(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputf(conn->Pfdebug, message, &LogCursor);
break;
case 'G': /* Start Copy In */
- pqTraceOutputG(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputG(conn->Pfdebug, message, &LogCursor);
break;
case 'H': /* Flush(F) or Start Copy Out(B) */
if (!toServer)
- pqTraceOutputH(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputH(conn->Pfdebug, message, &LogCursor);
else
fprintf(conn->Pfdebug, "Flush");
break;
case 'W': /* Start Copy Both */
- pqTraceOutputW(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputW(conn->Pfdebug, message, &LogCursor, length);
break;
case 'D': /* Describe(F) or Data Row(B) */
- pqTraceOutputD(conn->Pfdebug, toServer, message + LogCursor, LogEnd);
+ pqTraceOutputD(conn->Pfdebug, toServer, message, &LogCursor);
break;
case 'E': /* Execute(F) or Error Response(B) */
- pqTraceOutputE(conn->Pfdebug, toServer, message + LogCursor, LogEnd);
+ pqTraceOutputE(conn->Pfdebug, toServer, message, &LogCursor, length);
break;
case 'F': /* Function Call */
- pqTraceOutputF(conn->Pfdebug, message + LogCursor);
+ pqTraceOutputF(conn->Pfdebug, message, &LogCursor);
break;
case 'V': /* Function Call response */
- pqTraceOutputV(conn->Pfdebug, message + LogCursor);
+ pqTraceOutputV(conn->Pfdebug, message, &LogCursor);
break;
case 'v': /* Negotiate Protocol Version */
- pqTraceOutputv(conn->Pfdebug, message + LogCursor);
+ pqTraceOutputv(conn->Pfdebug, message, &LogCursor);
break;
case 'N': /* Notice Response */
- pqTraceOutputN(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputN(conn->Pfdebug, message, &LogCursor, length);
break;
case 'A': /* Notification Response */
- pqTraceOutputA(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputA(conn->Pfdebug, message, &LogCursor);
break;
case 't': /* Parameter Description */
- pqTraceOutputt(conn->Pfdebug, message + LogCursor);
+ pqTraceOutputt(conn->Pfdebug, message, &LogCursor);
break;
case 'S': /* Parameter Status(B) or Sync(F) */
if (!toServer)
- pqTraceOutputS(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputS(conn->Pfdebug, message, &LogCursor);
else
fprintf(conn->Pfdebug, "Sync");
break;
case 'P': /* Parse */
- pqTraceOutputP(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputP(conn->Pfdebug, message, &LogCursor);
break;
case 'Q': /* Query */
- pqTraceOutputQ(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputQ(conn->Pfdebug, message, &LogCursor);
break;
case 'Z': /* Ready For Query */
- pqTraceOutputZ(conn->Pfdebug, message + LogCursor);
+ pqTraceOutputZ(conn->Pfdebug, message, &LogCursor);
break;
case 'T': /* Row Description */
- pqTraceOutputT(conn->Pfdebug, message + LogCursor, LogEnd);
+ pqTraceOutputT(conn->Pfdebug, message, &LogCursor);
break;
case '2': /* Bind Complete */
fprintf(conn->Pfdebug, "BindComplete");
--
2.20.1
[text/x-diff] v30-0006-add-length-check.patch (966B, ../20210327192812.GA25115@alvherre.pgsql/7-v30-0006-add-length-check.patch)
download | inline diff:
From 4d645bdf08de419b207b0064986d81f758900809 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 26 Mar 2021 20:05:10 -0300
Subject: [PATCH v30 6/7] add length check
---
src/interfaces/libpq/libpq-trace.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/interfaces/libpq/libpq-trace.c b/src/interfaces/libpq/libpq-trace.c
index 06d8d981a3..6c58a578ac 100644
--- a/src/interfaces/libpq/libpq-trace.c
+++ b/src/interfaces/libpq/libpq-trace.c
@@ -637,6 +637,16 @@ pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
}
fputc('\n', conn->Pfdebug);
+
+ /*
+ * Verify the printing routine did it right. Note that the one-byte
+ * message identifier is not included in the length, but our cursor
+ * does include it.
+ */
+ if (LogCursor - 1 != length)
+ fprintf(conn->Pfdebug,
+ "mismatched message length: consumed %d, expected %d\n",
+ LogCursor - 1, length);
}
void
--
2.20.1
[text/x-diff] v30-0007-Use-libpq_pipeline-to-test-PQtrace.patch (6.1K, ../20210327192812.GA25115@alvherre.pgsql/8-v30-0007-Use-libpq_pipeline-to-test-PQtrace.patch)
download | inline diff:
From d040e90b1ed206a14b031ac92f494b87b1d32ae8 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Sat, 27 Mar 2021 16:10:08 -0300
Subject: [PATCH v30 7/7] Use libpq_pipeline to test PQtrace
---
.../libpq_pipeline/t/001_libpq_pipeline.pl | 24 ++++++++++-
.../traces/multi_pipelines.trace | 26 ++++++++++++
.../libpq_pipeline/traces/prepared.trace | 21 ++++++++++
.../traces/simple_pipeline.trace | 15 +++++++
.../libpq_pipeline/traces/singlerow.trace | 42 +++++++++++++++++++
5 files changed, 126 insertions(+), 2 deletions(-)
create mode 100644 src/test/modules/libpq_pipeline/traces/multi_pipelines.trace
create mode 100644 src/test/modules/libpq_pipeline/traces/prepared.trace
create mode 100644 src/test/modules/libpq_pipeline/traces/simple_pipeline.trace
create mode 100644 src/test/modules/libpq_pipeline/traces/singlerow.trace
diff --git a/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl b/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl
index 0213f21ee8..a0ee8640a7 100644
--- a/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl
+++ b/src/test/modules/libpq_pipeline/t/001_libpq_pipeline.pl
@@ -4,7 +4,7 @@ use warnings;
use Config;
use PostgresNode;
use TestLib;
-use Test::More tests => 8;
+use Test::More tests => 12;
use Cwd;
my $node = get_new_node('main');
@@ -20,9 +20,29 @@ my @tests = split(/\s+/, $out);
for my $testname (@tests)
{
+ my @extraargs = ();
+ my $cmptrace = grep(/^$testname$/,
+ qw(simple_pipeline multi_pipelines prepared singlerow)) > 0;
+ my $traceout = "$TestLib::log_path/$testname.trace";
+
+ # For a bunch of tests, generate a libpq trace file too.
+ if ($cmptrace)
+ {
+ push @extraargs, "-t", $traceout;
+ }
+
+
$node->command_ok(
- [ 'libpq_pipeline', $testname, $node->connstr('postgres'), $numrows ],
+ [ 'libpq_pipeline', @extraargs, $testname, $node->connstr('postgres'), $numrows ],
"libpq_pipeline $testname");
+
+ if ($cmptrace)
+ {
+ my $expected = slurp_file("traces/$testname.trace");
+ my $result = slurp_file($traceout);
+
+ is($expected, $result, "$testname trace match");
+ }
}
$node->stop('fast');
diff --git a/src/test/modules/libpq_pipeline/traces/multi_pipelines.trace b/src/test/modules/libpq_pipeline/traces/multi_pipelines.trace
new file mode 100644
index 0000000000..f7dfbef11f
--- /dev/null
+++ b/src/test/modules/libpq_pipeline/traces/multi_pipelines.trace
@@ -0,0 +1,26 @@
+F 27 Query "SET lc_messages TO "C""
+B 8 CommandComplete "SET"
+B 5 ReadyForQuery I
+F 21 Parse "" "SELECT $1" 1 23
+F 19 Bind "" "" 0 1 1 '1' 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 4 Sync
+F 21 Parse "" "SELECT $1" 1 23
+F 19 Bind "" "" 0 1 1 '1' 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 4 Sync
+B 4 ParseComplete
+B 4 BindComplete
+B 33 RowDescription 1 "?column?" 0 0 23 4 -1 0
+B 11 DataRow 1 1 '1'
+B 13 CommandComplete "SELECT 1"
+B 5 ReadyForQuery I
+B 4 ParseComplete
+B 4 BindComplete
+B 33 RowDescription 1 "?column?" 0 0 23 4 -1 0
+B 11 DataRow 1 1 '1'
+B 13 CommandComplete "SELECT 1"
+B 5 ReadyForQuery I
+F 4 Terminate
diff --git a/src/test/modules/libpq_pipeline/traces/prepared.trace b/src/test/modules/libpq_pipeline/traces/prepared.trace
new file mode 100644
index 0000000000..62c5c38b6a
--- /dev/null
+++ b/src/test/modules/libpq_pipeline/traces/prepared.trace
@@ -0,0 +1,21 @@
+F 27 Query "SET lc_messages TO "C""
+B 8 CommandComplete "SET"
+B 5 ReadyForQuery I
+F 68 Parse "select_one" "SELECT $1, '42', $1::numeric, interval '1 sec'" 1 23
+F 16 Describe S "select_one"
+F 4 Sync
+B 4 ParseComplete
+B 10 ParameterDescription 1 23
+B 113 RowDescription 4 "?column?" 0 0 23 4 -1 0 "?column?" 0 0 25 65535 -1 0 "numeric" 0 0 1700 65535 -1 0 "interval" 0 0 1186 16 -1 0
+B 5 ReadyForQuery I
+F 10 Query "BEGIN"
+B 10 CommandComplete "BEGIN"
+B 5 ReadyForQuery T
+F 43 Query "DECLARE cursor_one CURSOR FOR SELECT 1"
+B 19 CommandComplete "DECLARE CURSOR"
+B 5 ReadyForQuery T
+F 16 Describe P "cursor_one"
+F 4 Sync
+B 33 RowDescription 1 "?column?" 0 0 23 4 -1 0
+B 5 ReadyForQuery T
+F 4 Terminate
diff --git a/src/test/modules/libpq_pipeline/traces/simple_pipeline.trace b/src/test/modules/libpq_pipeline/traces/simple_pipeline.trace
new file mode 100644
index 0000000000..82a80c9191
--- /dev/null
+++ b/src/test/modules/libpq_pipeline/traces/simple_pipeline.trace
@@ -0,0 +1,15 @@
+F 27 Query "SET lc_messages TO "C""
+B 8 CommandComplete "SET"
+B 5 ReadyForQuery I
+F 21 Parse "" "SELECT $1" 1 23
+F 19 Bind "" "" 0 1 1 '1' 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 4 Sync
+B 4 ParseComplete
+B 4 BindComplete
+B 33 RowDescription 1 "?column?" 0 0 23 4 -1 0
+B 11 DataRow 1 1 '1'
+B 13 CommandComplete "SELECT 1"
+B 5 ReadyForQuery I
+F 4 Terminate
diff --git a/src/test/modules/libpq_pipeline/traces/singlerow.trace b/src/test/modules/libpq_pipeline/traces/singlerow.trace
new file mode 100644
index 0000000000..7708569f39
--- /dev/null
+++ b/src/test/modules/libpq_pipeline/traces/singlerow.trace
@@ -0,0 +1,42 @@
+F 27 Query "SET lc_messages TO "C""
+B 8 CommandComplete "SET"
+B 5 ReadyForQuery I
+F 38 Parse "" "SELECT generate_series(42, $1)" 0
+F 20 Bind "" "" 0 1 2 '44' 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 38 Parse "" "SELECT generate_series(42, $1)" 0
+F 20 Bind "" "" 0 1 2 '45' 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 38 Parse "" "SELECT generate_series(42, $1)" 0
+F 20 Bind "" "" 0 1 2 '46' 1 0
+F 6 Describe P ""
+F 9 Execute "" 0
+F 4 Sync
+B 4 ParseComplete
+B 4 BindComplete
+B 40 RowDescription 1 "generate_series" 0 0 23 4 -1 0
+B 12 DataRow 1 2 '42'
+B 12 DataRow 1 2 '43'
+B 12 DataRow 1 2 '44'
+B 13 CommandComplete "SELECT 3"
+B 4 ParseComplete
+B 4 BindComplete
+B 40 RowDescription 1 "generate_series" 0 0 23 4 -1 0
+B 12 DataRow 1 2 '42'
+B 12 DataRow 1 2 '43'
+B 12 DataRow 1 2 '44'
+B 12 DataRow 1 2 '45'
+B 13 CommandComplete "SELECT 4"
+B 4 ParseComplete
+B 4 BindComplete
+B 40 RowDescription 1 "generate_series" 0 0 23 4 -1 0
+B 12 DataRow 1 2 '42'
+B 12 DataRow 1 2 '43'
+B 12 DataRow 1 2 '44'
+B 12 DataRow 1 2 '45'
+B 12 DataRow 1 2 '46'
+B 13 CommandComplete "SELECT 5"
+B 5 ReadyForQuery I
+F 4 Terminate
--
2.20.1
view thread (234+ messages) latest in thread
Message-ID: <20210327192812.GA25115@alvherre.pgsql>
Permalink: ../20210327192812.GA25115@alvherre.pgsql/
Also on: postgresql.org/message-id/20210327192812.GA25115@alvherre.pgsql
copy link · copy postgr.es · copy git am
reply Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: alvherre@alvh.no-ip.org, tsunakawa.takay@fujitsu.com, iwata.aya@fujitsu.com, horikyota.ntt@gmail.com, tgl@sss.pgh.pa.us, k.jamison@fujitsu.com, pgsql-hackers@lists.postgresql.org
Subject: Re: libpq debug log
In-Reply-To: <20210327192812.GA25115@alvherre.pgsql>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox