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-2008, PostgreSQL Global Development Group
25 * Portions Copyright (c) 1994, Regents of the University of California
27 * $PostgreSQL: pgsql/src/backend/libpq/pqformat.c,v 1.47 2008/01/01 19:45:49 momjian Exp $
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_endmessage - send the completed message to the frontend
45 * Note: it is also possible to append data to the StringInfo buffer using
46 * the regular StringInfo routines, but this is discouraged since required
47 * character set conversion may not occur.
49 * typsend support (construct a bytea value containing external binary data):
50 * pq_begintypsend - initialize StringInfo buffer
51 * pq_endtypsend - return the completed string as a "bytea*"
53 * Special-case message output:
54 * pq_puttextmessage - generate a character set-converted message in one step
55 * pq_putemptymessage - convenience routine for message with empty body
57 * Message parsing after input:
58 * pq_getmsgbyte - get a raw byte from a message buffer
59 * pq_getmsgint - get a binary integer from a message buffer
60 * pq_getmsgint64 - get a binary 8-byte int from a message buffer
61 * pq_getmsgfloat4 - get a float4 from a message buffer
62 * pq_getmsgfloat8 - get a float8 from a message buffer
63 * pq_getmsgbytes - get raw data from a message buffer
64 * pq_copymsgbytes - copy raw data from a message buffer
65 * pq_getmsgtext - get a counted text string (with conversion)
66 * pq_getmsgstring - get a null-terminated text string (with conversion)
67 * pq_getmsgend - verify message fully consumed
72 #include <sys/param.h>
73 #include <netinet/in.h>
74 #include <arpa/inet.h>
76 #include "libpq/libpq.h"
77 #include "libpq/pqformat.h"
78 #include "mb/pg_wchar.h"
81 /* --------------------------------
82 * pq_beginmessage - initialize for sending a message
83 * --------------------------------
86 pq_beginmessage(StringInfo buf, char msgtype)
91 * We stash the message type into the buffer's cursor field, expecting
92 * that the pq_sendXXX routines won't touch it. We could alternatively
93 * make it the first byte of the buffer contents, but this seems easier.
95 buf->cursor = msgtype;
98 /* --------------------------------
99 * pq_sendbyte - append a raw byte to a StringInfo buffer
100 * --------------------------------
103 pq_sendbyte(StringInfo buf, int byt)
105 appendStringInfoCharMacro(buf, byt);
108 /* --------------------------------
109 * pq_sendbytes - append raw data to a StringInfo buffer
110 * --------------------------------
113 pq_sendbytes(StringInfo buf, const char *data, int datalen)
115 appendBinaryStringInfo(buf, data, datalen);
118 /* --------------------------------
119 * pq_sendcountedtext - append a counted text string (with character set conversion)
121 * The data sent to the frontend by this routine is a 4-byte count field
122 * followed by the string. The count includes itself or not, as per the
123 * countincludesself flag (pre-3.0 protocol requires it to include itself).
124 * The passed text string need not be null-terminated, and the data sent
125 * to the frontend isn't either.
126 * --------------------------------
129 pq_sendcountedtext(StringInfo buf, const char *str, int slen,
130 bool countincludesself)
132 int extra = countincludesself ? 4 : 0;
135 p = pg_server_to_client(str, slen);
136 if (p != str) /* actual conversion has been done? */
139 pq_sendint(buf, slen + extra, 4);
140 appendBinaryStringInfo(buf, p, slen);
145 pq_sendint(buf, slen + extra, 4);
146 appendBinaryStringInfo(buf, str, slen);
150 /* --------------------------------
151 * pq_sendtext - append a text string (with conversion)
153 * The passed text string need not be null-terminated, and the data sent
154 * to the frontend isn't either. Note that this is not actually useful
155 * for direct frontend transmissions, since there'd be no way for the
156 * frontend to determine the string length. But it is useful for binary
157 * format conversions.
158 * --------------------------------
161 pq_sendtext(StringInfo buf, const char *str, int slen)
165 p = pg_server_to_client(str, slen);
166 if (p != str) /* actual conversion has been done? */
169 appendBinaryStringInfo(buf, p, slen);
173 appendBinaryStringInfo(buf, str, slen);
176 /* --------------------------------
177 * pq_sendstring - append a null-terminated text string (with conversion)
179 * NB: passed text string must be null-terminated, and so is the data
180 * sent to the frontend.
181 * --------------------------------
184 pq_sendstring(StringInfo buf, const char *str)
186 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_sendint - append a binary integer to a StringInfo buffer
203 * --------------------------------
206 pq_sendint(StringInfo buf, int i, int b)
215 n8 = (unsigned char) i;
216 appendBinaryStringInfo(buf, (char *) &n8, 1);
219 n16 = htons((uint16) i);
220 appendBinaryStringInfo(buf, (char *) &n16, 2);
223 n32 = htonl((uint32) i);
224 appendBinaryStringInfo(buf, (char *) &n32, 4);
227 elog(ERROR, "unsupported integer size %d", b);
232 /* --------------------------------
233 * pq_sendint64 - append a binary 8-byte int to a StringInfo buffer
235 * It is tempting to merge this with pq_sendint, but we'd have to make the
236 * argument int64 for all data widths --- that could be a big performance
237 * hit on machines where int64 isn't efficient.
238 * --------------------------------
241 pq_sendint64(StringInfo buf, int64 i)
245 /* High order half first, since we're doing MSB-first */
246 #ifdef INT64_IS_BUSTED
247 /* don't try a right shift of 32 on a 32-bit word */
248 n32 = (i < 0) ? -1 : 0;
250 n32 = (uint32) (i >> 32);
253 appendBinaryStringInfo(buf, (char *) &n32, 4);
255 /* Now the low order half */
258 appendBinaryStringInfo(buf, (char *) &n32, 4);
261 /* --------------------------------
262 * pq_sendfloat4 - append a float4 to a StringInfo buffer
264 * The point of this routine is to localize knowledge of the external binary
265 * representation of float4, which is a component of several datatypes.
267 * We currently assume that float4 should be byte-swapped in the same way
268 * as int4. This rule is not perfect but it gives us portability across
269 * most IEEE-float-using architectures.
270 * --------------------------------
273 pq_sendfloat4(StringInfo buf, float4 f)
282 swap.i = htonl(swap.i);
284 appendBinaryStringInfo(buf, (char *) &swap.i, 4);
287 /* --------------------------------
288 * pq_sendfloat8 - append a float8 to a StringInfo buffer
290 * The point of this routine is to localize knowledge of the external binary
291 * representation of float8, which is a component of several datatypes.
293 * We currently assume that float8 should be byte-swapped in the same way
294 * as int8. This rule is not perfect but it gives us portability across
295 * most IEEE-float-using architectures.
296 * --------------------------------
299 pq_sendfloat8(StringInfo buf, float8 f)
301 #ifdef INT64_IS_BUSTED
309 swap.h[0] = htonl(swap.h[0]);
310 swap.h[1] = htonl(swap.h[1]);
312 #ifdef WORDS_BIGENDIAN
313 /* machine seems to be big-endian, send h[0] first */
314 appendBinaryStringInfo(buf, (char *) &swap.h[0], 4);
315 appendBinaryStringInfo(buf, (char *) &swap.h[1], 4);
317 /* machine seems to be little-endian, send h[1] first */
318 appendBinaryStringInfo(buf, (char *) &swap.h[1], 4);
319 appendBinaryStringInfo(buf, (char *) &swap.h[0], 4);
321 #else /* INT64 works */
329 pq_sendint64(buf, swap.i);
333 /* --------------------------------
334 * pq_endmessage - send the completed message to the frontend
336 * The data buffer is pfree()d, but if the StringInfo was allocated with
337 * makeStringInfo then the caller must still pfree it.
338 * --------------------------------
341 pq_endmessage(StringInfo buf)
343 /* msgtype was saved in cursor field */
344 (void) pq_putmessage(buf->cursor, buf->data, buf->len);
345 /* no need to complain about any failure, since pqcomm.c already did */
351 /* --------------------------------
352 * pq_begintypsend - initialize for constructing a bytea result
353 * --------------------------------
356 pq_begintypsend(StringInfo buf)
359 /* Reserve four bytes for the bytea length word */
360 appendStringInfoCharMacro(buf, '\0');
361 appendStringInfoCharMacro(buf, '\0');
362 appendStringInfoCharMacro(buf, '\0');
363 appendStringInfoCharMacro(buf, '\0');
366 /* --------------------------------
367 * pq_endtypsend - finish constructing a bytea result
369 * The data buffer is returned as the palloc'd bytea value. (We expect
370 * that it will be suitably aligned for this because it has been palloc'd.)
371 * We assume the StringInfoData is just a local variable in the caller and
372 * need not be pfree'd.
373 * --------------------------------
376 pq_endtypsend(StringInfo buf)
378 bytea *result = (bytea *) buf->data;
380 /* Insert correct length into bytea length word */
381 Assert(buf->len >= VARHDRSZ);
382 SET_VARSIZE(result, buf->len);
388 /* --------------------------------
389 * pq_puttextmessage - generate a character set-converted message in one step
391 * This is the same as the pqcomm.c routine pq_putmessage, except that
392 * the message body is a null-terminated string to which encoding
393 * conversion applies.
394 * --------------------------------
397 pq_puttextmessage(char msgtype, const char *str)
399 int slen = strlen(str);
402 p = pg_server_to_client(str, slen);
403 if (p != str) /* actual conversion has been done? */
405 (void) pq_putmessage(msgtype, p, strlen(p) + 1);
409 (void) pq_putmessage(msgtype, str, slen + 1);
413 /* --------------------------------
414 * pq_putemptymessage - convenience routine for message with empty body
415 * --------------------------------
418 pq_putemptymessage(char msgtype)
420 (void) pq_putmessage(msgtype, NULL, 0);
424 /* --------------------------------
425 * pq_getmsgbyte - get a raw byte from a message buffer
426 * --------------------------------
429 pq_getmsgbyte(StringInfo msg)
431 if (msg->cursor >= msg->len)
433 (errcode(ERRCODE_PROTOCOL_VIOLATION),
434 errmsg("no data left in message")));
435 return (unsigned char) msg->data[msg->cursor++];
438 /* --------------------------------
439 * pq_getmsgint - get a binary integer from a message buffer
441 * Values are treated as unsigned.
442 * --------------------------------
445 pq_getmsgint(StringInfo msg, int b)
455 pq_copymsgbytes(msg, (char *) &n8, 1);
459 pq_copymsgbytes(msg, (char *) &n16, 2);
463 pq_copymsgbytes(msg, (char *) &n32, 4);
467 elog(ERROR, "unsupported integer size %d", b);
468 result = 0; /* keep compiler quiet */
474 /* --------------------------------
475 * pq_getmsgint64 - get a binary 8-byte int from a message buffer
477 * It is tempting to merge this with pq_getmsgint, but we'd have to make the
478 * result int64 for all data widths --- that could be a big performance
479 * hit on machines where int64 isn't efficient.
480 * --------------------------------
483 pq_getmsgint64(StringInfo msg)
489 pq_copymsgbytes(msg, (char *) &h32, 4);
490 pq_copymsgbytes(msg, (char *) &l32, 4);
494 #ifdef INT64_IS_BUSTED
495 /* error out if incoming value is wider than 32 bits */
497 if ((result < 0) ? (h32 != -1) : (h32 != 0))
499 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
500 errmsg("binary value is out of range for type bigint")));
510 /* --------------------------------
511 * pq_getmsgfloat4 - get a float4 from a message buffer
513 * See notes for pq_sendfloat4.
514 * --------------------------------
517 pq_getmsgfloat4(StringInfo msg)
525 swap.i = pq_getmsgint(msg, 4);
529 /* --------------------------------
530 * pq_getmsgfloat8 - get a float8 from a message buffer
532 * See notes for pq_sendfloat8.
533 * --------------------------------
536 pq_getmsgfloat8(StringInfo msg)
538 #ifdef INT64_IS_BUSTED
545 #ifdef WORDS_BIGENDIAN
546 /* machine seems to be big-endian, receive h[0] first */
547 swap.h[0] = pq_getmsgint(msg, 4);
548 swap.h[1] = pq_getmsgint(msg, 4);
550 /* machine seems to be little-endian, receive h[1] first */
551 swap.h[1] = pq_getmsgint(msg, 4);
552 swap.h[0] = pq_getmsgint(msg, 4);
555 #else /* INT64 works */
562 swap.i = pq_getmsgint64(msg);
567 /* --------------------------------
568 * pq_getmsgbytes - get raw data from a message buffer
570 * Returns a pointer directly into the message buffer; note this
571 * may not have any particular alignment.
572 * --------------------------------
575 pq_getmsgbytes(StringInfo msg, int datalen)
579 if (datalen < 0 || datalen > (msg->len - msg->cursor))
581 (errcode(ERRCODE_PROTOCOL_VIOLATION),
582 errmsg("insufficient data left in message")));
583 result = &msg->data[msg->cursor];
584 msg->cursor += datalen;
588 /* --------------------------------
589 * pq_copymsgbytes - copy raw data from a message buffer
591 * Same as above, except data is copied to caller's buffer.
592 * --------------------------------
595 pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
597 if (datalen < 0 || datalen > (msg->len - msg->cursor))
599 (errcode(ERRCODE_PROTOCOL_VIOLATION),
600 errmsg("insufficient data left in message")));
601 memcpy(buf, &msg->data[msg->cursor], datalen);
602 msg->cursor += datalen;
605 /* --------------------------------
606 * pq_getmsgtext - get a counted text string (with conversion)
608 * Always returns a pointer to a freshly palloc'd result.
609 * The result has a trailing null, *and* we return its strlen in *nbytes.
610 * --------------------------------
613 pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
618 if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor))
620 (errcode(ERRCODE_PROTOCOL_VIOLATION),
621 errmsg("insufficient data left in message")));
622 str = &msg->data[msg->cursor];
623 msg->cursor += rawbytes;
625 p = pg_client_to_server(str, rawbytes);
626 if (p != str) /* actual conversion has been done? */
630 p = (char *) palloc(rawbytes + 1);
631 memcpy(p, str, rawbytes);
638 /* --------------------------------
639 * pq_getmsgstring - get a null-terminated text string (with conversion)
641 * May return a pointer directly into the message buffer, or a pointer
642 * to a palloc'd conversion result.
643 * --------------------------------
646 pq_getmsgstring(StringInfo msg)
651 str = &msg->data[msg->cursor];
654 * It's safe to use strlen() here because a StringInfo is guaranteed to
655 * have a trailing null byte. But check we found a null inside the
659 if (msg->cursor + slen >= msg->len)
661 (errcode(ERRCODE_PROTOCOL_VIOLATION),
662 errmsg("invalid string in message")));
663 msg->cursor += slen + 1;
665 return pg_client_to_server(str, slen);
668 /* --------------------------------
669 * pq_getmsgend - verify message fully consumed
670 * --------------------------------
673 pq_getmsgend(StringInfo msg)
675 if (msg->cursor != msg->len)
677 (errcode(ERRCODE_PROTOCOL_VIOLATION),
678 errmsg("invalid message format")));