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-2024, 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_getmsgrawstring - get a null-terminated text string - NO conversion
69 * pq_getmsgend - verify message fully consumed
74 #include <sys/param.h>
76 #include "libpq/libpq.h"
77 #include "libpq/pqformat.h"
78 #include "mb/pg_wchar.h"
79 #include "port/pg_bswap.h"
83 /* --------------------------------
84 * pq_beginmessage - initialize for sending a message
85 * --------------------------------
88 pq_beginmessage(StringInfo buf
, char msgtype
)
93 * We stash the message type into the buffer's cursor field, expecting
94 * that the pq_sendXXX routines won't touch it. We could alternatively
95 * make it the first byte of the buffer contents, but this seems easier.
97 buf
->cursor
= msgtype
;
100 /* --------------------------------
102 * pq_beginmessage_reuse - initialize for sending a message, reuse buffer
104 * This requires the buffer to be allocated in a sufficiently long-lived
106 * --------------------------------
109 pq_beginmessage_reuse(StringInfo buf
, char msgtype
)
111 resetStringInfo(buf
);
114 * We stash the message type into the buffer's cursor field, expecting
115 * that the pq_sendXXX routines won't touch it. We could alternatively
116 * make it the first byte of the buffer contents, but this seems easier.
118 buf
->cursor
= msgtype
;
121 /* --------------------------------
122 * pq_sendbytes - append raw data to a StringInfo buffer
123 * --------------------------------
126 pq_sendbytes(StringInfo buf
, const void *data
, int datalen
)
128 /* use variant that maintains a trailing null-byte, out of caution */
129 appendBinaryStringInfo(buf
, data
, datalen
);
132 /* --------------------------------
133 * pq_sendcountedtext - append a counted text string (with character set conversion)
135 * The data sent to the frontend by this routine is a 4-byte count field
136 * followed by the string. The count does not include itself, as required by
137 * protocol version 3.0. The passed text string need not be null-terminated,
138 * and the data sent to the frontend isn't either.
139 * --------------------------------
142 pq_sendcountedtext(StringInfo buf
, const char *str
, int slen
)
146 p
= pg_server_to_client(str
, slen
);
147 if (p
!= str
) /* actual conversion has been done? */
150 pq_sendint32(buf
, slen
);
151 appendBinaryStringInfoNT(buf
, p
, slen
);
156 pq_sendint32(buf
, slen
);
157 appendBinaryStringInfoNT(buf
, str
, slen
);
161 /* --------------------------------
162 * pq_sendtext - append a text string (with conversion)
164 * The passed text string need not be null-terminated, and the data sent
165 * to the frontend isn't either. Note that this is not actually useful
166 * for direct frontend transmissions, since there'd be no way for the
167 * frontend to determine the string length. But it is useful for binary
168 * format conversions.
169 * --------------------------------
172 pq_sendtext(StringInfo buf
, const char *str
, int slen
)
176 p
= pg_server_to_client(str
, slen
);
177 if (p
!= str
) /* actual conversion has been done? */
180 appendBinaryStringInfo(buf
, p
, slen
);
184 appendBinaryStringInfo(buf
, str
, slen
);
187 /* --------------------------------
188 * pq_sendstring - append a null-terminated text string (with conversion)
190 * NB: passed text string must be null-terminated, and so is the data
191 * sent to the frontend.
192 * --------------------------------
195 pq_sendstring(StringInfo buf
, const char *str
)
197 int slen
= strlen(str
);
200 p
= pg_server_to_client(str
, slen
);
201 if (p
!= str
) /* actual conversion has been done? */
204 appendBinaryStringInfoNT(buf
, p
, slen
+ 1);
208 appendBinaryStringInfoNT(buf
, str
, slen
+ 1);
211 /* --------------------------------
212 * pq_send_ascii_string - append a null-terminated text string (without conversion)
214 * This function intentionally bypasses encoding conversion, instead just
215 * silently replacing any non-7-bit-ASCII characters with question marks.
216 * It is used only when we are having trouble sending an error message to
217 * the client with normal localization and encoding conversion. The caller
218 * should already have taken measures to ensure the string is just ASCII;
219 * the extra work here is just to make certain we don't send a badly encoded
220 * string to the client (which might or might not be robust about that).
222 * NB: passed text string must be null-terminated, and so is the data
223 * sent to the frontend.
224 * --------------------------------
227 pq_send_ascii_string(StringInfo buf
, const char *str
)
233 if (IS_HIGHBIT_SET(ch
))
235 appendStringInfoCharMacro(buf
, ch
);
237 appendStringInfoChar(buf
, '\0');
240 /* --------------------------------
241 * pq_sendfloat4 - append a float4 to a StringInfo buffer
243 * The point of this routine is to localize knowledge of the external binary
244 * representation of float4, which is a component of several datatypes.
246 * We currently assume that float4 should be byte-swapped in the same way
247 * as int4. This rule is not perfect but it gives us portability across
248 * most IEEE-float-using architectures.
249 * --------------------------------
252 pq_sendfloat4(StringInfo buf
, float4 f
)
261 pq_sendint32(buf
, swap
.i
);
264 /* --------------------------------
265 * pq_sendfloat8 - append a float8 to a StringInfo buffer
267 * The point of this routine is to localize knowledge of the external binary
268 * representation of float8, which is a component of several datatypes.
270 * We currently assume that float8 should be byte-swapped in the same way
271 * as int8. This rule is not perfect but it gives us portability across
272 * most IEEE-float-using architectures.
273 * --------------------------------
276 pq_sendfloat8(StringInfo buf
, float8 f
)
285 pq_sendint64(buf
, swap
.i
);
288 /* --------------------------------
289 * pq_endmessage - send the completed message to the frontend
291 * The data buffer is pfree()d, but if the StringInfo was allocated with
292 * makeStringInfo then the caller must still pfree it.
293 * --------------------------------
296 pq_endmessage(StringInfo buf
)
298 /* msgtype was saved in cursor field */
299 (void) pq_putmessage(buf
->cursor
, buf
->data
, buf
->len
);
300 /* no need to complain about any failure, since pqcomm.c already did */
305 /* --------------------------------
306 * pq_endmessage_reuse - send the completed message to the frontend
308 * The data buffer is *not* freed, allowing to reuse the buffer with
309 * pq_beginmessage_reuse.
310 --------------------------------
314 pq_endmessage_reuse(StringInfo buf
)
316 /* msgtype was saved in cursor field */
317 (void) pq_putmessage(buf
->cursor
, buf
->data
, buf
->len
);
321 /* --------------------------------
322 * pq_begintypsend - initialize for constructing a bytea result
323 * --------------------------------
326 pq_begintypsend(StringInfo buf
)
329 /* Reserve four bytes for the bytea length word */
330 appendStringInfoCharMacro(buf
, '\0');
331 appendStringInfoCharMacro(buf
, '\0');
332 appendStringInfoCharMacro(buf
, '\0');
333 appendStringInfoCharMacro(buf
, '\0');
336 /* --------------------------------
337 * pq_endtypsend - finish constructing a bytea result
339 * The data buffer is returned as the palloc'd bytea value. (We expect
340 * that it will be suitably aligned for this because it has been palloc'd.)
341 * We assume the StringInfoData is just a local variable in the caller and
342 * need not be pfree'd.
343 * --------------------------------
346 pq_endtypsend(StringInfo buf
)
348 bytea
*result
= (bytea
*) buf
->data
;
350 /* Insert correct length into bytea length word */
351 Assert(buf
->len
>= VARHDRSZ
);
352 SET_VARSIZE(result
, buf
->len
);
358 /* --------------------------------
359 * pq_puttextmessage - generate a character set-converted message in one step
361 * This is the same as the pqcomm.c routine pq_putmessage, except that
362 * the message body is a null-terminated string to which encoding
363 * conversion applies.
364 * --------------------------------
367 pq_puttextmessage(char msgtype
, const char *str
)
369 int slen
= strlen(str
);
372 p
= pg_server_to_client(str
, slen
);
373 if (p
!= str
) /* actual conversion has been done? */
375 (void) pq_putmessage(msgtype
, p
, strlen(p
) + 1);
379 (void) pq_putmessage(msgtype
, str
, slen
+ 1);
383 /* --------------------------------
384 * pq_putemptymessage - convenience routine for message with empty body
385 * --------------------------------
388 pq_putemptymessage(char msgtype
)
390 (void) pq_putmessage(msgtype
, NULL
, 0);
394 /* --------------------------------
395 * pq_getmsgbyte - get a raw byte from a message buffer
396 * --------------------------------
399 pq_getmsgbyte(StringInfo msg
)
401 if (msg
->cursor
>= msg
->len
)
403 (errcode(ERRCODE_PROTOCOL_VIOLATION
),
404 errmsg("no data left in message")));
405 return (unsigned char) msg
->data
[msg
->cursor
++];
408 /* --------------------------------
409 * pq_getmsgint - get a binary integer from a message buffer
411 * Values are treated as unsigned.
412 * --------------------------------
415 pq_getmsgint(StringInfo msg
, int b
)
425 pq_copymsgbytes(msg
, (char *) &n8
, 1);
429 pq_copymsgbytes(msg
, (char *) &n16
, 2);
430 result
= pg_ntoh16(n16
);
433 pq_copymsgbytes(msg
, (char *) &n32
, 4);
434 result
= pg_ntoh32(n32
);
437 elog(ERROR
, "unsupported integer size %d", b
);
438 result
= 0; /* keep compiler quiet */
444 /* --------------------------------
445 * pq_getmsgint64 - get a binary 8-byte int from a message buffer
447 * It is tempting to merge this with pq_getmsgint, but we'd have to make the
448 * result int64 for all data widths --- that could be a big performance
449 * hit on machines where int64 isn't efficient.
450 * --------------------------------
453 pq_getmsgint64(StringInfo msg
)
457 pq_copymsgbytes(msg
, (char *) &n64
, sizeof(n64
));
459 return pg_ntoh64(n64
);
462 /* --------------------------------
463 * pq_getmsgfloat4 - get a float4 from a message buffer
465 * See notes for pq_sendfloat4.
466 * --------------------------------
469 pq_getmsgfloat4(StringInfo msg
)
477 swap
.i
= pq_getmsgint(msg
, 4);
481 /* --------------------------------
482 * pq_getmsgfloat8 - get a float8 from a message buffer
484 * See notes for pq_sendfloat8.
485 * --------------------------------
488 pq_getmsgfloat8(StringInfo msg
)
496 swap
.i
= pq_getmsgint64(msg
);
500 /* --------------------------------
501 * pq_getmsgbytes - get raw data from a message buffer
503 * Returns a pointer directly into the message buffer; note this
504 * may not have any particular alignment.
505 * --------------------------------
508 pq_getmsgbytes(StringInfo msg
, int datalen
)
512 if (datalen
< 0 || datalen
> (msg
->len
- msg
->cursor
))
514 (errcode(ERRCODE_PROTOCOL_VIOLATION
),
515 errmsg("insufficient data left in message")));
516 result
= &msg
->data
[msg
->cursor
];
517 msg
->cursor
+= datalen
;
521 /* --------------------------------
522 * pq_copymsgbytes - copy raw data from a message buffer
524 * Same as above, except data is copied to caller's buffer.
525 * --------------------------------
528 pq_copymsgbytes(StringInfo msg
, char *buf
, int datalen
)
530 if (datalen
< 0 || datalen
> (msg
->len
- msg
->cursor
))
532 (errcode(ERRCODE_PROTOCOL_VIOLATION
),
533 errmsg("insufficient data left in message")));
534 memcpy(buf
, &msg
->data
[msg
->cursor
], datalen
);
535 msg
->cursor
+= datalen
;
538 /* --------------------------------
539 * pq_getmsgtext - get a counted text string (with conversion)
541 * Always returns a pointer to a freshly palloc'd result.
542 * The result has a trailing null, *and* we return its strlen in *nbytes.
543 * --------------------------------
546 pq_getmsgtext(StringInfo msg
, int rawbytes
, int *nbytes
)
551 if (rawbytes
< 0 || rawbytes
> (msg
->len
- msg
->cursor
))
553 (errcode(ERRCODE_PROTOCOL_VIOLATION
),
554 errmsg("insufficient data left in message")));
555 str
= &msg
->data
[msg
->cursor
];
556 msg
->cursor
+= rawbytes
;
558 p
= pg_client_to_server(str
, rawbytes
);
559 if (p
!= str
) /* actual conversion has been done? */
563 p
= (char *) palloc(rawbytes
+ 1);
564 memcpy(p
, str
, rawbytes
);
571 /* --------------------------------
572 * pq_getmsgstring - get a null-terminated text string (with conversion)
574 * May return a pointer directly into the message buffer, or a pointer
575 * to a palloc'd conversion result.
576 * --------------------------------
579 pq_getmsgstring(StringInfo msg
)
584 str
= &msg
->data
[msg
->cursor
];
587 * It's safe to use strlen() here because a StringInfo is guaranteed to
588 * have a trailing null byte. But check we found a null inside the
592 if (msg
->cursor
+ slen
>= msg
->len
)
594 (errcode(ERRCODE_PROTOCOL_VIOLATION
),
595 errmsg("invalid string in message")));
596 msg
->cursor
+= slen
+ 1;
598 return pg_client_to_server(str
, slen
);
601 /* --------------------------------
602 * pq_getmsgrawstring - get a null-terminated text string - NO conversion
604 * Returns a pointer directly into the message buffer.
605 * --------------------------------
608 pq_getmsgrawstring(StringInfo msg
)
613 str
= &msg
->data
[msg
->cursor
];
616 * It's safe to use strlen() here because a StringInfo is guaranteed to
617 * have a trailing null byte. But check we found a null inside the
621 if (msg
->cursor
+ slen
>= msg
->len
)
623 (errcode(ERRCODE_PROTOCOL_VIOLATION
),
624 errmsg("invalid string in message")));
625 msg
->cursor
+= slen
+ 1;
630 /* --------------------------------
631 * pq_getmsgend - verify message fully consumed
632 * --------------------------------
635 pq_getmsgend(StringInfo msg
)
637 if (msg
->cursor
!= msg
->len
)
639 (errcode(ERRCODE_PROTOCOL_VIOLATION
),
640 errmsg("invalid message format")));