1 /*-------------------------------------------------------------------------
4 * Routines for formatting and parsing frontend/backend messages
6 * Outgoing messages are built up in a StringInfo buffer (which is expansible)
7 * and then sent in a single call to pq_putmessage. This module provides data
8 * formatting/conversion routines that are needed to produce valid messages.
9 * Note in particular the distinction between "raw data" and "text"; raw data
10 * is message protocol characters and binary values that are not subject to
11 * character set conversion, while text is converted by character encoding
14 * Incoming messages are similarly read into a StringInfo buffer, via
15 * pq_getmessage, and then parsed and converted from that using the routines
18 * These same routines support reading and writing of external binary formats
19 * (typsend/typreceive routines). The conversion routines for individual
20 * data types are exactly the same, only initialization and completion
24 * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
25 * Portions Copyright (c) 1994, Regents of the University of California
27 * src/backend/libpq/pqformat.c
29 *-------------------------------------------------------------------------
33 * Message assembly and output:
34 * pq_beginmessage - initialize StringInfo buffer
35 * pq_sendbyte - append a raw byte to a StringInfo buffer
36 * pq_sendint - append a binary integer to a StringInfo buffer
37 * pq_sendint64 - append a binary 8-byte int to a StringInfo buffer
38 * pq_sendfloat4 - append a float4 to a StringInfo buffer
39 * pq_sendfloat8 - append a float8 to a StringInfo buffer
40 * pq_sendbytes - append raw data to a StringInfo buffer
41 * pq_sendcountedtext - append a counted text string (with character set conversion)
42 * pq_sendtext - append a text string (with conversion)
43 * pq_sendstring - append a null-terminated text string (with conversion)
44 * pq_send_ascii_string - append a null-terminated text string (without conversion)
45 * pq_endmessage - send the completed message to the frontend
46 * Note: it is also possible to append data to the StringInfo buffer using
47 * the regular StringInfo routines, but this is discouraged since required
48 * character set conversion may not occur.
50 * typsend support (construct a bytea value containing external binary data):
51 * pq_begintypsend - initialize StringInfo buffer
52 * pq_endtypsend - return the completed string as a "bytea*"
54 * Special-case message output:
55 * pq_puttextmessage - generate a character set-converted message in one step
56 * pq_putemptymessage - convenience routine for message with empty body
58 * Message parsing after input:
59 * pq_getmsgbyte - get a raw byte from a message buffer
60 * pq_getmsgint - get a binary integer from a message buffer
61 * pq_getmsgint64 - get a binary 8-byte int from a message buffer
62 * pq_getmsgfloat4 - get a float4 from a message buffer
63 * pq_getmsgfloat8 - get a float8 from a message buffer
64 * pq_getmsgbytes - get raw data from a message buffer
65 * pq_copymsgbytes - copy raw data from a message buffer
66 * pq_getmsgtext - get a counted text string (with conversion)
67 * pq_getmsgstring - get a null-terminated text string (with conversion)
68 * pq_getmsgend - verify message fully consumed
73 #include <sys/param.h>
74 #include <netinet/in.h>
75 #include <arpa/inet.h>
77 #include "libpq/libpq.h"
78 #include "libpq/pqformat.h"
79 #include "mb/pg_wchar.h"
82 /* --------------------------------
83 * pq_beginmessage - initialize for sending a message
84 * --------------------------------
87 pq_beginmessage(StringInfo buf, char msgtype)
92 * We stash the message type into the buffer's cursor field, expecting
93 * that the pq_sendXXX routines won't touch it. We could alternatively
94 * make it the first byte of the buffer contents, but this seems easier.
96 buf->cursor = msgtype;
99 /* --------------------------------
100 * pq_sendbyte - append a raw byte to a StringInfo buffer
101 * --------------------------------
104 pq_sendbyte(StringInfo buf, int byt)
106 appendStringInfoCharMacro(buf, byt);
109 /* --------------------------------
110 * pq_sendbytes - append raw data to a StringInfo buffer
111 * --------------------------------
114 pq_sendbytes(StringInfo buf, const char *data, int datalen)
116 appendBinaryStringInfo(buf, data, datalen);
119 /* --------------------------------
120 * pq_sendcountedtext - append a counted text string (with character set conversion)
122 * The data sent to the frontend by this routine is a 4-byte count field
123 * followed by the string. The count includes itself or not, as per the
124 * countincludesself flag (pre-3.0 protocol requires it to include itself).
125 * The passed text string need not be null-terminated, and the data sent
126 * to the frontend isn't either.
127 * --------------------------------
130 pq_sendcountedtext(StringInfo buf, const char *str, int slen,
131 bool countincludesself)
133 int extra = countincludesself ? 4 : 0;
136 p = pg_server_to_client(str, slen);
137 if (p != str) /* actual conversion has been done? */
140 pq_sendint(buf, slen + extra, 4);
141 appendBinaryStringInfo(buf, p, slen);
146 pq_sendint(buf, slen + extra, 4);
147 appendBinaryStringInfo(buf, str, slen);
151 /* --------------------------------
152 * pq_sendtext - append a text string (with conversion)
154 * The passed text string need not be null-terminated, and the data sent
155 * to the frontend isn't either. Note that this is not actually useful
156 * for direct frontend transmissions, since there'd be no way for the
157 * frontend to determine the string length. But it is useful for binary
158 * format conversions.
159 * --------------------------------
162 pq_sendtext(StringInfo buf, const char *str, int slen)
166 p = pg_server_to_client(str, slen);
167 if (p != str) /* actual conversion has been done? */
170 appendBinaryStringInfo(buf, p, slen);
174 appendBinaryStringInfo(buf, str, slen);
177 /* --------------------------------
178 * pq_sendstring - append a null-terminated text string (with conversion)
180 * NB: passed text string must be null-terminated, and so is the data
181 * sent to the frontend.
182 * --------------------------------
185 pq_sendstring(StringInfo buf, const char *str)
187 int slen = strlen(str);
190 p = pg_server_to_client(str, slen);
191 if (p != str) /* actual conversion has been done? */
194 appendBinaryStringInfo(buf, p, slen + 1);
198 appendBinaryStringInfo(buf, str, slen + 1);
201 /* --------------------------------
202 * pq_send_ascii_string - append a null-terminated text string (without conversion)
204 * This function intentionally bypasses encoding conversion, instead just
205 * silently replacing any non-7-bit-ASCII characters with question marks.
206 * It is used only when we are having trouble sending an error message to
207 * the client with normal localization and encoding conversion. The caller
208 * should already have taken measures to ensure the string is just ASCII;
209 * the extra work here is just to make certain we don't send a badly encoded
210 * string to the client (which might or might not be robust about that).
212 * NB: passed text string must be null-terminated, and so is the data
213 * sent to the frontend.
214 * --------------------------------
217 pq_send_ascii_string(StringInfo buf, const char *str)
223 if (IS_HIGHBIT_SET(ch))
225 appendStringInfoCharMacro(buf, ch);
227 appendStringInfoChar(buf, '\0');
230 /* --------------------------------
231 * pq_sendint - append a binary integer to a StringInfo buffer
232 * --------------------------------
235 pq_sendint(StringInfo buf, int i, int b)
244 n8 = (unsigned char) i;
245 appendBinaryStringInfo(buf, (char *) &n8, 1);
248 n16 = htons((uint16) i);
249 appendBinaryStringInfo(buf, (char *) &n16, 2);
252 n32 = htonl((uint32) i);
253 appendBinaryStringInfo(buf, (char *) &n32, 4);
256 elog(ERROR, "unsupported integer size %d", b);
261 /* --------------------------------
262 * pq_sendint64 - append a binary 8-byte int to a StringInfo buffer
264 * It is tempting to merge this with pq_sendint, but we'd have to make the
265 * argument int64 for all data widths --- that could be a big performance
266 * hit on machines where int64 isn't efficient.
267 * --------------------------------
270 pq_sendint64(StringInfo buf, int64 i)
274 /* High order half first, since we're doing MSB-first */
275 n32 = (uint32) (i >> 32);
277 appendBinaryStringInfo(buf, (char *) &n32, 4);
279 /* Now the low order half */
282 appendBinaryStringInfo(buf, (char *) &n32, 4);
285 /* --------------------------------
286 * pq_sendfloat4 - append a float4 to a StringInfo buffer
288 * The point of this routine is to localize knowledge of the external binary
289 * representation of float4, which is a component of several datatypes.
291 * We currently assume that float4 should be byte-swapped in the same way
292 * as int4. This rule is not perfect but it gives us portability across
293 * most IEEE-float-using architectures.
294 * --------------------------------
297 pq_sendfloat4(StringInfo buf, float4 f)
306 swap.i = htonl(swap.i);
308 appendBinaryStringInfo(buf, (char *) &swap.i, 4);
311 /* --------------------------------
312 * pq_sendfloat8 - append a float8 to a StringInfo buffer
314 * The point of this routine is to localize knowledge of the external binary
315 * representation of float8, which is a component of several datatypes.
317 * We currently assume that float8 should be byte-swapped in the same way
318 * as int8. This rule is not perfect but it gives us portability across
319 * most IEEE-float-using architectures.
320 * --------------------------------
323 pq_sendfloat8(StringInfo buf, float8 f)
332 pq_sendint64(buf, swap.i);
335 /* --------------------------------
336 * pq_endmessage - send the completed message to the frontend
338 * The data buffer is pfree()d, but if the StringInfo was allocated with
339 * makeStringInfo then the caller must still pfree it.
340 * --------------------------------
343 pq_endmessage(StringInfo buf)
345 /* msgtype was saved in cursor field */
346 (void) pq_putmessage(buf->cursor, buf->data, buf->len);
347 /* no need to complain about any failure, since pqcomm.c already did */
353 /* --------------------------------
354 * pq_begintypsend - initialize for constructing a bytea result
355 * --------------------------------
358 pq_begintypsend(StringInfo buf)
361 /* Reserve four bytes for the bytea length word */
362 appendStringInfoCharMacro(buf, '\0');
363 appendStringInfoCharMacro(buf, '\0');
364 appendStringInfoCharMacro(buf, '\0');
365 appendStringInfoCharMacro(buf, '\0');
368 /* --------------------------------
369 * pq_endtypsend - finish constructing a bytea result
371 * The data buffer is returned as the palloc'd bytea value. (We expect
372 * that it will be suitably aligned for this because it has been palloc'd.)
373 * We assume the StringInfoData is just a local variable in the caller and
374 * need not be pfree'd.
375 * --------------------------------
378 pq_endtypsend(StringInfo buf)
380 bytea *result = (bytea *) buf->data;
382 /* Insert correct length into bytea length word */
383 Assert(buf->len >= VARHDRSZ);
384 SET_VARSIZE(result, buf->len);
390 /* --------------------------------
391 * pq_puttextmessage - generate a character set-converted message in one step
393 * This is the same as the pqcomm.c routine pq_putmessage, except that
394 * the message body is a null-terminated string to which encoding
395 * conversion applies.
396 * --------------------------------
399 pq_puttextmessage(char msgtype, const char *str)
401 int slen = strlen(str);
404 p = pg_server_to_client(str, slen);
405 if (p != str) /* actual conversion has been done? */
407 (void) pq_putmessage(msgtype, p, strlen(p) + 1);
411 (void) pq_putmessage(msgtype, str, slen + 1);
415 /* --------------------------------
416 * pq_putemptymessage - convenience routine for message with empty body
417 * --------------------------------
420 pq_putemptymessage(char msgtype)
422 (void) pq_putmessage(msgtype, NULL, 0);
426 /* --------------------------------
427 * pq_getmsgbyte - get a raw byte from a message buffer
428 * --------------------------------
431 pq_getmsgbyte(StringInfo msg)
433 if (msg->cursor >= msg->len)
435 (errcode(ERRCODE_PROTOCOL_VIOLATION),
436 errmsg("no data left in message")));
437 return (unsigned char) msg->data[msg->cursor++];
440 /* --------------------------------
441 * pq_getmsgint - get a binary integer from a message buffer
443 * Values are treated as unsigned.
444 * --------------------------------
447 pq_getmsgint(StringInfo msg, int b)
457 pq_copymsgbytes(msg, (char *) &n8, 1);
461 pq_copymsgbytes(msg, (char *) &n16, 2);
465 pq_copymsgbytes(msg, (char *) &n32, 4);
469 elog(ERROR, "unsupported integer size %d", b);
470 result = 0; /* keep compiler quiet */
476 /* --------------------------------
477 * pq_getmsgint64 - get a binary 8-byte int from a message buffer
479 * It is tempting to merge this with pq_getmsgint, but we'd have to make the
480 * result int64 for all data widths --- that could be a big performance
481 * hit on machines where int64 isn't efficient.
482 * --------------------------------
485 pq_getmsgint64(StringInfo msg)
491 pq_copymsgbytes(msg, (char *) &h32, 4);
492 pq_copymsgbytes(msg, (char *) &l32, 4);
503 /* --------------------------------
504 * pq_getmsgfloat4 - get a float4 from a message buffer
506 * See notes for pq_sendfloat4.
507 * --------------------------------
510 pq_getmsgfloat4(StringInfo msg)
518 swap.i = pq_getmsgint(msg, 4);
522 /* --------------------------------
523 * pq_getmsgfloat8 - get a float8 from a message buffer
525 * See notes for pq_sendfloat8.
526 * --------------------------------
529 pq_getmsgfloat8(StringInfo msg)
537 swap.i = pq_getmsgint64(msg);
541 /* --------------------------------
542 * pq_getmsgbytes - get raw data from a message buffer
544 * Returns a pointer directly into the message buffer; note this
545 * may not have any particular alignment.
546 * --------------------------------
549 pq_getmsgbytes(StringInfo msg, int datalen)
553 if (datalen < 0 || datalen > (msg->len - msg->cursor))
555 (errcode(ERRCODE_PROTOCOL_VIOLATION),
556 errmsg("insufficient data left in message")));
557 result = &msg->data[msg->cursor];
558 msg->cursor += datalen;
562 /* --------------------------------
563 * pq_copymsgbytes - copy raw data from a message buffer
565 * Same as above, except data is copied to caller's buffer.
566 * --------------------------------
569 pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
571 if (datalen < 0 || datalen > (msg->len - msg->cursor))
573 (errcode(ERRCODE_PROTOCOL_VIOLATION),
574 errmsg("insufficient data left in message")));
575 memcpy(buf, &msg->data[msg->cursor], datalen);
576 msg->cursor += datalen;
579 /* --------------------------------
580 * pq_getmsgtext - get a counted text string (with conversion)
582 * Always returns a pointer to a freshly palloc'd result.
583 * The result has a trailing null, *and* we return its strlen in *nbytes.
584 * --------------------------------
587 pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
592 if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor))
594 (errcode(ERRCODE_PROTOCOL_VIOLATION),
595 errmsg("insufficient data left in message")));
596 str = &msg->data[msg->cursor];
597 msg->cursor += rawbytes;
599 p = pg_client_to_server(str, rawbytes);
600 if (p != str) /* actual conversion has been done? */
604 p = (char *) palloc(rawbytes + 1);
605 memcpy(p, str, rawbytes);
612 /* --------------------------------
613 * pq_getmsgstring - get a null-terminated text string (with conversion)
615 * May return a pointer directly into the message buffer, or a pointer
616 * to a palloc'd conversion result.
617 * --------------------------------
620 pq_getmsgstring(StringInfo msg)
625 str = &msg->data[msg->cursor];
628 * It's safe to use strlen() here because a StringInfo is guaranteed to
629 * have a trailing null byte. But check we found a null inside the
633 if (msg->cursor + slen >= msg->len)
635 (errcode(ERRCODE_PROTOCOL_VIOLATION),
636 errmsg("invalid string in message")));
637 msg->cursor += slen + 1;
639 return pg_client_to_server(str, slen);
642 /* --------------------------------
643 * pq_getmsgend - verify message fully consumed
644 * --------------------------------
647 pq_getmsgend(StringInfo msg)
649 if (msg->cursor != msg->len)
651 (errcode(ERRCODE_PROTOCOL_VIOLATION),
652 errmsg("invalid message format")));