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-2021, 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  {
55  fflush(conn->Pfdebug);
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 setup_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 /* NotificationResponse */
219 static void
220 pqTraceOutputA(FILE *f, const char *message, int *cursor, bool regress)
221 {
222  fprintf(f, "NotificationResponse\t");
223  pqTraceOutputInt32(f, message, cursor, regress);
224  pqTraceOutputString(f, message, cursor, false);
225  pqTraceOutputString(f, message, cursor, false);
226 }
227 
228 /* Bind */
229 static void
230 pqTraceOutputB(FILE *f, const char *message, int *cursor)
231 {
232  int nparams;
233 
234  fprintf(f, "Bind\t");
235  pqTraceOutputString(f, message, cursor, false);
236  pqTraceOutputString(f, message, cursor, false);
237  nparams = pqTraceOutputInt16(f, message, cursor);
238 
239  for (int i = 0; i < nparams; i++)
240  pqTraceOutputInt16(f, message, cursor);
241 
242  nparams = pqTraceOutputInt16(f, message, cursor);
243 
244  for (int i = 0; i < nparams; i++)
245  {
246  int nbytes;
247 
248  nbytes = pqTraceOutputInt32(f, message, cursor, false);
249  if (nbytes == -1)
250  continue;
251  pqTraceOutputNchar(f, nbytes, message, cursor);
252  }
253 
254  nparams = pqTraceOutputInt16(f, message, cursor);
255  for (int i = 0; i < nparams; i++)
256  pqTraceOutputInt16(f, message, cursor);
257 }
258 
259 /* Close(F) or CommandComplete(B) */
260 static void
261 pqTraceOutputC(FILE *f, bool toServer, const char *message, int *cursor)
262 {
263  if (toServer)
264  {
265  fprintf(f, "Close\t");
266  pqTraceOutputByte1(f, message, cursor);
267  pqTraceOutputString(f, message, cursor, false);
268  }
269  else
270  {
271  fprintf(f, "CommandComplete\t");
272  pqTraceOutputString(f, message, cursor, false);
273  }
274 }
275 
276 /* Describe(F) or DataRow(B) */
277 static void
278 pqTraceOutputD(FILE *f, bool toServer, const char *message, int *cursor)
279 {
280  if (toServer)
281  {
282  fprintf(f, "Describe\t");
283  pqTraceOutputByte1(f, message, cursor);
284  pqTraceOutputString(f, message, cursor, false);
285  }
286  else
287  {
288  int nfields;
289  int len;
290  int i;
291 
292  fprintf(f, "DataRow\t");
293  nfields = pqTraceOutputInt16(f, message, cursor);
294  for (i = 0; i < nfields; i++)
295  {
296  len = pqTraceOutputInt32(f, message, cursor, false);
297  if (len == -1)
298  continue;
299  pqTraceOutputNchar(f, len, message, cursor);
300  }
301  }
302 }
303 
304 /* NoticeResponse / ErrorResponse */
305 static void
306 pqTraceOutputNR(FILE *f, const char *type, const char *message, int *cursor,
307  bool regress)
308 {
309  fprintf(f, "%s\t", type);
310  for (;;)
311  {
312  char field;
313  bool suppress;
314 
315  pqTraceOutputByte1(f, message, cursor);
316  field = message[*cursor - 1];
317  if (field == '\0')
318  break;
319 
320  suppress = regress && (field == 'L' || field == 'F' || field == 'R');
321  pqTraceOutputString(f, message, cursor, suppress);
322  }
323 }
324 
325 /* Execute(F) or ErrorResponse(B) */
326 static void
327 pqTraceOutputE(FILE *f, bool toServer, const char *message, int *cursor, bool regress)
328 {
329  if (toServer)
330  {
331  fprintf(f, "Execute\t");
332  pqTraceOutputString(f, message, cursor, false);
333  pqTraceOutputInt32(f, message, cursor, false);
334  }
335  else
336  pqTraceOutputNR(f, "ErrorResponse", message, cursor, regress);
337 }
338 
339 /* CopyFail */
340 static void
341 pqTraceOutputf(FILE *f, const char *message, int *cursor)
342 {
343  fprintf(f, "CopyFail\t");
344  pqTraceOutputString(f, message, cursor, false);
345 }
346 
347 /* FunctionCall */
348 static void
349 pqTraceOutputF(FILE *f, const char *message, int *cursor, bool regress)
350 {
351  int nfields;
352  int nbytes;
353 
354  fprintf(f, "FunctionCall\t");
355  pqTraceOutputInt32(f, message, cursor, regress);
356  nfields = pqTraceOutputInt16(f, message, cursor);
357 
358  for (int i = 0; i < nfields; i++)
359  pqTraceOutputInt16(f, message, cursor);
360 
361  nfields = pqTraceOutputInt16(f, message, cursor);
362 
363  for (int i = 0; i < nfields; i++)
364  {
365  nbytes = pqTraceOutputInt32(f, message, cursor, false);
366  if (nbytes == -1)
367  continue;
368  pqTraceOutputNchar(f, nbytes, message, cursor);
369  }
370 
371  pqTraceOutputInt16(f, message, cursor);
372 }
373 
374 /* CopyInResponse */
375 static void
376 pqTraceOutputG(FILE *f, const char *message, int *cursor)
377 {
378  int nfields;
379 
380  fprintf(f, "CopyInResponse\t");
381  pqTraceOutputByte1(f, message, cursor);
382  nfields = pqTraceOutputInt16(f, message, cursor);
383 
384  for (int i = 0; i < nfields; i++)
385  pqTraceOutputInt16(f, message, cursor);
386 }
387 
388 /* CopyOutResponse */
389 static void
390 pqTraceOutputH(FILE *f, const char *message, int *cursor)
391 {
392  int nfields;
393 
394  fprintf(f, "CopyOutResponse\t");
395  pqTraceOutputByte1(f, message, cursor);
396  nfields = pqTraceOutputInt16(f, message, cursor);
397 
398  for (int i = 0; i < nfields; i++)
399  pqTraceOutputInt16(f, message, cursor);
400 }
401 
402 /* BackendKeyData */
403 static void
404 pqTraceOutputK(FILE *f, const char *message, int *cursor, bool regress)
405 {
406  fprintf(f, "BackendKeyData\t");
407  pqTraceOutputInt32(f, message, cursor, regress);
408  pqTraceOutputInt32(f, message, cursor, regress);
409 }
410 
411 /* Parse */
412 static void
413 pqTraceOutputP(FILE *f, const char *message, int *cursor, bool regress)
414 {
415  int nparams;
416 
417  fprintf(f, "Parse\t");
418  pqTraceOutputString(f, message, cursor, false);
419  pqTraceOutputString(f, message, cursor, false);
420  nparams = pqTraceOutputInt16(f, message, cursor);
421 
422  for (int i = 0; i < nparams; i++)
423  pqTraceOutputInt32(f, message, cursor, regress);
424 }
425 
426 /* Query */
427 static void
428 pqTraceOutputQ(FILE *f, const char *message, int *cursor)
429 {
430  fprintf(f, "Query\t");
431  pqTraceOutputString(f, message, cursor, false);
432 }
433 
434 /* Authentication */
435 static void
436 pqTraceOutputR(FILE *f, const char *message, int *cursor)
437 {
438  fprintf(f, "Authentication\t");
439  pqTraceOutputInt32(f, message, cursor, false);
440 }
441 
442 /* ParameterStatus */
443 static void
444 pqTraceOutputS(FILE *f, const char *message, int *cursor)
445 {
446  fprintf(f, "ParameterStatus\t");
447  pqTraceOutputString(f, message, cursor, false);
448  pqTraceOutputString(f, message, cursor, false);
449 }
450 
451 /* ParameterDescription */
452 static void
453 pqTraceOutputt(FILE *f, const char *message, int *cursor, bool regress)
454 {
455  int nfields;
456 
457  fprintf(f, "ParameterDescription\t");
458  nfields = pqTraceOutputInt16(f, message, cursor);
459 
460  for (int i = 0; i < nfields; i++)
461  pqTraceOutputInt32(f, message, cursor, regress);
462 }
463 
464 /* RowDescription */
465 static void
466 pqTraceOutputT(FILE *f, const char *message, int *cursor, bool regress)
467 {
468  int nfields;
469 
470  fprintf(f, "RowDescription\t");
471  nfields = pqTraceOutputInt16(f, message, cursor);
472 
473  for (int i = 0; i < nfields; i++)
474  {
475  pqTraceOutputString(f, message, cursor, false);
476  pqTraceOutputInt32(f, message, cursor, regress);
477  pqTraceOutputInt16(f, message, cursor);
478  pqTraceOutputInt32(f, message, cursor, regress);
479  pqTraceOutputInt16(f, message, cursor);
480  pqTraceOutputInt32(f, message, cursor, false);
481  pqTraceOutputInt16(f, message, cursor);
482  }
483 }
484 
485 /* NegotiateProtocolVersion */
486 static void
487 pqTraceOutputv(FILE *f, const char *message, int *cursor)
488 {
489  fprintf(f, "NegotiateProtocolVersion\t");
490  pqTraceOutputInt32(f, message, cursor, false);
491  pqTraceOutputInt32(f, message, cursor, false);
492 }
493 
494 /* FunctionCallResponse */
495 static void
496 pqTraceOutputV(FILE *f, const char *message, int *cursor)
497 {
498  int len;
499 
500  fprintf(f, "FunctionCallResponse\t");
501  len = pqTraceOutputInt32(f, message, cursor, false);
502  if (len != -1)
503  pqTraceOutputNchar(f, len, message, cursor);
504 }
505 
506 /* CopyBothResponse */
507 static void
508 pqTraceOutputW(FILE *f, const char *message, int *cursor, int length)
509 {
510  fprintf(f, "CopyBothResponse\t");
511  pqTraceOutputByte1(f, message, cursor);
512 
513  while (length > *cursor)
514  pqTraceOutputInt16(f, message, cursor);
515 }
516 
517 /* ReadyForQuery */
518 static void
519 pqTraceOutputZ(FILE *f, const char *message, int *cursor)
520 {
521  fprintf(f, "ReadyForQuery\t");
522  pqTraceOutputByte1(f, message, cursor);
523 }
524 
525 /*
526  * Print the given message to the trace output stream.
527  */
528 void
529 pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
530 {
531  char id;
532  int length;
533  char *prefix = toServer ? "F" : "B";
534  int logCursor = 0;
535  bool regress;
536 
537  if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0)
538  {
539  char timestr[128];
540 
541  pqTraceFormatTimestamp(timestr, sizeof(timestr));
542  fprintf(conn->Pfdebug, "%s\t", timestr);
543  }
544  regress = (conn->traceFlags & PQTRACE_REGRESS_MODE) != 0;
545 
546  id = message[logCursor++];
547 
548  memcpy(&length, message + logCursor, 4);
549  length = (int) pg_ntoh32(length);
550  logCursor += 4;
551 
552  /*
553  * In regress mode, suppress the length of ErrorResponse and
554  * NoticeResponse. The F (file name), L (line number) and R (routine
555  * name) fields can change as server code is modified, and if their
556  * lengths differ from the originals, that would break tests.
557  */
558  if (regress && !toServer && (id == 'E' || id == 'N'))
559  fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
560  else
561  fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
562 
563  switch (id)
564  {
565  case '1':
566  fprintf(conn->Pfdebug, "ParseComplete");
567  /* No message content */
568  break;
569  case '2':
570  fprintf(conn->Pfdebug, "BindComplete");
571  /* No message content */
572  break;
573  case '3':
574  fprintf(conn->Pfdebug, "CloseComplete");
575  /* No message content */
576  break;
577  case 'A': /* Notification Response */
578  pqTraceOutputA(conn->Pfdebug, message, &logCursor, regress);
579  break;
580  case 'B': /* Bind */
581  pqTraceOutputB(conn->Pfdebug, message, &logCursor);
582  break;
583  case 'c':
584  fprintf(conn->Pfdebug, "CopyDone");
585  /* No message content */
586  break;
587  case 'C': /* Close(F) or Command Complete(B) */
588  pqTraceOutputC(conn->Pfdebug, toServer, message, &logCursor);
589  break;
590  case 'd': /* Copy Data */
591  /* Drop COPY data to reduce the overhead of logging. */
592  break;
593  case 'D': /* Describe(F) or Data Row(B) */
594  pqTraceOutputD(conn->Pfdebug, toServer, message, &logCursor);
595  break;
596  case 'E': /* Execute(F) or Error Response(B) */
597  pqTraceOutputE(conn->Pfdebug, toServer, message, &logCursor,
598  regress);
599  break;
600  case 'f': /* Copy Fail */
601  pqTraceOutputf(conn->Pfdebug, message, &logCursor);
602  break;
603  case 'F': /* Function Call */
604  pqTraceOutputF(conn->Pfdebug, message, &logCursor, regress);
605  break;
606  case 'G': /* Start Copy In */
607  pqTraceOutputG(conn->Pfdebug, message, &logCursor);
608  break;
609  case 'H': /* Flush(F) or Start Copy Out(B) */
610  if (!toServer)
611  pqTraceOutputH(conn->Pfdebug, message, &logCursor);
612  else
613  fprintf(conn->Pfdebug, "Flush"); /* no message content */
614  break;
615  case 'I':
616  fprintf(conn->Pfdebug, "EmptyQueryResponse");
617  /* No message content */
618  break;
619  case 'K': /* secret key data from the backend */
620  pqTraceOutputK(conn->Pfdebug, message, &logCursor, regress);
621  break;
622  case 'n':
623  fprintf(conn->Pfdebug, "NoData");
624  /* No message content */
625  break;
626  case 'N':
627  pqTraceOutputNR(conn->Pfdebug, "NoticeResponse", message,
628  &logCursor, regress);
629  break;
630  case 'P': /* Parse */
631  pqTraceOutputP(conn->Pfdebug, message, &logCursor, regress);
632  break;
633  case 'Q': /* Query */
634  pqTraceOutputQ(conn->Pfdebug, message, &logCursor);
635  break;
636  case 'R': /* Authentication */
637  pqTraceOutputR(conn->Pfdebug, message, &logCursor);
638  break;
639  case 's':
640  fprintf(conn->Pfdebug, "PortalSuspended");
641  /* No message content */
642  break;
643  case 'S': /* Parameter Status(B) or Sync(F) */
644  if (!toServer)
645  pqTraceOutputS(conn->Pfdebug, message, &logCursor);
646  else
647  fprintf(conn->Pfdebug, "Sync"); /* no message content */
648  break;
649  case 't': /* Parameter Description */
650  pqTraceOutputt(conn->Pfdebug, message, &logCursor, regress);
651  break;
652  case 'T': /* Row Description */
653  pqTraceOutputT(conn->Pfdebug, message, &logCursor, regress);
654  break;
655  case 'v': /* Negotiate Protocol Version */
656  pqTraceOutputv(conn->Pfdebug, message, &logCursor);
657  break;
658  case 'V': /* Function Call response */
659  pqTraceOutputV(conn->Pfdebug, message, &logCursor);
660  break;
661  case 'W': /* Start Copy Both */
662  pqTraceOutputW(conn->Pfdebug, message, &logCursor, length);
663  break;
664  case 'X':
665  fprintf(conn->Pfdebug, "Terminate");
666  /* No message content */
667  break;
668  case 'Z': /* Ready For Query */
669  pqTraceOutputZ(conn->Pfdebug, message, &logCursor);
670  break;
671  default:
672  fprintf(conn->Pfdebug, "Unknown message: %02x", id);
673  break;
674  }
675 
676  fputc('\n', conn->Pfdebug);
677 
678  /*
679  * Verify the printing routine did it right. Note that the one-byte
680  * message identifier is not included in the length, but our cursor does
681  * include it.
682  */
683  if (logCursor - 1 != length)
684  fprintf(conn->Pfdebug,
685  "mismatched message length: consumed %d, expected %d\n",
686  logCursor - 1, length);
687 }
688 
689 /*
690  * Print special messages (those containing no type byte) to the trace output
691  * stream.
692  */
693 void
695 {
696  int length;
697  int logCursor = 0;
698 
699  if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0)
700  {
701  char timestr[128];
702 
703  pqTraceFormatTimestamp(timestr, sizeof(timestr));
704  fprintf(conn->Pfdebug, "%s\t", timestr);
705  }
706 
707  memcpy(&length, message + logCursor, 4);
708  length = (int) pg_ntoh32(length);
709  logCursor += 4;
710 
711  fprintf(conn->Pfdebug, "F\t%d\t", length);
712 
713  switch (length)
714  {
715  case 16: /* CancelRequest */
716  fprintf(conn->Pfdebug, "CancelRequest\t");
717  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
718  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
719  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
720  break;
721  case 8: /* GSSENCRequest or SSLRequest */
722  /* These messages do not reach here. */
723  default:
724  fprintf(conn->Pfdebug, "Unknown message: length is %d", length);
725  break;
726  }
727 
728  fputc('\n', conn->Pfdebug);
729 }
static void pqTraceOutputK(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:404
void PQsetTraceFlags(PGconn *conn, int flags)
Definition: fe-trace.c:64
int gettimeofday(struct timeval *tp, struct timezone *tzp)
Definition: gettimeofday.c:104
static void pqTraceOutputC(FILE *f, bool toServer, const char *message, int *cursor)
Definition: fe-trace.c:261
static void pqTraceOutputNR(FILE *f, const char *type, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:306
static int32 next
Definition: blutils.c:219
static void pqTraceOutputG(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:376
static void pqTraceOutputT(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:466
static void pqTraceOutputQ(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:428
static void pqTraceOutputA(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:220
static void pqTraceOutputR(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:436
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
static void pqTraceOutputV(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:496
static void pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition: fe-trace.c:163
static void pqTraceOutputH(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:390
static void pqTraceOutputf(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:341
static void pqTraceOutputW(FILE *f, const char *message, int *cursor, int length)
Definition: fe-trace.c:508
int traceFlags
Definition: libpq-int.h:399
#define fprintf
Definition: port.h:220
FILE * Pfdebug
Definition: libpq-int.h:398
static void pqTraceOutputB(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:230
unsigned short uint16
Definition: c.h:440
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
static void pqTraceOutputF(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:349
static void pqTraceOutputD(FILE *f, bool toServer, const char *message, int *cursor)
Definition: fe-trace.c:278
PGconn * conn
Definition: streamutil.c:54
static void pqTraceOutputt(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:453
Definition: type.h:130
static void pqTraceOutputZ(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:519
static void pqTraceOutputE(FILE *f, bool toServer, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:327
static void pqTraceOutputP(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:413
static void pqTraceOutputByte1(FILE *pfdebug, const char *data, int *cursor)
Definition: fe-trace.c:106
#define PQTRACE_REGRESS_MODE
Definition: libpq-fe.h:414
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
Definition: fe-trace.c:529
void PQtrace(PGconn *conn, FILE *debug_port)
Definition: fe-trace.c:35
static void pqTraceOutputv(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:487
static int pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
Definition: fe-trace.c:125
void pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
Definition: fe-trace.c:694
#define PQTRACE_SUPPRESS_TIMESTAMPS
Definition: libpq-fe.h:412
static int pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition: fe-trace.c:144
static void pqTraceFormatTimestamp(char *timestr, size_t ts_len)
Definition: fe-trace.c:80
int i
static void pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor)
Definition: fe-trace.c:188
#define snprintf
Definition: port.h:216
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1544
void PQuntrace(PGconn *conn)
Definition: fe-trace.c:49
static void pqTraceOutputS(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:444