Age Owner Branch data TLA Line data Source code
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
1111 alvherre@alvh.no-ip. 35 :CBC 9 : PQtrace(PGconn *conn, FILE *debug_port)
36 : : {
37 [ - + ]: 9 : if (conn == NULL)
1111 alvherre@alvh.no-ip. 38 :UBC 0 : return;
1111 alvherre@alvh.no-ip. 39 :CBC 9 : PQuntrace(conn);
40 [ - + ]: 9 : if (debug_port == NULL)
1111 alvherre@alvh.no-ip. 41 :UBC 0 : return;
42 : :
1111 alvherre@alvh.no-ip. 43 :CBC 9 : conn->Pfdebug = debug_port;
44 : 9 : conn->traceFlags = 0;
45 : : }
46 : :
47 : : /* Disable tracing */
48 : : void
49 : 9 : PQuntrace(PGconn *conn)
50 : : {
51 [ - + ]: 9 : if (conn == NULL)
1111 alvherre@alvh.no-ip. 52 :UBC 0 : return;
1111 alvherre@alvh.no-ip. 53 [ - + ]:CBC 9 : if (conn->Pfdebug)
54 : : {
1111 alvherre@alvh.no-ip. 55 :UBC 0 : fflush(conn->Pfdebug);
56 : 0 : conn->Pfdebug = NULL;
57 : : }
58 : :
1111 alvherre@alvh.no-ip. 59 :CBC 9 : conn->traceFlags = 0;
60 : : }
61 : :
62 : : /* Set flags for current tracing session */
63 : : void
1039 noah@leadboat.com 64 : 9 : PQsetTraceFlags(PGconn *conn, int flags)
65 : : {
1111 alvherre@alvh.no-ip. 66 [ - + ]: 9 : if (conn == NULL)
1111 alvherre@alvh.no-ip. 67 :UBC 0 : return;
68 : : /* If PQtrace() failed, do nothing. */
1111 alvherre@alvh.no-ip. 69 [ - + ]:CBC 9 : if (conn->Pfdebug == NULL)
1111 alvherre@alvh.no-ip. 70 :UBC 0 : return;
1111 alvherre@alvh.no-ip. 71 :CBC 9 : 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
1111 alvherre@alvh.no-ip. 80 :UBC 0 : pqTraceFormatTimestamp(char *timestr, size_t ts_len)
81 : : {
82 : : struct timeval tval;
83 : : time_t now;
84 : :
85 : 0 : 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 : : */
1104 drowley@postgresql.o 93 : 0 : now = tval.tv_sec;
1111 alvherre@alvh.no-ip. 94 : 0 : strftime(timestr, ts_len,
95 : : "%Y-%m-%d %H:%M:%S",
1104 drowley@postgresql.o 96 : 0 : localtime(&now));
97 : : /* append microseconds */
1110 tgl@sss.pgh.pa.us 98 : 0 : snprintf(timestr + strlen(timestr), ts_len - strlen(timestr),
99 : 0 : ".%06u", (unsigned int) (tval.tv_usec));
1111 alvherre@alvh.no-ip. 100 : 0 : }
101 : :
102 : : /*
103 : : * pqTraceOutputByte1: output a 1-char message to the log
104 : : */
105 : : static void
1111 alvherre@alvh.no-ip. 106 :CBC 155 : pqTraceOutputByte1(FILE *pfdebug, const char *data, int *cursor)
107 : : {
108 : 155 : 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 : : */
1110 tgl@sss.pgh.pa.us 114 [ + + ]: 155 : if (!isprint((unsigned char) *v))
1111 alvherre@alvh.no-ip. 115 : 10 : fprintf(pfdebug, " \\x%02x", *v);
116 : : else
117 : 145 : fprintf(pfdebug, " %c", *v);
118 : 155 : *cursor += 1;
119 : 155 : }
120 : :
121 : : /*
122 : : * pqTraceOutputInt16: output a 2-byte integer message to the log
123 : : */
124 : : static int
125 : 348 : pqTraceOutputInt16(FILE *pfdebug, const char *data, int *cursor)
126 : : {
127 : : uint16 tmp;
128 : : int result;
129 : :
130 : 348 : memcpy(&tmp, data + *cursor, 2);
131 : 348 : *cursor += 2;
132 : 348 : result = (int) pg_ntoh16(tmp);
133 : 348 : fprintf(pfdebug, " %d", result);
134 : :
135 : 348 : 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 : 195 : pqTraceOutputInt32(FILE *pfdebug, const char *data, int *cursor, bool suppress)
145 : : {
146 : : int result;
147 : :
148 : 195 : memcpy(&result, data + *cursor, 4);
149 : 195 : *cursor += 4;
150 : 195 : result = (int) pg_ntoh32(result);
151 [ + + ]: 195 : if (suppress)
152 : 74 : fprintf(pfdebug, " NNNN");
153 : : else
154 : 121 : fprintf(pfdebug, " %d", result);
155 : :
156 : 195 : return result;
157 : : }
158 : :
159 : : /*
160 : : * pqTraceOutputString: output a string message to the log
161 : : */
162 : : static void
163 : 373 : pqTraceOutputString(FILE *pfdebug, const char *data, int *cursor, bool suppress)
164 : : {
165 : : int len;
166 : :
167 [ + + ]: 373 : if (suppress)
168 : : {
169 : 30 : fprintf(pfdebug, " \"SSSS\"");
170 : 30 : *cursor += strlen(data + *cursor) + 1;
171 : : }
172 : : else
173 : : {
174 : 343 : 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 : 343 : *cursor += (len - 3 + 1);
181 : : }
182 : 373 : }
183 : :
184 : : /*
185 : : * pqTraceOutputNchar: output a string of exactly len bytes message to the log
186 : : */
187 : : static void
188 : 53 : pqTraceOutputNchar(FILE *pfdebug, int len, const char *data, int *cursor)
189 : : {
190 : : int i,
191 : : next; /* first char not yet printed */
192 : 53 : const char *v = data + *cursor;
193 : :
194 : 53 : fprintf(pfdebug, " \'");
195 : :
196 [ + + ]: 774 : for (next = i = 0; i < len; ++i)
197 : : {
1110 tgl@sss.pgh.pa.us 198 [ + - ]: 721 : if (isprint((unsigned char) v[i]))
1111 alvherre@alvh.no-ip. 199 : 721 : continue;
200 : : else
201 : : {
1111 alvherre@alvh.no-ip. 202 :UBC 0 : fwrite(v + next, 1, i - next, pfdebug);
203 : 0 : fprintf(pfdebug, "\\x%02x", v[i]);
204 : 0 : next = i + 1;
205 : : }
206 : : }
1111 alvherre@alvh.no-ip. 207 [ + - ]:CBC 53 : if (next < len)
208 : 53 : fwrite(v + next, 1, len - next, pfdebug);
209 : :
210 : 53 : fprintf(pfdebug, "\'");
211 : 53 : *cursor += len;
212 : 53 : }
213 : :
214 : : /*
215 : : * Output functions by protocol message type
216 : : */
217 : :
218 : : /* NotificationResponse */
219 : : static void
1111 alvherre@alvh.no-ip. 220 :UBC 0 : pqTraceOutputA(FILE *f, const char *message, int *cursor, bool regress)
221 : : {
222 : 0 : fprintf(f, "NotificationResponse\t");
223 : 0 : pqTraceOutputInt32(f, message, cursor, regress);
224 : 0 : pqTraceOutputString(f, message, cursor, false);
225 : 0 : pqTraceOutputString(f, message, cursor, false);
226 : 0 : }
227 : :
228 : : /* Bind */
229 : : static void
1111 alvherre@alvh.no-ip. 230 :CBC 36 : pqTraceOutputB(FILE *f, const char *message, int *cursor)
231 : : {
232 : : int nparams;
233 : :
234 : 36 : fprintf(f, "Bind\t");
235 : 36 : pqTraceOutputString(f, message, cursor, false);
236 : 36 : pqTraceOutputString(f, message, cursor, false);
237 : 36 : nparams = pqTraceOutputInt16(f, message, cursor);
238 : :
239 [ - + ]: 36 : for (int i = 0; i < nparams; i++)
1111 alvherre@alvh.no-ip. 240 :UBC 0 : pqTraceOutputInt16(f, message, cursor);
241 : :
1111 alvherre@alvh.no-ip. 242 :CBC 36 : nparams = pqTraceOutputInt16(f, message, cursor);
243 : :
244 [ + + ]: 47 : for (int i = 0; i < nparams; i++)
245 : : {
246 : : int nbytes;
247 : :
248 : 11 : nbytes = pqTraceOutputInt32(f, message, cursor, false);
249 [ - + ]: 11 : if (nbytes == -1)
1111 alvherre@alvh.no-ip. 250 :UBC 0 : continue;
1111 alvherre@alvh.no-ip. 251 :CBC 11 : pqTraceOutputNchar(f, nbytes, message, cursor);
252 : : }
253 : :
254 : 36 : nparams = pqTraceOutputInt16(f, message, cursor);
255 [ + + ]: 72 : for (int i = 0; i < nparams; i++)
256 : 36 : pqTraceOutputInt16(f, message, cursor);
257 : 36 : }
258 : :
259 : : /* Close(F) or CommandComplete(B) */
260 : : static void
261 : 41 : pqTraceOutputC(FILE *f, bool toServer, const char *message, int *cursor)
262 : : {
263 [ + + ]: 41 : if (toServer)
264 : : {
1111 alvherre@alvh.no-ip. 265 :GBC 4 : fprintf(f, "Close\t");
266 : 4 : pqTraceOutputByte1(f, message, cursor);
267 : 4 : pqTraceOutputString(f, message, cursor, false);
268 : : }
269 : : else
270 : : {
1111 alvherre@alvh.no-ip. 271 :CBC 37 : fprintf(f, "CommandComplete\t");
272 : 37 : pqTraceOutputString(f, message, cursor, false);
273 : : }
274 : 41 : }
275 : :
276 : : /* Describe(F) or DataRow(B) */
277 : : static void
278 : 82 : pqTraceOutputD(FILE *f, bool toServer, const char *message, int *cursor)
279 : : {
280 [ + + ]: 82 : if (toServer)
281 : : {
282 : 40 : fprintf(f, "Describe\t");
283 : 40 : pqTraceOutputByte1(f, message, cursor);
284 : 40 : pqTraceOutputString(f, message, cursor, false);
285 : : }
286 : : else
287 : : {
288 : : int nfields;
289 : : int len;
290 : : int i;
291 : :
292 : 42 : fprintf(f, "DataRow\t");
293 : 42 : nfields = pqTraceOutputInt16(f, message, cursor);
294 [ + + ]: 84 : for (i = 0; i < nfields; i++)
295 : : {
296 : 42 : len = pqTraceOutputInt32(f, message, cursor, false);
297 [ - + ]: 42 : if (len == -1)
1111 alvherre@alvh.no-ip. 298 :UBC 0 : continue;
1111 alvherre@alvh.no-ip. 299 :CBC 42 : pqTraceOutputNchar(f, len, message, cursor);
300 : : }
301 : : }
302 : 82 : }
303 : :
304 : : /* NoticeResponse / ErrorResponse */
305 : : static void
306 : 10 : pqTraceOutputNR(FILE *f, const char *type, const char *message, int *cursor,
307 : : bool regress)
308 : : {
309 : 10 : fprintf(f, "%s\t", type);
310 : : for (;;)
311 : 72 : {
312 : : char field;
313 : : bool suppress;
314 : :
315 : 82 : pqTraceOutputByte1(f, message, cursor);
316 : 82 : field = message[*cursor - 1];
317 [ + + ]: 82 : if (field == '\0')
318 : 10 : break;
319 : :
320 [ + - + + : 72 : suppress = regress && (field == 'L' || field == 'F' || field == 'R');
+ + + + ]
321 : 72 : pqTraceOutputString(f, message, cursor, suppress);
322 : : }
323 : 10 : }
324 : :
325 : : /* Execute(F) or ErrorResponse(B) */
326 : : static void
1070 peter@eisentraut.org 327 : 43 : pqTraceOutputE(FILE *f, bool toServer, const char *message, int *cursor, bool regress)
328 : : {
1111 alvherre@alvh.no-ip. 329 [ + + ]: 43 : if (toServer)
330 : : {
331 : 36 : fprintf(f, "Execute\t");
332 : 36 : pqTraceOutputString(f, message, cursor, false);
333 : 36 : pqTraceOutputInt32(f, message, cursor, false);
334 : : }
335 : : else
1070 peter@eisentraut.org 336 : 7 : pqTraceOutputNR(f, "ErrorResponse", message, cursor, regress);
1111 alvherre@alvh.no-ip. 337 : 43 : }
338 : :
339 : : /* CopyFail */
340 : : static void
1111 alvherre@alvh.no-ip. 341 :UBC 0 : pqTraceOutputf(FILE *f, const char *message, int *cursor)
342 : : {
343 : 0 : fprintf(f, "CopyFail\t");
344 : 0 : pqTraceOutputString(f, message, cursor, false);
345 : 0 : }
346 : :
347 : : /* FunctionCall */
348 : : static void
349 : 0 : pqTraceOutputF(FILE *f, const char *message, int *cursor, bool regress)
350 : : {
351 : : int nfields;
352 : : int nbytes;
353 : :
354 : 0 : fprintf(f, "FunctionCall\t");
355 : 0 : pqTraceOutputInt32(f, message, cursor, regress);
356 : 0 : nfields = pqTraceOutputInt16(f, message, cursor);
357 : :
358 [ # # ]: 0 : for (int i = 0; i < nfields; i++)
359 : 0 : pqTraceOutputInt16(f, message, cursor);
360 : :
361 : 0 : nfields = pqTraceOutputInt16(f, message, cursor);
362 : :
363 [ # # ]: 0 : for (int i = 0; i < nfields; i++)
364 : : {
365 : 0 : nbytes = pqTraceOutputInt32(f, message, cursor, false);
366 [ # # ]: 0 : if (nbytes == -1)
367 : 0 : continue;
368 : 0 : pqTraceOutputNchar(f, nbytes, message, cursor);
369 : : }
370 : :
371 : 0 : pqTraceOutputInt16(f, message, cursor);
372 : 0 : }
373 : :
374 : : /* CopyInResponse */
375 : : static void
376 : 0 : pqTraceOutputG(FILE *f, const char *message, int *cursor)
377 : : {
378 : : int nfields;
379 : :
380 : 0 : fprintf(f, "CopyInResponse\t");
381 : 0 : pqTraceOutputByte1(f, message, cursor);
382 : 0 : nfields = pqTraceOutputInt16(f, message, cursor);
383 : :
384 [ # # ]: 0 : for (int i = 0; i < nfields; i++)
385 : 0 : pqTraceOutputInt16(f, message, cursor);
386 : 0 : }
387 : :
388 : : /* CopyOutResponse */
389 : : static void
390 : 0 : pqTraceOutputH(FILE *f, const char *message, int *cursor)
391 : : {
392 : : int nfields;
393 : :
394 : 0 : fprintf(f, "CopyOutResponse\t");
395 : 0 : pqTraceOutputByte1(f, message, cursor);
396 : 0 : nfields = pqTraceOutputInt16(f, message, cursor);
397 : :
398 [ # # ]: 0 : for (int i = 0; i < nfields; i++)
399 : 0 : pqTraceOutputInt16(f, message, cursor);
400 : 0 : }
401 : :
402 : : /* BackendKeyData */
403 : : static void
404 : 0 : pqTraceOutputK(FILE *f, const char *message, int *cursor, bool regress)
405 : : {
406 : 0 : fprintf(f, "BackendKeyData\t");
407 : 0 : pqTraceOutputInt32(f, message, cursor, regress);
408 : 0 : pqTraceOutputInt32(f, message, cursor, regress);
409 : 0 : }
410 : :
411 : : /* Parse */
412 : : static void
1111 alvherre@alvh.no-ip. 413 :CBC 36 : pqTraceOutputP(FILE *f, const char *message, int *cursor, bool regress)
414 : : {
415 : : int nparams;
416 : :
417 : 36 : fprintf(f, "Parse\t");
418 : 36 : pqTraceOutputString(f, message, cursor, false);
419 : 36 : pqTraceOutputString(f, message, cursor, false);
420 : 36 : nparams = pqTraceOutputInt16(f, message, cursor);
421 : :
422 [ + + ]: 45 : for (int i = 0; i < nparams; i++)
423 : 9 : pqTraceOutputInt32(f, message, cursor, regress);
424 : 36 : }
425 : :
426 : : /* Query */
427 : : static void
428 : 8 : pqTraceOutputQ(FILE *f, const char *message, int *cursor)
429 : : {
430 : 8 : fprintf(f, "Query\t");
431 : 8 : pqTraceOutputString(f, message, cursor, false);
432 : 8 : }
433 : :
434 : : /* Authentication */
435 : : static void
1111 alvherre@alvh.no-ip. 436 :UBC 0 : pqTraceOutputR(FILE *f, const char *message, int *cursor)
437 : : {
438 : 0 : fprintf(f, "Authentication\t");
439 : 0 : pqTraceOutputInt32(f, message, cursor, false);
440 : 0 : }
441 : :
442 : : /* ParameterStatus */
443 : : static void
444 : 0 : pqTraceOutputS(FILE *f, const char *message, int *cursor)
445 : : {
446 : 0 : fprintf(f, "ParameterStatus\t");
447 : 0 : pqTraceOutputString(f, message, cursor, false);
448 : 0 : pqTraceOutputString(f, message, cursor, false);
449 : 0 : }
450 : :
451 : : /* ParameterDescription */
452 : : static void
1111 alvherre@alvh.no-ip. 453 :CBC 1 : pqTraceOutputt(FILE *f, const char *message, int *cursor, bool regress)
454 : : {
455 : : int nfields;
456 : :
457 : 1 : fprintf(f, "ParameterDescription\t");
458 : 1 : nfields = pqTraceOutputInt16(f, message, cursor);
459 : :
460 [ + + ]: 2 : for (int i = 0; i < nfields; i++)
461 : 1 : pqTraceOutputInt32(f, message, cursor, regress);
462 : 1 : }
463 : :
464 : : /* RowDescription */
465 : : static void
466 : 29 : pqTraceOutputT(FILE *f, const char *message, int *cursor, bool regress)
467 : : {
468 : : int nfields;
469 : :
470 : 29 : fprintf(f, "RowDescription\t");
471 : 29 : nfields = pqTraceOutputInt16(f, message, cursor);
472 : :
473 [ + + ]: 61 : for (int i = 0; i < nfields; i++)
474 : : {
475 : 32 : pqTraceOutputString(f, message, cursor, false);
476 : 32 : pqTraceOutputInt32(f, message, cursor, regress);
477 : 32 : pqTraceOutputInt16(f, message, cursor);
478 : 32 : pqTraceOutputInt32(f, message, cursor, regress);
479 : 32 : pqTraceOutputInt16(f, message, cursor);
480 : 32 : pqTraceOutputInt32(f, message, cursor, false);
481 : 32 : pqTraceOutputInt16(f, message, cursor);
482 : : }
483 : 29 : }
484 : :
485 : : /* NegotiateProtocolVersion */
486 : : static void
1111 alvherre@alvh.no-ip. 487 :UBC 0 : pqTraceOutputv(FILE *f, const char *message, int *cursor)
488 : : {
489 : 0 : fprintf(f, "NegotiateProtocolVersion\t");
490 : 0 : pqTraceOutputInt32(f, message, cursor, false);
491 : 0 : pqTraceOutputInt32(f, message, cursor, false);
492 : 0 : }
493 : :
494 : : /* FunctionCallResponse */
495 : : static void
496 : 0 : pqTraceOutputV(FILE *f, const char *message, int *cursor)
497 : : {
498 : : int len;
499 : :
500 : 0 : fprintf(f, "FunctionCallResponse\t");
501 : 0 : len = pqTraceOutputInt32(f, message, cursor, false);
502 [ # # ]: 0 : if (len != -1)
503 : 0 : pqTraceOutputNchar(f, len, message, cursor);
504 : 0 : }
505 : :
506 : : /* CopyBothResponse */
507 : : static void
508 : 0 : pqTraceOutputW(FILE *f, const char *message, int *cursor, int length)
509 : : {
510 : 0 : fprintf(f, "CopyBothResponse\t");
511 : 0 : pqTraceOutputByte1(f, message, cursor);
512 : :
513 [ # # ]: 0 : while (length > *cursor)
514 : 0 : pqTraceOutputInt16(f, message, cursor);
515 : 0 : }
516 : :
517 : : /* ReadyForQuery */
518 : : static void
1111 alvherre@alvh.no-ip. 519 :CBC 29 : pqTraceOutputZ(FILE *f, const char *message, int *cursor)
520 : : {
521 : 29 : fprintf(f, "ReadyForQuery\t");
522 : 29 : pqTraceOutputByte1(f, message, cursor);
523 : 29 : }
524 : :
525 : : /*
526 : : * Print the given message to the trace output stream.
527 : : */
528 : : void
529 : 414 : pqTraceOutputMessage(PGconn *conn, const char *message, bool toServer)
530 : : {
531 : : char id;
532 : : int length;
533 [ + + ]: 414 : char *prefix = toServer ? "F" : "B";
534 : 414 : int logCursor = 0;
535 : : bool regress;
536 : :
537 [ - + ]: 414 : if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0)
538 : : {
539 : : char timestr[128];
540 : :
1111 alvherre@alvh.no-ip. 541 :UBC 0 : pqTraceFormatTimestamp(timestr, sizeof(timestr));
542 : 0 : fprintf(conn->Pfdebug, "%s\t", timestr);
543 : : }
1111 alvherre@alvh.no-ip. 544 :CBC 414 : regress = (conn->traceFlags & PQTRACE_REGRESS_MODE) != 0;
545 : :
546 : 414 : id = message[logCursor++];
547 : :
548 : 414 : memcpy(&length, message + logCursor, 4);
549 : 414 : length = (int) pg_ntoh32(length);
550 : 414 : 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 : : */
1101 558 [ + - + + : 414 : if (regress && !toServer && (id == 'E' || id == 'N'))
+ + + + ]
559 : 10 : fprintf(conn->Pfdebug, "%s\tNN\t", prefix);
560 : : else
561 : 404 : fprintf(conn->Pfdebug, "%s\t%d\t", prefix, length);
562 : :
1111 563 [ + + + - : 414 : switch (id)
+ - + - +
+ - - - +
- - + + +
+ - - + +
+ - - - +
+ - ]
564 : : {
236 nathan@postgresql.or 565 :GNC 31 : case PqMsg_ParseComplete:
1111 alvherre@alvh.no-ip. 566 :CBC 31 : fprintf(conn->Pfdebug, "ParseComplete");
567 : : /* No message content */
568 : 31 : break;
236 nathan@postgresql.or 569 :GNC 29 : case PqMsg_BindComplete:
1111 alvherre@alvh.no-ip. 570 :CBC 29 : fprintf(conn->Pfdebug, "BindComplete");
571 : : /* No message content */
572 : 29 : break;
236 nathan@postgresql.or 573 :GNC 4 : case PqMsg_CloseComplete:
1111 alvherre@alvh.no-ip. 574 :GBC 4 : fprintf(conn->Pfdebug, "CloseComplete");
575 : : /* No message content */
576 : 4 : break;
236 nathan@postgresql.or 577 :UNC 0 : case PqMsg_NotificationResponse:
1111 alvherre@alvh.no-ip. 578 :UBC 0 : pqTraceOutputA(conn->Pfdebug, message, &logCursor, regress);
579 : 0 : break;
236 nathan@postgresql.or 580 :GNC 36 : case PqMsg_Bind:
1111 alvherre@alvh.no-ip. 581 :CBC 36 : pqTraceOutputB(conn->Pfdebug, message, &logCursor);
582 : 36 : break;
236 nathan@postgresql.or 583 :UNC 0 : case PqMsg_CopyDone:
1111 alvherre@alvh.no-ip. 584 :UBC 0 : fprintf(conn->Pfdebug, "CopyDone");
585 : : /* No message content */
586 : 0 : break;
236 nathan@postgresql.or 587 :GNC 41 : case PqMsg_CommandComplete:
588 : : /* Close(F) and CommandComplete(B) use the same identifier. */
589 : : Assert(PqMsg_Close == PqMsg_CommandComplete);
1111 alvherre@alvh.no-ip. 590 :CBC 41 : pqTraceOutputC(conn->Pfdebug, toServer, message, &logCursor);
591 : 41 : break;
236 nathan@postgresql.or 592 :UNC 0 : case PqMsg_CopyData:
593 : : /* Drop COPY data to reduce the overhead of logging. */
1111 alvherre@alvh.no-ip. 594 :UBC 0 : break;
236 nathan@postgresql.or 595 :GNC 82 : case PqMsg_Describe:
596 : : /* Describe(F) and DataRow(B) use the same identifier. */
597 : : Assert(PqMsg_Describe == PqMsg_DataRow);
1111 alvherre@alvh.no-ip. 598 :CBC 82 : pqTraceOutputD(conn->Pfdebug, toServer, message, &logCursor);
599 : 82 : break;
236 nathan@postgresql.or 600 :GNC 43 : case PqMsg_Execute:
601 : : /* Execute(F) and ErrorResponse(B) use the same identifier. */
602 : : Assert(PqMsg_Execute == PqMsg_ErrorResponse);
1111 alvherre@alvh.no-ip. 603 :CBC 43 : pqTraceOutputE(conn->Pfdebug, toServer, message, &logCursor,
604 : : regress);
605 : 43 : break;
236 nathan@postgresql.or 606 :UNC 0 : case PqMsg_CopyFail:
1111 alvherre@alvh.no-ip. 607 :UBC 0 : pqTraceOutputf(conn->Pfdebug, message, &logCursor);
608 : 0 : break;
236 nathan@postgresql.or 609 :UNC 0 : case PqMsg_FunctionCall:
1111 alvherre@alvh.no-ip. 610 :UBC 0 : pqTraceOutputF(conn->Pfdebug, message, &logCursor, regress);
611 : 0 : break;
236 nathan@postgresql.or 612 :UNC 0 : case PqMsg_CopyInResponse:
1111 alvherre@alvh.no-ip. 613 :UBC 0 : pqTraceOutputG(conn->Pfdebug, message, &logCursor);
614 : 0 : break;
236 nathan@postgresql.or 615 :GNC 7 : case PqMsg_Flush:
616 : : /* Flush(F) and CopyOutResponse(B) use the same identifier */
617 : : Assert(PqMsg_CopyOutResponse == PqMsg_Flush);
1111 alvherre@alvh.no-ip. 618 [ - + ]:CBC 7 : if (!toServer)
1111 alvherre@alvh.no-ip. 619 :UBC 0 : pqTraceOutputH(conn->Pfdebug, message, &logCursor);
620 : : else
1111 alvherre@alvh.no-ip. 621 :CBC 7 : fprintf(conn->Pfdebug, "Flush"); /* no message content */
622 : 7 : break;
236 nathan@postgresql.or 623 :UNC 0 : case PqMsg_EmptyQueryResponse:
1111 alvherre@alvh.no-ip. 624 :UBC 0 : fprintf(conn->Pfdebug, "EmptyQueryResponse");
625 : : /* No message content */
626 : 0 : break;
236 nathan@postgresql.or 627 :UNC 0 : case PqMsg_BackendKeyData:
1111 alvherre@alvh.no-ip. 628 :UBC 0 : pqTraceOutputK(conn->Pfdebug, message, &logCursor, regress);
629 : 0 : break;
236 nathan@postgresql.or 630 :GNC 5 : case PqMsg_NoData:
1111 alvherre@alvh.no-ip. 631 :CBC 5 : fprintf(conn->Pfdebug, "NoData");
632 : : /* No message content */
633 : 5 : break;
236 nathan@postgresql.or 634 :GNC 3 : case PqMsg_NoticeResponse:
1111 alvherre@alvh.no-ip. 635 :CBC 3 : pqTraceOutputNR(conn->Pfdebug, "NoticeResponse", message,
636 : : &logCursor, regress);
637 : 3 : break;
236 nathan@postgresql.or 638 :GNC 36 : case PqMsg_Parse:
1111 alvherre@alvh.no-ip. 639 :CBC 36 : pqTraceOutputP(conn->Pfdebug, message, &logCursor, regress);
640 : 36 : break;
236 nathan@postgresql.or 641 :GNC 8 : case PqMsg_Query:
1111 alvherre@alvh.no-ip. 642 :CBC 8 : pqTraceOutputQ(conn->Pfdebug, message, &logCursor);
643 : 8 : break;
236 nathan@postgresql.or 644 :UNC 0 : case PqMsg_AuthenticationRequest:
1111 alvherre@alvh.no-ip. 645 :UBC 0 : pqTraceOutputR(conn->Pfdebug, message, &logCursor);
646 : 0 : break;
236 nathan@postgresql.or 647 :UNC 0 : case PqMsg_PortalSuspended:
1111 alvherre@alvh.no-ip. 648 :UBC 0 : fprintf(conn->Pfdebug, "PortalSuspended");
649 : : /* No message content */
650 : 0 : break;
236 nathan@postgresql.or 651 :GNC 21 : case PqMsg_Sync:
652 : : /* Parameter Status(B) and Sync(F) use the same identifier */
653 : : Assert(PqMsg_ParameterStatus == PqMsg_Sync);
1111 alvherre@alvh.no-ip. 654 [ - + ]:CBC 21 : if (!toServer)
1111 alvherre@alvh.no-ip. 655 :UBC 0 : pqTraceOutputS(conn->Pfdebug, message, &logCursor);
656 : : else
1068 tgl@sss.pgh.pa.us 657 :CBC 21 : fprintf(conn->Pfdebug, "Sync"); /* no message content */
1111 alvherre@alvh.no-ip. 658 : 21 : break;
236 nathan@postgresql.or 659 :GNC 1 : case PqMsg_ParameterDescription:
1111 alvherre@alvh.no-ip. 660 :CBC 1 : pqTraceOutputt(conn->Pfdebug, message, &logCursor, regress);
661 : 1 : break;
236 nathan@postgresql.or 662 :GNC 29 : case PqMsg_RowDescription:
1111 alvherre@alvh.no-ip. 663 :CBC 29 : pqTraceOutputT(conn->Pfdebug, message, &logCursor, regress);
664 : 29 : break;
236 nathan@postgresql.or 665 :UNC 0 : case PqMsg_NegotiateProtocolVersion:
1111 alvherre@alvh.no-ip. 666 :UBC 0 : pqTraceOutputv(conn->Pfdebug, message, &logCursor);
667 : 0 : break;
236 nathan@postgresql.or 668 :UNC 0 : case PqMsg_FunctionCallResponse:
1111 alvherre@alvh.no-ip. 669 :UBC 0 : pqTraceOutputV(conn->Pfdebug, message, &logCursor);
670 : 0 : break;
236 nathan@postgresql.or 671 :UNC 0 : case PqMsg_CopyBothResponse:
1111 alvherre@alvh.no-ip. 672 :UBC 0 : pqTraceOutputW(conn->Pfdebug, message, &logCursor, length);
673 : 0 : break;
236 nathan@postgresql.or 674 :GNC 9 : case PqMsg_Terminate:
1111 alvherre@alvh.no-ip. 675 :CBC 9 : fprintf(conn->Pfdebug, "Terminate");
676 : : /* No message content */
677 : 9 : break;
236 nathan@postgresql.or 678 :GNC 29 : case PqMsg_ReadyForQuery:
1111 alvherre@alvh.no-ip. 679 :CBC 29 : pqTraceOutputZ(conn->Pfdebug, message, &logCursor);
680 : 29 : break;
1111 alvherre@alvh.no-ip. 681 :UBC 0 : default:
682 : 0 : fprintf(conn->Pfdebug, "Unknown message: %02x", id);
683 : 0 : break;
684 : : }
685 : :
1111 alvherre@alvh.no-ip. 686 :CBC 414 : 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 [ - + ]: 414 : if (logCursor - 1 != length)
1111 alvherre@alvh.no-ip. 694 :UBC 0 : fprintf(conn->Pfdebug,
695 : : "mismatched message length: consumed %d, expected %d\n",
696 : : logCursor - 1, length);
1111 alvherre@alvh.no-ip. 697 :CBC 414 : }
698 : :
699 : : /*
700 : : * Print special messages (those containing no type byte) to the trace output
701 : : * stream.
702 : : */
703 : : void
1111 alvherre@alvh.no-ip. 704 :UBC 0 : pqTraceOutputNoTypeByteMessage(PGconn *conn, const char *message)
705 : : {
706 : : int length;
707 : 0 : int logCursor = 0;
708 : :
709 [ # # ]: 0 : if ((conn->traceFlags & PQTRACE_SUPPRESS_TIMESTAMPS) == 0)
710 : : {
711 : : char timestr[128];
712 : :
713 : 0 : pqTraceFormatTimestamp(timestr, sizeof(timestr));
714 : 0 : fprintf(conn->Pfdebug, "%s\t", timestr);
715 : : }
716 : :
717 : 0 : memcpy(&length, message + logCursor, 4);
718 : 0 : length = (int) pg_ntoh32(length);
719 : 0 : logCursor += 4;
720 : :
721 : 0 : fprintf(conn->Pfdebug, "F\t%d\t", length);
722 : :
723 [ # # ]: 0 : switch (length)
724 : : {
725 : 0 : case 16: /* CancelRequest */
726 : 0 : fprintf(conn->Pfdebug, "CancelRequest\t");
727 : 0 : pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
728 : 0 : pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
729 : 0 : pqTraceOutputInt32(conn->Pfdebug, message, &logCursor, false);
730 : 0 : break;
731 : 0 : case 8: /* GSSENCRequest or SSLRequest */
732 : : /* These messages do not reach here. */
733 : : default:
734 : 0 : fprintf(conn->Pfdebug, "Unknown message: length is %d", length);
735 : 0 : break;
736 : : }
737 : :
738 : 0 : fputc('\n', conn->Pfdebug);
739 : 0 : }
|