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-2024, 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  */
87 void
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  */
108 void
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  */
125 void
126 pq_sendbytes(StringInfo buf, const void *data, int datalen)
127 {
128  /* use variant that maintains a trailing null-byte, out of caution */
129  appendBinaryStringInfo(buf, data, datalen);
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  */
141 void
142 pq_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);
151  appendBinaryStringInfoNT(buf, p, 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  */
171 void
172 pq_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  */
194 void
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  */
226 void
228 {
229  while (*str)
230  {
231  char ch = *str++;
232 
233  if (IS_HIGHBIT_SET(ch))
234  ch = '?';
236  }
237  appendStringInfoChar(buf, '\0');
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  */
251 void
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  */
275 void
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  */
295 void
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  */
312 
313 void
315 {
316  /* msgtype was saved in cursor field */
317  (void) pq_putmessage(buf->cursor, buf->data, buf->len);
318 }
319 
320 
321 /* --------------------------------
322  * pq_begintypsend - initialize for constructing a bytea result
323  * --------------------------------
324  */
325 void
327 {
329  /* Reserve four bytes for the bytea length word */
334 }
335 
336 /* --------------------------------
337  * pq_endtypsend - finish constructing a bytea result
338  *
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  * --------------------------------
344  */
345 bytea *
347 {
348  bytea *result = (bytea *) buf->data;
349 
350  /* Insert correct length into bytea length word */
351  Assert(buf->len >= VARHDRSZ);
352  SET_VARSIZE(result, buf->len);
353 
354  return result;
355 }
356 
357 
358 /* --------------------------------
359  * pq_puttextmessage - generate a character set-converted message in one step
360  *
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  * --------------------------------
365  */
366 void
367 pq_puttextmessage(char msgtype, const char *str)
368 {
369  int slen = strlen(str);
370  char *p;
371 
372  p = pg_server_to_client(str, slen);
373  if (p != str) /* actual conversion has been done? */
374  {
375  (void) pq_putmessage(msgtype, p, strlen(p) + 1);
376  pfree(p);
377  return;
378  }
379  (void) pq_putmessage(msgtype, str, slen + 1);
380 }
381 
382 
383 /* --------------------------------
384  * pq_putemptymessage - convenience routine for message with empty body
385  * --------------------------------
386  */
387 void
388 pq_putemptymessage(char msgtype)
389 {
390  (void) pq_putmessage(msgtype, NULL, 0);
391 }
392 
393 
394 /* --------------------------------
395  * pq_getmsgbyte - get a raw byte from a message buffer
396  * --------------------------------
397  */
398 int
400 {
401  if (msg->cursor >= msg->len)
402  ereport(ERROR,
403  (errcode(ERRCODE_PROTOCOL_VIOLATION),
404  errmsg("no data left in message")));
405  return (unsigned char) msg->data[msg->cursor++];
406 }
407 
408 /* --------------------------------
409  * pq_getmsgint - get a binary integer from a message buffer
410  *
411  * Values are treated as unsigned.
412  * --------------------------------
413  */
414 unsigned int
416 {
417  unsigned int result;
418  unsigned char n8;
419  uint16 n16;
420  uint32 n32;
421 
422  switch (b)
423  {
424  case 1:
425  pq_copymsgbytes(msg, (char *) &n8, 1);
426  result = n8;
427  break;
428  case 2:
429  pq_copymsgbytes(msg, (char *) &n16, 2);
430  result = pg_ntoh16(n16);
431  break;
432  case 4:
433  pq_copymsgbytes(msg, (char *) &n32, 4);
434  result = pg_ntoh32(n32);
435  break;
436  default:
437  elog(ERROR, "unsupported integer size %d", b);
438  result = 0; /* keep compiler quiet */
439  break;
440  }
441  return result;
442 }
443 
444 /* --------------------------------
445  * pq_getmsgint64 - get a binary 8-byte int from a message buffer
446  *
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  * --------------------------------
451  */
452 int64
454 {
455  uint64 n64;
456 
457  pq_copymsgbytes(msg, (char *) &n64, sizeof(n64));
458 
459  return pg_ntoh64(n64);
460 }
461 
462 /* --------------------------------
463  * pq_getmsgfloat4 - get a float4 from a message buffer
464  *
465  * See notes for pq_sendfloat4.
466  * --------------------------------
467  */
468 float4
470 {
471  union
472  {
473  float4 f;
474  uint32 i;
475  } swap;
476 
477  swap.i = pq_getmsgint(msg, 4);
478  return swap.f;
479 }
480 
481 /* --------------------------------
482  * pq_getmsgfloat8 - get a float8 from a message buffer
483  *
484  * See notes for pq_sendfloat8.
485  * --------------------------------
486  */
487 float8
489 {
490  union
491  {
492  float8 f;
493  int64 i;
494  } swap;
495 
496  swap.i = pq_getmsgint64(msg);
497  return swap.f;
498 }
499 
500 /* --------------------------------
501  * pq_getmsgbytes - get raw data from a message buffer
502  *
503  * Returns a pointer directly into the message buffer; note this
504  * may not have any particular alignment.
505  * --------------------------------
506  */
507 const char *
508 pq_getmsgbytes(StringInfo msg, int datalen)
509 {
510  const char *result;
511 
512  if (datalen < 0 || datalen > (msg->len - msg->cursor))
513  ereport(ERROR,
514  (errcode(ERRCODE_PROTOCOL_VIOLATION),
515  errmsg("insufficient data left in message")));
516  result = &msg->data[msg->cursor];
517  msg->cursor += datalen;
518  return result;
519 }
520 
521 /* --------------------------------
522  * pq_copymsgbytes - copy raw data from a message buffer
523  *
524  * Same as above, except data is copied to caller's buffer.
525  * --------------------------------
526  */
527 void
528 pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
529 {
530  if (datalen < 0 || datalen > (msg->len - msg->cursor))
531  ereport(ERROR,
532  (errcode(ERRCODE_PROTOCOL_VIOLATION),
533  errmsg("insufficient data left in message")));
534  memcpy(buf, &msg->data[msg->cursor], datalen);
535  msg->cursor += datalen;
536 }
537 
538 /* --------------------------------
539  * pq_getmsgtext - get a counted text string (with conversion)
540  *
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  * --------------------------------
544  */
545 char *
546 pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
547 {
548  char *str;
549  char *p;
550 
551  if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor))
552  ereport(ERROR,
553  (errcode(ERRCODE_PROTOCOL_VIOLATION),
554  errmsg("insufficient data left in message")));
555  str = &msg->data[msg->cursor];
556  msg->cursor += rawbytes;
557 
558  p = pg_client_to_server(str, rawbytes);
559  if (p != str) /* actual conversion has been done? */
560  *nbytes = strlen(p);
561  else
562  {
563  p = (char *) palloc(rawbytes + 1);
564  memcpy(p, str, rawbytes);
565  p[rawbytes] = '\0';
566  *nbytes = rawbytes;
567  }
568  return p;
569 }
570 
571 /* --------------------------------
572  * pq_getmsgstring - get a null-terminated text string (with conversion)
573  *
574  * May return a pointer directly into the message buffer, or a pointer
575  * to a palloc'd conversion result.
576  * --------------------------------
577  */
578 const char *
580 {
581  char *str;
582  int slen;
583 
584  str = &msg->data[msg->cursor];
585 
586  /*
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
589  * message.
590  */
591  slen = strlen(str);
592  if (msg->cursor + slen >= msg->len)
593  ereport(ERROR,
594  (errcode(ERRCODE_PROTOCOL_VIOLATION),
595  errmsg("invalid string in message")));
596  msg->cursor += slen + 1;
597 
598  return pg_client_to_server(str, slen);
599 }
600 
601 /* --------------------------------
602  * pq_getmsgrawstring - get a null-terminated text string - NO conversion
603  *
604  * Returns a pointer directly into the message buffer.
605  * --------------------------------
606  */
607 const char *
609 {
610  char *str;
611  int slen;
612 
613  str = &msg->data[msg->cursor];
614 
615  /*
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
618  * message.
619  */
620  slen = strlen(str);
621  if (msg->cursor + slen >= msg->len)
622  ereport(ERROR,
623  (errcode(ERRCODE_PROTOCOL_VIOLATION),
624  errmsg("invalid string in message")));
625  msg->cursor += slen + 1;
626 
627  return str;
628 }
629 
630 /* --------------------------------
631  * pq_getmsgend - verify message fully consumed
632  * --------------------------------
633  */
634 void
636 {
637  if (msg->cursor != msg->len)
638  ereport(ERROR,
639  (errcode(ERRCODE_PROTOCOL_VIOLATION),
640  errmsg("invalid message format")));
641 }
unsigned short uint16
Definition: c.h:505
unsigned int uint32
Definition: c.h:506
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1155
#define VARHDRSZ
Definition: c.h:692
#define Assert(condition)
Definition: c.h:858
double float8
Definition: c.h:630
float float4
Definition: c.h:629
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
const char * str
int b
Definition: isn.c:70
int i
Definition: isn.c:73
#define pq_putmessage(msgtype, s, len)
Definition: libpq.h:49
char * pg_client_to_server(const char *s, int len)
Definition: mbutils.c:660
char * pg_server_to_client(const char *s, int len)
Definition: mbutils.c:738
void pfree(void *pointer)
Definition: mcxt.c:1520
void * palloc(Size size)
Definition: mcxt.c:1316
#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
Definition: pg_test_fsync.c:73
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
float4 pq_getmsgfloat4(StringInfo msg)
Definition: pqformat.c:469
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
const char * pq_getmsgstring(StringInfo msg)
Definition: pqformat.c:579
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:635
void pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
Definition: pqformat.c:528
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:508
void pq_putemptymessage(char msgtype)
Definition: pqformat.c:388
float8 pq_getmsgfloat8(StringInfo msg)
Definition: pqformat.c:488
void pq_puttextmessage(char msgtype, const char *str)
Definition: pqformat.c:367
void pq_sendstring(StringInfo buf, const char *str)
Definition: pqformat.c:195
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:296
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:546
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
int pq_getmsgbyte(StringInfo msg)
Definition: pqformat.c:399
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:453
void pq_sendfloat4(StringInfo buf, float4 f)
Definition: pqformat.c:252
const char * pq_getmsgrawstring(StringInfo msg)
Definition: pqformat.c:608
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
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
void pq_sendfloat8(StringInfo buf, float8 f)
Definition: pqformat.c:276
void pq_endmessage_reuse(StringInfo buf)
Definition: pqformat.c:314
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:78
void appendBinaryStringInfoNT(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:259
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204
Definition: c.h:687
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305