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-2023, 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 includes itself or not, as per the
137  * countincludesself flag (pre-3.0 protocol requires it to include itself).
138  * The passed text string need not be null-terminated, and the data sent
139  * to the frontend isn't either.
140  * --------------------------------
141  */
142 void
143 pq_sendcountedtext(StringInfo buf, const char *str, int slen,
144  bool countincludesself)
145 {
146  int extra = countincludesself ? 4 : 0;
147  char *p;
148 
149  p = pg_server_to_client(str, slen);
150  if (p != str) /* actual conversion has been done? */
151  {
152  slen = strlen(p);
153  pq_sendint32(buf, slen + extra);
154  appendBinaryStringInfoNT(buf, p, slen);
155  pfree(p);
156  }
157  else
158  {
159  pq_sendint32(buf, slen + extra);
161  }
162 }
163 
164 /* --------------------------------
165  * pq_sendtext - append a text string (with conversion)
166  *
167  * The passed text string need not be null-terminated, and the data sent
168  * to the frontend isn't either. Note that this is not actually useful
169  * for direct frontend transmissions, since there'd be no way for the
170  * frontend to determine the string length. But it is useful for binary
171  * format conversions.
172  * --------------------------------
173  */
174 void
175 pq_sendtext(StringInfo buf, const char *str, int slen)
176 {
177  char *p;
178 
179  p = pg_server_to_client(str, slen);
180  if (p != str) /* actual conversion has been done? */
181  {
182  slen = strlen(p);
183  appendBinaryStringInfo(buf, p, slen);
184  pfree(p);
185  }
186  else
188 }
189 
190 /* --------------------------------
191  * pq_sendstring - append a null-terminated text string (with conversion)
192  *
193  * NB: passed text string must be null-terminated, and so is the data
194  * sent to the frontend.
195  * --------------------------------
196  */
197 void
199 {
200  int slen = strlen(str);
201  char *p;
202 
203  p = pg_server_to_client(str, slen);
204  if (p != str) /* actual conversion has been done? */
205  {
206  slen = strlen(p);
207  appendBinaryStringInfoNT(buf, p, slen + 1);
208  pfree(p);
209  }
210  else
211  appendBinaryStringInfoNT(buf, str, slen + 1);
212 }
213 
214 /* --------------------------------
215  * pq_send_ascii_string - append a null-terminated text string (without conversion)
216  *
217  * This function intentionally bypasses encoding conversion, instead just
218  * silently replacing any non-7-bit-ASCII characters with question marks.
219  * It is used only when we are having trouble sending an error message to
220  * the client with normal localization and encoding conversion. The caller
221  * should already have taken measures to ensure the string is just ASCII;
222  * the extra work here is just to make certain we don't send a badly encoded
223  * string to the client (which might or might not be robust about that).
224  *
225  * NB: passed text string must be null-terminated, and so is the data
226  * sent to the frontend.
227  * --------------------------------
228  */
229 void
231 {
232  while (*str)
233  {
234  char ch = *str++;
235 
236  if (IS_HIGHBIT_SET(ch))
237  ch = '?';
239  }
240  appendStringInfoChar(buf, '\0');
241 }
242 
243 /* --------------------------------
244  * pq_sendfloat4 - append a float4 to a StringInfo buffer
245  *
246  * The point of this routine is to localize knowledge of the external binary
247  * representation of float4, which is a component of several datatypes.
248  *
249  * We currently assume that float4 should be byte-swapped in the same way
250  * as int4. This rule is not perfect but it gives us portability across
251  * most IEEE-float-using architectures.
252  * --------------------------------
253  */
254 void
256 {
257  union
258  {
259  float4 f;
260  uint32 i;
261  } swap;
262 
263  swap.f = f;
264  pq_sendint32(buf, swap.i);
265 }
266 
267 /* --------------------------------
268  * pq_sendfloat8 - append a float8 to a StringInfo buffer
269  *
270  * The point of this routine is to localize knowledge of the external binary
271  * representation of float8, which is a component of several datatypes.
272  *
273  * We currently assume that float8 should be byte-swapped in the same way
274  * as int8. This rule is not perfect but it gives us portability across
275  * most IEEE-float-using architectures.
276  * --------------------------------
277  */
278 void
280 {
281  union
282  {
283  float8 f;
284  int64 i;
285  } swap;
286 
287  swap.f = f;
288  pq_sendint64(buf, swap.i);
289 }
290 
291 /* --------------------------------
292  * pq_endmessage - send the completed message to the frontend
293  *
294  * The data buffer is pfree()d, but if the StringInfo was allocated with
295  * makeStringInfo then the caller must still pfree it.
296  * --------------------------------
297  */
298 void
300 {
301  /* msgtype was saved in cursor field */
302  (void) pq_putmessage(buf->cursor, buf->data, buf->len);
303  /* no need to complain about any failure, since pqcomm.c already did */
304  pfree(buf->data);
305  buf->data = NULL;
306 }
307 
308 /* --------------------------------
309  * pq_endmessage_reuse - send the completed message to the frontend
310  *
311  * The data buffer is *not* freed, allowing to reuse the buffer with
312  * pq_beginmessage_reuse.
313  --------------------------------
314  */
315 
316 void
318 {
319  /* msgtype was saved in cursor field */
320  (void) pq_putmessage(buf->cursor, buf->data, buf->len);
321 }
322 
323 
324 /* --------------------------------
325  * pq_begintypsend - initialize for constructing a bytea result
326  * --------------------------------
327  */
328 void
330 {
332  /* Reserve four bytes for the bytea length word */
337 }
338 
339 /* --------------------------------
340  * pq_endtypsend - finish constructing a bytea result
341  *
342  * The data buffer is returned as the palloc'd bytea value. (We expect
343  * that it will be suitably aligned for this because it has been palloc'd.)
344  * We assume the StringInfoData is just a local variable in the caller and
345  * need not be pfree'd.
346  * --------------------------------
347  */
348 bytea *
350 {
351  bytea *result = (bytea *) buf->data;
352 
353  /* Insert correct length into bytea length word */
354  Assert(buf->len >= VARHDRSZ);
355  SET_VARSIZE(result, buf->len);
356 
357  return result;
358 }
359 
360 
361 /* --------------------------------
362  * pq_puttextmessage - generate a character set-converted message in one step
363  *
364  * This is the same as the pqcomm.c routine pq_putmessage, except that
365  * the message body is a null-terminated string to which encoding
366  * conversion applies.
367  * --------------------------------
368  */
369 void
370 pq_puttextmessage(char msgtype, const char *str)
371 {
372  int slen = strlen(str);
373  char *p;
374 
375  p = pg_server_to_client(str, slen);
376  if (p != str) /* actual conversion has been done? */
377  {
378  (void) pq_putmessage(msgtype, p, strlen(p) + 1);
379  pfree(p);
380  return;
381  }
382  (void) pq_putmessage(msgtype, str, slen + 1);
383 }
384 
385 
386 /* --------------------------------
387  * pq_putemptymessage - convenience routine for message with empty body
388  * --------------------------------
389  */
390 void
391 pq_putemptymessage(char msgtype)
392 {
393  (void) pq_putmessage(msgtype, NULL, 0);
394 }
395 
396 
397 /* --------------------------------
398  * pq_getmsgbyte - get a raw byte from a message buffer
399  * --------------------------------
400  */
401 int
403 {
404  if (msg->cursor >= msg->len)
405  ereport(ERROR,
406  (errcode(ERRCODE_PROTOCOL_VIOLATION),
407  errmsg("no data left in message")));
408  return (unsigned char) msg->data[msg->cursor++];
409 }
410 
411 /* --------------------------------
412  * pq_getmsgint - get a binary integer from a message buffer
413  *
414  * Values are treated as unsigned.
415  * --------------------------------
416  */
417 unsigned int
419 {
420  unsigned int result;
421  unsigned char n8;
422  uint16 n16;
423  uint32 n32;
424 
425  switch (b)
426  {
427  case 1:
428  pq_copymsgbytes(msg, (char *) &n8, 1);
429  result = n8;
430  break;
431  case 2:
432  pq_copymsgbytes(msg, (char *) &n16, 2);
433  result = pg_ntoh16(n16);
434  break;
435  case 4:
436  pq_copymsgbytes(msg, (char *) &n32, 4);
437  result = pg_ntoh32(n32);
438  break;
439  default:
440  elog(ERROR, "unsupported integer size %d", b);
441  result = 0; /* keep compiler quiet */
442  break;
443  }
444  return result;
445 }
446 
447 /* --------------------------------
448  * pq_getmsgint64 - get a binary 8-byte int from a message buffer
449  *
450  * It is tempting to merge this with pq_getmsgint, but we'd have to make the
451  * result int64 for all data widths --- that could be a big performance
452  * hit on machines where int64 isn't efficient.
453  * --------------------------------
454  */
455 int64
457 {
458  uint64 n64;
459 
460  pq_copymsgbytes(msg, (char *) &n64, sizeof(n64));
461 
462  return pg_ntoh64(n64);
463 }
464 
465 /* --------------------------------
466  * pq_getmsgfloat4 - get a float4 from a message buffer
467  *
468  * See notes for pq_sendfloat4.
469  * --------------------------------
470  */
471 float4
473 {
474  union
475  {
476  float4 f;
477  uint32 i;
478  } swap;
479 
480  swap.i = pq_getmsgint(msg, 4);
481  return swap.f;
482 }
483 
484 /* --------------------------------
485  * pq_getmsgfloat8 - get a float8 from a message buffer
486  *
487  * See notes for pq_sendfloat8.
488  * --------------------------------
489  */
490 float8
492 {
493  union
494  {
495  float8 f;
496  int64 i;
497  } swap;
498 
499  swap.i = pq_getmsgint64(msg);
500  return swap.f;
501 }
502 
503 /* --------------------------------
504  * pq_getmsgbytes - get raw data from a message buffer
505  *
506  * Returns a pointer directly into the message buffer; note this
507  * may not have any particular alignment.
508  * --------------------------------
509  */
510 const char *
511 pq_getmsgbytes(StringInfo msg, int datalen)
512 {
513  const char *result;
514 
515  if (datalen < 0 || datalen > (msg->len - msg->cursor))
516  ereport(ERROR,
517  (errcode(ERRCODE_PROTOCOL_VIOLATION),
518  errmsg("insufficient data left in message")));
519  result = &msg->data[msg->cursor];
520  msg->cursor += datalen;
521  return result;
522 }
523 
524 /* --------------------------------
525  * pq_copymsgbytes - copy raw data from a message buffer
526  *
527  * Same as above, except data is copied to caller's buffer.
528  * --------------------------------
529  */
530 void
531 pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
532 {
533  if (datalen < 0 || datalen > (msg->len - msg->cursor))
534  ereport(ERROR,
535  (errcode(ERRCODE_PROTOCOL_VIOLATION),
536  errmsg("insufficient data left in message")));
537  memcpy(buf, &msg->data[msg->cursor], datalen);
538  msg->cursor += datalen;
539 }
540 
541 /* --------------------------------
542  * pq_getmsgtext - get a counted text string (with conversion)
543  *
544  * Always returns a pointer to a freshly palloc'd result.
545  * The result has a trailing null, *and* we return its strlen in *nbytes.
546  * --------------------------------
547  */
548 char *
549 pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
550 {
551  char *str;
552  char *p;
553 
554  if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor))
555  ereport(ERROR,
556  (errcode(ERRCODE_PROTOCOL_VIOLATION),
557  errmsg("insufficient data left in message")));
558  str = &msg->data[msg->cursor];
559  msg->cursor += rawbytes;
560 
561  p = pg_client_to_server(str, rawbytes);
562  if (p != str) /* actual conversion has been done? */
563  *nbytes = strlen(p);
564  else
565  {
566  p = (char *) palloc(rawbytes + 1);
567  memcpy(p, str, rawbytes);
568  p[rawbytes] = '\0';
569  *nbytes = rawbytes;
570  }
571  return p;
572 }
573 
574 /* --------------------------------
575  * pq_getmsgstring - get a null-terminated text string (with conversion)
576  *
577  * May return a pointer directly into the message buffer, or a pointer
578  * to a palloc'd conversion result.
579  * --------------------------------
580  */
581 const char *
583 {
584  char *str;
585  int slen;
586 
587  str = &msg->data[msg->cursor];
588 
589  /*
590  * It's safe to use strlen() here because a StringInfo is guaranteed to
591  * have a trailing null byte. But check we found a null inside the
592  * message.
593  */
594  slen = strlen(str);
595  if (msg->cursor + slen >= msg->len)
596  ereport(ERROR,
597  (errcode(ERRCODE_PROTOCOL_VIOLATION),
598  errmsg("invalid string in message")));
599  msg->cursor += slen + 1;
600 
601  return pg_client_to_server(str, slen);
602 }
603 
604 /* --------------------------------
605  * pq_getmsgrawstring - get a null-terminated text string - NO conversion
606  *
607  * Returns a pointer directly into the message buffer.
608  * --------------------------------
609  */
610 const char *
612 {
613  char *str;
614  int slen;
615 
616  str = &msg->data[msg->cursor];
617 
618  /*
619  * It's safe to use strlen() here because a StringInfo is guaranteed to
620  * have a trailing null byte. But check we found a null inside the
621  * message.
622  */
623  slen = strlen(str);
624  if (msg->cursor + slen >= msg->len)
625  ereport(ERROR,
626  (errcode(ERRCODE_PROTOCOL_VIOLATION),
627  errmsg("invalid string in message")));
628  msg->cursor += slen + 1;
629 
630  return str;
631 }
632 
633 /* --------------------------------
634  * pq_getmsgend - verify message fully consumed
635  * --------------------------------
636  */
637 void
639 {
640  if (msg->cursor != msg->len)
641  ereport(ERROR,
642  (errcode(ERRCODE_PROTOCOL_VIOLATION),
643  errmsg("invalid message format")));
644 }
unsigned short uint16
Definition: c.h:494
unsigned int uint32
Definition: c.h:495
#define IS_HIGHBIT_SET(ch)
Definition: c.h:1168
#define VARHDRSZ
Definition: c.h:681
double float8
Definition: c.h:619
float float4
Definition: c.h:618
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int b
Definition: isn.c:70
int i
Definition: isn.c:73
#define pq_putmessage(msgtype, s, len)
Definition: libpq.h:49
Assert(fmt[strlen(fmt) - 1] !='\n')
char * pg_client_to_server(const char *s, int len)
Definition: mbutils.c:661
char * pg_server_to_client(const char *s, int len)
Definition: mbutils.c:739
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1226
#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:67
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:418
float4 pq_getmsgfloat4(StringInfo msg)
Definition: pqformat.c:472
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:175
const char * pq_getmsgstring(StringInfo msg)
Definition: pqformat.c:582
void pq_getmsgend(StringInfo msg)
Definition: pqformat.c:638
void pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
Definition: pqformat.c:531
const char * pq_getmsgbytes(StringInfo msg, int datalen)
Definition: pqformat.c:511
void pq_putemptymessage(char msgtype)
Definition: pqformat.c:391
float8 pq_getmsgfloat8(StringInfo msg)
Definition: pqformat.c:491
void pq_puttextmessage(char msgtype, const char *str)
Definition: pqformat.c:370
void pq_sendstring(StringInfo buf, const char *str)
Definition: pqformat.c:198
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:299
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:549
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:329
int pq_getmsgbyte(StringInfo msg)
Definition: pqformat.c:402
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:456
void pq_sendfloat4(StringInfo buf, float4 f)
Definition: pqformat.c:255
const char * pq_getmsgrawstring(StringInfo msg)
Definition: pqformat.c:611
void pq_beginmessage_reuse(StringInfo buf, char msgtype)
Definition: pqformat.c:109
void pq_sendcountedtext(StringInfo buf, const char *str, int slen, bool countincludesself)
Definition: pqformat.c:143
void pq_send_ascii_string(StringInfo buf, const char *str)
Definition: pqformat.c:230
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:349
void pq_sendfloat8(StringInfo buf, float8 f)
Definition: pqformat.c:279
void pq_endmessage_reuse(StringInfo buf)
Definition: pqformat.c:317
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:153
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
void appendBinaryStringInfoNT(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:253
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:227
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:128
Definition: c.h:676
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305