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