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-2011, 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_getmsgend - verify message fully consumed
73
#include <sys/param.h>
74
#include <netinet/in.h>
75
#include <arpa/inet.h>
77
#include "libpq/libpq.h"
78
#include "libpq/pqformat.h"
79
#include "mb/pg_wchar.h"
82
/* --------------------------------
83
* pq_beginmessage - initialize for sending a message
84
* --------------------------------
87
pq_beginmessage(StringInfo buf, char msgtype)
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.
96
buf->cursor = msgtype;
99
/* --------------------------------
100
* pq_sendbyte - append a raw byte to a StringInfo buffer
101
* --------------------------------
104
pq_sendbyte(StringInfo buf, int byt)
106
appendStringInfoCharMacro(buf, byt);
109
/* --------------------------------
110
* pq_sendbytes - append raw data to a StringInfo buffer
111
* --------------------------------
114
pq_sendbytes(StringInfo buf, const char *data, int datalen)
116
appendBinaryStringInfo(buf, data, datalen);
119
/* --------------------------------
120
* pq_sendcountedtext - append a counted text string (with character set conversion)
122
* The data sent to the frontend by this routine is a 4-byte count field
123
* followed by the string. The count includes itself or not, as per the
124
* countincludesself flag (pre-3.0 protocol requires it to include itself).
125
* The passed text string need not be null-terminated, and the data sent
126
* to the frontend isn't either.
127
* --------------------------------
130
pq_sendcountedtext(StringInfo buf, const char *str, int slen,
131
bool countincludesself)
133
int extra = countincludesself ? 4 : 0;
136
p = pg_server_to_client(str, slen);
137
if (p != str) /* actual conversion has been done? */
140
pq_sendint(buf, slen + extra, 4);
141
appendBinaryStringInfo(buf, p, slen);
146
pq_sendint(buf, slen + extra, 4);
147
appendBinaryStringInfo(buf, str, slen);
151
/* --------------------------------
152
* pq_sendtext - append a text string (with conversion)
154
* The passed text string need not be null-terminated, and the data sent
155
* to the frontend isn't either. Note that this is not actually useful
156
* for direct frontend transmissions, since there'd be no way for the
157
* frontend to determine the string length. But it is useful for binary
158
* format conversions.
159
* --------------------------------
162
pq_sendtext(StringInfo buf, const char *str, int slen)
166
p = pg_server_to_client(str, slen);
167
if (p != str) /* actual conversion has been done? */
170
appendBinaryStringInfo(buf, p, slen);
174
appendBinaryStringInfo(buf, str, slen);
177
/* --------------------------------
178
* pq_sendstring - append a null-terminated text string (with conversion)
180
* NB: passed text string must be null-terminated, and so is the data
181
* sent to the frontend.
182
* --------------------------------
185
pq_sendstring(StringInfo buf, const char *str)
187
int slen = strlen(str);
190
p = pg_server_to_client(str, slen);
191
if (p != str) /* actual conversion has been done? */
194
appendBinaryStringInfo(buf, p, slen + 1);
198
appendBinaryStringInfo(buf, str, slen + 1);
201
/* --------------------------------
202
* pq_send_ascii_string - append a null-terminated text string (without conversion)
204
* This function intentionally bypasses encoding conversion, instead just
205
* silently replacing any non-7-bit-ASCII characters with question marks.
206
* It is used only when we are having trouble sending an error message to
207
* the client with normal localization and encoding conversion. The caller
208
* should already have taken measures to ensure the string is just ASCII;
209
* the extra work here is just to make certain we don't send a badly encoded
210
* string to the client (which might or might not be robust about that).
212
* NB: passed text string must be null-terminated, and so is the data
213
* sent to the frontend.
214
* --------------------------------
217
pq_send_ascii_string(StringInfo buf, const char *str)
223
if (IS_HIGHBIT_SET(ch))
225
appendStringInfoCharMacro(buf, ch);
227
appendStringInfoChar(buf, '\0');
230
/* --------------------------------
231
* pq_sendint - append a binary integer to a StringInfo buffer
232
* --------------------------------
235
pq_sendint(StringInfo buf, int i, int b)
244
n8 = (unsigned char) i;
245
appendBinaryStringInfo(buf, (char *) &n8, 1);
248
n16 = htons((uint16) i);
249
appendBinaryStringInfo(buf, (char *) &n16, 2);
252
n32 = htonl((uint32) i);
253
appendBinaryStringInfo(buf, (char *) &n32, 4);
256
elog(ERROR, "unsupported integer size %d", b);
261
/* --------------------------------
262
* pq_sendint64 - append a binary 8-byte int to a StringInfo buffer
264
* It is tempting to merge this with pq_sendint, but we'd have to make the
265
* argument int64 for all data widths --- that could be a big performance
266
* hit on machines where int64 isn't efficient.
267
* --------------------------------
270
pq_sendint64(StringInfo buf, int64 i)
274
/* High order half first, since we're doing MSB-first */
275
n32 = (uint32) (i >> 32);
277
appendBinaryStringInfo(buf, (char *) &n32, 4);
279
/* Now the low order half */
282
appendBinaryStringInfo(buf, (char *) &n32, 4);
285
/* --------------------------------
286
* pq_sendfloat4 - append a float4 to a StringInfo buffer
288
* The point of this routine is to localize knowledge of the external binary
289
* representation of float4, which is a component of several datatypes.
291
* We currently assume that float4 should be byte-swapped in the same way
292
* as int4. This rule is not perfect but it gives us portability across
293
* most IEEE-float-using architectures.
294
* --------------------------------
297
pq_sendfloat4(StringInfo buf, float4 f)
306
swap.i = htonl(swap.i);
308
appendBinaryStringInfo(buf, (char *) &swap.i, 4);
311
/* --------------------------------
312
* pq_sendfloat8 - append a float8 to a StringInfo buffer
314
* The point of this routine is to localize knowledge of the external binary
315
* representation of float8, which is a component of several datatypes.
317
* We currently assume that float8 should be byte-swapped in the same way
318
* as int8. This rule is not perfect but it gives us portability across
319
* most IEEE-float-using architectures.
320
* --------------------------------
323
pq_sendfloat8(StringInfo buf, float8 f)
332
pq_sendint64(buf, swap.i);
335
/* --------------------------------
336
* pq_endmessage - send the completed message to the frontend
338
* The data buffer is pfree()d, but if the StringInfo was allocated with
339
* makeStringInfo then the caller must still pfree it.
340
* --------------------------------
343
pq_endmessage(StringInfo buf)
345
/* msgtype was saved in cursor field */
346
(void) pq_putmessage(buf->cursor, buf->data, buf->len);
347
/* no need to complain about any failure, since pqcomm.c already did */
353
/* --------------------------------
354
* pq_begintypsend - initialize for constructing a bytea result
355
* --------------------------------
358
pq_begintypsend(StringInfo buf)
361
/* Reserve four bytes for the bytea length word */
362
appendStringInfoCharMacro(buf, '\0');
363
appendStringInfoCharMacro(buf, '\0');
364
appendStringInfoCharMacro(buf, '\0');
365
appendStringInfoCharMacro(buf, '\0');
368
/* --------------------------------
369
* pq_endtypsend - finish constructing a bytea result
371
* The data buffer is returned as the palloc'd bytea value. (We expect
372
* that it will be suitably aligned for this because it has been palloc'd.)
373
* We assume the StringInfoData is just a local variable in the caller and
374
* need not be pfree'd.
375
* --------------------------------
378
pq_endtypsend(StringInfo buf)
380
bytea *result = (bytea *) buf->data;
382
/* Insert correct length into bytea length word */
383
Assert(buf->len >= VARHDRSZ);
384
SET_VARSIZE(result, buf->len);
390
/* --------------------------------
391
* pq_puttextmessage - generate a character set-converted message in one step
393
* This is the same as the pqcomm.c routine pq_putmessage, except that
394
* the message body is a null-terminated string to which encoding
395
* conversion applies.
396
* --------------------------------
399
pq_puttextmessage(char msgtype, const char *str)
401
int slen = strlen(str);
404
p = pg_server_to_client(str, slen);
405
if (p != str) /* actual conversion has been done? */
407
(void) pq_putmessage(msgtype, p, strlen(p) + 1);
411
(void) pq_putmessage(msgtype, str, slen + 1);
415
/* --------------------------------
416
* pq_putemptymessage - convenience routine for message with empty body
417
* --------------------------------
420
pq_putemptymessage(char msgtype)
422
(void) pq_putmessage(msgtype, NULL, 0);
426
/* --------------------------------
427
* pq_getmsgbyte - get a raw byte from a message buffer
428
* --------------------------------
431
pq_getmsgbyte(StringInfo msg)
433
if (msg->cursor >= msg->len)
435
(errcode(ERRCODE_PROTOCOL_VIOLATION),
436
errmsg("no data left in message")));
437
return (unsigned char) msg->data[msg->cursor++];
440
/* --------------------------------
441
* pq_getmsgint - get a binary integer from a message buffer
443
* Values are treated as unsigned.
444
* --------------------------------
447
pq_getmsgint(StringInfo msg, int b)
457
pq_copymsgbytes(msg, (char *) &n8, 1);
461
pq_copymsgbytes(msg, (char *) &n16, 2);
465
pq_copymsgbytes(msg, (char *) &n32, 4);
469
elog(ERROR, "unsupported integer size %d", b);
470
result = 0; /* keep compiler quiet */
476
/* --------------------------------
477
* pq_getmsgint64 - get a binary 8-byte int from a message buffer
479
* It is tempting to merge this with pq_getmsgint, but we'd have to make the
480
* result int64 for all data widths --- that could be a big performance
481
* hit on machines where int64 isn't efficient.
482
* --------------------------------
485
pq_getmsgint64(StringInfo msg)
491
pq_copymsgbytes(msg, (char *) &h32, 4);
492
pq_copymsgbytes(msg, (char *) &l32, 4);
503
/* --------------------------------
504
* pq_getmsgfloat4 - get a float4 from a message buffer
506
* See notes for pq_sendfloat4.
507
* --------------------------------
510
pq_getmsgfloat4(StringInfo msg)
518
swap.i = pq_getmsgint(msg, 4);
522
/* --------------------------------
523
* pq_getmsgfloat8 - get a float8 from a message buffer
525
* See notes for pq_sendfloat8.
526
* --------------------------------
529
pq_getmsgfloat8(StringInfo msg)
537
swap.i = pq_getmsgint64(msg);
541
/* --------------------------------
542
* pq_getmsgbytes - get raw data from a message buffer
544
* Returns a pointer directly into the message buffer; note this
545
* may not have any particular alignment.
546
* --------------------------------
549
pq_getmsgbytes(StringInfo msg, int datalen)
553
if (datalen < 0 || datalen > (msg->len - msg->cursor))
555
(errcode(ERRCODE_PROTOCOL_VIOLATION),
556
errmsg("insufficient data left in message")));
557
result = &msg->data[msg->cursor];
558
msg->cursor += datalen;
562
/* --------------------------------
563
* pq_copymsgbytes - copy raw data from a message buffer
565
* Same as above, except data is copied to caller's buffer.
566
* --------------------------------
569
pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
571
if (datalen < 0 || datalen > (msg->len - msg->cursor))
573
(errcode(ERRCODE_PROTOCOL_VIOLATION),
574
errmsg("insufficient data left in message")));
575
memcpy(buf, &msg->data[msg->cursor], datalen);
576
msg->cursor += datalen;
579
/* --------------------------------
580
* pq_getmsgtext - get a counted text string (with conversion)
582
* Always returns a pointer to a freshly palloc'd result.
583
* The result has a trailing null, *and* we return its strlen in *nbytes.
584
* --------------------------------
587
pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
592
if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor))
594
(errcode(ERRCODE_PROTOCOL_VIOLATION),
595
errmsg("insufficient data left in message")));
596
str = &msg->data[msg->cursor];
597
msg->cursor += rawbytes;
599
p = pg_client_to_server(str, rawbytes);
600
if (p != str) /* actual conversion has been done? */
604
p = (char *) palloc(rawbytes + 1);
605
memcpy(p, str, rawbytes);
612
/* --------------------------------
613
* pq_getmsgstring - get a null-terminated text string (with conversion)
615
* May return a pointer directly into the message buffer, or a pointer
616
* to a palloc'd conversion result.
617
* --------------------------------
620
pq_getmsgstring(StringInfo msg)
625
str = &msg->data[msg->cursor];
628
* It's safe to use strlen() here because a StringInfo is guaranteed to
629
* have a trailing null byte. But check we found a null inside the
633
if (msg->cursor + slen >= msg->len)
635
(errcode(ERRCODE_PROTOCOL_VIOLATION),
636
errmsg("invalid string in message")));
637
msg->cursor += slen + 1;
639
return pg_client_to_server(str, slen);
642
/* --------------------------------
643
* pq_getmsgend - verify message fully consumed
644
* --------------------------------
647
pq_getmsgend(StringInfo msg)
649
if (msg->cursor != msg->len)
651
(errcode(ERRCODE_PROTOCOL_VIOLATION),
652
errmsg("invalid message format")));