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 /* 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 
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 PqMsg_ParseComplete:
566  fprintf(conn->Pfdebug, "ParseComplete");
567  /* No message content */
568  break;
569  case PqMsg_BindComplete:
570  fprintf(conn->Pfdebug, "BindComplete");
571  /* No message content */
572  break;
573  case PqMsg_CloseComplete:
574  fprintf(conn->Pfdebug, "CloseComplete");
575  /* No message content */
576  break;
578  pqTraceOutputA(conn->Pfdebug, message, &logCursor, regress);
579  break;
580  case PqMsg_Bind:
581  pqTraceOutputB(conn->Pfdebug, message, &logCursor);
582  break;
583  case PqMsg_CopyDone:
584  fprintf(conn->Pfdebug, "CopyDone");
585  /* No message content */
586  break;
588  /* Close(F) and CommandComplete(B) use the same identifier. */
590  pqTraceOutputC(conn->Pfdebug, toServer, message, &logCursor);
591  break;
592  case PqMsg_CopyData:
593  /* Drop COPY data to reduce the overhead of logging. */
594  break;
595  case PqMsg_Describe:
596  /* Describe(F) and DataRow(B) use the same identifier. */
598  pqTraceOutputD(conn->Pfdebug, toServer, message, &logCursor);
599  break;
600  case PqMsg_Execute:
601  /* Execute(F) and ErrorResponse(B) use the same identifier. */
603  pqTraceOutputE(conn->Pfdebug, toServer, message, &logCursor,
604  regress);
605  break;
606  case PqMsg_CopyFail:
607  pqTraceOutputf(conn->Pfdebug, message, &logCursor);
608  break;
609  case PqMsg_FunctionCall:
610  pqTraceOutputF(conn->Pfdebug, message, &logCursor, regress);
611  break;
613  pqTraceOutputG(conn->Pfdebug, message, &logCursor);
614  break;
615  case PqMsg_Flush:
616  /* Flush(F) and CopyOutResponse(B) use the same identifier */
618  if (!toServer)
619  pqTraceOutputH(conn->Pfdebug, message, &logCursor);
620  else
621  fprintf(conn->Pfdebug, "Flush"); /* no message content */
622  break;
624  fprintf(conn->Pfdebug, "EmptyQueryResponse");
625  /* No message content */
626  break;
628  pqTraceOutputK(conn->Pfdebug, message, &logCursor, regress);
629  break;
630  case PqMsg_NoData:
631  fprintf(conn->Pfdebug, "NoData");
632  /* No message content */
633  break;
635  pqTraceOutputNR(conn->Pfdebug, "NoticeResponse", message,
636  &logCursor, regress);
637  break;
638  case PqMsg_Parse:
639  pqTraceOutputP(conn->Pfdebug, message, &logCursor, regress);
640  break;
641  case PqMsg_Query:
642  pqTraceOutputQ(conn->Pfdebug, message, &logCursor);
643  break;
645  pqTraceOutputR(conn->Pfdebug, message, &logCursor);
646  break;
648  fprintf(conn->Pfdebug, "PortalSuspended");
649  /* No message content */
650  break;
651  case PqMsg_Sync:
652  /* Parameter Status(B) and Sync(F) use the same identifier */
654  if (!toServer)
655  pqTraceOutputS(conn->Pfdebug, message, &logCursor);
656  else
657  fprintf(conn->Pfdebug, "Sync"); /* no message content */
658  break;
660  pqTraceOutputt(conn->Pfdebug, message, &logCursor, regress);
661  break;
663  pqTraceOutputT(conn->Pfdebug, message, &logCursor, regress);
664  break;
666  pqTraceOutputv(conn->Pfdebug, message, &logCursor);
667  break;
669  pqTraceOutputV(conn->Pfdebug, message, &logCursor);
670  break;
672  pqTraceOutputW(conn->Pfdebug, message, &logCursor, length);
673  break;
674  case PqMsg_Terminate:
675  fprintf(conn->Pfdebug, "Terminate");
676  /* No message content */
677  break;
678  case PqMsg_ReadyForQuery:
679  pqTraceOutputZ(conn->Pfdebug, message, &logCursor);
680  break;
681  default:
682  fprintf(conn->Pfdebug, "Unknown message: %02x", id);
683  break;
684  }
685 
686  fputc('\n', conn->Pfdebug);
687 
688  /*
689  * Verify the printing routine did it right. Note that the one-byte
690  * message identifier is not included in the length, but our cursor does
691  * include it.
692  */
693  if (logCursor - 1 != length)
695  "mismatched message length: consumed %d, expected %d\n",
696  logCursor - 1, length);
697 }
698 
699 /*
700  * Print special messages (those containing no type byte) to the trace output
701  * stream.
702  */
703 void
705 {
706  int length;
707  int logCursor = 0;
708 
710  {
711  char timestr[128];
712 
713  pqTraceFormatTimestamp(timestr, sizeof(timestr));
714  fprintf(conn->Pfdebug, "%s\t", timestr);
715  }
716 
717  memcpy(&length, message + logCursor, 4);
718  length = (int) pg_ntoh32(length);
719  logCursor += 4;
720 
721  fprintf(conn->Pfdebug, "F\t%d\t", length);
722 
723  switch (length)
724  {
725  case 16: /* CancelRequest */
726  fprintf(conn->Pfdebug, "CancelRequest\t");
727  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
728  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
729  pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
730  break;
731  case 8: /* GSSENCRequest or SSLRequest */
732  /* These messages do not reach here. */
733  default:
734  fprintf(conn->Pfdebug, "Unknown message: length is %d", length);
735  break;
736  }
737 
738  fputc('\n', conn->Pfdebug);
739 }
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1618
static int32 next
Definition: blutils.c:221
unsigned short uint16
Definition: c.h:492
static void pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress)
Definition: fe-trace.c:163
static void pqTraceOutputQ(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:428
static void pqTraceOutputS(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:444
static void pqTraceOutputH(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:390
static void pqTraceOutputZ(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:519
static void pqTraceOutputW(FILE *f, const char *message, int *cursor, int length)
Definition: fe-trace.c:508
static void pqTraceOutputE(FILE *f, bool toServer, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:327
static void pqTraceOutputV(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:496
static void pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor)
Definition: fe-trace.c:188
static void pqTraceOutputK(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:404
static void pqTraceOutputF(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:349
static void pqTraceOutputP(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:413
static void pqTraceOutputT(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:466
static void pqTraceOutputA(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:220
void PQtrace(PGconn *conn, FILE *debug_port)
Definition: fe-trace.c:35
static void pqTraceOutputD(FILE *f, bool toServer, const char *message, int *cursor)
Definition: fe-trace.c:278
static void pqTraceOutputG(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:376
static int pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
Definition: fe-trace.c:125
static void pqTraceOutputf(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:341
static void pqTraceOutputNR(FILE *f, const char *type, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:306
static void pqTraceOutputR(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:436
static void pqTraceOutputByte1(FILE *pfdebug, const char *data, int *cursor)
Definition: fe-trace.c:106
static void pqTraceOutputt(FILE *f, const char *message, int *cursor, bool regress)
Definition: fe-trace.c:453
void pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
Definition: fe-trace.c:529
void PQsetTraceFlags(PGconn *conn, int flags)
Definition: fe-trace.c:64
static void pqTraceOutputB(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:230
void PQuntrace(PGconn *conn)
Definition: fe-trace.c:49
static void pqTraceOutputv(FILE *f, const char *message, int *cursor)
Definition: fe-trace.c:487
static void pqTraceOutputC(FILE *f, bool toServer, const char *message, int *cursor)
Definition: fe-trace.c:261
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:704
static void pqTraceFormatTimestamp(char *timestr, size_t ts_len)
Definition: fe-trace.c:80
int i
Definition: isn.c:73
#define PQTRACE_SUPPRESS_TIMESTAMPS
Definition: libpq-fe.h:441
#define PQTRACE_REGRESS_MODE
Definition: libpq-fe.h:443
static void const char fflush(stdout)
Assert(fmt[strlen(fmt) - 1] !='\n')
#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:417
int traceFlags
Definition: libpq-int.h:418
const char * type
int gettimeofday(struct timeval *tp, void *tzp)