PostgreSQL Source Code git master
pqformat.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pqformat.c
4 * Routines for formatting and parsing frontend/backend messages
5 *
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
12 * rules.
13 *
14 * Incoming messages are similarly read into a StringInfo buffer, via
15 * pq_getmessage, and then parsed and converted from that using the routines
16 * in this module.
17 *
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
21 * are different.
22 *
23 *
24 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
25 * Portions Copyright (c) 1994, Regents of the University of California
26 *
27 * src/backend/libpq/pqformat.c
28 *
29 *-------------------------------------------------------------------------
30 */
31/*
32 * INTERFACE ROUTINES
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.
49 *
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*"
53 *
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
57 *
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
70 */
71
72#include "postgres.h"
73
74#include <sys/param.h>
75
76#include "libpq/libpq.h"
77#include "libpq/pqformat.h"
78#include "mb/pg_wchar.h"
79#include "port/pg_bswap.h"
80#include "varatt.h"
81
82
83/* --------------------------------
84 * pq_beginmessage - initialize for sending a message
85 * --------------------------------
86 */
87void
89{
91
92 /*
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.
96 */
97 buf->cursor = msgtype;
98}
99
100/* --------------------------------
101
102 * pq_beginmessage_reuse - initialize for sending a message, reuse buffer
103 *
104 * This requires the buffer to be allocated in a sufficiently long-lived
105 * memory context.
106 * --------------------------------
107 */
108void
110{
112
113 /*
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.
117 */
118 buf->cursor = msgtype;
119}
120
121/* --------------------------------
122 * pq_sendbytes - append raw data to a StringInfo buffer
123 * --------------------------------
124 */
125void
126pq_sendbytes(StringInfo buf, const void *data, int datalen)
127{
128 /* use variant that maintains a trailing null-byte, out of caution */
130}
131
132/* --------------------------------
133 * pq_sendcountedtext - append a counted text string (with character set conversion)
134 *
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 * --------------------------------
140 */
141void
142pq_sendcountedtext(StringInfo buf, const char *str, int slen)
143{
144 char *p;
145
146 p = pg_server_to_client(str, slen);
147 if (p != str) /* actual conversion has been done? */
148 {
149 slen = strlen(p);
150 pq_sendint32(buf, slen);
152 pfree(p);
153 }
154 else
155 {
156 pq_sendint32(buf, slen);
158 }
159}
160
161/* --------------------------------
162 * pq_sendtext - append a text string (with conversion)
163 *
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 * --------------------------------
170 */
171void
172pq_sendtext(StringInfo buf, const char *str, int slen)
173{
174 char *p;
175
176 p = pg_server_to_client(str, slen);
177 if (p != str) /* actual conversion has been done? */
178 {
179 slen = strlen(p);
180 appendBinaryStringInfo(buf, p, slen);
181 pfree(p);
182 }
183 else
185}
186
187/* --------------------------------
188 * pq_sendstring - append a null-terminated text string (with conversion)
189 *
190 * NB: passed text string must be null-terminated, and so is the data
191 * sent to the frontend.
192 * --------------------------------
193 */
194void
196{
197 int slen = strlen(str);
198 char *p;
199
200 p = pg_server_to_client(str, slen);
201 if (p != str) /* actual conversion has been done? */
202 {
203 slen = strlen(p);
204 appendBinaryStringInfoNT(buf, p, slen + 1);
205 pfree(p);
206 }
207 else
208 appendBinaryStringInfoNT(buf, str, slen + 1);
209}
210
211/* --------------------------------
212 * pq_send_ascii_string - append a null-terminated text string (without conversion)
213 *
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).
221 *
222 * NB: passed text string must be null-terminated, and so is the data
223 * sent to the frontend.
224 * --------------------------------
225 */
226void
228{
229 while (*str)
230 {
231 char ch = *str++;
232
233 if (IS_HIGHBIT_SET(ch))
234 ch = '?';
236 }
238}
239
240/* --------------------------------
241 * pq_sendfloat4 - append a float4 to a StringInfo buffer
242 *
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.
245 *
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 * --------------------------------
250 */
251void
253{
254 union
255 {
256 float4 f;
257 uint32 i;
258 } swap;
259
260 swap.f = f;
261 pq_sendint32(buf, swap.i);
262}
263
264/* --------------------------------
265 * pq_sendfloat8 - append a float8 to a StringInfo buffer
266 *
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.
269 *
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 * --------------------------------
274 */
275void
277{
278 union
279 {
280 float8 f;
281 int64 i;
282 } swap;
283
284 swap.f = f;
285 pq_sendint64(buf, swap.i);
286}
287
288/* --------------------------------
289 * pq_endmessage - send the completed message to the frontend
290 *
291 * The data buffer is pfree()d, but if the StringInfo was allocated with
292 * makeStringInfo then the caller must still pfree it.
293 * --------------------------------
294 */
295void
297{
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 */
301 pfree(buf->data);
302 buf->data = NULL;
303}
304
305/* --------------------------------
306 * pq_endmessage_reuse - send the completed message to the frontend
307 *
308 * The data buffer is *not* freed, allowing to reuse the buffer with
309 * pq_beginmessage_reuse.
310 * --------------------------------
311 */
312void
314{
315 /* msgtype was saved in cursor field */
316 (void) pq_putmessage(buf->cursor, buf->data, buf->len);
317}
318
319
320/* --------------------------------
321 * pq_begintypsend - initialize for constructing a bytea result
322 * --------------------------------
323 */
324void
326{
328 /* Reserve four bytes for the bytea length word */
333}
334
335/* --------------------------------
336 * pq_endtypsend - finish constructing a bytea result
337 *
338 * The data buffer is returned as the palloc'd bytea value. (We expect
339 * that it will be suitably aligned for this because it has been palloc'd.)
340 * We assume the StringInfoData is just a local variable in the caller and
341 * need not be pfree'd.
342 * --------------------------------
343 */
344bytea *
346{
347 bytea *result = (bytea *) buf->data;
348
349 /* Insert correct length into bytea length word */
350 Assert(buf->len >= VARHDRSZ);
351 SET_VARSIZE(result, buf->len);
352
353 return result;
354}
355
356
357/* --------------------------------
358 * pq_puttextmessage - generate a character set-converted message in one step
359 *
360 * This is the same as the pqcomm.c routine pq_putmessage, except that
361 * the message body is a null-terminated string to which encoding
362 * conversion applies.
363 * --------------------------------
364 */
365void
366pq_puttextmessage(char msgtype, const char *str)
367{
368 int slen = strlen(str);
369 char *p;
370
371 p = pg_server_to_client(str, slen);
372 if (p != str) /* actual conversion has been done? */
373 {
374 (void) pq_putmessage(msgtype, p, strlen(p) + 1);
375 pfree(p);
376 return;
377 }
378 (void) pq_putmessage(msgtype, str, slen + 1);
379}
380
381
382/* --------------------------------
383 * pq_putemptymessage - convenience routine for message with empty body
384 * --------------------------------
385 */
386void
388{
389 (void) pq_putmessage(msgtype, NULL, 0);
390}
391
392
393/* --------------------------------
394 * pq_getmsgbyte - get a raw byte from a message buffer
395 * --------------------------------
396 */
397int
399{
400 if (msg->cursor >= msg->len)
402 (errcode(ERRCODE_PROTOCOL_VIOLATION),
403 errmsg("no data left in message")));
404 return (unsigned char) msg->data[msg->cursor++];
405}
406
407/* --------------------------------
408 * pq_getmsgint - get a binary integer from a message buffer
409 *
410 * Values are treated as unsigned.
411 * --------------------------------
412 */
413unsigned int
415{
416 unsigned int result;
417 unsigned char n8;
418 uint16 n16;
419 uint32 n32;
420
421 switch (b)
422 {
423 case 1:
424 pq_copymsgbytes(msg, &n8, 1);
425 result = n8;
426 break;
427 case 2:
428 pq_copymsgbytes(msg, &n16, 2);
429 result = pg_ntoh16(n16);
430 break;
431 case 4:
432 pq_copymsgbytes(msg, &n32, 4);
433 result = pg_ntoh32(n32);
434 break;
435 default:
436 elog(ERROR, "unsupported integer size %d", b);
437 result = 0; /* keep compiler quiet */
438 break;
439 }
440 return result;
441}
442
443/* --------------------------------
444 * pq_getmsgint64 - get a binary 8-byte int from a message buffer
445 *
446 * It is tempting to merge this with pq_getmsgint, but we'd have to make the
447 * result int64 for all data widths --- that could be a big performance
448 * hit on machines where int64 isn't efficient.
449 * --------------------------------
450 */
451int64
453{
454 uint64 n64;
455
456 pq_copymsgbytes(msg, &n64, sizeof(n64));
457
458 return pg_ntoh64(n64);
459}
460
461/* --------------------------------
462 * pq_getmsgfloat4 - get a float4 from a message buffer
463 *
464 * See notes for pq_sendfloat4.
465 * --------------------------------
466 */
467float4
469{
470 union
471 {
472 float4 f;
473 uint32 i;
474 } swap;
475
476 swap.i = pq_getmsgint(msg, 4);
477 return swap.f;
478}
479
480/* --------------------------------
481 * pq_getmsgfloat8 - get a float8 from a message buffer
482 *
483 * See notes for pq_sendfloat8.
484 * --------------------------------
485 */
486float8
488{
489 union
490 {
491 float8 f;
492 int64 i;
493 } swap;
494
495 swap.i = pq_getmsgint64(msg);
496 return swap.f;
497}
498
499/* --------------------------------
500 * pq_getmsgbytes - get raw data from a message buffer
501 *
502 * Returns a pointer directly into the message buffer; note this
503 * may not have any particular alignment.
504 * --------------------------------
505 */
506const char *
507pq_getmsgbytes(StringInfo msg, int datalen)
508{
509 const char *result;
510
511 if (datalen < 0 || datalen > (msg->len - msg->cursor))
513 (errcode(ERRCODE_PROTOCOL_VIOLATION),
514 errmsg("insufficient data left in message")));
515 result = &msg->data[msg->cursor];
516 msg->cursor += datalen;
517 return result;
518}
519
520/* --------------------------------
521 * pq_copymsgbytes - copy raw data from a message buffer
522 *
523 * Same as above, except data is copied to caller's buffer.
524 * --------------------------------
525 */
526void
527pq_copymsgbytes(StringInfo msg, void *buf, int datalen)
528{
529 if (datalen < 0 || datalen > (msg->len - msg->cursor))
531 (errcode(ERRCODE_PROTOCOL_VIOLATION),
532 errmsg("insufficient data left in message")));
533 memcpy(buf, &msg->data[msg->cursor], datalen);
534 msg->cursor += datalen;
535}
536
537/* --------------------------------
538 * pq_getmsgtext - get a counted text string (with conversion)
539 *
540 * Always returns a pointer to a freshly palloc'd result.
541 * The result has a trailing null, *and* we return its strlen in *nbytes.
542 * --------------------------------
543 */
544char *
545pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
546{
547 char *str;
548 char *p;
549
550 if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor))
552 (errcode(ERRCODE_PROTOCOL_VIOLATION),
553 errmsg("insufficient data left in message")));
554 str = &msg->data[msg->cursor];
555 msg->cursor += rawbytes;
556
557 p = pg_client_to_server(str, rawbytes);
558 if (p != str) /* actual conversion has been done? */
559 *nbytes = strlen(p);
560 else
561 {
562 p = (char *) palloc(rawbytes + 1);
563 memcpy(p, str, rawbytes);
564 p[rawbytes] = '\0';
565 *nbytes = rawbytes;
566 }
567 return p;
568}
569
570/* --------------------------------
571 * pq_getmsgstring - get a null-terminated text string (with conversion)
572 *
573 * May return a pointer directly into the message buffer, or a pointer
574 * to a palloc'd conversion result.
575 * --------------------------------
576 */
577const char *
579{
580 char *str;
581 int slen;
582
583 str = &msg->data[msg->cursor];
584
585 /*
586 * It's safe to use strlen() here because a StringInfo is guaranteed to
587 * have a trailing null byte. But check we found a null inside the
588 * message.
589 */
590 slen = strlen(str);
591 if (msg->cursor + slen >= msg->len)
593 (errcode(ERRCODE_PROTOCOL_VIOLATION),
594 errmsg("invalid string in message")));
595 msg->cursor += slen + 1;
596
597 return pg_client_to_server(str, slen);
598}
599
600/* --------------------------------
601 * pq_getmsgrawstring - get a null-terminated text string - NO conversion
602 *
603 * Returns a pointer directly into the message buffer.
604 * --------------------------------
605 */
606const char *
608{
609 char *str;
610 int slen;
611
612 str = &msg->data[msg->cursor];
613
614 /*
615 * It's safe to use strlen() here because a StringInfo is guaranteed to
616 * have a trailing null byte. But check we found a null inside the
617 * message.
618 */
619 slen = strlen(str);
620 if (msg->cursor + slen >= msg->len)
622 (errcode(ERRCODE_PROTOCOL_VIOLATION),
623 errmsg("invalid string in message")));
624 msg->cursor += slen + 1;
625
626 return str;
627}
628
629/* --------------------------------
630 * pq_getmsgend - verify message fully consumed
631 * --------------------------------
632 */
633void
635{
636 if (msg->cursor != msg->len)
638 (errcode(ERRCODE_PROTOCOL_VIOLATION),
639 errmsg("invalid message format")));
640}
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1153
#define VARHDRSZ
Definition: c.h:711
int64_t int64
Definition: c.h:549
double float8
Definition: c.h:649
uint64_t uint64
Definition: c.h:553
uint16_t uint16
Definition: c.h:551
uint32_t uint32
Definition: c.h:552
float float4
Definition: c.h:648
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:150
Assert(PointerIsAligned(start, uint64))
const char * str
int b
Definition: isn.c:74
int i
Definition: isn.c:77
#define pq_putmessage(msgtype, s, len)
Definition: libpq.h:49
char * pg_client_to_server(const char *s, int len)
Definition: mbutils.c:663
char * pg_server_to_client(const char *s, int len)
Definition: mbutils.c:741
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc(Size size)
Definition: mcxt.c:1365
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
#define pg_ntoh64(x)
Definition: pg_bswap.h:126
#define pg_ntoh16(x)
Definition: pg_bswap.h:124
const void * data
static char buf[DEFAULT_XLOG_SEG_SIZE]
Definition: pg_test_fsync.c:71
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:414
float4 pq_getmsgfloat4(StringInfo msg)
Definition: pqformat.c:468
void pq_sendbytes(StringInfo buf, const void *data, int datalen)
Definition: pqformat.c:126
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:172
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:634
const char * pq_getmsgstring(StringInfo msg)
Definition: pqformat.c:578
void pq_putemptymessage(char msgtype)
Definition: pqformat.c:387
float8 pq_getmsgfloat8(StringInfo msg)
Definition: pqformat.c:487
void pq_puttextmessage(char msgtype, const char *str)
Definition: pqformat.c:366
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:545
void pq_sendstring(StringInfo buf, const char *str)
Definition: pqformat.c:195
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:296
void pq_copymsgbytes(StringInfo msg, void *buf, int datalen)
Definition: pqformat.c:527
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:325
int pq_getmsgbyte(StringInfo msg)
Definition: pqformat.c:398
const char * pq_getmsgrawstring(StringInfo msg)
Definition: pqformat.c:607
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:452
void pq_sendfloat4(StringInfo buf, float4 f)
Definition: pqformat.c:252
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:507
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:345
void pq_beginmessage_reuse(StringInfo buf, char msgtype)
Definition: pqformat.c:109
void pq_send_ascii_string(StringInfo buf, const char *str)
Definition: pqformat.c:227
void pq_sendfloat8(StringInfo buf, float8 f)
Definition: pqformat.c:276
void pq_endmessage_reuse(StringInfo buf)
Definition: pqformat.c:313
void pq_sendcountedtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:142
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:126
void appendBinaryStringInfoNT(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:307
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:231
Definition: c.h:706
static void SET_VARSIZE(void *PTR, Size len)
Definition: varatt.h:432