1 /*-------------------------------------------------------------------------
4 * functions that are specific to frontend/backend protocol version 3
6 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/interfaces/libpq/fe-protocol3.c
13 *-------------------------------------------------------------------------
15 #include "postgres_fe.h"
21 #include "libpq-int.h"
23 #include "mb/pg_wchar.h"
29 #include <netinet/in.h>
30 #ifdef HAVE_NETINET_TCP_H
31 #include <netinet/tcp.h>
33 #include <arpa/inet.h>
38 * This macro lists the backend message types that could be "long" (more
39 * than a couple of kilobytes).
41 #define VALID_LONG_MESSAGE_TYPE(id) \
42 ((id) == 'T' || (id) == 'D' || (id) == 'd' || (id) == 'V' || \
43 (id) == 'E' || (id) == 'N' || (id) == 'A')
46 static void handleSyncLoss(PGconn *conn, char id, int msgLength);
47 static int getRowDescriptions(PGconn *conn, int msgLength);
48 static int getParamDescriptions(PGconn *conn);
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);
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.
66 pqParseInput3(PGconn *conn)
73 * Loop to parse successive complete messages available in the buffer.
78 * Try to read a message. First get the type code and length. Return
81 conn->inCursor = conn->inStart;
82 if (pqGetc(&id, conn))
84 if (pqGetInt(&msgLength, 4, conn))
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
94 handleSyncLoss(conn, id, msgLength);
97 if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
99 handleSyncLoss(conn, id, msgLength);
104 * Can't process if message body isn't all here yet.
107 avail = conn->inEnd - conn->inCursor;
108 if (avail < msgLength)
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
118 if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
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
127 handleSyncLoss(conn, id, msgLength);
133 * NOTIFY and NOTICE messages can happen in any state; always process
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.)
140 * However, if the state is IDLE then we got trouble; we need to deal
141 * with the unexpected message somehow.
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
155 if (pqGetErrorNotice3(conn, false))
158 else if (conn->asyncStatus != PGASYNC_BUSY)
160 /* If not IDLE state, just wait ... */
161 if (conn->asyncStatus != PGASYNC_IDLE)
165 * Unexpected message in IDLE state; need to recover somehow.
166 * ERROR messages are displayed 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
175 if (pqGetErrorNotice3(conn, false /* treat as notice */ ))
180 if (getParameterStatus(conn))
185 pqInternalNotice(&conn->noticeHooks,
186 "message type 0x%02x arrived from server while idle",
188 /* Discard the unexpected message */
189 conn->inCursor += msgLength;
195 * In BUSY state, we can process everything.
199 case 'C': /* command complete */
200 if (pqGets(&conn->workBuffer, conn))
202 if (conn->result == NULL)
204 conn->result = PQmakeEmptyPGresult(conn,
209 strncpy(conn->result->cmdStatus, conn->workBuffer.data,
211 conn->asyncStatus = PGASYNC_READY;
213 case 'E': /* error return */
214 if (pqGetErrorNotice3(conn, true))
216 conn->asyncStatus = PGASYNC_READY;
218 case 'Z': /* backend is ready for new query */
219 if (getReadyForQuery(conn))
221 conn->asyncStatus = PGASYNC_IDLE;
223 case 'I': /* empty query */
224 if (conn->result == NULL)
226 conn->result = PQmakeEmptyPGresult(conn,
231 conn->asyncStatus = PGASYNC_READY;
233 case '1': /* Parse Complete */
234 /* If we're doing PQprepare, we're done; else ignore */
235 if (conn->queryclass == PGQUERY_PREPARE)
237 if (conn->result == NULL)
239 conn->result = PQmakeEmptyPGresult(conn,
244 conn->asyncStatus = PGASYNC_READY;
247 case '2': /* Bind Complete */
248 case '3': /* Close Complete */
249 /* Nothing to do for these message types */
251 case 'S': /* parameter status */
252 if (getParameterStatus(conn))
255 case 'K': /* secret key data from the backend */
258 * This is expected only during backend startup, but it's
259 * just as easy to handle it as part of the main loop.
260 * Save the data and continue processing.
262 if (pqGetInt(&(conn->be_pid), 4, conn))
264 if (pqGetInt(&(conn->be_key), 4, conn))
267 case 'T': /* Row Description */
268 if (conn->result == NULL ||
269 conn->queryclass == PGQUERY_DESCRIBE)
271 /* First 'T' in a query sequence */
272 if (getRowDescriptions(conn, msgLength))
274 /* getRowDescriptions() moves inStart itself */
280 * A new 'T' message is treated as the start of
281 * another PGresult. (It is not clear that this is
282 * really possible with the current backend.) We stop
283 * parsing until the application accepts the current
286 conn->asyncStatus = PGASYNC_READY;
290 case 'n': /* No Data */
293 * NoData indicates that we will not be seeing a
294 * RowDescription message because the statement or portal
295 * inquired about doesn't return rows.
297 * If we're doing a Describe, we have to pass something
298 * back to the client, so set up a COMMAND_OK result,
299 * instead of TUPLES_OK. Otherwise we can just ignore
302 if (conn->queryclass == PGQUERY_DESCRIBE)
304 if (conn->result == NULL)
306 conn->result = PQmakeEmptyPGresult(conn,
311 conn->asyncStatus = PGASYNC_READY;
314 case 't': /* Parameter Description */
315 if (getParamDescriptions(conn))
318 case 'D': /* Data Row */
319 if (conn->result != NULL &&
320 conn->result->resultStatus == PGRES_TUPLES_OK)
322 /* Read another tuple of a normal query response */
323 if (getAnotherTuple(conn, msgLength))
325 /* getAnotherTuple() moves inStart itself */
328 else if (conn->result != NULL &&
329 conn->result->resultStatus == PGRES_FATAL_ERROR)
332 * We've already choked for some reason. Just discard
333 * tuples till we get to the end of the query.
335 conn->inCursor += msgLength;
339 /* Set up to report error at end of query */
340 printfPQExpBuffer(&conn->errorMessage,
341 libpq_gettext("server sent data (\"D\" message) without prior row description (\"T\" message)\n"));
342 pqSaveErrorResult(conn);
343 /* Discard the unexpected message */
344 conn->inCursor += msgLength;
347 case 'G': /* Start Copy In */
348 if (getCopyStart(conn, PGRES_COPY_IN))
350 conn->asyncStatus = PGASYNC_COPY_IN;
352 case 'H': /* Start Copy Out */
353 if (getCopyStart(conn, PGRES_COPY_OUT))
355 conn->asyncStatus = PGASYNC_COPY_OUT;
356 conn->copy_already_done = 0;
358 case 'W': /* Start Copy Both */
359 if (getCopyStart(conn, PGRES_COPY_BOTH))
361 conn->asyncStatus = PGASYNC_COPY_BOTH;
362 conn->copy_already_done = 0;
364 case 'd': /* Copy Data */
367 * If we see Copy Data, just silently drop it. This would
368 * only occur if application exits COPY OUT mode too
371 conn->inCursor += msgLength;
373 case 'c': /* Copy Done */
376 * If we see Copy Done, just silently drop it. This is
377 * the normal case during PQendcopy. We will keep
378 * swallowing data, expecting to see command-complete for
383 printfPQExpBuffer(&conn->errorMessage,
385 "unexpected response from server; first received character was \"%c\"\n"),
387 /* build an error result holding the error message */
388 pqSaveErrorResult(conn);
389 /* not sure if we will see more, so go to ready state */
390 conn->asyncStatus = PGASYNC_READY;
391 /* Discard the unexpected message */
392 conn->inCursor += msgLength;
394 } /* switch on protocol character */
396 /* Successfully consumed this message */
397 if (conn->inCursor == conn->inStart + 5 + msgLength)
399 /* Normal case: parsing agrees with specified length */
400 conn->inStart = conn->inCursor;
404 /* Trouble --- report it */
405 printfPQExpBuffer(&conn->errorMessage,
406 libpq_gettext("message contents do not agree with length in message type \"%c\"\n"),
408 /* build an error result holding the error message */
409 pqSaveErrorResult(conn);
410 conn->asyncStatus = PGASYNC_READY;
411 /* trust the specified message length as what to skip */
412 conn->inStart += 5 + msgLength;
418 * handleSyncLoss: clean up after loss of message-boundary sync
420 * There isn't really a lot we can do here except abandon the connection.
423 handleSyncLoss(PGconn *conn, char id, int msgLength)
425 printfPQExpBuffer(&conn->errorMessage,
427 "lost synchronization with server: got message type \"%c\", length %d\n"),
429 /* build an error result holding the error message */
430 pqSaveErrorResult(conn);
431 conn->asyncStatus = PGASYNC_READY; /* drop out of GetResult wait loop */
433 pqDropConnection(conn);
434 conn->status = CONNECTION_BAD; /* No more connection to backend */
438 * parseInput subroutine to read a 'T' (row descriptions) message.
439 * We'll build a new PGresult structure (unless called for a Describe
440 * command for a prepared statement) containing the attribute data.
441 * Returns: 0 if processed message successfully, EOF to suspend parsing
442 * (the latter case is not actually used currently).
443 * In either case, conn->inStart has been advanced past the message.
446 getRowDescriptions(PGconn *conn, int msgLength)
454 * When doing Describe for a prepared statement, there'll already be a
455 * PGresult created by getParamDescriptions, and we should fill data into
456 * that. Otherwise, create a new, empty PGresult.
458 if (conn->queryclass == PGQUERY_DESCRIBE)
461 result = conn->result;
463 result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
466 result = PQmakeEmptyPGresult(conn, PGRES_TUPLES_OK);
469 errmsg = NULL; /* means "out of memory", see below */
470 goto advance_and_error;
473 /* parseInput already read the 'T' label and message length. */
474 /* the next two bytes are the number of fields */
475 if (pqGetInt(&(result->numAttributes), 2, conn))
477 /* We should not run out of data here, so complain */
478 errmsg = libpq_gettext("insufficient data in \"T\" message");
479 goto advance_and_error;
481 nfields = result->numAttributes;
483 /* allocate space for the attribute descriptors */
486 result->attDescs = (PGresAttDesc *)
487 pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
488 if (!result->attDescs)
490 errmsg = NULL; /* means "out of memory", see below */
491 goto advance_and_error;
493 MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
496 /* result->binary is true only if ALL columns are binary */
497 result->binary = (nfields > 0) ? 1 : 0;
500 for (i = 0; i < nfields; i++)
509 if (pqGets(&conn->workBuffer, conn) ||
510 pqGetInt(&tableid, 4, conn) ||
511 pqGetInt(&columnid, 2, conn) ||
512 pqGetInt(&typid, 4, conn) ||
513 pqGetInt(&typlen, 2, conn) ||
514 pqGetInt(&atttypmod, 4, conn) ||
515 pqGetInt(&format, 2, conn))
517 /* We should not run out of data here, so complain */
518 errmsg = libpq_gettext("insufficient data in \"T\" message");
519 goto advance_and_error;
523 * Since pqGetInt treats 2-byte integers as unsigned, we need to
524 * coerce these results to signed form.
526 columnid = (int) ((int16) columnid);
527 typlen = (int) ((int16) typlen);
528 format = (int) ((int16) format);
530 result->attDescs[i].name = pqResultStrdup(result,
531 conn->workBuffer.data);
532 if (!result->attDescs[i].name)
534 errmsg = NULL; /* means "out of memory", see below */
535 goto advance_and_error;
537 result->attDescs[i].tableid = tableid;
538 result->attDescs[i].columnid = columnid;
539 result->attDescs[i].format = format;
540 result->attDescs[i].typid = typid;
541 result->attDescs[i].typlen = typlen;
542 result->attDescs[i].atttypmod = atttypmod;
548 /* Sanity check that we absorbed all the data */
549 if (conn->inCursor != conn->inStart + 5 + msgLength)
551 errmsg = libpq_gettext("extraneous data in \"T\" message");
552 goto advance_and_error;
556 conn->result = result;
558 /* Advance inStart to show that the "T" message has been processed. */
559 conn->inStart = conn->inCursor;
562 * If we're doing a Describe, we're done, and ready to pass the result
563 * back to the client.
565 if (conn->queryclass == PGQUERY_DESCRIBE)
567 conn->asyncStatus = PGASYNC_READY;
572 * We could perform additional setup for the new result set here, but for
573 * now there's nothing else to do.
576 /* And we're done. */
580 /* Discard unsaved result, if any */
581 if (result && result != conn->result)
584 /* Discard the failed message by pretending we read it */
585 conn->inStart += 5 + msgLength;
588 * Replace partially constructed result with an error result. First
589 * discard the old result to try to win back some memory.
591 pqClearAsyncResult(conn);
594 * If preceding code didn't provide an error message, assume "out of
595 * memory" was meant. The advantage of having this special case is that
596 * freeing the old result first greatly improves the odds that gettext()
597 * will succeed in providing a translation.
600 errmsg = libpq_gettext("out of memory for query result");
602 printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
603 pqSaveErrorResult(conn);
606 * Return zero to allow input parsing to continue. Subsequent "D"
607 * messages will be ignored until we get to end of data, since an error
608 * result is already set up.
614 * parseInput subroutine to read a 't' (ParameterDescription) message.
615 * We'll build a new PGresult structure containing the parameter data.
616 * Returns: 0 if completed message, EOF if not enough data yet.
618 * Note that if we run out of data, we have to release the partially
619 * constructed PGresult, and rebuild it again next time. Fortunately,
620 * that shouldn't happen often, since 't' messages usually fit in a packet.
623 getParamDescriptions(PGconn *conn)
629 result = PQmakeEmptyPGresult(conn, PGRES_COMMAND_OK);
633 /* parseInput already read the 't' label and message length. */
634 /* the next two bytes are the number of parameters */
635 if (pqGetInt(&(result->numParameters), 2, conn))
637 nparams = result->numParameters;
639 /* allocate space for the parameter descriptors */
642 result->paramDescs = (PGresParamDesc *)
643 pqResultAlloc(result, nparams * sizeof(PGresParamDesc), TRUE);
644 if (!result->paramDescs)
646 MemSet(result->paramDescs, 0, nparams * sizeof(PGresParamDesc));
649 /* get parameter info */
650 for (i = 0; i < nparams; i++)
654 if (pqGetInt(&typid, 4, conn))
656 result->paramDescs[i].typid = typid;
660 conn->result = result;
669 * parseInput subroutine to read a 'D' (row data) message.
670 * We fill rowbuf with column pointers and then call the row processor.
671 * Returns: 0 if processed message successfully, EOF to suspend parsing
672 * (the latter case is not actually used currently).
673 * In either case, conn->inStart has been advanced past the message.
676 getAnotherTuple(PGconn *conn, int msgLength)
678 PGresult *result = conn->result;
679 int nfields = result->numAttributes;
682 int tupnfields; /* # fields from tuple */
683 int vlen; /* length of the current field value */
686 /* Get the field count and make sure it's what we expect */
687 if (pqGetInt(&tupnfields, 2, conn))
689 /* We should not run out of data here, so complain */
690 errmsg = libpq_gettext("insufficient data in \"D\" message");
691 goto advance_and_error;
694 if (tupnfields != nfields)
696 errmsg = libpq_gettext("unexpected field count in \"D\" message");
697 goto advance_and_error;
700 /* Resize row buffer if needed */
701 rowbuf = conn->rowBuf;
702 if (nfields > conn->rowBufLen)
704 rowbuf = (PGdataValue *) realloc(rowbuf,
705 nfields * sizeof(PGdataValue));
708 errmsg = NULL; /* means "out of memory", see below */
709 goto advance_and_error;
711 conn->rowBuf = rowbuf;
712 conn->rowBufLen = nfields;
715 /* Scan the fields */
716 for (i = 0; i < nfields; i++)
718 /* get the value length */
719 if (pqGetInt(&vlen, 4, conn))
721 /* We should not run out of data here, so complain */
722 errmsg = libpq_gettext("insufficient data in \"D\" message");
723 goto advance_and_error;
725 rowbuf[i].len = vlen;
728 * rowbuf[i].value always points to the next address in the data
729 * buffer even if the value is NULL. This allows row processors to
730 * estimate data sizes more easily.
732 rowbuf[i].value = conn->inBuffer + conn->inCursor;
734 /* Skip over the data value */
737 if (pqSkipnchar(vlen, conn))
739 /* We should not run out of data here, so complain */
740 errmsg = libpq_gettext("insufficient data in \"D\" message");
741 goto advance_and_error;
746 /* Sanity check that we absorbed all the data */
747 if (conn->inCursor != conn->inStart + 5 + msgLength)
749 errmsg = libpq_gettext("extraneous data in \"D\" message");
750 goto advance_and_error;
753 /* Advance inStart to show that the "D" message has been processed. */
754 conn->inStart = conn->inCursor;
756 /* Process the collected row */
758 if (pqRowProcessor(conn, &errmsg))
759 return 0; /* normal, successful exit */
761 goto set_error_result; /* pqRowProcessor failed, report it */
764 /* Discard the failed message by pretending we read it */
765 conn->inStart += 5 + msgLength;
770 * Replace partially constructed result with an error result. First
771 * discard the old result to try to win back some memory.
773 pqClearAsyncResult(conn);
776 * If preceding code didn't provide an error message, assume "out of
777 * memory" was meant. The advantage of having this special case is that
778 * freeing the old result first greatly improves the odds that gettext()
779 * will succeed in providing a translation.
782 errmsg = libpq_gettext("out of memory for query result");
784 printfPQExpBuffer(&conn->errorMessage, "%s\n", errmsg);
785 pqSaveErrorResult(conn);
788 * Return zero to allow input parsing to continue. Subsequent "D"
789 * messages will be ignored until we get to end of data, since an error
790 * result is already set up.
797 * Attempt to read an Error or Notice response message.
798 * This is possible in several places, so we break it out as a subroutine.
799 * Entry: 'E' or 'N' message type and length have already been consumed.
800 * Exit: returns 0 if successfully consumed message.
801 * returns EOF if not enough data.
804 pqGetErrorNotice3(PGconn *conn, bool isError)
806 PGresult *res = NULL;
807 PQExpBufferData workBuf;
810 const char *querytext = NULL;
814 * Since the fields might be pretty long, we create a temporary
815 * PQExpBuffer rather than using conn->workBuffer. workBuffer is intended
816 * for stuff that is expected to be short. We shouldn't use
817 * conn->errorMessage either, since this might be only a notice.
819 initPQExpBuffer(&workBuf);
822 * Make a PGresult to hold the accumulated fields. We temporarily lie
823 * about the result status, so that PQmakeEmptyPGresult doesn't uselessly
824 * copy conn->errorMessage.
826 res = PQmakeEmptyPGresult(conn, PGRES_EMPTY_QUERY);
829 res->resultStatus = isError ? PGRES_FATAL_ERROR : PGRES_NONFATAL_ERROR;
832 * Read the fields and save into res.
836 if (pqGetc(&id, conn))
839 break; /* terminator found */
840 if (pqGets(&workBuf, conn))
842 pqSaveMessageField(res, id, workBuf.data);
846 * Now build the "overall" error message for PQresultErrorMessage.
848 * Also, save the SQLSTATE in conn->last_sqlstate.
850 resetPQExpBuffer(&workBuf);
851 val = PQresultErrorField(res, PG_DIAG_SEVERITY);
853 appendPQExpBuffer(&workBuf, "%s: ", val);
854 val = PQresultErrorField(res, PG_DIAG_SQLSTATE);
857 if (strlen(val) < sizeof(conn->last_sqlstate))
858 strcpy(conn->last_sqlstate, val);
859 if (conn->verbosity == PQERRORS_VERBOSE)
860 appendPQExpBuffer(&workBuf, "%s: ", val);
862 val = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
864 appendPQExpBufferStr(&workBuf, val);
865 val = PQresultErrorField(res, PG_DIAG_STATEMENT_POSITION);
868 if (conn->verbosity != PQERRORS_TERSE && conn->last_query != NULL)
870 /* emit position as a syntax cursor display */
871 querytext = conn->last_query;
872 querypos = atoi(val);
876 /* emit position as text addition to primary message */
877 /* translator: %s represents a digit string */
878 appendPQExpBuffer(&workBuf, libpq_gettext(" at character %s"),
884 val = PQresultErrorField(res, PG_DIAG_INTERNAL_POSITION);
887 querytext = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
888 if (conn->verbosity != PQERRORS_TERSE && querytext != NULL)
890 /* emit position as a syntax cursor display */
891 querypos = atoi(val);
895 /* emit position as text addition to primary message */
896 /* translator: %s represents a digit string */
897 appendPQExpBuffer(&workBuf, libpq_gettext(" at character %s"),
902 appendPQExpBufferChar(&workBuf, '\n');
903 if (conn->verbosity != PQERRORS_TERSE)
905 if (querytext && querypos > 0)
906 reportErrorPosition(&workBuf, querytext, querypos,
907 conn->client_encoding);
908 val = PQresultErrorField(res, PG_DIAG_MESSAGE_DETAIL);
910 appendPQExpBuffer(&workBuf, libpq_gettext("DETAIL: %s\n"), val);
911 val = PQresultErrorField(res, PG_DIAG_MESSAGE_HINT);
913 appendPQExpBuffer(&workBuf, libpq_gettext("HINT: %s\n"), val);
914 val = PQresultErrorField(res, PG_DIAG_INTERNAL_QUERY);
916 appendPQExpBuffer(&workBuf, libpq_gettext("QUERY: %s\n"), val);
917 val = PQresultErrorField(res, PG_DIAG_CONTEXT);
919 appendPQExpBuffer(&workBuf, libpq_gettext("CONTEXT: %s\n"), val);
921 if (conn->verbosity == PQERRORS_VERBOSE)
923 val = PQresultErrorField(res, PG_DIAG_SCHEMA_NAME);
925 appendPQExpBuffer(&workBuf,
926 libpq_gettext("SCHEMA NAME: %s\n"), val);
927 val = PQresultErrorField(res, PG_DIAG_TABLE_NAME);
929 appendPQExpBuffer(&workBuf,
930 libpq_gettext("TABLE NAME: %s\n"), val);
931 val = PQresultErrorField(res, PG_DIAG_COLUMN_NAME);
933 appendPQExpBuffer(&workBuf,
934 libpq_gettext("COLUMN NAME: %s\n"), val);
935 val = PQresultErrorField(res, PG_DIAG_DATATYPE_NAME);
937 appendPQExpBuffer(&workBuf,
938 libpq_gettext("DATATYPE NAME: %s\n"), val);
939 val = PQresultErrorField(res, PG_DIAG_CONSTRAINT_NAME);
941 appendPQExpBuffer(&workBuf,
942 libpq_gettext("CONSTRAINT NAME: %s\n"), val);
944 if (conn->verbosity == PQERRORS_VERBOSE)
949 valf = PQresultErrorField(res, PG_DIAG_SOURCE_FILE);
950 vall = PQresultErrorField(res, PG_DIAG_SOURCE_LINE);
951 val = PQresultErrorField(res, PG_DIAG_SOURCE_FUNCTION);
952 if (val || valf || vall)
954 appendPQExpBufferStr(&workBuf, libpq_gettext("LOCATION: "));
956 appendPQExpBuffer(&workBuf, libpq_gettext("%s, "), val);
957 if (valf && vall) /* unlikely we'd have just one */
958 appendPQExpBuffer(&workBuf, libpq_gettext("%s:%s"),
960 appendPQExpBufferChar(&workBuf, '\n');
965 * Either save error as current async result, or just emit the notice.
969 res->errMsg = pqResultStrdup(res, workBuf.data);
972 pqClearAsyncResult(conn);
974 appendPQExpBufferStr(&conn->errorMessage, workBuf.data);
978 /* We can cheat a little here and not copy the message. */
979 res->errMsg = workBuf.data;
980 if (res->noticeHooks.noticeRec != NULL)
981 (*res->noticeHooks.noticeRec) (res->noticeHooks.noticeRecArg, res);
985 termPQExpBuffer(&workBuf);
990 termPQExpBuffer(&workBuf);
995 * Add an error-location display to the error message under construction.
997 * The cursor location is measured in logical characters; the query string
998 * is presumed to be in the specified encoding.
1001 reportErrorPosition(PQExpBuffer msg, const char *query, int loc, int encoding)
1003 #define DISPLAY_SIZE 60 /* screen width limit, in screen cols */
1004 #define MIN_RIGHT_CUT 10 /* try to keep this far away from EOL */
1021 /* Convert loc from 1-based to 0-based; no-op if out of range */
1026 /* Need a writable copy of the query */
1027 wquery = strdup(query);
1029 return; /* fail silently if out of memory */
1032 * Each character might occupy multiple physical bytes in the string, and
1033 * in some Far Eastern character sets it might take more than one screen
1034 * column as well. We compute the starting byte offset and starting
1035 * screen column of each logical character, and store these in qidx[] and
1036 * scridx[] respectively.
1039 /* we need a safe allocation size... */
1040 slen = strlen(wquery) + 1;
1042 qidx = (int *) malloc(slen * sizeof(int));
1048 scridx = (int *) malloc(slen * sizeof(int));
1056 /* We can optimize a bit if it's a single-byte encoding */
1057 mb_encoding = (pg_encoding_max_length(encoding) != 1);
1060 * Within the scanning loop, cno is the current character's logical
1061 * number, qoffset is its offset in wquery, and scroffset is its starting
1062 * logical screen column (all indexed from 0). "loc" is the logical
1063 * character number of the error location. We scan to determine loc_line
1064 * (the 1-based line number containing loc) and ibeg/iend (first character
1065 * number and last+1 character number of the line containing loc). Note
1066 * that qidx[] and scridx[] are filled only as far as iend.
1072 iend = -1; /* -1 means not set yet */
1074 for (cno = 0; wquery[qoffset] != '\0'; cno++)
1076 char ch = wquery[qoffset];
1078 qidx[cno] = qoffset;
1079 scridx[cno] = scroffset;
1082 * Replace tabs with spaces in the writable copy. (Later we might
1083 * want to think about coping with their variable screen width, but
1087 wquery[qoffset] = ' ';
1090 * If end-of-line, count lines and mark positions. Each \r or \n
1091 * counts as a line except when \r \n appear together.
1093 else if (ch == '\r' || ch == '\n')
1099 wquery[qidx[cno - 1]] != '\r')
1101 /* extract beginning = last line start before loc. */
1106 /* set extract end. */
1108 /* done scanning. */
1118 w = pg_encoding_dsplen(encoding, &wquery[qoffset]);
1119 /* treat any non-tab control chars as width 1 */
1123 qoffset += pg_encoding_mblen(encoding, &wquery[qoffset]);
1127 /* We assume wide chars only exist in multibyte encodings */
1132 /* Fix up if we didn't find an end-of-line after loc */
1135 iend = cno; /* query length in chars, +1 */
1136 qidx[iend] = qoffset;
1137 scridx[iend] = scroffset;
1140 /* Print only if loc is within computed query length */
1143 /* If the line extracted is too long, we truncate it. */
1146 if (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
1149 * We first truncate right if it is enough. This code might be
1150 * off a space or so on enforcing MIN_RIGHT_CUT if there's a wide
1151 * character right there, but that should be okay.
1153 if (scridx[ibeg] + DISPLAY_SIZE >= scridx[loc] + MIN_RIGHT_CUT)
1155 while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
1161 /* Truncate right if not too close to loc. */
1162 while (scridx[loc] + MIN_RIGHT_CUT < scridx[iend])
1168 /* Truncate left if still too long. */
1169 while (scridx[iend] - scridx[ibeg] > DISPLAY_SIZE)
1177 /* truncate working copy at desired endpoint */
1178 wquery[qidx[iend]] = '\0';
1180 /* Begin building the finished message. */
1182 appendPQExpBuffer(msg, libpq_gettext("LINE %d: "), loc_line);
1184 appendPQExpBufferStr(msg, "...");
1187 * While we have the prefix in the msg buffer, compute its screen
1191 for (; i < msg->len; i += pg_encoding_mblen(encoding, &msg->data[i]))
1193 int w = pg_encoding_dsplen(encoding, &msg->data[i]);
1200 /* Finish up the LINE message line. */
1201 appendPQExpBufferStr(msg, &wquery[qidx[ibeg]]);
1203 appendPQExpBufferStr(msg, "...");
1204 appendPQExpBufferChar(msg, '\n');
1206 /* Now emit the cursor marker line. */
1207 scroffset += scridx[loc] - scridx[ibeg];
1208 for (i = 0; i < scroffset; i++)
1209 appendPQExpBufferChar(msg, ' ');
1210 appendPQExpBufferChar(msg, '^');
1211 appendPQExpBufferChar(msg, '\n');
1222 * Attempt to read a ParameterStatus message.
1223 * This is possible in several places, so we break it out as a subroutine.
1224 * Entry: 'S' message type and length have already been consumed.
1225 * Exit: returns 0 if successfully consumed message.
1226 * returns EOF if not enough data.
1229 getParameterStatus(PGconn *conn)
1231 PQExpBufferData valueBuf;
1233 /* Get the parameter name */
1234 if (pqGets(&conn->workBuffer, conn))
1236 /* Get the parameter value (could be large) */
1237 initPQExpBuffer(&valueBuf);
1238 if (pqGets(&valueBuf, conn))
1240 termPQExpBuffer(&valueBuf);
1244 pqSaveParameterStatus(conn, conn->workBuffer.data, valueBuf.data);
1245 termPQExpBuffer(&valueBuf);
1251 * Attempt to read a Notify response message.
1252 * This is possible in several places, so we break it out as a subroutine.
1253 * Entry: 'A' message type and length have already been consumed.
1254 * Exit: returns 0 if successfully consumed Notify message.
1255 * returns EOF if not enough data.
1258 getNotify(PGconn *conn)
1264 PGnotify *newNotify;
1266 if (pqGetInt(&be_pid, 4, conn))
1268 if (pqGets(&conn->workBuffer, conn))
1270 /* must save name while getting extra string */
1271 svname = strdup(conn->workBuffer.data);
1274 if (pqGets(&conn->workBuffer, conn))
1281 * Store the strings right after the PQnotify structure so it can all be
1282 * freed at once. We don't use NAMEDATALEN because we don't want to tie
1283 * this interface to a specific server name length.
1285 nmlen = strlen(svname);
1286 extralen = strlen(conn->workBuffer.data);
1287 newNotify = (PGnotify *) malloc(sizeof(PGnotify) + nmlen + extralen + 2);
1290 newNotify->relname = (char *) newNotify + sizeof(PGnotify);
1291 strcpy(newNotify->relname, svname);
1292 newNotify->extra = newNotify->relname + nmlen + 1;
1293 strcpy(newNotify->extra, conn->workBuffer.data);
1294 newNotify->be_pid = be_pid;
1295 newNotify->next = NULL;
1296 if (conn->notifyTail)
1297 conn->notifyTail->next = newNotify;
1299 conn->notifyHead = newNotify;
1300 conn->notifyTail = newNotify;
1308 * getCopyStart - process CopyInResponse, CopyOutResponse or
1309 * CopyBothResponse message
1311 * parseInput already read the message type and length.
1314 getCopyStart(PGconn *conn, ExecStatusType copytype)
1320 result = PQmakeEmptyPGresult(conn, copytype);
1324 if (pqGetc(&conn->copy_is_binary, conn))
1326 result->binary = conn->copy_is_binary;
1327 /* the next two bytes are the number of fields */
1328 if (pqGetInt(&(result->numAttributes), 2, conn))
1330 nfields = result->numAttributes;
1332 /* allocate space for the attribute descriptors */
1335 result->attDescs = (PGresAttDesc *)
1336 pqResultAlloc(result, nfields * sizeof(PGresAttDesc), TRUE);
1337 if (!result->attDescs)
1339 MemSet(result->attDescs, 0, nfields * sizeof(PGresAttDesc));
1342 for (i = 0; i < nfields; i++)
1346 if (pqGetInt(&format, 2, conn))
1350 * Since pqGetInt treats 2-byte integers as unsigned, we need to
1351 * coerce these results to signed form.
1353 format = (int) ((int16) format);
1354 result->attDescs[i].format = format;
1358 conn->result = result;
1367 * getReadyForQuery - process ReadyForQuery message
1370 getReadyForQuery(PGconn *conn)
1374 if (pqGetc(&xact_status, conn))
1376 switch (xact_status)
1379 conn->xactStatus = PQTRANS_IDLE;
1382 conn->xactStatus = PQTRANS_INTRANS;
1385 conn->xactStatus = PQTRANS_INERROR;
1388 conn->xactStatus = PQTRANS_UNKNOWN;
1396 * getCopyDataMessage - fetch next CopyData message, process async messages
1398 * Returns length word of CopyData message (> 0), or 0 if no complete
1399 * message available, -1 if end of copy, -2 if error.
1402 getCopyDataMessage(PGconn *conn)
1411 * Do we have the next input message? To make life simpler for async
1412 * callers, we keep returning 0 until the next message is fully
1413 * available, even if it is not Copy Data.
1415 conn->inCursor = conn->inStart;
1416 if (pqGetc(&id, conn))
1418 if (pqGetInt(&msgLength, 4, conn))
1422 handleSyncLoss(conn, id, msgLength);
1425 avail = conn->inEnd - conn->inCursor;
1426 if (avail < msgLength - 4)
1429 * Before returning, enlarge the input buffer if needed to hold
1430 * the whole message. See notes in parseInput.
1432 if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength - 4,
1436 * XXX add some better recovery code... plan is to skip over
1437 * the message using its length, then report an error. For the
1438 * moment, just treat this like loss of sync (which indeed it
1441 handleSyncLoss(conn, id, msgLength);
1448 * If it's a legitimate async message type, process it. (NOTIFY
1449 * messages are not currently possible here, but we handle them for
1450 * completeness.) Otherwise, if it's anything except Copy Data,
1451 * report end-of-copy.
1455 case 'A': /* NOTIFY */
1456 if (getNotify(conn))
1459 case 'N': /* NOTICE */
1460 if (pqGetErrorNotice3(conn, false))
1463 case 'S': /* ParameterStatus */
1464 if (getParameterStatus(conn))
1467 case 'd': /* Copy Data, pass it back to caller */
1472 * If this is a CopyDone message, exit COPY_OUT mode and let
1473 * caller read status with PQgetResult(). If we're in
1474 * COPY_BOTH mode, return to COPY_IN mode.
1476 if (conn->asyncStatus == PGASYNC_COPY_BOTH)
1477 conn->asyncStatus = PGASYNC_COPY_IN;
1479 conn->asyncStatus = PGASYNC_BUSY;
1481 default: /* treat as end of copy */
1484 * Any other message terminates either COPY_IN or COPY_BOTH
1487 conn->asyncStatus = PGASYNC_BUSY;
1491 /* Drop the processed message and loop around for another */
1492 conn->inStart = conn->inCursor;
1497 * PQgetCopyData - read a row of data from the backend during COPY OUT
1500 * If successful, sets *buffer to point to a malloc'd row of data, and
1501 * returns row length (always > 0) as result.
1502 * Returns 0 if no row available yet (only possible if async is true),
1503 * -1 if end of copy (consult PQgetResult), or -2 if error (consult
1507 pqGetCopyData3(PGconn *conn, char **buffer, int async)
1514 * Collect the next input message. To make life simpler for async
1515 * callers, we keep returning 0 until the next message is fully
1516 * available, even if it is not Copy Data.
1518 msgLength = getCopyDataMessage(conn);
1520 return msgLength; /* end-of-copy or error */
1523 /* Don't block if async read requested */
1526 /* Need to load more data */
1527 if (pqWait(TRUE, FALSE, conn) ||
1528 pqReadData(conn) < 0)
1534 * Drop zero-length messages (shouldn't happen anyway). Otherwise
1535 * pass the data back to the caller.
1540 *buffer = (char *) malloc(msgLength + 1);
1541 if (*buffer == NULL)
1543 printfPQExpBuffer(&conn->errorMessage,
1544 libpq_gettext("out of memory\n"));
1547 memcpy(*buffer, &conn->inBuffer[conn->inCursor], msgLength);
1548 (*buffer)[msgLength] = '\0'; /* Add terminating null */
1550 /* Mark message consumed */
1551 conn->inStart = conn->inCursor + msgLength;
1556 /* Empty, so drop it and loop around for another */
1557 conn->inStart = conn->inCursor;
1562 * PQgetline - gets a newline-terminated string from the backend.
1564 * See fe-exec.c for documentation.
1567 pqGetline3(PGconn *conn, char *s, int maxlen)
1571 if (conn->sock < 0 ||
1572 (conn->asyncStatus != PGASYNC_COPY_OUT &&
1573 conn->asyncStatus != PGASYNC_COPY_BOTH) ||
1574 conn->copy_is_binary)
1576 printfPQExpBuffer(&conn->errorMessage,
1577 libpq_gettext("PQgetline: not doing text COPY OUT\n"));
1582 while ((status = PQgetlineAsync(conn, s, maxlen - 1)) == 0)
1584 /* need to load more data */
1585 if (pqWait(TRUE, FALSE, conn) ||
1586 pqReadData(conn) < 0)
1595 /* End of copy detected; gin up old-style terminator */
1600 /* Add null terminator, and strip trailing \n if present */
1601 if (s[status - 1] == '\n')
1603 s[status - 1] = '\0';
1614 * PQgetlineAsync - gets a COPY data row without blocking.
1616 * See fe-exec.c for documentation.
1619 pqGetlineAsync3(PGconn *conn, char *buffer, int bufsize)
1624 if (conn->asyncStatus != PGASYNC_COPY_OUT
1625 && conn->asyncStatus != PGASYNC_COPY_BOTH)
1626 return -1; /* we are not doing a copy... */
1629 * Recognize the next input message. To make life simpler for async
1630 * callers, we keep returning 0 until the next message is fully available
1631 * even if it is not Copy Data. This should keep PQendcopy from blocking.
1632 * (Note: unlike pqGetCopyData3, we do not change asyncStatus here.)
1634 msgLength = getCopyDataMessage(conn);
1636 return -1; /* end-of-copy or error */
1638 return 0; /* no data yet */
1641 * Move data from libpq's buffer to the caller's. In the case where a
1642 * prior call found the caller's buffer too small, we use
1643 * conn->copy_already_done to remember how much of the row was already
1644 * returned to the caller.
1646 conn->inCursor += conn->copy_already_done;
1647 avail = msgLength - 4 - conn->copy_already_done;
1648 if (avail <= bufsize)
1650 /* Able to consume the whole message */
1651 memcpy(buffer, &conn->inBuffer[conn->inCursor], avail);
1652 /* Mark message consumed */
1653 conn->inStart = conn->inCursor + avail;
1654 /* Reset state for next time */
1655 conn->copy_already_done = 0;
1660 /* We must return a partial message */
1661 memcpy(buffer, &conn->inBuffer[conn->inCursor], bufsize);
1662 /* The message is NOT consumed from libpq's buffer */
1663 conn->copy_already_done += bufsize;
1671 * See fe-exec.c for documentation.
1674 pqEndcopy3(PGconn *conn)
1678 if (conn->asyncStatus != PGASYNC_COPY_IN &&
1679 conn->asyncStatus != PGASYNC_COPY_OUT &&
1680 conn->asyncStatus != PGASYNC_COPY_BOTH)
1682 printfPQExpBuffer(&conn->errorMessage,
1683 libpq_gettext("no COPY in progress\n"));
1687 /* Send the CopyDone message if needed */
1688 if (conn->asyncStatus == PGASYNC_COPY_IN ||
1689 conn->asyncStatus == PGASYNC_COPY_BOTH)
1691 if (pqPutMsgStart('c', false, conn) < 0 ||
1692 pqPutMsgEnd(conn) < 0)
1696 * If we sent the COPY command in extended-query mode, we must issue a
1699 if (conn->queryclass != PGQUERY_SIMPLE)
1701 if (pqPutMsgStart('S', false, conn) < 0 ||
1702 pqPutMsgEnd(conn) < 0)
1708 * make sure no data is waiting to be sent, abort if we are non-blocking
1709 * and the flush fails
1711 if (pqFlush(conn) && pqIsnonblocking(conn))
1714 /* Return to active duty */
1715 conn->asyncStatus = PGASYNC_BUSY;
1716 resetPQExpBuffer(&conn->errorMessage);
1719 * Non blocking connections may have to abort at this point. If everyone
1720 * played the game there should be no problem, but in error scenarios the
1721 * expected messages may not have arrived yet. (We are assuming that the
1722 * backend's packetizing will ensure that CommandComplete arrives along
1723 * with the CopyDone; are there corner cases where that doesn't happen?)
1725 if (pqIsnonblocking(conn) && PQisBusy(conn))
1728 /* Wait for the completion response */
1729 result = PQgetResult(conn);
1731 /* Expecting a successful result */
1732 if (result && result->resultStatus == PGRES_COMMAND_OK)
1739 * Trouble. For backwards-compatibility reasons, we issue the error
1740 * message as if it were a notice (would be nice to get rid of this
1741 * silliness, but too many apps probably don't handle errors from
1742 * PQendcopy reasonably). Note that the app can still obtain the error
1743 * status from the PGconn object.
1745 if (conn->errorMessage.len > 0)
1747 /* We have to strip the trailing newline ... pain in neck... */
1748 char svLast = conn->errorMessage.data[conn->errorMessage.len - 1];
1751 conn->errorMessage.data[conn->errorMessage.len - 1] = '\0';
1752 pqInternalNotice(&conn->noticeHooks, "%s", conn->errorMessage.data);
1753 conn->errorMessage.data[conn->errorMessage.len - 1] = svLast;
1763 * PQfn - Send a function call to the POSTGRES backend.
1765 * See fe-exec.c for documentation.
1768 pqFunctionCall3(PGconn *conn, Oid fnid,
1769 int *result_buf, int *actual_result_len,
1771 const PQArgBlock *args, int nargs)
1773 bool needInput = false;
1774 ExecStatusType status = PGRES_FATAL_ERROR;
1780 /* PQfn already validated connection state */
1782 if (pqPutMsgStart('F', false, conn) < 0 || /* function call msg */
1783 pqPutInt(fnid, 4, conn) < 0 || /* function id */
1784 pqPutInt(1, 2, conn) < 0 || /* # of format codes */
1785 pqPutInt(1, 2, conn) < 0 || /* format code: BINARY */
1786 pqPutInt(nargs, 2, conn) < 0) /* # of args */
1788 pqHandleSendFailure(conn);
1792 for (i = 0; i < nargs; ++i)
1793 { /* len.int4 + contents */
1794 if (pqPutInt(args[i].len, 4, conn))
1796 pqHandleSendFailure(conn);
1799 if (args[i].len == -1)
1800 continue; /* it's NULL */
1804 if (pqPutInt(args[i].u.integer, args[i].len, conn))
1806 pqHandleSendFailure(conn);
1812 if (pqPutnchar((char *) args[i].u.ptr, args[i].len, conn))
1814 pqHandleSendFailure(conn);
1820 if (pqPutInt(1, 2, conn) < 0) /* result format code: BINARY */
1822 pqHandleSendFailure(conn);
1826 if (pqPutMsgEnd(conn) < 0 ||
1829 pqHandleSendFailure(conn);
1837 /* Wait for some data to arrive (or for the channel to close) */
1838 if (pqWait(TRUE, FALSE, conn) ||
1839 pqReadData(conn) < 0)
1844 * Scan the message. If we run out of data, loop around to try again.
1848 conn->inCursor = conn->inStart;
1849 if (pqGetc(&id, conn))
1851 if (pqGetInt(&msgLength, 4, conn))
1855 * Try to validate message type/length here. A length less than 4 is
1856 * definitely broken. Large lengths should only be believed for a few
1861 handleSyncLoss(conn, id, msgLength);
1864 if (msgLength > 30000 && !VALID_LONG_MESSAGE_TYPE(id))
1866 handleSyncLoss(conn, id, msgLength);
1871 * Can't process if message body isn't all here yet.
1874 avail = conn->inEnd - conn->inCursor;
1875 if (avail < msgLength)
1878 * Before looping, enlarge the input buffer if needed to hold the
1879 * whole message. See notes in parseInput.
1881 if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
1885 * XXX add some better recovery code... plan is to skip over
1886 * the message using its length, then report an error. For the
1887 * moment, just treat this like loss of sync (which indeed it
1890 handleSyncLoss(conn, id, msgLength);
1897 * We should see V or E response to the command, but might get N
1898 * and/or A notices first. We also need to swallow the final Z before
1903 case 'V': /* function result */
1904 if (pqGetInt(actual_result_len, 4, conn))
1906 if (*actual_result_len != -1)
1910 if (pqGetInt(result_buf, *actual_result_len, conn))
1915 if (pqGetnchar((char *) result_buf,
1921 /* correctly finished function result message */
1922 status = PGRES_COMMAND_OK;
1924 case 'E': /* error return */
1925 if (pqGetErrorNotice3(conn, true))
1927 status = PGRES_FATAL_ERROR;
1929 case 'A': /* notify message */
1930 /* handle notify and go back to processing return values */
1931 if (getNotify(conn))
1934 case 'N': /* notice */
1935 /* handle notice and go back to processing return values */
1936 if (pqGetErrorNotice3(conn, false))
1939 case 'Z': /* backend is ready for new query */
1940 if (getReadyForQuery(conn))
1942 /* consume the message and exit */
1943 conn->inStart += 5 + msgLength;
1944 /* if we saved a result object (probably an error), use it */
1946 return pqPrepareAsyncResult(conn);
1947 return PQmakeEmptyPGresult(conn, status);
1948 case 'S': /* parameter status */
1949 if (getParameterStatus(conn))
1953 /* The backend violates the protocol. */
1954 printfPQExpBuffer(&conn->errorMessage,
1955 libpq_gettext("protocol error: id=0x%x\n"),
1957 pqSaveErrorResult(conn);
1958 /* trust the specified message length as what to skip */
1959 conn->inStart += 5 + msgLength;
1960 return pqPrepareAsyncResult(conn);
1962 /* Completed this message, keep going */
1963 /* trust the specified message length as what to skip */
1964 conn->inStart += 5 + msgLength;
1969 * We fall out of the loop only upon failing to read data.
1970 * conn->errorMessage has been set by pqWait or pqReadData. We want to
1971 * append it to any already-received error message.
1973 pqSaveErrorResult(conn);
1974 return pqPrepareAsyncResult(conn);
1979 * Construct startup packet
1981 * Returns a malloc'd packet buffer, or NULL if out of memory
1984 pqBuildStartupPacket3(PGconn *conn, int *packetlen,
1985 const PQEnvironmentOption *options)
1989 *packetlen = build_startup_packet(conn, NULL, options);
1990 startpacket = (char *) malloc(*packetlen);
1993 *packetlen = build_startup_packet(conn, startpacket, options);
1998 * Build a startup packet given a filled-in PGconn structure.
2000 * We need to figure out how much space is needed, then fill it in.
2001 * To avoid duplicate logic, this routine is called twice: the first time
2002 * (with packet == NULL) just counts the space needed, the second time
2003 * (with packet == allocated space) fills it in. Return value is the number
2007 build_startup_packet(const PGconn *conn, char *packet,
2008 const PQEnvironmentOption *options)
2011 const PQEnvironmentOption *next_eo;
2014 /* Protocol version comes first. */
2017 ProtocolVersion pv = htonl(conn->pversion);
2019 memcpy(packet + packet_len, &pv, sizeof(ProtocolVersion));
2021 packet_len += sizeof(ProtocolVersion);
2023 /* Add user name, database name, options */
2025 #define ADD_STARTUP_OPTION(optname, optval) \
2028 strcpy(packet + packet_len, optname); \
2029 packet_len += strlen(optname) + 1; \
2031 strcpy(packet + packet_len, optval); \
2032 packet_len += strlen(optval) + 1; \
2035 if (conn->pguser && conn->pguser[0])
2036 ADD_STARTUP_OPTION("user", conn->pguser);
2037 if (conn->dbName && conn->dbName[0])
2038 ADD_STARTUP_OPTION("database", conn->dbName);
2039 if (conn->replication && conn->replication[0])
2040 ADD_STARTUP_OPTION("replication", conn->replication);
2041 if (conn->pgoptions && conn->pgoptions[0])
2042 ADD_STARTUP_OPTION("options", conn->pgoptions);
2043 if (conn->send_appname)
2045 /* Use appname if present, otherwise use fallback */
2046 val = conn->appname ? conn->appname : conn->fbappname;
2048 ADD_STARTUP_OPTION("application_name", val);
2051 if (conn->client_encoding_initial && conn->client_encoding_initial[0])
2052 ADD_STARTUP_OPTION("client_encoding", conn->client_encoding_initial);
2054 /* Add any environment-driven GUC settings needed */
2055 for (next_eo = options; next_eo->envName; next_eo++)
2057 if ((val = getenv(next_eo->envName)) != NULL)
2059 if (pg_strcasecmp(val, "default") != 0)
2060 ADD_STARTUP_OPTION(next_eo->pgName, val);
2064 /* Add trailing terminator */
2066 packet[packet_len] = '\0';