Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * fe-protocol3.c
4 : * functions that are specific to frontend/backend protocol version 3
5 : *
6 : * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/interfaces/libpq/fe-protocol3.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres_fe.h"
16 :
17 : #include <ctype.h>
18 : #include <fcntl.h>
19 :
20 : #include "libpq-fe.h"
21 : #include "libpq-int.h"
22 :
23 : #include "mb/pg_wchar.h"
24 :
25 : #ifdef WIN32
26 : #include "win32.h"
27 : #else
28 : #include <unistd.h>
29 : #include <netinet/in.h>
30 : #ifdef HAVE_NETINET_TCP_H
31 : #include <netinet/tcp.h>
32 : #endif
33 : #include <arpa/inet.h>
34 : #endif
35 :
36 :
37 : /*
38 : * This macro lists the backend message types that could be "long" (more
39 : * than a couple of kilobytes).
40 : */
41 : #define VALID_LONG_MESSAGE_TYPE(id) \
42 : ((id) == 'T' || (id) == 'D' || (id) == 'd' || (id) == 'V' || \
43 : (id) == 'E' || (id) == 'N' || (id) == 'A')
44 :
45 :
46 : static void handleSyncLoss(PGconn *conn, char id, int msgLength);
47 : static int getRowDescriptions(PGconn *conn, int msgLength);
48 : static int getParamDescriptions(PGconn *conn, int msgLength);
49 : static int getAnotherTuple(PGconn *conn, int msgLength);
50 : static int getParameterStatus(PGconn *conn);
51 : static int getNotify(PGconn *conn);
52 : static int getCopyStart(PGconn *conn, ExecStatusType copytype);
53 : static int getReadyForQuery(PGconn *conn);
54 : static void reportErrorPosition(PQExpBuffer msg, const char *query,
55 : int loc, int encoding);
56 : static int build_startup_packet(const PGconn *conn, char *packet,
57 : const PQEnvironmentOption *options);
58 :
59 :
60 : /*
61 : * parseInput: if appropriate, parse input data from backend
62 : * until input is exhausted or a stopping state is reached.
63 : * Note that this function will NOT attempt to read more data from the backend.
64 : */
65 : void
66 244561 : pqParseInput3(PGconn *conn)
67 : {
68 : char id;
69 : int msgLength;
70 : int avail;
71 :
72 : /*
73 : * Loop to parse successive complete messages available in the buffer.
74 : */
75 : for (;;)
76 : {
77 : /*
78 : * Try to read a message. First get the type code and length. Return
79 : * if not enough data.
80 : */
81 244561 : conn->inCursor = conn->inStart;
82 244561 : if (pqGetc(&id, conn))
83 112714 : return;
84 131847 : if (pqGetInt(&msgLength, 4, conn))
85 1 : return;
86 :
87 : /*
88 : * Try to validate message type/length here. A length less than 4 is
89 : * definitely broken. Large lengths should only be believed for a few
90 : * message types.
91 : */
92 131846 : if (msgLength < 4)
93 : {
94 0 : handleSyncLoss(conn, id, msgLength);
95 0 : return;
96 : }
97 131846 : if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
98 : {
99 0 : handleSyncLoss(conn, id, msgLength);
100 0 : return;
101 : }
102 :
103 : /*
104 : * Can't process if message body isn't all here yet.
105 : */
106 131846 : msgLength -= 4;
107 131846 : avail = conn->inEnd - conn->inCursor;
108 131846 : if (avail < msgLength)
109 : {
110 : /*
111 : * Before returning, enlarge the input buffer if needed to hold
112 : * the whole message. This is better than leaving it to
113 : * pqReadData because we can avoid multiple cycles of realloc()
114 : * when the message is large; also, we can implement a reasonable
115 : * recovery strategy if we are unable to make the buffer big
116 : * enough.
117 : */
118 39 : if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
119 : conn))
120 : {
121 : /*
122 : * XXX add some better recovery code... plan is to skip over
123 : * the message using its length, then report an error. For the
124 : * moment, just treat this like loss of sync (which indeed it
125 : * might be!)
126 : */
127 0 : handleSyncLoss(conn, id, msgLength);
128 : }
129 39 : return;
130 : }
131 :
132 : /*
133 : * NOTIFY and NOTICE messages can happen in any state; always process
134 : * them right away.
135 : *
136 : * Most other messages should only be processed while in BUSY state.
137 : * (In particular, in READY state we hold off further parsing until
138 : * the application collects the current PGresult.)
139 : *
140 : * However, if the state is IDLE then we got trouble; we need to deal
141 : * with the unexpected message somehow.
142 : *
143 : * ParameterStatus ('S') messages are a special case: in IDLE state we
144 : * must process 'em (this case could happen if a new value was adopted
145 : * from config file due to SIGHUP), but otherwise we hold off until
146 : * BUSY state.
147 : */
148 131807 : if (id == 'A')
149 : {
150 0 : if (getNotify(conn))
151 0 : return;
152 : }
153 131807 : else if (id == 'N')
154 : {
155 1739 : if (pqGetErrorNotice3(conn, false))
156 0 : return;
157 : }
158 130068 : else if (conn->asyncStatus != PGASYNC_BUSY)
159 : {
160 : /* If not IDLE state, just wait ... */
161 23493 : if (conn->asyncStatus != PGASYNC_IDLE)
162 23493 : return;
163 :
164 : /*
165 : * Unexpected message in IDLE state; need to recover somehow.
166 : * ERROR messages are handled using the notice processor;
167 : * ParameterStatus is handled normally; anything else is just
168 : * dropped on the floor after displaying a suitable warning
169 : * notice. (An ERROR is very possibly the backend telling us why
170 : * it is about to close the connection, so we don't want to just
171 : * discard it...)
172 : */
173 0 : if (id == 'E')
174 : {
175 0 : if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
176 0 : return;
177 : }
178 0 : else if (id == 'S')
179 : {
180 0 : if (getParameterStatus(conn))
181 0 : return;
182 : }
183 : else
184 : {
185 0 : pqInternalNotice(&conn->noticeHooks,
186 : "message type 0x%02x arrived from server while idle",
187 : id);
188 : /* Discard the unexpected message */
189 0 : conn->inCursor += msgLength;
190 : }
191 : }
192 : else
193 : {
194 : /*
195 : * In BUSY state, we can process everything.
196 : */
197 106575 : switch (id)
198 : {
199 : case 'C': /* command complete */
200 23304 : if (pqGets(&conn->workBuffer, conn))
201 0 : return;
202 23304 : if (conn->result == NULL)
203 : {
204 12090 : conn->result = PQmakeEmptyPGresult(conn,
205 : PGRES_COMMAND_OK);
206 12090 : if (!conn->result)
207 : {
208 0 : printfPQExpBuffer(&conn->errorMessage,
209 : libpq_gettext("out of memory"));
210 0 : pqSaveErrorResult(conn);
211 : }
212 : }
213 23304 : if (conn->result)
214 23304 : strlcpy(conn->result->cmdStatus, conn->workBuffer.data,
215 : CMDSTATUS_LEN);
216 23304 : conn->asyncStatus = PGASYNC_READY;
217 23304 : break;
218 : case 'E': /* error return */
219 3249 : if (pqGetErrorNotice3(conn, true))
220 0 : return;
221 3249 : conn->asyncStatus = PGASYNC_READY;
222 3249 : break;
223 : case 'Z': /* backend is ready for new query */
224 26762 : if (getReadyForQuery(conn))
225 0 : return;
226 26762 : conn->asyncStatus = PGASYNC_IDLE;
227 26762 : break;
228 : case 'I': /* empty query */
229 5 : if (conn->result == NULL)
230 : {
231 5 : conn->result = PQmakeEmptyPGresult(conn,
232 : PGRES_EMPTY_QUERY);
233 5 : if (!conn->result)
234 : {
235 0 : printfPQExpBuffer(&conn->errorMessage,
236 : libpq_gettext("out of memory"));
237 0 : pqSaveErrorResult(conn);
238 : }
239 : }
240 5 : conn->asyncStatus = PGASYNC_READY;
241 5 : break;
242 : case '1': /* Parse Complete */
243 : /* If we're doing PQprepare, we're done; else ignore */
244 0 : if (conn->queryclass == PGQUERY_PREPARE)
245 : {
246 0 : if (conn->result == NULL)
247 : {
248 0 : conn->result = PQmakeEmptyPGresult(conn,
249 : PGRES_COMMAND_OK);
250 0 : if (!conn->result)
251 : {
252 0 : printfPQExpBuffer(&conn->errorMessage,
253 : libpq_gettext("out of memory"));
254 0 : pqSaveErrorResult(conn);
255 : }
256 : }
257 0 : conn->asyncStatus = PGASYNC_READY;
258 : }
259 0 : break;
260 : case '2': /* Bind Complete */
261 : case '3': /* Close Complete */
262 : /* Nothing to do for these message types */
263 0 : break;
264 : case 'S': /* parameter status */
265 3202 : if (getParameterStatus(conn))
266 0 : return;
267 3202 : break;
268 : case 'K': /* secret key data from the backend */
269 :
270 : /*
271 : * This is expected only during backend startup, but it's
272 : * just as easy to handle it as part of the main loop.
273 : * Save the data and continue processing.
274 : */
275 216 : if (pqGetInt(&(conn->be_pid), 4, conn))
276 0 : return;
277 216 : if (pqGetInt(&(conn->be_key), 4, conn))
278 0 : return;
279 216 : break;
280 : case 'T': /* Row Description */
281 11606 : if (conn->result != NULL &&
282 0 : conn->result->resultStatus == PGRES_FATAL_ERROR)
283 : {
284 : /*
285 : * We've already choked for some reason. Just discard
286 : * the data till we get to the end of the query.
287 : */
288 0 : conn->inCursor += msgLength;
289 : }
290 11606 : else if (conn->result == NULL ||
291 0 : conn->queryclass == PGQUERY_DESCRIBE)
292 : {
293 : /* First 'T' in a query sequence */
294 11606 : if (getRowDescriptions(conn, msgLength))
295 0 : return;
296 : /* getRowDescriptions() moves inStart itself */
297 11606 : continue;
298 : }
299 : else
300 : {
301 : /*
302 : * A new 'T' message is treated as the start of
303 : * another PGresult. (It is not clear that this is
304 : * really possible with the current backend.) We stop
305 : * parsing until the application accepts the current
306 : * result.
307 : */
308 0 : conn->asyncStatus = PGASYNC_READY;
309 0 : return;
310 : }
311 0 : break;
312 : case 'n': /* No Data */
313 :
314 : /*
315 : * NoData indicates that we will not be seeing a
316 : * RowDescription message because the statement or portal
317 : * inquired about doesn't return rows.
318 : *
319 : * If we're doing a Describe, we have to pass something
320 : * back to the client, so set up a COMMAND_OK result,
321 : * instead of TUPLES_OK. Otherwise we can just ignore
322 : * this message.
323 : */
324 0 : if (conn->queryclass == PGQUERY_DESCRIBE)
325 : {
326 0 : if (conn->result == NULL)
327 : {
328 0 : conn->result = PQmakeEmptyPGresult(conn,
329 : PGRES_COMMAND_OK);
330 0 : if (!conn->result)
331 : {
332 0 : printfPQExpBuffer(&conn->errorMessage,
333 : libpq_gettext("out of memory"));
334 0 : pqSaveErrorResult(conn);
335 : }
336 : }
337 0 : conn->asyncStatus = PGASYNC_READY;
338 : }
339 0 : break;
340 : case 't': /* Parameter Description */
341 0 : if (getParamDescriptions(conn, msgLength))
342 0 : return;
343 : /* getParamDescriptions() moves inStart itself */
344 0 : continue;
345 : case 'D': /* Data Row */
346 76052 : if (conn->result != NULL &&
347 38026 : conn->result->resultStatus == PGRES_TUPLES_OK)
348 : {
349 : /* Read another tuple of a normal query response */
350 38026 : if (getAnotherTuple(conn, msgLength))
351 0 : return;
352 : /* getAnotherTuple() moves inStart itself */
353 38026 : continue;
354 : }
355 0 : else if (conn->result != NULL &&
356 0 : conn->result->resultStatus == PGRES_FATAL_ERROR)
357 : {
358 : /*
359 : * We've already choked for some reason. Just discard
360 : * tuples till we get to the end of the query.
361 : */
362 0 : conn->inCursor += msgLength;
363 : }
364 : else
365 : {
366 : /* Set up to report error at end of query */
367 0 : printfPQExpBuffer(&conn->errorMessage,
368 : libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
369 0 : pqSaveErrorResult(conn);
370 : /* Discard the unexpected message */
371 0 : conn->inCursor += msgLength;
372 : }
373 0 : break;
374 : case 'G': /* Start Copy In */
375 77 : if (getCopyStart(conn, PGRES_COPY_IN))
376 0 : return;
377 77 : conn->asyncStatus = PGASYNC_COPY_IN;
378 77 : break;
379 : case 'H': /* Start Copy Out */
380 64 : if (getCopyStart(conn, PGRES_COPY_OUT))
381 0 : return;
382 64 : conn->asyncStatus = PGASYNC_COPY_OUT;
383 64 : conn->copy_already_done = 0;
384 64 : break;
385 : case 'W': /* Start Copy Both */
386 0 : if (getCopyStart(conn, PGRES_COPY_BOTH))
387 0 : return;
388 0 : conn->asyncStatus = PGASYNC_COPY_BOTH;
389 0 : conn->copy_already_done = 0;
390 0 : break;
391 : case 'd': /* Copy Data */
392 :
393 : /*
394 : * If we see Copy Data, just silently drop it. This would
395 : * only occur if application exits COPY OUT mode too
396 : * early.
397 : */
398 0 : conn->inCursor += msgLength;
399 0 : break;
400 : case 'c': /* Copy Done */
401 :
402 : /*
403 : * If we see Copy Done, just silently drop it. This is
404 : * the normal case during PQendcopy. We will keep
405 : * swallowing data, expecting to see command-complete for
406 : * the COPY command.
407 : */
408 64 : break;
409 : default:
410 0 : printfPQExpBuffer(&conn->errorMessage,
411 : libpq_gettext(
412 : "unexpected response from server; first received character was \"%c\"\n"),
413 : id);
414 : /* build an error result holding the error message */
415 0 : pqSaveErrorResult(conn);
416 : /* not sure if we will see more, so go to ready state */
417 0 : conn->asyncStatus = PGASYNC_READY;
418 : /* Discard the unexpected message */
419 0 : conn->inCursor += msgLength;
420 0 : break;
421 : } /* switch on protocol character */
422 : }
423 : /* Successfully consumed this message */
424 58682 : if (conn->inCursor == conn->inStart + 5 + msgLength)
425 : {
426 : /* Normal case: parsing agrees with specified length */
427 58682 : conn->inStart = conn->inCursor;
428 : }
429 : else
430 : {
431 : /* Trouble --- report it */
432 0 : printfPQExpBuffer(&conn->errorMessage,
433 : libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
434 : id);
435 : /* build an error result holding the error message */
436 0 : pqSaveErrorResult(conn);
437 0 : conn->asyncStatus = PGASYNC_READY;
438 : /* trust the specified message length as what to skip */
439 0 : conn->inStart += 5 + msgLength;
440 : }
441 108314 : }
442 : }
443 :
444 : /*
445 : * handleSyncLoss: clean up after loss of message-boundary sync
446 : *
447 : * There isn't really a lot we can do here except abandon the connection.
448 : */
449 : static void
450 0 : handleSyncLoss(PGconn *conn, char id, int msgLength)
451 : {
452 0 : printfPQExpBuffer(&conn->errorMessage,
453 : libpq_gettext(
454 : "lost synchronization with server: got message type \"%c\", length %d\n"),
455 : id, msgLength);
456 : /* build an error result holding the error message */
457 0 : pqSaveErrorResult(conn);
458 0 : conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
459 : /* flush input data since we're giving up on processing it */
460 0 : pqDropConnection(conn, true);
461 0 : conn->status = CONNECTION_BAD; /* No more connection to backend */
462 0 : }
463 :
464 : /*
465 : * parseInput subroutine to read a 'T' (row descriptions) message.
466 : * We'll build a new PGresult structure (unless called for a Describe
467 : * command for a prepared statement) containing the attribute data.
468 : * Returns: 0 if processed message successfully, EOF to suspend parsing
469 : * (the latter case is not actually used currently).
470 : * In the former case, conn->inStart has been advanced past the message.
471 : */
472 : static int
473 11606 : getRowDescriptions(PGconn *conn, int msgLength)
474 : {
475 : PGresult *result;
476 : int nfields;
477 : const char *errmsg;
478 : int i;
479 :
480 : /*
481 : * When doing Describe for a prepared statement, there'll already be a
482 : * PGresult created by getParamDescriptions, and we should fill data into
483 : * that. Otherwise, create a new, empty PGresult.
484 : */
485 11606 : if (conn->queryclass == PGQUERY_DESCRIBE)
486 : {
487 0 : if (conn->result)
488 0 : result = conn->result;
489 : else
490 0 : result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
491 : }
492 : else
493 11606 : result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
494 11606 : if (!result)
495 : {
496 0 : errmsg = NULL; /* means "out of memory", see below */
497 0 : goto advance_and_error;
498 : }
499 :
500 : /* parseInput already read the 'T' label and message length. */
501 : /* the next two bytes are the number of fields */
502 11606 : if (pqGetInt(&(result->numAttributes), 2, conn))
503 : {
504 : /* We should not run out of data here, so complain */
505 0 : errmsg = libpq_gettext("insufficient data in \"T\" message");
506 0 : goto advance_and_error;
507 : }
508 11606 : nfields = result->numAttributes;
509 :
510 : /* allocate space for the attribute descriptors */
511 11606 : if (nfields > 0)
512 : {
513 11604 : result->attDescs = (PGresAttDesc *)
514 11604 : pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
515 11604 : if (!result->attDescs)
516 : {
517 0 : errmsg = NULL; /* means "out of memory", see below */
518 0 : goto advance_and_error;
519 : }
520 11604 : MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
521 : }
522 :
523 : /* result->binary is true only if ALL columns are binary */
524 11606 : result->binary = (nfields > 0) ? 1 : 0;
525 :
526 : /* get type info */
527 80416 : for (i = 0; i < nfields; i++)
528 : {
529 : int tableid;
530 : int columnid;
531 : int typid;
532 : int typlen;
533 : int atttypmod;
534 : int format;
535 :
536 57204 : if (pqGets(&conn->workBuffer, conn) ||
537 57204 : pqGetInt(&tableid, 4, conn) ||
538 57204 : pqGetInt(&columnid, 2, conn) ||
539 57204 : pqGetInt(&typid, 4, conn) ||
540 57204 : pqGetInt(&typlen, 2, conn) ||
541 57204 : pqGetInt(&atttypmod, 4, conn) ||
542 28602 : pqGetInt(&format, 2, conn))
543 : {
544 : /* We should not run out of data here, so complain */
545 0 : errmsg = libpq_gettext("insufficient data in \"T\" message");
546 0 : goto advance_and_error;
547 : }
548 :
549 : /*
550 : * Since pqGetInt treats 2-byte integers as unsigned, we need to
551 : * coerce these results to signed form.
552 : */
553 28602 : columnid = (int) ((int16) columnid);
554 28602 : typlen = (int) ((int16) typlen);
555 28602 : format = (int) ((int16) format);
556 :
557 57204 : result->attDescs[i].name = pqResultStrdup(result,
558 28602 : conn->workBuffer.data);
559 28602 : if (!result->attDescs[i].name)
560 : {
561 0 : errmsg = NULL; /* means "out of memory", see below */
562 0 : goto advance_and_error;
563 : }
564 28602 : result->attDescs[i].tableid = tableid;
565 28602 : result->attDescs[i].columnid = columnid;
566 28602 : result->attDescs[i].format = format;
567 28602 : result->attDescs[i].typid = typid;
568 28602 : result->attDescs[i].typlen = typlen;
569 28602 : result->attDescs[i].atttypmod = atttypmod;
570 :
571 28602 : if (format != 1)
572 28602 : result->binary = 0;
573 : }
574 :
575 : /* Sanity check that we absorbed all the data */
576 11606 : if (conn->inCursor != conn->inStart + 5 + msgLength)
577 : {
578 0 : errmsg = libpq_gettext("extraneous data in \"T\" message");
579 0 : goto advance_and_error;
580 : }
581 :
582 : /* Success! */
583 11606 : conn->result = result;
584 :
585 : /* Advance inStart to show that the "T" message has been processed. */
586 11606 : conn->inStart = conn->inCursor;
587 :
588 : /*
589 : * If we're doing a Describe, we're done, and ready to pass the result
590 : * back to the client.
591 : */
592 11606 : if (conn->queryclass == PGQUERY_DESCRIBE)
593 : {
594 0 : conn->asyncStatus = PGASYNC_READY;
595 0 : return 0;
596 : }
597 :
598 : /*
599 : * We could perform additional setup for the new result set here, but for
600 : * now there's nothing else to do.
601 : */
602 :
603 : /* And we're done. */
604 11606 : return 0;
605 :
606 : advance_and_error:
607 : /* Discard unsaved result, if any */
608 0 : if (result && result != conn->result)
609 0 : PQclear(result);
610 :
611 : /* Discard the failed message by pretending we read it */
612 0 : conn->inStart += 5 + msgLength;
613 :
614 : /*
615 : * Replace partially constructed result with an error result. First
616 : * discard the old result to try to win back some memory.
617 : */
618 0 : pqClearAsyncResult(conn);
619 :
620 : /*
621 : * If preceding code didn't provide an error message, assume "out of
622 : * memory" was meant. The advantage of having this special case is that
623 : * freeing the old result first greatly improves the odds that gettext()
624 : * will succeed in providing a translation.
625 : */
626 0 : if (!errmsg)
627 0 : errmsg = libpq_gettext("out of memory for query result");
628 :
629 0 : printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
630 0 : pqSaveErrorResult(conn);
631 :
632 : /*
633 : * Return zero to allow input parsing to continue. Subsequent "D"
634 : * messages will be ignored until we get to end of data, since an error
635 : * result is already set up.
636 : */
637 0 : return 0;
638 : }
639 :
640 : /*
641 : * parseInput subroutine to read a 't' (ParameterDescription) message.
642 : * We'll build a new PGresult structure containing the parameter data.
643 : * Returns: 0 if completed message, EOF if not enough data yet.
644 : * In the former case, conn->inStart has been advanced past the message.
645 : *
646 : * Note that if we run out of data, we have to release the partially
647 : * constructed PGresult, and rebuild it again next time. Fortunately,
648 : * that shouldn't happen often, since 't' messages usually fit in a packet.
649 : */
650 : static int
651 0 : getParamDescriptions(PGconn *conn, int msgLength)
652 : {
653 : PGresult *result;
654 0 : const char *errmsg = NULL; /* means "out of memory", see below */
655 : int nparams;
656 : int i;
657 :
658 0 : result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
659 0 : if (!result)
660 0 : goto advance_and_error;
661 :
662 : /* parseInput already read the 't' label and message length. */
663 : /* the next two bytes are the number of parameters */
664 0 : if (pqGetInt(&(result->numParameters), 2, conn))
665 0 : goto not_enough_data;
666 0 : nparams = result->numParameters;
667 :
668 : /* allocate space for the parameter descriptors */
669 0 : if (nparams > 0)
670 : {
671 0 : result->paramDescs = (PGresParamDesc *)
672 0 : pqResultAlloc(result, nparams * sizeof(PGresParamDesc), TRUE);
673 0 : if (!result->paramDescs)
674 0 : goto advance_and_error;
675 0 : MemSet(result->paramDescs, 0, nparams * sizeof(PGresParamDesc));
676 : }
677 :
678 : /* get parameter info */
679 0 : for (i = 0; i < nparams; i++)
680 : {
681 : int typid;
682 :
683 0 : if (pqGetInt(&typid, 4, conn))
684 0 : goto not_enough_data;
685 0 : result->paramDescs[i].typid = typid;
686 : }
687 :
688 : /* Sanity check that we absorbed all the data */
689 0 : if (conn->inCursor != conn->inStart + 5 + msgLength)
690 : {
691 0 : errmsg = libpq_gettext("extraneous data in \"t\" message");
692 0 : goto advance_and_error;
693 : }
694 :
695 : /* Success! */
696 0 : conn->result = result;
697 :
698 : /* Advance inStart to show that the "t" message has been processed. */
699 0 : conn->inStart = conn->inCursor;
700 :
701 0 : return 0;
702 :
703 : not_enough_data:
704 0 : PQclear(result);
705 0 : return EOF;
706 :
707 : advance_and_error:
708 : /* Discard unsaved result, if any */
709 0 : if (result && result != conn->result)
710 0 : PQclear(result);
711 :
712 : /* Discard the failed message by pretending we read it */
713 0 : conn->inStart += 5 + msgLength;
714 :
715 : /*
716 : * Replace partially constructed result with an error result. First
717 : * discard the old result to try to win back some memory.
718 : */
719 0 : pqClearAsyncResult(conn);
720 :
721 : /*
722 : * If preceding code didn't provide an error message, assume "out of
723 : * memory" was meant. The advantage of having this special case is that
724 : * freeing the old result first greatly improves the odds that gettext()
725 : * will succeed in providing a translation.
726 : */
727 0 : if (!errmsg)
728 0 : errmsg = libpq_gettext("out of memory");
729 0 : printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
730 0 : pqSaveErrorResult(conn);
731 :
732 : /*
733 : * Return zero to allow input parsing to continue. Essentially, we've
734 : * replaced the COMMAND_OK result with an error result, but since this
735 : * doesn't affect the protocol state, it's fine.
736 : */
737 0 : return 0;
738 : }
739 :
740 : /*
741 : * parseInput subroutine to read a 'D' (row data) message.
742 : * We fill rowbuf with column pointers and then call the row processor.
743 : * Returns: 0 if processed message successfully, EOF to suspend parsing
744 : * (the latter case is not actually used currently).
745 : * In the former case, conn->inStart has been advanced past the message.
746 : */
747 : static int
748 38026 : getAnotherTuple(PGconn *conn, int msgLength)
749 : {
750 38026 : PGresult *result = conn->result;
751 38026 : int nfields = result->numAttributes;
752 : const char *errmsg;
753 : PGdataValue *rowbuf;
754 : int tupnfields; /* # fields from tuple */
755 : int vlen; /* length of the current field value */
756 : int i;
757 :
758 : /* Get the field count and make sure it's what we expect */
759 38026 : if (pqGetInt(&tupnfields, 2, conn))
760 : {
761 : /* We should not run out of data here, so complain */
762 0 : errmsg = libpq_gettext("insufficient data in \"D\" message");
763 0 : goto advance_and_error;
764 : }
765 :
766 38026 : if (tupnfields != nfields)
767 : {
768 0 : errmsg = libpq_gettext("unexpected field count in \"D\" message");
769 0 : goto advance_and_error;
770 : }
771 :
772 : /* Resize row buffer if needed */
773 38026 : rowbuf = conn->rowBuf;
774 38026 : if (nfields > conn->rowBufLen)
775 : {
776 0 : rowbuf = (PGdataValue *) realloc(rowbuf,
777 : nfields * sizeof(PGdataValue));
778 0 : if (!rowbuf)
779 : {
780 0 : errmsg = NULL; /* means "out of memory", see below */
781 0 : goto advance_and_error;
782 : }
783 0 : conn->rowBuf = rowbuf;
784 0 : conn->rowBufLen = nfields;
785 : }
786 :
787 : /* Scan the fields */
788 148369 : for (i = 0; i < nfields; i++)
789 : {
790 : /* get the value length */
791 110343 : if (pqGetInt(&vlen, 4, conn))
792 : {
793 : /* We should not run out of data here, so complain */
794 0 : errmsg = libpq_gettext("insufficient data in \"D\" message");
795 0 : goto advance_and_error;
796 : }
797 110343 : rowbuf[i].len = vlen;
798 :
799 : /*
800 : * rowbuf[i].value always points to the next address in the data
801 : * buffer even if the value is NULL. This allows row processors to
802 : * estimate data sizes more easily.
803 : */
804 110343 : rowbuf[i].value = conn->inBuffer + conn->inCursor;
805 :
806 : /* Skip over the data value */
807 110343 : if (vlen > 0)
808 : {
809 93134 : if (pqSkipnchar(vlen, conn))
810 : {
811 : /* We should not run out of data here, so complain */
812 0 : errmsg = libpq_gettext("insufficient data in \"D\" message");
813 0 : goto advance_and_error;
814 : }
815 : }
816 : }
817 :
818 : /* Sanity check that we absorbed all the data */
819 38026 : if (conn->inCursor != conn->inStart + 5 + msgLength)
820 : {
821 0 : errmsg = libpq_gettext("extraneous data in \"D\" message");
822 0 : goto advance_and_error;
823 : }
824 :
825 : /* Advance inStart to show that the "D" message has been processed. */
826 38026 : conn->inStart = conn->inCursor;
827 :
828 : /* Process the collected row */
829 38026 : errmsg = NULL;
830 38026 : if (pqRowProcessor(conn, &errmsg))
831 38026 : return 0; /* normal, successful exit */
832 :
833 0 : goto set_error_result; /* pqRowProcessor failed, report it */
834 :
835 : advance_and_error:
836 : /* Discard the failed message by pretending we read it */
837 0 : conn->inStart += 5 + msgLength;
838 :
839 : set_error_result:
840 :
841 : /*
842 : * Replace partially constructed result with an error result. First
843 : * discard the old result to try to win back some memory.
844 : */
845 0 : pqClearAsyncResult(conn);
846 :
847 : /*
848 : * If preceding code didn't provide an error message, assume "out of
849 : * memory" was meant. The advantage of having this special case is that
850 : * freeing the old result first greatly improves the odds that gettext()
851 : * will succeed in providing a translation.
852 : */
853 0 : if (!errmsg)
854 0 : errmsg = libpq_gettext("out of memory for query result");
855 :
856 0 : printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
857 0 : pqSaveErrorResult(conn);
858 :
859 : /*
860 : * Return zero to allow input parsing to continue. Subsequent "D"
861 : * messages will be ignored until we get to end of data, since an error
862 : * result is already set up.
863 : */
864 0 : return 0;
865 : }
866 :
867 :
868 : /*
869 : * Attempt to read an Error or Notice response message.
870 : * This is possible in several places, so we break it out as a subroutine.
871 : * Entry: 'E' or 'N' message type and length have already been consumed.
872 : * Exit: returns 0 if successfully consumed message.
873 : * returns EOF if not enough data.
874 : */
875 : int
876 4988 : pqGetErrorNotice3(PGconn *conn, bool isError)
877 : {
878 4988 : PGresult *res = NULL;
879 4988 : bool have_position = false;
880 : PQExpBufferData workBuf;
881 : char id;
882 :
883 : /*
884 : * Since the fields might be pretty long, we create a temporary
885 : * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
886 : * for stuff that is expected to be short. We shouldn't use
887 : * conn->errorMessage either, since this might be only a notice.
888 : */
889 4988 : initPQExpBuffer(&workBuf);
890 :
891 : /*
892 : * Make a PGresult to hold the accumulated fields. We temporarily lie
893 : * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
894 : * copy conn->errorMessage.
895 : *
896 : * NB: This allocation can fail, if you run out of memory. The rest of the
897 : * function handles that gracefully, and we still try to set the error
898 : * message as the connection's error message.
899 : */
900 4988 : res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
901 4988 : if (res)
902 4988 : res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
903 :
904 : /*
905 : * Read the fields and save into res.
906 : *
907 : * While at it, save the SQLSTATE in conn->last_sqlstate, and note whether
908 : * we saw a PG_DIAG_STATEMENT_POSITION field.
909 : */
910 : for (;;)
911 : {
912 44442 : if (pqGetc(&id, conn))
913 0 : goto fail;
914 44442 : if (id == '\0')
915 4988 : break; /* terminator found */
916 39454 : if (pqGets(&workBuf, conn))
917 0 : goto fail;
918 39454 : pqSaveMessageField(res, id, workBuf.data);
919 39454 : if (id == PG_DIAG_SQLSTATE)
920 4988 : strlcpy(conn->last_sqlstate, workBuf.data,
921 : sizeof(conn->last_sqlstate));
922 34466 : else if (id == PG_DIAG_STATEMENT_POSITION)
923 886 : have_position = true;
924 39454 : }
925 :
926 : /*
927 : * Save the active query text, if any, into res as well; but only if we
928 : * might need it for an error cursor display, which is only true if there
929 : * is a PG_DIAG_STATEMENT_POSITION field.
930 : */
931 4988 : if (have_position && conn->last_query && res)
932 886 : res->errQuery = pqResultStrdup(res, conn->last_query);
933 :
934 : /*
935 : * Now build the "overall" error message for PQresultErrorMessage.
936 : */
937 4988 : resetPQExpBuffer(&workBuf);
938 4988 : pqBuildErrorMessage3(&workBuf, res, conn->verbosity, conn->show_context);
939 :
940 : /*
941 : * Either save error as current async result, or just emit the notice.
942 : */
943 4988 : if (isError)
944 : {
945 3249 : if (res)
946 3249 : res->errMsg = pqResultStrdup(res, workBuf.data);
947 3249 : pqClearAsyncResult(conn);
948 3249 : conn->result = res;
949 3249 : if (PQExpBufferDataBroken(workBuf))
950 0 : printfPQExpBuffer(&conn->errorMessage,
951 : libpq_gettext("out of memory"));
952 : else
953 3249 : appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
954 : }
955 : else
956 : {
957 : /* if we couldn't allocate the result set, just discard the NOTICE */
958 1739 : if (res)
959 : {
960 : /* We can cheat a little here and not copy the message. */
961 1739 : res->errMsg = workBuf.data;
962 1739 : if (res->noticeHooks.noticeRec != NULL)
963 1739 : (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
964 1739 : PQclear(res);
965 : }
966 : }
967 :
968 4988 : termPQExpBuffer(&workBuf);
969 4988 : return 0;
970 :
971 : fail:
972 0 : PQclear(res);
973 0 : termPQExpBuffer(&workBuf);
974 0 : return EOF;
975 : }
976 :
977 : /*
978 : * Construct an error message from the fields in the given PGresult,
979 : * appending it to the contents of "msg".
980 : */
981 : void
982 4988 : pqBuildErrorMessage3(PQExpBuffer msg, const PGresult *res,
983 : PGVerbosity verbosity, PGContextVisibility show_context)
984 : {
985 : const char *val;
986 4988 : const char *querytext = NULL;
987 4988 : int querypos = 0;
988 :
989 : /* If we couldn't allocate a PGresult, just say "out of memory" */
990 4988 : if (res == NULL)
991 : {
992 0 : appendPQExpBuffer(msg, libpq_gettext("out of memory\n"));
993 0 : return;
994 : }
995 :
996 : /*
997 : * If we don't have any broken-down fields, just return the base message.
998 : * This mainly applies if we're given a libpq-generated error result.
999 : */
1000 4988 : if (res->errFields == NULL)
1001 : {
1002 0 : if (res->errMsg && res->errMsg[0])
1003 0 : appendPQExpBufferStr(msg, res->errMsg);
1004 : else
1005 0 : appendPQExpBuffer(msg, libpq_gettext("no error message available\n"));
1006 0 : return;
1007 : }
1008 :
1009 : /* Else build error message from relevant fields */
1010 4988 : val = PQresultErrorField(res, PG_DIAG_SEVERITY);
1011 4988 : if (val)
1012 4988 : appendPQExpBuffer(msg, "%s: ", val);
1013 4988 : if (verbosity == PQERRORS_VERBOSE)
1014 : {
1015 0 : val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
1016 0 : if (val)
1017 0 : appendPQExpBuffer(msg, "%s: ", val);
1018 : }
1019 4988 : val = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
1020 4988 : if (val)
1021 4988 : appendPQExpBufferStr(msg, val);
1022 4988 : val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
1023 4988 : if (val)
1024 : {
1025 886 : if (verbosity != PQERRORS_TERSE && res->errQuery != NULL)
1026 : {
1027 : /* emit position as a syntax cursor display */
1028 885 : querytext = res->errQuery;
1029 885 : querypos = atoi(val);
1030 : }
1031 : else
1032 : {
1033 : /* emit position as text addition to primary message */
1034 : /* translator: %s represents a digit string */
1035 1 : appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1036 : val);
1037 : }
1038 : }
1039 : else
1040 : {
1041 4102 : val = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION);
1042 4102 : if (val)
1043 : {
1044 6 : querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
1045 6 : if (verbosity != PQERRORS_TERSE && querytext != NULL)
1046 : {
1047 : /* emit position as a syntax cursor display */
1048 6 : querypos = atoi(val);
1049 : }
1050 : else
1051 : {
1052 : /* emit position as text addition to primary message */
1053 : /* translator: %s represents a digit string */
1054 0 : appendPQExpBuffer(msg, libpq_gettext(" at character %s"),
1055 : val);
1056 : }
1057 : }
1058 : }
1059 4988 : appendPQExpBufferChar(msg, '\n');
1060 4988 : if (verbosity != PQERRORS_TERSE)
1061 : {
1062 4957 : if (querytext && querypos > 0)
1063 891 : reportErrorPosition(msg, querytext, querypos,
1064 : res->client_encoding);
1065 4957 : val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
1066 4957 : if (val)
1067 827 : appendPQExpBuffer(msg, libpq_gettext("DETAIL: %s\n"), val);
1068 4957 : val = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
1069 4957 : if (val)
1070 492 : appendPQExpBuffer(msg, libpq_gettext("HINT: %s\n"), val);
1071 4957 : val = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
1072 4957 : if (val)
1073 6 : appendPQExpBuffer(msg, libpq_gettext("QUERY: %s\n"), val);
1074 4957 : if (show_context == PQSHOW_CONTEXT_ALWAYS ||
1075 4953 : (show_context == PQSHOW_CONTEXT_ERRORS &&
1076 4953 : res->resultStatus == PGRES_FATAL_ERROR))
1077 : {
1078 3241 : val = PQresultErrorField(res, PG_DIAG_CONTEXT);
1079 3241 : if (val)
1080 188 : appendPQExpBuffer(msg, libpq_gettext("CONTEXT: %s\n"),
1081 : val);
1082 : }
1083 : }
1084 4988 : if (verbosity == PQERRORS_VERBOSE)
1085 : {
1086 0 : val = PQresultErrorField(res, PG_DIAG_SCHEMA_NAME);
1087 0 : if (val)
1088 0 : appendPQExpBuffer(msg,
1089 : libpq_gettext("SCHEMA NAME: %s\n"), val);
1090 0 : val = PQresultErrorField(res, PG_DIAG_TABLE_NAME);
1091 0 : if (val)
1092 0 : appendPQExpBuffer(msg,
1093 : libpq_gettext("TABLE NAME: %s\n"), val);
1094 0 : val = PQresultErrorField(res, PG_DIAG_COLUMN_NAME);
1095 0 : if (val)
1096 0 : appendPQExpBuffer(msg,
1097 : libpq_gettext("COLUMN NAME: %s\n"), val);
1098 0 : val = PQresultErrorField(res, PG_DIAG_DATATYPE_NAME);
1099 0 : if (val)
1100 0 : appendPQExpBuffer(msg,
1101 : libpq_gettext("DATATYPE NAME: %s\n"), val);
1102 0 : val = PQresultErrorField(res, PG_DIAG_CONSTRAINT_NAME);
1103 0 : if (val)
1104 0 : appendPQExpBuffer(msg,
1105 : libpq_gettext("CONSTRAINT NAME: %s\n"), val);
1106 : }
1107 4988 : if (verbosity == PQERRORS_VERBOSE)
1108 : {
1109 : const char *valf;
1110 : const char *vall;
1111 :
1112 0 : valf = PQresultErrorField(res, PG_DIAG_SOURCE_FILE);
1113 0 : vall = PQresultErrorField(res, PG_DIAG_SOURCE_LINE);
1114 0 : val = PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION);
1115 0 : if (val || valf || vall)
1116 : {
1117 0 : appendPQExpBufferStr(msg, libpq_gettext("LOCATION: "));
1118 0 : if (val)
1119 0 : appendPQExpBuffer(msg, libpq_gettext("%s, "), val);
1120 0 : if (valf && vall) /* unlikely we'd have just one */
1121 0 : appendPQExpBuffer(msg, libpq_gettext("%s:%s"),
1122 : valf, vall);
1123 0 : appendPQExpBufferChar(msg, '\n');
1124 : }
1125 : }
1126 : }
1127 :
1128 : /*
1129 : * Add an error-location display to the error message under construction.
1130 : *
1131 : * The cursor location is measured in logical characters; the query string
1132 : * is presumed to be in the specified encoding.
1133 : */
1134 : static void
1135 891 : reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
1136 : {
1137 : #define DISPLAY_SIZE 60 /* screen width limit, in screen cols */
1138 : #define MIN_RIGHT_CUT 10 /* try to keep this far away from EOL */
1139 :
1140 : char *wquery;
1141 : int slen,
1142 : cno,
1143 : i,
1144 : *qidx,
1145 : *scridx,
1146 : qoffset,
1147 : scroffset,
1148 : ibeg,
1149 : iend,
1150 : loc_line;
1151 : bool mb_encoding,
1152 : beg_trunc,
1153 : end_trunc;
1154 :
1155 : /* Convert loc from 1-based to 0-based; no-op if out of range */
1156 891 : loc--;
1157 891 : if (loc < 0)
1158 0 : return;
1159 :
1160 : /* Need a writable copy of the query */
1161 891 : wquery = strdup(query);
1162 891 : if (wquery == NULL)
1163 0 : return; /* fail silently if out of memory */
1164 :
1165 : /*
1166 : * Each character might occupy multiple physical bytes in the string, and
1167 : * in some Far Eastern character sets it might take more than one screen
1168 : * column as well. We compute the starting byte offset and starting
1169 : * screen column of each logical character, and store these in qidx[] and
1170 : * scridx[] respectively.
1171 : */
1172 :
1173 : /* we need a safe allocation size... */
1174 891 : slen = strlen(wquery) + 1;
1175 :
1176 891 : qidx = (int *) malloc(slen * sizeof(int));
1177 891 : if (qidx == NULL)
1178 : {
1179 0 : free(wquery);
1180 0 : return;
1181 : }
1182 891 : scridx = (int *) malloc(slen * sizeof(int));
1183 891 : if (scridx == NULL)
1184 : {
1185 0 : free(qidx);
1186 0 : free(wquery);
1187 0 : return;
1188 : }
1189 :
1190 : /* We can optimize a bit if it's a single-byte encoding */
1191 891 : mb_encoding = (pg_encoding_max_length(encoding) != 1);
1192 :
1193 : /*
1194 : * Within the scanning loop, cno is the current character's logical
1195 : * number, qoffset is its offset in wquery, and scroffset is its starting
1196 : * logical screen column (all indexed from 0). "loc" is the logical
1197 : * character number of the error location. We scan to determine loc_line
1198 : * (the 1-based line number containing loc) and ibeg/iend (first character
1199 : * number and last+1 character number of the line containing loc). Note
1200 : * that qidx[] and scridx[] are filled only as far as iend.
1201 : */
1202 891 : qoffset = 0;
1203 891 : scroffset = 0;
1204 891 : loc_line = 1;
1205 891 : ibeg = 0;
1206 891 : iend = -1; /* -1 means not set yet */
1207 :
1208 47712 : for (cno = 0; wquery[qoffset] != '\0'; cno++)
1209 : {
1210 46943 : char ch = wquery[qoffset];
1211 :
1212 46943 : qidx[cno] = qoffset;
1213 46943 : scridx[cno] = scroffset;
1214 :
1215 : /*
1216 : * Replace tabs with spaces in the writable copy. (Later we might
1217 : * want to think about coping with their variable screen width, but
1218 : * not today.)
1219 : */
1220 46943 : if (ch == '\t')
1221 38 : wquery[qoffset] = ' ';
1222 :
1223 : /*
1224 : * If end-of-line, count lines and mark positions. Each \r or \n
1225 : * counts as a line except when \r \n appear together.
1226 : */
1227 46905 : else if (ch == '\r' || ch == '\n')
1228 : {
1229 363 : if (cno < loc)
1230 : {
1231 241 : if (ch == '\r' ||
1232 241 : cno == 0 ||
1233 241 : wquery[qidx[cno - 1]] != '\r')
1234 241 : loc_line++;
1235 : /* extract beginning = last line start before loc. */
1236 241 : ibeg = cno + 1;
1237 : }
1238 : else
1239 : {
1240 : /* set extract end. */
1241 122 : iend = cno;
1242 : /* done scanning. */
1243 122 : break;
1244 : }
1245 : }
1246 :
1247 : /* Advance */
1248 46821 : if (mb_encoding)
1249 : {
1250 : int w;
1251 :
1252 46821 : w = pg_encoding_dsplen(encoding, &wquery[qoffset]);
1253 : /* treat any non-tab control chars as width 1 */
1254 46821 : if (w <= 0)
1255 241 : w = 1;
1256 46821 : scroffset += w;
1257 46821 : qoffset += pg_encoding_mblen(encoding, &wquery[qoffset]);
1258 : }
1259 : else
1260 : {
1261 : /* We assume wide chars only exist in multibyte encodings */
1262 0 : scroffset++;
1263 0 : qoffset++;
1264 : }
1265 : }
1266 : /* Fix up if we didn't find an end-of-line after loc */
1267 891 : if (iend < 0)
1268 : {
1269 769 : iend = cno; /* query length in chars, +1 */
1270 769 : qidx[iend] = qoffset;
1271 769 : scridx[iend] = scroffset;
1272 : }
1273 :
1274 : /* Print only if loc is within computed query length */
1275 891 : if (loc <= cno)
1276 : {
1277 : /* If the line extracted is too long, we truncate it. */
1278 888 : beg_trunc = false;
1279 888 : end_trunc = false;
1280 888 : if (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
1281 : {
1282 : /*
1283 : * We first truncate right if it is enough. This code might be
1284 : * off a space or so on enforcing MIN_RIGHT_CUT if there's a wide
1285 : * character right there, but that should be okay.
1286 : */
1287 189 : if (scridx[ibeg] + DISPLAY_SIZE >= scridx[loc] + MIN_RIGHT_CUT)
1288 : {
1289 3353 : while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
1290 3097 : iend--;
1291 128 : end_trunc = true;
1292 : }
1293 : else
1294 : {
1295 : /* Truncate right if not too close to loc. */
1296 933 : while (scridx[loc] + MIN_RIGHT_CUT < scridx[iend])
1297 : {
1298 811 : iend--;
1299 811 : end_trunc = true;
1300 : }
1301 :
1302 : /* Truncate left if still too long. */
1303 1051 : while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
1304 : {
1305 929 : ibeg++;
1306 929 : beg_trunc = true;
1307 : }
1308 : }
1309 : }
1310 :
1311 : /* truncate working copy at desired endpoint */
1312 888 : wquery[qidx[iend]] = '\0';
1313 :
1314 : /* Begin building the finished message. */
1315 888 : i = msg->len;
1316 888 : appendPQExpBuffer(msg, libpq_gettext("LINE %d: "), loc_line);
1317 888 : if (beg_trunc)
1318 61 : appendPQExpBufferStr(msg, "...");
1319 :
1320 : /*
1321 : * While we have the prefix in the msg buffer, compute its screen
1322 : * width.
1323 : */
1324 888 : scroffset = 0;
1325 8176 : for (; i < msg->len; i += pg_encoding_mblen(encoding, &msg->data[i]))
1326 : {
1327 7288 : int w = pg_encoding_dsplen(encoding, &msg->data[i]);
1328 :
1329 7288 : if (w <= 0)
1330 0 : w = 1;
1331 7288 : scroffset += w;
1332 : }
1333 :
1334 : /* Finish up the LINE message line. */
1335 888 : appendPQExpBufferStr(msg, &wquery[qidx[ibeg]]);
1336 888 : if (end_trunc)
1337 168 : appendPQExpBufferStr(msg, "...");
1338 888 : appendPQExpBufferChar(msg, '\n');
1339 :
1340 : /* Now emit the cursor marker line. */
1341 888 : scroffset += scridx[loc] - scridx[ibeg];
1342 27771 : for (i = 0; i < scroffset; i++)
1343 26883 : appendPQExpBufferChar(msg, ' ');
1344 888 : appendPQExpBufferChar(msg, '^');
1345 888 : appendPQExpBufferChar(msg, '\n');
1346 : }
1347 :
1348 : /* Clean up. */
1349 891 : free(scridx);
1350 891 : free(qidx);
1351 891 : free(wquery);
1352 : }
1353 :
1354 :
1355 : /*
1356 : * Attempt to read a ParameterStatus message.
1357 : * This is possible in several places, so we break it out as a subroutine.
1358 : * Entry: 'S' message type and length have already been consumed.
1359 : * Exit: returns 0 if successfully consumed message.
1360 : * returns EOF if not enough data.
1361 : */
1362 : static int
1363 3202 : getParameterStatus(PGconn *conn)
1364 : {
1365 : PQExpBufferData valueBuf;
1366 :
1367 : /* Get the parameter name */
1368 3202 : if (pqGets(&conn->workBuffer, conn))
1369 0 : return EOF;
1370 : /* Get the parameter value (could be large) */
1371 3202 : initPQExpBuffer(&valueBuf);
1372 3202 : if (pqGets(&valueBuf, conn))
1373 : {
1374 0 : termPQExpBuffer(&valueBuf);
1375 0 : return EOF;
1376 : }
1377 : /* And save it */
1378 3202 : pqSaveParameterStatus(conn, conn->workBuffer.data, valueBuf.data);
1379 3202 : termPQExpBuffer(&valueBuf);
1380 3202 : return 0;
1381 : }
1382 :
1383 :
1384 : /*
1385 : * Attempt to read a Notify response message.
1386 : * This is possible in several places, so we break it out as a subroutine.
1387 : * Entry: 'A' message type and length have already been consumed.
1388 : * Exit: returns 0 if successfully consumed Notify message.
1389 : * returns EOF if not enough data.
1390 : */
1391 : static int
1392 0 : getNotify(PGconn *conn)
1393 : {
1394 : int be_pid;
1395 : char *svname;
1396 : int nmlen;
1397 : int extralen;
1398 : PGnotify *newNotify;
1399 :
1400 0 : if (pqGetInt(&be_pid, 4, conn))
1401 0 : return EOF;
1402 0 : if (pqGets(&conn->workBuffer, conn))
1403 0 : return EOF;
1404 : /* must save name while getting extra string */
1405 0 : svname = strdup(conn->workBuffer.data);
1406 0 : if (!svname)
1407 0 : return EOF;
1408 0 : if (pqGets(&conn->workBuffer, conn))
1409 : {
1410 0 : free(svname);
1411 0 : return EOF;
1412 : }
1413 :
1414 : /*
1415 : * Store the strings right after the PQnotify structure so it can all be
1416 : * freed at once. We don't use NAMEDATALEN because we don't want to tie
1417 : * this interface to a specific server name length.
1418 : */
1419 0 : nmlen = strlen(svname);
1420 0 : extralen = strlen(conn->workBuffer.data);
1421 0 : newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + extralen + 2);
1422 0 : if (newNotify)
1423 : {
1424 0 : newNotify->relname = (char *) newNotify + sizeof(PGnotify);
1425 0 : strcpy(newNotify->relname, svname);
1426 0 : newNotify->extra = newNotify->relname + nmlen + 1;
1427 0 : strcpy(newNotify->extra, conn->workBuffer.data);
1428 0 : newNotify->be_pid = be_pid;
1429 0 : newNotify->next = NULL;
1430 0 : if (conn->notifyTail)
1431 0 : conn->notifyTail->next = newNotify;
1432 : else
1433 0 : conn->notifyHead = newNotify;
1434 0 : conn->notifyTail = newNotify;
1435 : }
1436 :
1437 0 : free(svname);
1438 0 : return 0;
1439 : }
1440 :
1441 : /*
1442 : * getCopyStart - process CopyInResponse, CopyOutResponse or
1443 : * CopyBothResponse message
1444 : *
1445 : * parseInput already read the message type and length.
1446 : */
1447 : static int
1448 141 : getCopyStart(PGconn *conn, ExecStatusType copytype)
1449 : {
1450 : PGresult *result;
1451 : int nfields;
1452 : int i;
1453 :
1454 141 : result = PQmakeEmptyPGresult(conn, copytype);
1455 141 : if (!result)
1456 0 : goto failure;
1457 :
1458 141 : if (pqGetc(&conn->copy_is_binary, conn))
1459 0 : goto failure;
1460 141 : result->binary = conn->copy_is_binary;
1461 : /* the next two bytes are the number of fields */
1462 141 : if (pqGetInt(&(result->numAttributes), 2, conn))
1463 0 : goto failure;
1464 141 : nfields = result->numAttributes;
1465 :
1466 : /* allocate space for the attribute descriptors */
1467 141 : if (nfields > 0)
1468 : {
1469 141 : result->attDescs = (PGresAttDesc *)
1470 141 : pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
1471 141 : if (!result->attDescs)
1472 0 : goto failure;
1473 141 : MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
1474 : }
1475 :
1476 447 : for (i = 0; i < nfields; i++)
1477 : {
1478 : int format;
1479 :
1480 306 : if (pqGetInt(&format, 2, conn))
1481 0 : goto failure;
1482 :
1483 : /*
1484 : * Since pqGetInt treats 2-byte integers as unsigned, we need to
1485 : * coerce these results to signed form.
1486 : */
1487 306 : format = (int) ((int16) format);
1488 306 : result->attDescs[i].format = format;
1489 : }
1490 :
1491 : /* Success! */
1492 141 : conn->result = result;
1493 141 : return 0;
1494 :
1495 : failure:
1496 0 : PQclear(result);
1497 0 : return EOF;
1498 : }
1499 :
1500 : /*
1501 : * getReadyForQuery - process ReadyForQuery message
1502 : */
1503 : static int
1504 27020 : getReadyForQuery(PGconn *conn)
1505 : {
1506 : char xact_status;
1507 :
1508 27020 : if (pqGetc(&xact_status, conn))
1509 0 : return EOF;
1510 27020 : switch (xact_status)
1511 : {
1512 : case 'I':
1513 24425 : conn->xactStatus = PQTRANS_IDLE;
1514 24425 : break;
1515 : case 'T':
1516 2482 : conn->xactStatus = PQTRANS_INTRANS;
1517 2482 : break;
1518 : case 'E':
1519 113 : conn->xactStatus = PQTRANS_INERROR;
1520 113 : break;
1521 : default:
1522 0 : conn->xactStatus = PQTRANS_UNKNOWN;
1523 0 : break;
1524 : }
1525 :
1526 27020 : return 0;
1527 : }
1528 :
1529 : /*
1530 : * getCopyDataMessage - fetch next CopyData message, process async messages
1531 : *
1532 : * Returns length word of CopyData message (> 0), or 0 if no complete
1533 : * message available, -1 if end of copy, -2 if error.
1534 : */
1535 : static int
1536 321 : getCopyDataMessage(PGconn *conn)
1537 : {
1538 : char id;
1539 : int msgLength;
1540 : int avail;
1541 :
1542 : for (;;)
1543 : {
1544 : /*
1545 : * Do we have the next input message? To make life simpler for async
1546 : * callers, we keep returning 0 until the next message is fully
1547 : * available, even if it is not Copy Data.
1548 : */
1549 321 : conn->inCursor = conn->inStart;
1550 321 : if (pqGetc(&id, conn))
1551 3 : return 0;
1552 318 : if (pqGetInt(&msgLength, 4, conn))
1553 0 : return 0;
1554 318 : if (msgLength < 4)
1555 : {
1556 0 : handleSyncLoss(conn, id, msgLength);
1557 0 : return -2;
1558 : }
1559 318 : avail = conn->inEnd - conn->inCursor;
1560 318 : if (avail < msgLength - 4)
1561 : {
1562 : /*
1563 : * Before returning, enlarge the input buffer if needed to hold
1564 : * the whole message. See notes in parseInput.
1565 : */
1566 0 : if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength - 4,
1567 : conn))
1568 : {
1569 : /*
1570 : * XXX add some better recovery code... plan is to skip over
1571 : * the message using its length, then report an error. For the
1572 : * moment, just treat this like loss of sync (which indeed it
1573 : * might be!)
1574 : */
1575 0 : handleSyncLoss(conn, id, msgLength);
1576 0 : return -2;
1577 : }
1578 0 : return 0;
1579 : }
1580 :
1581 : /*
1582 : * If it's a legitimate async message type, process it. (NOTIFY
1583 : * messages are not currently possible here, but we handle them for
1584 : * completeness.) Otherwise, if it's anything except Copy Data,
1585 : * report end-of-copy.
1586 : */
1587 318 : switch (id)
1588 : {
1589 : case 'A': /* NOTIFY */
1590 0 : if (getNotify(conn))
1591 0 : return 0;
1592 0 : break;
1593 : case 'N': /* NOTICE */
1594 0 : if (pqGetErrorNotice3(conn, false))
1595 0 : return 0;
1596 0 : break;
1597 : case 'S': /* ParameterStatus */
1598 0 : if (getParameterStatus(conn))
1599 0 : return 0;
1600 0 : break;
1601 : case 'd': /* Copy Data, pass it back to caller */
1602 254 : return msgLength;
1603 : case 'c':
1604 :
1605 : /*
1606 : * If this is a CopyDone message, exit COPY_OUT mode and let
1607 : * caller read status with PQgetResult(). If we're in
1608 : * COPY_BOTH mode, return to COPY_IN mode.
1609 : */
1610 64 : if (conn->asyncStatus == PGASYNC_COPY_BOTH)
1611 0 : conn->asyncStatus = PGASYNC_COPY_IN;
1612 : else
1613 64 : conn->asyncStatus = PGASYNC_BUSY;
1614 64 : return -1;
1615 : default: /* treat as end of copy */
1616 :
1617 : /*
1618 : * Any other message terminates either COPY_IN or COPY_BOTH
1619 : * mode.
1620 : */
1621 0 : conn->asyncStatus = PGASYNC_BUSY;
1622 0 : return -1;
1623 : }
1624 :
1625 : /* Drop the processed message and loop around for another */
1626 0 : conn->inStart = conn->inCursor;
1627 0 : }
1628 : }
1629 :
1630 : /*
1631 : * PQgetCopyData - read a row of data from the backend during COPY OUT
1632 : * or COPY BOTH
1633 : *
1634 : * If successful, sets *buffer to point to a malloc'd row of data, and
1635 : * returns row length (always > 0) as result.
1636 : * Returns 0 if no row available yet (only possible if async is true),
1637 : * -1 if end of copy (consult PQgetResult), or -2 if error (consult
1638 : * PQerrorMessage).
1639 : */
1640 : int
1641 321 : pqGetCopyData3(PGconn *conn, char **buffer, int async)
1642 : {
1643 : int msgLength;
1644 :
1645 : for (;;)
1646 : {
1647 : /*
1648 : * Collect the next input message. To make life simpler for async
1649 : * callers, we keep returning 0 until the next message is fully
1650 : * available, even if it is not Copy Data.
1651 : */
1652 321 : msgLength = getCopyDataMessage(conn);
1653 321 : if (msgLength < 0)
1654 64 : return msgLength; /* end-of-copy or error */
1655 257 : if (msgLength == 0)
1656 : {
1657 : /* Don't block if async read requested */
1658 3 : if (async)
1659 0 : return 0;
1660 : /* Need to load more data */
1661 6 : if (pqWait(TRUE, FALSE, conn) ||
1662 3 : pqReadData(conn) < 0)
1663 0 : return -2;
1664 3 : continue;
1665 : }
1666 :
1667 : /*
1668 : * Drop zero-length messages (shouldn't happen anyway). Otherwise
1669 : * pass the data back to the caller.
1670 : */
1671 254 : msgLength -= 4;
1672 254 : if (msgLength > 0)
1673 : {
1674 254 : *buffer = (char *) malloc(msgLength + 1);
1675 254 : if (*buffer == NULL)
1676 : {
1677 0 : printfPQExpBuffer(&conn->errorMessage,
1678 : libpq_gettext("out of memory\n"));
1679 0 : return -2;
1680 : }
1681 254 : memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1682 254 : (*buffer)[msgLength] = '\0'; /* Add terminating null */
1683 :
1684 : /* Mark message consumed */
1685 254 : conn->inStart = conn->inCursor + msgLength;
1686 :
1687 254 : return msgLength;
1688 : }
1689 :
1690 : /* Empty, so drop it and loop around for another */
1691 0 : conn->inStart = conn->inCursor;
1692 3 : }
1693 : }
1694 :
1695 : /*
1696 : * PQgetline - gets a newline-terminated string from the backend.
1697 : *
1698 : * See fe-exec.c for documentation.
1699 : */
1700 : int
1701 0 : pqGetline3(PGconn *conn, char *s, int maxlen)
1702 : {
1703 : int status;
1704 :
1705 0 : if (conn->sock == PGINVALID_SOCKET ||
1706 0 : (conn->asyncStatus != PGASYNC_COPY_OUT &&
1707 0 : conn->asyncStatus != PGASYNC_COPY_BOTH) ||
1708 0 : conn->copy_is_binary)
1709 : {
1710 0 : printfPQExpBuffer(&conn->errorMessage,
1711 : libpq_gettext("PQgetline: not doing text COPY OUT\n"));
1712 0 : *s = '\0';
1713 0 : return EOF;
1714 : }
1715 :
1716 0 : while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1717 : {
1718 : /* need to load more data */
1719 0 : if (pqWait(TRUE, FALSE, conn) ||
1720 0 : pqReadData(conn) < 0)
1721 : {
1722 0 : *s = '\0';
1723 0 : return EOF;
1724 : }
1725 : }
1726 :
1727 0 : if (status < 0)
1728 : {
1729 : /* End of copy detected; gin up old-style terminator */
1730 0 : strcpy(s, "\\.");
1731 0 : return 0;
1732 : }
1733 :
1734 : /* Add null terminator, and strip trailing \n if present */
1735 0 : if (s[status - 1] == '\n')
1736 : {
1737 0 : s[status - 1] = '\0';
1738 0 : return 0;
1739 : }
1740 : else
1741 : {
1742 0 : s[status] = '\0';
1743 0 : return 1;
1744 : }
1745 : }
1746 :
1747 : /*
1748 : * PQgetlineAsync - gets a COPY data row without blocking.
1749 : *
1750 : * See fe-exec.c for documentation.
1751 : */
1752 : int
1753 0 : pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize)
1754 : {
1755 : int msgLength;
1756 : int avail;
1757 :
1758 0 : if (conn->asyncStatus != PGASYNC_COPY_OUT
1759 0 : && conn->asyncStatus != PGASYNC_COPY_BOTH)
1760 0 : return -1; /* we are not doing a copy... */
1761 :
1762 : /*
1763 : * Recognize the next input message. To make life simpler for async
1764 : * callers, we keep returning 0 until the next message is fully available
1765 : * even if it is not Copy Data. This should keep PQendcopy from blocking.
1766 : * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
1767 : */
1768 0 : msgLength = getCopyDataMessage(conn);
1769 0 : if (msgLength < 0)
1770 0 : return -1; /* end-of-copy or error */
1771 0 : if (msgLength == 0)
1772 0 : return 0; /* no data yet */
1773 :
1774 : /*
1775 : * Move data from libpq's buffer to the caller's. In the case where a
1776 : * prior call found the caller's buffer too small, we use
1777 : * conn->copy_already_done to remember how much of the row was already
1778 : * returned to the caller.
1779 : */
1780 0 : conn->inCursor += conn->copy_already_done;
1781 0 : avail = msgLength - 4 - conn->copy_already_done;
1782 0 : if (avail <= bufsize)
1783 : {
1784 : /* Able to consume the whole message */
1785 0 : memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
1786 : /* Mark message consumed */
1787 0 : conn->inStart = conn->inCursor + avail;
1788 : /* Reset state for next time */
1789 0 : conn->copy_already_done = 0;
1790 0 : return avail;
1791 : }
1792 : else
1793 : {
1794 : /* We must return a partial message */
1795 0 : memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
1796 : /* The message is NOT consumed from libpq's buffer */
1797 0 : conn->copy_already_done += bufsize;
1798 0 : return bufsize;
1799 : }
1800 : }
1801 :
1802 : /*
1803 : * PQendcopy
1804 : *
1805 : * See fe-exec.c for documentation.
1806 : */
1807 : int
1808 0 : pqEndcopy3(PGconn *conn)
1809 : {
1810 : PGresult *result;
1811 :
1812 0 : if (conn->asyncStatus != PGASYNC_COPY_IN &&
1813 0 : conn->asyncStatus != PGASYNC_COPY_OUT &&
1814 0 : conn->asyncStatus != PGASYNC_COPY_BOTH)
1815 : {
1816 0 : printfPQExpBuffer(&conn->errorMessage,
1817 : libpq_gettext("no COPY in progress\n"));
1818 0 : return 1;
1819 : }
1820 :
1821 : /* Send the CopyDone message if needed */
1822 0 : if (conn->asyncStatus == PGASYNC_COPY_IN ||
1823 0 : conn->asyncStatus == PGASYNC_COPY_BOTH)
1824 : {
1825 0 : if (pqPutMsgStart('c', false, conn) < 0 ||
1826 0 : pqPutMsgEnd(conn) < 0)
1827 0 : return 1;
1828 :
1829 : /*
1830 : * If we sent the COPY command in extended-query mode, we must issue a
1831 : * Sync as well.
1832 : */
1833 0 : if (conn->queryclass != PGQUERY_SIMPLE)
1834 : {
1835 0 : if (pqPutMsgStart('S', false, conn) < 0 ||
1836 0 : pqPutMsgEnd(conn) < 0)
1837 0 : return 1;
1838 : }
1839 : }
1840 :
1841 : /*
1842 : * make sure no data is waiting to be sent, abort if we are non-blocking
1843 : * and the flush fails
1844 : */
1845 0 : if (pqFlush(conn) && pqIsnonblocking(conn))
1846 0 : return 1;
1847 :
1848 : /* Return to active duty */
1849 0 : conn->asyncStatus = PGASYNC_BUSY;
1850 0 : resetPQExpBuffer(&conn->errorMessage);
1851 :
1852 : /*
1853 : * Non blocking connections may have to abort at this point. If everyone
1854 : * played the game there should be no problem, but in error scenarios the
1855 : * expected messages may not have arrived yet. (We are assuming that the
1856 : * backend's packetizing will ensure that CommandComplete arrives along
1857 : * with the CopyDone; are there corner cases where that doesn't happen?)
1858 : */
1859 0 : if (pqIsnonblocking(conn) && PQisBusy(conn))
1860 0 : return 1;
1861 :
1862 : /* Wait for the completion response */
1863 0 : result = PQgetResult(conn);
1864 :
1865 : /* Expecting a successful result */
1866 0 : if (result && result->resultStatus == PGRES_COMMAND_OK)
1867 : {
1868 0 : PQclear(result);
1869 0 : return 0;
1870 : }
1871 :
1872 : /*
1873 : * Trouble. For backwards-compatibility reasons, we issue the error
1874 : * message as if it were a notice (would be nice to get rid of this
1875 : * silliness, but too many apps probably don't handle errors from
1876 : * PQendcopy reasonably). Note that the app can still obtain the error
1877 : * status from the PGconn object.
1878 : */
1879 0 : if (conn->errorMessage.len > 0)
1880 : {
1881 : /* We have to strip the trailing newline ... pain in neck... */
1882 0 : char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1883 :
1884 0 : if (svLast == '\n')
1885 0 : conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1886 0 : pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
1887 0 : conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1888 : }
1889 :
1890 0 : PQclear(result);
1891 :
1892 0 : return 1;
1893 : }
1894 :
1895 :
1896 : /*
1897 : * PQfn - Send a function call to the POSTGRES backend.
1898 : *
1899 : * See fe-exec.c for documentation.
1900 : */
1901 : PGresult *
1902 258 : pqFunctionCall3(PGconn *conn, Oid fnid,
1903 : int *result_buf, int *actual_result_len,
1904 : int result_is_int,
1905 : const PQArgBlock *args, int nargs)
1906 : {
1907 258 : bool needInput = false;
1908 258 : ExecStatusType status = PGRES_FATAL_ERROR;
1909 : char id;
1910 : int msgLength;
1911 : int avail;
1912 : int i;
1913 :
1914 : /* PQfn already validated connection state */
1915 :
1916 516 : if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
1917 516 : pqPutInt(fnid, 4, conn) < 0 || /* function id */
1918 516 : pqPutInt(1, 2, conn) < 0 || /* # of format codes */
1919 516 : pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
1920 258 : pqPutInt(nargs, 2, conn) < 0) /* # of args */
1921 : {
1922 0 : pqHandleSendFailure(conn);
1923 0 : return NULL;
1924 : }
1925 :
1926 766 : for (i = 0; i < nargs; ++i)
1927 : { /* len.int4 + contents */
1928 508 : if (pqPutInt(args[i].len, 4, conn))
1929 : {
1930 0 : pqHandleSendFailure(conn);
1931 0 : return NULL;
1932 : }
1933 508 : if (args[i].len == -1)
1934 0 : continue; /* it's NULL */
1935 :
1936 508 : if (args[i].isint)
1937 : {
1938 344 : if (pqPutInt(args[i].u.integer, args[i].len, conn))
1939 : {
1940 0 : pqHandleSendFailure(conn);
1941 0 : return NULL;
1942 : }
1943 : }
1944 : else
1945 : {
1946 164 : if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1947 : {
1948 0 : pqHandleSendFailure(conn);
1949 0 : return NULL;
1950 : }
1951 : }
1952 : }
1953 :
1954 258 : if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
1955 : {
1956 0 : pqHandleSendFailure(conn);
1957 0 : return NULL;
1958 : }
1959 :
1960 516 : if (pqPutMsgEnd(conn) < 0 ||
1961 258 : pqFlush(conn))
1962 : {
1963 0 : pqHandleSendFailure(conn);
1964 0 : return NULL;
1965 : }
1966 :
1967 : for (;;)
1968 : {
1969 855 : if (needInput)
1970 : {
1971 : /* Wait for some data to arrive (or for the channel to close) */
1972 678 : if (pqWait(TRUE, FALSE, conn) ||
1973 339 : pqReadData(conn) < 0)
1974 : break;
1975 : }
1976 :
1977 : /*
1978 : * Scan the message. If we run out of data, loop around to try again.
1979 : */
1980 855 : needInput = true;
1981 :
1982 855 : conn->inCursor = conn->inStart;
1983 855 : if (pqGetc(&id, conn))
1984 258 : continue;
1985 597 : if (pqGetInt(&msgLength, 4, conn))
1986 0 : continue;
1987 :
1988 : /*
1989 : * Try to validate message type/length here. A length less than 4 is
1990 : * definitely broken. Large lengths should only be believed for a few
1991 : * message types.
1992 : */
1993 597 : if (msgLength < 4)
1994 : {
1995 0 : handleSyncLoss(conn, id, msgLength);
1996 0 : break;
1997 : }
1998 597 : if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
1999 : {
2000 0 : handleSyncLoss(conn, id, msgLength);
2001 0 : break;
2002 : }
2003 :
2004 : /*
2005 : * Can't process if message body isn't all here yet.
2006 : */
2007 597 : msgLength -= 4;
2008 597 : avail = conn->inEnd - conn->inCursor;
2009 597 : if (avail < msgLength)
2010 : {
2011 : /*
2012 : * Before looping, enlarge the input buffer if needed to hold the
2013 : * whole message. See notes in parseInput.
2014 : */
2015 81 : if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
2016 : conn))
2017 : {
2018 : /*
2019 : * XXX add some better recovery code... plan is to skip over
2020 : * the message using its length, then report an error. For the
2021 : * moment, just treat this like loss of sync (which indeed it
2022 : * might be!)
2023 : */
2024 0 : handleSyncLoss(conn, id, msgLength);
2025 0 : break;
2026 : }
2027 81 : continue;
2028 : }
2029 :
2030 : /*
2031 : * We should see V or E response to the command, but might get N
2032 : * and/or A notices first. We also need to swallow the final Z before
2033 : * returning.
2034 : */
2035 516 : switch (id)
2036 : {
2037 : case 'V': /* function result */
2038 258 : if (pqGetInt(actual_result_len, 4, conn))
2039 0 : continue;
2040 258 : if (*actual_result_len != -1)
2041 : {
2042 258 : if (result_is_int)
2043 : {
2044 175 : if (pqGetInt(result_buf, *actual_result_len, conn))
2045 0 : continue;
2046 : }
2047 : else
2048 : {
2049 83 : if (pqGetnchar((char *) result_buf,
2050 83 : *actual_result_len,
2051 : conn))
2052 0 : continue;
2053 : }
2054 : }
2055 : /* correctly finished function result message */
2056 258 : status = PGRES_COMMAND_OK;
2057 258 : break;
2058 : case 'E': /* error return */
2059 0 : if (pqGetErrorNotice3(conn, true))
2060 0 : continue;
2061 0 : status = PGRES_FATAL_ERROR;
2062 0 : break;
2063 : case 'A': /* notify message */
2064 : /* handle notify and go back to processing return values */
2065 0 : if (getNotify(conn))
2066 0 : continue;
2067 0 : break;
2068 : case 'N': /* notice */
2069 : /* handle notice and go back to processing return values */
2070 0 : if (pqGetErrorNotice3(conn, false))
2071 0 : continue;
2072 0 : break;
2073 : case 'Z': /* backend is ready for new query */
2074 258 : if (getReadyForQuery(conn))
2075 0 : continue;
2076 : /* consume the message and exit */
2077 258 : conn->inStart += 5 + msgLength;
2078 : /* if we saved a result object (probably an error), use it */
2079 258 : if (conn->result)
2080 0 : return pqPrepareAsyncResult(conn);
2081 258 : return PQmakeEmptyPGresult(conn, status);
2082 : case 'S': /* parameter status */
2083 0 : if (getParameterStatus(conn))
2084 0 : continue;
2085 0 : break;
2086 : default:
2087 : /* The backend violates the protocol. */
2088 0 : printfPQExpBuffer(&conn->errorMessage,
2089 : libpq_gettext("protocol error: id=0x%x\n"),
2090 : id);
2091 0 : pqSaveErrorResult(conn);
2092 : /* trust the specified message length as what to skip */
2093 0 : conn->inStart += 5 + msgLength;
2094 0 : return pqPrepareAsyncResult(conn);
2095 : }
2096 : /* Completed this message, keep going */
2097 : /* trust the specified message length as what to skip */
2098 258 : conn->inStart += 5 + msgLength;
2099 258 : needInput = false;
2100 597 : }
2101 :
2102 : /*
2103 : * We fall out of the loop only upon failing to read data.
2104 : * conn->errorMessage has been set by pqWait or pqReadData. We want to
2105 : * append it to any already-received error message.
2106 : */
2107 0 : pqSaveErrorResult(conn);
2108 0 : return pqPrepareAsyncResult(conn);
2109 : }
2110 :
2111 :
2112 : /*
2113 : * Construct startup packet
2114 : *
2115 : * Returns a malloc'd packet buffer, or NULL if out of memory
2116 : */
2117 : char *
2118 216 : pqBuildStartupPacket3(PGconn *conn, int *packetlen,
2119 : const PQEnvironmentOption *options)
2120 : {
2121 : char *startpacket;
2122 :
2123 216 : *packetlen = build_startup_packet(conn, NULL, options);
2124 216 : startpacket = (char *) malloc(*packetlen);
2125 216 : if (!startpacket)
2126 0 : return NULL;
2127 216 : *packetlen = build_startup_packet(conn, startpacket, options);
2128 216 : return startpacket;
2129 : }
2130 :
2131 : /*
2132 : * Build a startup packet given a filled-in PGconn structure.
2133 : *
2134 : * We need to figure out how much space is needed, then fill it in.
2135 : * To avoid duplicate logic, this routine is called twice: the first time
2136 : * (with packet == NULL) just counts the space needed, the second time
2137 : * (with packet == allocated space) fills it in. Return value is the number
2138 : * of bytes used.
2139 : */
2140 : static int
2141 432 : build_startup_packet(const PGconn *conn, char *packet,
2142 : const PQEnvironmentOption *options)
2143 : {
2144 432 : int packet_len = 0;
2145 : const PQEnvironmentOption *next_eo;
2146 : const char *val;
2147 :
2148 : /* Protocol version comes first. */
2149 432 : if (packet)
2150 : {
2151 216 : ProtocolVersion pv = htonl(conn->pversion);
2152 :
2153 216 : memcpy(packet + packet_len, &pv, sizeof(ProtocolVersion));
2154 : }
2155 432 : packet_len += sizeof(ProtocolVersion);
2156 :
2157 : /* Add user name, database name, options */
2158 :
2159 : #define ADD_STARTUP_OPTION(optname, optval) \
2160 : do { \
2161 : if (packet) \
2162 : strcpy(packet + packet_len, optname); \
2163 : packet_len += strlen(optname) + 1; \
2164 : if (packet) \
2165 : strcpy(packet + packet_len, optval); \
2166 : packet_len += strlen(optval) + 1; \
2167 : } while(0)
2168 :
2169 432 : if (conn->pguser && conn->pguser[0])
2170 432 : ADD_STARTUP_OPTION("user", conn->pguser);
2171 432 : if (conn->dbName && conn->dbName[0])
2172 432 : ADD_STARTUP_OPTION("database", conn->dbName);
2173 432 : if (conn->replication && conn->replication[0])
2174 0 : ADD_STARTUP_OPTION("replication", conn->replication);
2175 432 : if (conn->pgoptions && conn->pgoptions[0])
2176 432 : ADD_STARTUP_OPTION("options", conn->pgoptions);
2177 432 : if (conn->send_appname)
2178 : {
2179 : /* Use appname if present, otherwise use fallback */
2180 432 : val = conn->appname ? conn->appname : conn->fbappname;
2181 432 : if (val && val[0])
2182 432 : ADD_STARTUP_OPTION("application_name", val);
2183 : }
2184 :
2185 432 : if (conn->client_encoding_initial && conn->client_encoding_initial[0])
2186 4 : ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial);
2187 :
2188 : /* Add any environment-driven GUC settings needed */
2189 1728 : for (next_eo = options; next_eo->envName; next_eo++)
2190 : {
2191 1296 : if ((val = getenv(next_eo->envName)) != NULL)
2192 : {
2193 864 : if (pg_strcasecmp(val, "default") != 0)
2194 864 : ADD_STARTUP_OPTION(next_eo->pgName, val);
2195 : }
2196 : }
2197 :
2198 : /* Add trailing terminator */
2199 432 : if (packet)
2200 216 : packet[packet_len] = '\0';
2201 432 : packet_len++;
2202 :
2203 432 : return packet_len;
2204 : }
|