PostgreSQL Source Code  git master
fe-trace.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * fe-trace.c
4  * functions for libpq protocol tracing
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  * src/interfaces/libpq/fe-trace.c
11  *
12  *-------------------------------------------------------------------------
13  */
14 
15 #include "postgres_fe.h"
16 
17 #include <ctype.h>
18 #include <limits.h>
19 #include <sys/time.h>
20 #include <time.h>
21 
22 #ifdef WIN32
23 #include "win32.h"
24 #else
25 #include <unistd.h>
26 #endif
27 
28 #include "libpq-fe.h"
29 #include "libpq-int.h"
30 #include "port/pg_bswap.h"
31 
32 
33 /* Enable tracing */
34 void
35 PQtrace(PGconn *conn, FILE *debug_port)
36 {
37  if (conn == NULL)
38  return;
39  PQuntrace(conn);
40  if (debug_port == NULL)
41  return;
42 
43  conn->Pfdebug = debug_port;
44  conn->traceFlags = 0;
45 }
46 
47 /* Disable tracing */
48 void
50 {
51  if (conn == NULL)
52  return;
53  if (conn->Pfdebug)
54  {
56  conn->Pfdebug = NULL;
57  }
58 
59  conn->traceFlags = 0;
60 }
61 
62 /* Set flags for current tracing session */
63 void
65 {
66  if (conn == NULL)
67  return;
68  /* If PQtrace() failed, do nothing. */
69  if (conn->Pfdebug == NULL)
70  return;
71  conn->traceFlags = flags;
72 }
73 
74 /*
75  * Print the current time, with microseconds, into a caller-supplied
76  * buffer.
77  * Cribbed from get_formatted_log_time, but much simpler.
78  */
79 static void
80 pqTraceFormatTimestamp(char *timestr, size_t ts_len)
81 {
82  struct timeval tval;
83  time_t now;
84 
85  gettimeofday(&tval, NULL);
86 
87  /*
88  * MSVC's implementation of timeval uses a long for tv_sec, however,
89  * localtime() expects a time_t pointer. Here we'll assign tv_sec to a
90  * local time_t variable so that we pass localtime() the correct pointer
91  * type.
92  */
93  now = tval.tv_sec;
94  strftime(timestr, ts_len,
95  "%Y-%m-%d %H:%M:%S",
96  localtime(&now));
97  /* append microseconds */
98  snprintf(timestr + strlen(timestr), ts_len - strlen(timestr),
99  ".%06u", (unsigned int) (tval.tv_usec));
100 }
101 
102 /*
103  * pqTraceOutputByte1: output a 1-char message to the log
104  */
105 static void
106 pqTraceOutputByte1(FILE *pfdebug, const char *data, int *cursor)
107 {
108  const char *v = data + *cursor;
109 
110  /*
111  * Show non-printable data in hex format, including the terminating \0
112  * that completes ErrorResponse and NoticeResponse messages.
113  */
114  if (!isprint((unsigned char) *v))
115  fprintf(pfdebug, " \\x%02x", *v);
116  else
117  fprintf(pfdebug, " %c", *v);
118  *cursor += 1;
119 }
120 
121 /*
122  * pqTraceOutputInt16: output a 2-byte integer message to the log
123  */
124 static int
125 pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
126 {
127  uint16 tmp;
128  int result;
129 
130  memcpy(&tmp, data + *cursor, 2);
131  *cursor += 2;
132  result = (int) pg_ntoh16(tmp);
133  fprintf(pfdebug, " %d", result);
134 
135  return result;
136 }
137 
138 /*
139  * pqTraceOutputInt32: output a 4-byte integer message to the log
140  *
141  * If 'suppress' is true, print a literal NNNN instead of the actual number.
142  */
143 static int
144 pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress)
145 {
146  int result;
147 
148  memcpy(&result, data + *cursor, 4);
149  *cursor += 4;
150  result = (int) pg_ntoh32(result);
151  if (suppress)
152  fprintf(pfdebug, " NNNN");
153  else
154  fprintf(pfdebug, " %d", result);
155 
156  return result;
157 }
158 
159 /*
160  * pqTraceOutputString: output a string message to the log
161  */
162 static void
163 pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress)
164 {
165  int len;
166 
167  if (suppress)
168  {
169  fprintf(pfdebug, " \"SSSS\"");
170  *cursor += strlen(data + *cursor) + 1;
171  }
172  else
173  {
174  len = fprintf(pfdebug, " \"%s\"", data + *cursor);
175 
176  /*
177  * This is a null-terminated string. So add 1 after subtracting 3
178  * which is the double quotes and space length from len.
179  */
180  *cursor += (len - 3 + 1);
181  }
182 }
183 
184 /*
185  * pqTraceOutputNchar: output a string of exactly len bytes message to the log
186  */
187 static void
188 pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor)
189 {
190  int i,
191  next; /* first char not yet printed */
192  const char *v = data + *cursor;
193 
194  fprintf(pfdebug, " \'");
195 
196  for (next = i = 0; i < len; ++i)
197  {
198  if (isprint((unsigned char) v[i]))
199  continue;
200  else
201  {
202  fwrite(v + next, 1, i - next, pfdebug);
203  fprintf(pfdebug, "\\x%02x", v[i]);
204  next = i + 1;
205  }
206  }
207  if (next < len)
208  fwrite(v + next, 1, len - next, pfdebug);
209 
210  fprintf(pfdebug, "\'");
211  *cursor += len;
212 }
213 
214 /*
215  * Output functions by protocol message type
216  */
217 
218 static void
219 pqTraceOutput_NotificationResponse(FILE *f, const char *message, int *cursor, bool regress)
220 {
221  fprintf(f, "NotificationResponse\t");
222  pqTraceOutputInt32(f, message, cursor, regress);
223  pqTraceOutputString(f, message, cursor, false);
224  pqTraceOutputString(f, message, cursor, false);
225 }
226 
227 static void
228 pqTraceOutput_Bind(FILE *f, const char *message, int *cursor)
229 {
230  int nparams;
231 
232  fprintf(f, "Bind\t");
233  pqTraceOutputString(f, message, cursor, false);
234  pqTraceOutputString(f, message, cursor, false);
235  nparams = pqTraceOutputInt16(f, message, cursor);
236 
237  for (int i = 0; i < nparams; i++)
238  pqTraceOutputInt16(f, message, cursor);
239 
240  nparams = pqTraceOutputInt16(f, message, cursor);
241 
242  for (int i = 0; i < nparams; i++)
243  {
244  int nbytes;
245 
246  nbytes = pqTraceOutputInt32(f, message, cursor, false);
247  if (nbytes == -1)
248  continue;
249  pqTraceOutputNchar(f, nbytes, message, cursor);
250  }
251 
252  nparams = pqTraceOutputInt16(f, message, cursor);
253  for (int i = 0; i < nparams; i++)
254  pqTraceOutputInt16(f, message, cursor);
255 }
256 
257 static void
258 pqTraceOutput_Close(FILE *f, const char *message, int *cursor)
259 {
260  fprintf(f, "Close\t");
261  pqTraceOutputByte1(f, message, cursor);
262  pqTraceOutputString(f, message, cursor, false);
263 }
264 
265 static void
266 pqTraceOutput_CommandComplete(FILE *f, const char *message, int *cursor)
267 {
268  fprintf(f, "CommandComplete\t");
269  pqTraceOutputString(f, message, cursor, false);
270 }
271 
272 static void
273 pqTraceOutput_DataRow(FILE *f, const char *message, int *cursor)
274 {
275  int nfields;
276  int len;
277  int i;
278 
279  fprintf(f, "DataRow\t");
280  nfields = pqTraceOutputInt16(f, message, cursor);
281  for (i = 0; i < nfields; i++)
282  {
283  len = pqTraceOutputInt32(f, message, cursor, false);
284  if (len == -1)
285  continue;
286  pqTraceOutputNchar(f, len, message, cursor);
287  }
288 }
289 
290 static void
291 pqTraceOutput_Describe(FILE *f, const char *message, int *cursor)
292 {
293  fprintf(f, "Describe\t");
294  pqTraceOutputByte1(f, message, cursor);
295  pqTraceOutputString(f, message, cursor, false);
296 }
297 
298 /* shared code NoticeResponse / ErrorResponse */
299 static void
300 pqTraceOutputNR(FILE *f, const char *type, const char *message, int *cursor,
301  bool regress)
302 {
303  fprintf(f, "%s\t", type);
304  for (;;)
305  {
306  char field;
307  bool suppress;
308 
309  pqTraceOutputByte1(f, message, cursor);
310  field = message[*cursor - 1];
311  if (field == '\0')
312  break;
313 
314  suppress = regress && (field == 'L' || field == 'F' || field == 'R');
315  pqTraceOutputString(f, message, cursor, suppress);
316  }
317 }
318 
319 static void
320 pqTraceOutput_ErrorResponse(FILE *f, const char *message, int *cursor, bool regress)
321 {
322  pqTraceOutputNR(f, "ErrorResponse", message, cursor, regress);
323 }
324 
325 static void
326 pqTraceOutput_NoticeResponse(FILE *f, const char *message, int *cursor, bool regress)
327 {
328  pqTraceOutputNR(f, "NoticeResponse", message, cursor, regress);
329 }
330 
331 static void
332 pqTraceOutput_Execute(FILE *f, const char *message, int *cursor, bool regress)
333 {
334  fprintf(f, "Execute\t");
335  pqTraceOutputString(f, message, cursor, false);
336  pqTraceOutputInt32(f, message, cursor, false);
337 }
338 
339 static void
340 pqTraceOutput_CopyFail(FILE *f, const char *message, int *cursor)
341 {
342  fprintf(f, "CopyFail\t");
343  pqTraceOutputString(f, message, cursor, false);
344 }
345 
346 static void
347 pqTraceOutput_FunctionCall(FILE *f, const char *message, int *cursor, bool regress)
348 {
349  int nfields;
350  int nbytes;
351 
352  fprintf(f, "FunctionCall\t");
353  pqTraceOutputInt32(f, message, cursor, regress);
354  nfields = pqTraceOutputInt16(f, message, cursor);
355 
356  for (int i = 0; i < nfields; i++)
357  pqTraceOutputInt16(f, message, cursor);
358 
359  nfields = pqTraceOutputInt16(f, message, cursor);
360 
361  for (int i = 0; i < nfields; i++)
362  {
363  nbytes = pqTraceOutputInt32(f, message, cursor, false);
364  if (nbytes == -1)
365  continue;
366  pqTraceOutputNchar(f, nbytes, message, cursor);
367  }
368 
369  pqTraceOutputInt16(f, message, cursor);
370 }
371 
372 static void
373 pqTraceOutput_CopyInResponse(FILE *f, const char *message, int *cursor)
374 {
375  int nfields;
376 
377  fprintf(f, "CopyInResponse\t");
378  pqTraceOutputByte1(f, message, cursor);
379  nfields = pqTraceOutputInt16(f, message, cursor);
380 
381  for (int i = 0; i < nfields; i++)
382  pqTraceOutputInt16(f, message, cursor);
383 }
384 
385 static void
386 pqTraceOutput_CopyOutResponse(FILE *f, const char *message, int *cursor)
387 {
388  int nfields;
389 
390  fprintf(f, "CopyOutResponse\t");
391  pqTraceOutputByte1(f, message, cursor);
392  nfields = pqTraceOutputInt16(f, message, cursor);
393 
394  for (int i = 0; i < nfields; i++)
395  pqTraceOutputInt16(f, message, cursor);
396 }
397 
398 static void
399 pqTraceOutput_BackendKeyData(FILE *f, const char *message, int *cursor, bool regress)
400 {
401  fprintf(f, "BackendKeyData\t");
402  pqTraceOutputInt32(f, message, cursor, regress);
403  pqTraceOutputInt32(f, message, cursor, regress);
404 }
405 
406 static void
407 pqTraceOutput_Parse(FILE *f, const char *message, int *cursor, bool regress)
408 {
409  int nparams;
410 
411  fprintf(f, "Parse\t");
412  pqTraceOutputString(f, message, cursor, false);
413  pqTraceOutputString(f, message, cursor, false);
414  nparams = pqTraceOutputInt16(f, message, cursor);
415 
416  for (int i = 0; i < nparams; i++)
417  pqTraceOutputInt32(f, message, cursor, regress);
418 }
419 
420 static void
421 pqTraceOutput_Query(FILE *f, const char *message, int *cursor)
422 {
423  fprintf(f, "Query\t");
424  pqTraceOutputString(f, message, cursor, false);
425 }
426 
427 static void
428 pqTraceOutput_Authentication(FILE *f, const char *message, int *cursor)
429 {
430  fprintf(f, "Authentication\t");
431  pqTraceOutputInt32(f, message, cursor, false);
432 }
433 
434 static void
435 pqTraceOutput_ParameterStatus(FILE *f, const char *message, int *cursor)
436 {
437  fprintf(f, "ParameterStatus\t");
438  pqTraceOutputString(f, message, cursor, false);
439  pqTraceOutputString(f, message, cursor, false);
440 }
441 
442 static void
443 pqTraceOutput_ParameterDescription(FILE *f, const char *message, int *cursor, bool regress)
444 {
445  int nfields;
446 
447  fprintf(f, "ParameterDescription\t");
448  nfields = pqTraceOutputInt16(f, message, cursor);
449 
450  for (int i = 0; i < nfields; i++)
451  pqTraceOutputInt32(f, message, cursor, regress);
452 }
453 
454 static void
455 pqTraceOutput_RowDescription(FILE *f, const char *message, int *cursor, bool regress)
456 {
457  int nfields;
458 
459  fprintf(f, "RowDescription\t");
460  nfields = pqTraceOutputInt16(f, message, cursor);
461 
462  for (int i = 0; i < nfields; i++)
463  {
464  pqTraceOutputString(f, message, cursor, false);
465  pqTraceOutputInt32(f, message, cursor, regress);
466  pqTraceOutputInt16(f, message, cursor);
467  pqTraceOutputInt32(f, message, cursor, regress);
468  pqTraceOutputInt16(f, message, cursor);
469  pqTraceOutputInt32(f, message, cursor, false);
470  pqTraceOutputInt16(f, message, cursor);
471  }
472 }
473 
474 static void
475 pqTraceOutput_NegotiateProtocolVersion(FILE *f, const char *message, int *cursor)
476 {
477  fprintf(f, "NegotiateProtocolVersion\t");
478  pqTraceOutputInt32(f, message, cursor, false);
479  pqTraceOutputInt32(f, message, cursor, false);
480 }
481 
482 static void
483 pqTraceOutput_FunctionCallResponse(FILE *f, const char *message, int *cursor)
484 {
485  int len;
486 
487  fprintf(f, "FunctionCallResponse\t");
488  len = pqTraceOutputInt32(f, message, cursor, false);
489  if (len != -1)
490  pqTraceOutputNchar(f, len, message, cursor);
491 }
492 
493 static void
494 pqTraceOutput_CopyBothResponse(FILE *f, const char *message, int *cursor, int length)
495 {
496  fprintf(f, "CopyBothResponse\t");
497  pqTraceOutputByte1(f, message, cursor);
498 
499  while (length > *cursor)
500  pqTraceOutputInt16(f, message, cursor);
501 }
502 
503 static void
504 pqTraceOutput_ReadyForQuery(FILE *f, const char *message, int *cursor)
505 {
506  fprintf(f, "ReadyForQuery\t");
507  pqTraceOutputByte1(f, message, cursor);
508 }
509 
510 /*
511  * Print the given message to the trace output stream.
512  */
513 void
514 pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
515 {
516  char id;
517  int length;
518  char *prefix = toServer ? "F" : "B";
519  int logCursor = 0;
520  bool regress;
521 
523  {
524  char timestr[128];
525 
526  pqTraceFormatTimestamp(timestr, sizeof(timestr));
527  fprintf(conn->Pfdebug, "%s\t", timestr);
528  }
529  regress = (conn->traceFlags & PQTRACE_REGRESS_MODE) != 0;
530 
531  id = message[logCursor++];
532 
533  memcpy(&length, message + logCursor, 4);
534  length = (int) pg_ntoh32(length);
535  logCursor += 4;
536 
537  /*
538  * In regress mode, suppress the length of ErrorResponse and
539  * NoticeResponse. The F (file name), L (line number) and R (routine
540  * name) fields can change as server code is modified, and if their
541  * lengths differ from the originals, that would break tests.
542  */
543  if (regress && !toServer && (id == PqMsg_ErrorResponse || id == PqMsg_NoticeResponse))
544  fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
545  else
546  fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
547 
548  switch (id)
549  {
550  case PqMsg_ParseComplete:
551  fprintf(conn->Pfdebug, "ParseComplete");
552  /* No message content */
553  break;
554  case PqMsg_BindComplete:
555  fprintf(conn->Pfdebug, "BindComplete");
556  /* No message content */
557  break;
558  case PqMsg_CloseComplete:
559  fprintf(conn->Pfdebug, "CloseComplete");
560  /* No message content */
561  break;
563  pqTraceOutput_NotificationResponse(conn->Pfdebug, message, &logCursor, regress);
564  break;
565  case PqMsg_Bind:
566  pqTraceOutput_Bind(conn->Pfdebug, message, &logCursor);
567  break;
568  case PqMsg_CopyDone:
569  fprintf(conn->Pfdebug, "CopyDone");
570  /* No message content */
571  break;
573  /* Close(F) and CommandComplete(B) use the same identifier. */
575  if (toServer)
576  pqTraceOutput_Close(conn->Pfdebug, message, &logCursor);
577  else
578  pqTraceOutput_CommandComplete(conn->Pfdebug, message, &logCursor);
579  break;
580  case PqMsg_CopyData:
581  /* Drop COPY data to reduce the overhead of logging. */
582  break;
583  case PqMsg_Describe:
584  /* Describe(F) and DataRow(B) use the same identifier. */
586  if (toServer)
587  pqTraceOutput_Describe(conn->Pfdebug, message, &logCursor);
588  else
589  pqTraceOutput_DataRow(conn->Pfdebug, message, &logCursor);
590  break;
591  case PqMsg_Execute:
592  /* Execute(F) and ErrorResponse(B) use the same identifier. */
594  if (toServer)
595  pqTraceOutput_Execute(conn->Pfdebug, message, &logCursor, regress);
596  else
597  pqTraceOutput_ErrorResponse(conn->Pfdebug, message, &logCursor, regress);
598  break;
599  case PqMsg_CopyFail:
600  pqTraceOutput_CopyFail(conn->Pfdebug, message, &logCursor);
601  break;
602  case PqMsg_FunctionCall:
603  pqTraceOutput_FunctionCall(conn->Pfdebug, message, &logCursor, regress);
604  break;
606  pqTraceOutput_CopyInResponse(conn->Pfdebug, message, &logCursor);
607  break;
608  case PqMsg_Flush:
609  /* Flush(F) and CopyOutResponse(B) use the same identifier */
611  if (toServer)
612  fprintf(conn->Pfdebug, "Flush"); /* no message content */
613  else
614  pqTraceOutput_CopyOutResponse(conn->Pfdebug, message, &logCursor);
615  break;
617  fprintf(conn->Pfdebug, "EmptyQueryResponse");
618  /* No message content */
619  break;
621  pqTraceOutput_BackendKeyData(conn->Pfdebug, message, &logCursor, regress);
622  break;
623  case PqMsg_NoData:
624  fprintf(conn->Pfdebug, "NoData");
625  /* No message content */
626  break;
628  pqTraceOutput_NoticeResponse(conn->Pfdebug, message, &logCursor, regress);
629  break;
630  case PqMsg_Parse:
631  pqTraceOutput_Parse(conn->Pfdebug, message, &logCursor, regress);
632  break;
633  case PqMsg_Query:
634  pqTraceOutput_Query(conn->Pfdebug, message, &logCursor);
635  break;
637  pqTraceOutput_Authentication(conn->Pfdebug, message, &logCursor);
638  break;
640  fprintf(conn->Pfdebug, "PortalSuspended");
641  /* No message content */
642  break;
643  case PqMsg_Sync:
644  /* ParameterStatus(B) and Sync(F) use the same identifier */
646  if (toServer)
647  fprintf(conn->Pfdebug, "Sync"); /* no message content */
648  else
649  pqTraceOutput_ParameterStatus(conn->Pfdebug, message, &logCursor);
650  break;
652  pqTraceOutput_ParameterDescription(conn->Pfdebug, message, &logCursor, regress);
653  break;
655  pqTraceOutput_RowDescription(conn->Pfdebug, message, &logCursor, regress);
656  break;
658  pqTraceOutput_NegotiateProtocolVersion(conn->Pfdebug, message, &logCursor);
659  break;
661  pqTraceOutput_FunctionCallResponse(conn->Pfdebug, message, &logCursor);
662  break;
664  pqTraceOutput_CopyBothResponse(conn->Pfdebug, message, &logCursor, length);
665  break;
666  case PqMsg_Terminate:
667  fprintf(conn->Pfdebug, "Terminate");
668  /* No message content */
669  break;
670  case PqMsg_ReadyForQuery:
671  pqTraceOutput_ReadyForQuery(conn->Pfdebug, message, &logCursor);
672  break;
673  default:
674  fprintf(conn->Pfdebug, "Unknown message: %02x", id);
675  break;
676  }
677 
678  fputc('\n', conn->Pfdebug);
679 
680  /*
681  * Verify the printing routine did it right. Note that the one-byte
682  * message identifier is not included in the length, but our cursor does
683  * include it.
684  */
685  if (logCursor - 1 != length)
687  "mismatched message length: consumed %d, expected %d\n",
688  logCursor - 1, length);
689 }
690 
691 /*
692  * Print special messages (those containing no type byte) to the trace output
693  * stream.
694  */
695 void
697 {
698  int length;
699  int logCursor = 0;
700 
702  {
703  char timestr[128];
704 
705  pqTraceFormatTimestamp(timestr, sizeof(timestr));
706  fprintf(conn->Pfdebug, "%s\t", timestr);
707  }
708 
709  memcpy(&length, message + logCursor, 4);
710  length = (int) pg_ntoh32(length);
711  logCursor += 4;
712 
713  fprintf(conn->Pfdebug, "F\t%d\t", length);
714 
715  switch (length)
716  {
717  case 16: /* CancelRequest */
718  fprintf(conn->Pfdebug, "CancelRequest\t");
719  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
720  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
721  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
722  break;
723  case 8: /* GSSENCRequest or SSLRequest */
724  /* These messages do not reach here. */
725  default:
726  fprintf(conn->Pfdebug, "Unknown message: length is %d", length);
727  break;
728  }
729 
730  fputc('\n', conn->Pfdebug);
731 }
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1618
static int32 next
Definition: blutils.c:221
unsigned short uint16
Definition: c.h:505
#define Assert(condition)
Definition: c.h:858
static void pqTraceOutput_RowDescription(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:455
static void pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition: fe-trace.c:163
static void pqTraceOutput_FunctionCall(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:347
static void pqTraceOutput_CopyInResponse(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:373
static void pqTraceOutput_BackendKeyData(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:399
static void pqTraceOutput_Parse(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:407
static void pqTraceOutput_NoticeResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:326
static void pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor)
Definition: fe-trace.c:188
void PQtrace(PGconn *conn, FILE *debug_port)
Definition: fe-trace.c:35
static void pqTraceOutput_ParameterDescription(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:443
static void pqTraceOutput_DataRow(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:273
static void pqTraceOutput_Query(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:421
static int pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
Definition: fe-trace.c:125
static void pqTraceOutput_NegotiateProtocolVersion(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:475
static void pqTraceOutput_CopyBothResponse(FILE *f, const char *message, int *cursor, int length)
Definition: fe-trace.c:494
static void pqTraceOutput_Bind(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:228
static void pqTraceOutput_ErrorResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:320
static void pqTraceOutputNR(FILE *f, const char *type, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:300
static void pqTraceOutput_Close(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:258
static void pqTraceOutputByte1(FILE *pfdebug, const char *data, int *cursor)
Definition: fe-trace.c:106
static void pqTraceOutput_Authentication(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:428
static void pqTraceOutput_Describe(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:291
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
Definition: fe-trace.c:514
static void pqTraceOutput_NotificationResponse(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:219
static void pqTraceOutput_CommandComplete(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:266
void PQsetTraceFlags(PGconn *conn, int flags)
Definition: fe-trace.c:64
static void pqTraceOutput_ParameterStatus(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:435
static void pqTraceOutput_Execute(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:332
void PQuntrace(PGconn *conn)
Definition: fe-trace.c:49
static void pqTraceOutput_CopyOutResponse(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:386
static void pqTraceOutput_ReadyForQuery(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:504
static int pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition: fe-trace.c:144
void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
Definition: fe-trace.c:696
static void pqTraceFormatTimestamp(char *timestr, size_t ts_len)
Definition: fe-trace.c:80
static void pqTraceOutput_CopyFail(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:340
static void pqTraceOutput_FunctionCallResponse(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:483
int i
Definition: isn.c:73
#define PQTRACE_SUPPRESS_TIMESTAMPS
Definition: libpq-fe.h:442
#define PQTRACE_REGRESS_MODE
Definition: libpq-fe.h:444
static void const char fflush(stdout)
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
const void size_t len
const void * data
#define snprintf
Definition: port.h:238
#define fprintf
Definition: port.h:242
#define PqMsg_CloseComplete
Definition: protocol.h:40
#define PqMsg_CopyDone
Definition: protocol.h:64
#define PqMsg_NotificationResponse
Definition: protocol.h:41
#define PqMsg_BindComplete
Definition: protocol.h:39
#define PqMsg_CopyData
Definition: protocol.h:65
#define PqMsg_ParameterDescription
Definition: protocol.h:58
#define PqMsg_FunctionCall
Definition: protocol.h:23
#define PqMsg_Describe
Definition: protocol.h:21
#define PqMsg_FunctionCallResponse
Definition: protocol.h:53
#define PqMsg_ReadyForQuery
Definition: protocol.h:55
#define PqMsg_AuthenticationRequest
Definition: protocol.h:50
#define PqMsg_CopyInResponse
Definition: protocol.h:45
#define PqMsg_EmptyQueryResponse
Definition: protocol.h:47
#define PqMsg_RowDescription
Definition: protocol.h:52
#define PqMsg_CopyBothResponse
Definition: protocol.h:54
#define PqMsg_ParameterStatus
Definition: protocol.h:51
#define PqMsg_NoData
Definition: protocol.h:56
#define PqMsg_NegotiateProtocolVersion
Definition: protocol.h:59
#define PqMsg_PortalSuspended
Definition: protocol.h:57
#define PqMsg_Parse
Definition: protocol.h:25
#define PqMsg_Bind
Definition: protocol.h:19
#define PqMsg_Sync
Definition: protocol.h:27
#define PqMsg_CopyFail
Definition: protocol.h:29
#define PqMsg_Flush
Definition: protocol.h:24
#define PqMsg_BackendKeyData
Definition: protocol.h:48
#define PqMsg_CommandComplete
Definition: protocol.h:42
#define PqMsg_Query
Definition: protocol.h:26
#define PqMsg_ErrorResponse
Definition: protocol.h:44
#define PqMsg_DataRow
Definition: protocol.h:43
#define PqMsg_NoticeResponse
Definition: protocol.h:49
#define PqMsg_Terminate
Definition: protocol.h:28
#define PqMsg_Execute
Definition: protocol.h:22
#define PqMsg_Close
Definition: protocol.h:20
#define PqMsg_CopyOutResponse
Definition: protocol.h:46
#define PqMsg_ParseComplete
Definition: protocol.h:38
PGconn * conn
Definition: streamutil.c:55
Definition: type.h:137
FILE * Pfdebug
Definition: libpq-int.h:424
int traceFlags
Definition: libpq-int.h:425
const char * type
int gettimeofday(struct timeval *tp, void *tzp)