Header And Logo

PostgreSQL
| The world's most advanced open source database.

pqformat.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * pqformat.c
00004  *      Routines for formatting and parsing frontend/backend messages
00005  *
00006  * Outgoing messages are built up in a StringInfo buffer (which is expansible)
00007  * and then sent in a single call to pq_putmessage.  This module provides data
00008  * formatting/conversion routines that are needed to produce valid messages.
00009  * Note in particular the distinction between "raw data" and "text"; raw data
00010  * is message protocol characters and binary values that are not subject to
00011  * character set conversion, while text is converted by character encoding
00012  * rules.
00013  *
00014  * Incoming messages are similarly read into a StringInfo buffer, via
00015  * pq_getmessage, and then parsed and converted from that using the routines
00016  * in this module.
00017  *
00018  * These same routines support reading and writing of external binary formats
00019  * (typsend/typreceive routines).  The conversion routines for individual
00020  * data types are exactly the same, only initialization and completion
00021  * are different.
00022  *
00023  *
00024  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00025  * Portions Copyright (c) 1994, Regents of the University of California
00026  *
00027  *  src/backend/libpq/pqformat.c
00028  *
00029  *-------------------------------------------------------------------------
00030  */
00031 /*
00032  * INTERFACE ROUTINES
00033  * Message assembly and output:
00034  *      pq_beginmessage - initialize StringInfo buffer
00035  *      pq_sendbyte     - append a raw byte to a StringInfo buffer
00036  *      pq_sendint      - append a binary integer to a StringInfo buffer
00037  *      pq_sendint64    - append a binary 8-byte int to a StringInfo buffer
00038  *      pq_sendfloat4   - append a float4 to a StringInfo buffer
00039  *      pq_sendfloat8   - append a float8 to a StringInfo buffer
00040  *      pq_sendbytes    - append raw data to a StringInfo buffer
00041  *      pq_sendcountedtext - append a counted text string (with character set conversion)
00042  *      pq_sendtext     - append a text string (with conversion)
00043  *      pq_sendstring   - append a null-terminated text string (with conversion)
00044  *      pq_send_ascii_string - append a null-terminated text string (without conversion)
00045  *      pq_endmessage   - send the completed message to the frontend
00046  * Note: it is also possible to append data to the StringInfo buffer using
00047  * the regular StringInfo routines, but this is discouraged since required
00048  * character set conversion may not occur.
00049  *
00050  * typsend support (construct a bytea value containing external binary data):
00051  *      pq_begintypsend - initialize StringInfo buffer
00052  *      pq_endtypsend   - return the completed string as a "bytea*"
00053  *
00054  * Special-case message output:
00055  *      pq_puttextmessage - generate a character set-converted message in one step
00056  *      pq_putemptymessage - convenience routine for message with empty body
00057  *
00058  * Message parsing after input:
00059  *      pq_getmsgbyte   - get a raw byte from a message buffer
00060  *      pq_getmsgint    - get a binary integer from a message buffer
00061  *      pq_getmsgint64  - get a binary 8-byte int from a message buffer
00062  *      pq_getmsgfloat4 - get a float4 from a message buffer
00063  *      pq_getmsgfloat8 - get a float8 from a message buffer
00064  *      pq_getmsgbytes  - get raw data from a message buffer
00065  *      pq_copymsgbytes - copy raw data from a message buffer
00066  *      pq_getmsgtext   - get a counted text string (with conversion)
00067  *      pq_getmsgstring - get a null-terminated text string (with conversion)
00068  *      pq_getmsgend    - verify message fully consumed
00069  */
00070 
00071 #include "postgres.h"
00072 
00073 #include <sys/param.h>
00074 #include <netinet/in.h>
00075 #include <arpa/inet.h>
00076 
00077 #include "libpq/libpq.h"
00078 #include "libpq/pqformat.h"
00079 #include "mb/pg_wchar.h"
00080 
00081 
00082 /* --------------------------------
00083  *      pq_beginmessage     - initialize for sending a message
00084  * --------------------------------
00085  */
00086 void
00087 pq_beginmessage(StringInfo buf, char msgtype)
00088 {
00089     initStringInfo(buf);
00090 
00091     /*
00092      * We stash the message type into the buffer's cursor field, expecting
00093      * that the pq_sendXXX routines won't touch it.  We could alternatively
00094      * make it the first byte of the buffer contents, but this seems easier.
00095      */
00096     buf->cursor = msgtype;
00097 }
00098 
00099 /* --------------------------------
00100  *      pq_sendbyte     - append a raw byte to a StringInfo buffer
00101  * --------------------------------
00102  */
00103 void
00104 pq_sendbyte(StringInfo buf, int byt)
00105 {
00106     appendStringInfoCharMacro(buf, byt);
00107 }
00108 
00109 /* --------------------------------
00110  *      pq_sendbytes    - append raw data to a StringInfo buffer
00111  * --------------------------------
00112  */
00113 void
00114 pq_sendbytes(StringInfo buf, const char *data, int datalen)
00115 {
00116     appendBinaryStringInfo(buf, data, datalen);
00117 }
00118 
00119 /* --------------------------------
00120  *      pq_sendcountedtext - append a counted text string (with character set conversion)
00121  *
00122  * The data sent to the frontend by this routine is a 4-byte count field
00123  * followed by the string.  The count includes itself or not, as per the
00124  * countincludesself flag (pre-3.0 protocol requires it to include itself).
00125  * The passed text string need not be null-terminated, and the data sent
00126  * to the frontend isn't either.
00127  * --------------------------------
00128  */
00129 void
00130 pq_sendcountedtext(StringInfo buf, const char *str, int slen,
00131                    bool countincludesself)
00132 {
00133     int         extra = countincludesself ? 4 : 0;
00134     char       *p;
00135 
00136     p = pg_server_to_client(str, slen);
00137     if (p != str)               /* actual conversion has been done? */
00138     {
00139         slen = strlen(p);
00140         pq_sendint(buf, slen + extra, 4);
00141         appendBinaryStringInfo(buf, p, slen);
00142         pfree(p);
00143     }
00144     else
00145     {
00146         pq_sendint(buf, slen + extra, 4);
00147         appendBinaryStringInfo(buf, str, slen);
00148     }
00149 }
00150 
00151 /* --------------------------------
00152  *      pq_sendtext     - append a text string (with conversion)
00153  *
00154  * The passed text string need not be null-terminated, and the data sent
00155  * to the frontend isn't either.  Note that this is not actually useful
00156  * for direct frontend transmissions, since there'd be no way for the
00157  * frontend to determine the string length.  But it is useful for binary
00158  * format conversions.
00159  * --------------------------------
00160  */
00161 void
00162 pq_sendtext(StringInfo buf, const char *str, int slen)
00163 {
00164     char       *p;
00165 
00166     p = pg_server_to_client(str, slen);
00167     if (p != str)               /* actual conversion has been done? */
00168     {
00169         slen = strlen(p);
00170         appendBinaryStringInfo(buf, p, slen);
00171         pfree(p);
00172     }
00173     else
00174         appendBinaryStringInfo(buf, str, slen);
00175 }
00176 
00177 /* --------------------------------
00178  *      pq_sendstring   - append a null-terminated text string (with conversion)
00179  *
00180  * NB: passed text string must be null-terminated, and so is the data
00181  * sent to the frontend.
00182  * --------------------------------
00183  */
00184 void
00185 pq_sendstring(StringInfo buf, const char *str)
00186 {
00187     int         slen = strlen(str);
00188     char       *p;
00189 
00190     p = pg_server_to_client(str, slen);
00191     if (p != str)               /* actual conversion has been done? */
00192     {
00193         slen = strlen(p);
00194         appendBinaryStringInfo(buf, p, slen + 1);
00195         pfree(p);
00196     }
00197     else
00198         appendBinaryStringInfo(buf, str, slen + 1);
00199 }
00200 
00201 /* --------------------------------
00202  *      pq_send_ascii_string    - append a null-terminated text string (without conversion)
00203  *
00204  * This function intentionally bypasses encoding conversion, instead just
00205  * silently replacing any non-7-bit-ASCII characters with question marks.
00206  * It is used only when we are having trouble sending an error message to
00207  * the client with normal localization and encoding conversion.  The caller
00208  * should already have taken measures to ensure the string is just ASCII;
00209  * the extra work here is just to make certain we don't send a badly encoded
00210  * string to the client (which might or might not be robust about that).
00211  *
00212  * NB: passed text string must be null-terminated, and so is the data
00213  * sent to the frontend.
00214  * --------------------------------
00215  */
00216 void
00217 pq_send_ascii_string(StringInfo buf, const char *str)
00218 {
00219     while (*str)
00220     {
00221         char        ch = *str++;
00222 
00223         if (IS_HIGHBIT_SET(ch))
00224             ch = '?';
00225         appendStringInfoCharMacro(buf, ch);
00226     }
00227     appendStringInfoChar(buf, '\0');
00228 }
00229 
00230 /* --------------------------------
00231  *      pq_sendint      - append a binary integer to a StringInfo buffer
00232  * --------------------------------
00233  */
00234 void
00235 pq_sendint(StringInfo buf, int i, int b)
00236 {
00237     unsigned char n8;
00238     uint16      n16;
00239     uint32      n32;
00240 
00241     switch (b)
00242     {
00243         case 1:
00244             n8 = (unsigned char) i;
00245             appendBinaryStringInfo(buf, (char *) &n8, 1);
00246             break;
00247         case 2:
00248             n16 = htons((uint16) i);
00249             appendBinaryStringInfo(buf, (char *) &n16, 2);
00250             break;
00251         case 4:
00252             n32 = htonl((uint32) i);
00253             appendBinaryStringInfo(buf, (char *) &n32, 4);
00254             break;
00255         default:
00256             elog(ERROR, "unsupported integer size %d", b);
00257             break;
00258     }
00259 }
00260 
00261 /* --------------------------------
00262  *      pq_sendint64    - append a binary 8-byte int to a StringInfo buffer
00263  *
00264  * It is tempting to merge this with pq_sendint, but we'd have to make the
00265  * argument int64 for all data widths --- that could be a big performance
00266  * hit on machines where int64 isn't efficient.
00267  * --------------------------------
00268  */
00269 void
00270 pq_sendint64(StringInfo buf, int64 i)
00271 {
00272     uint32      n32;
00273 
00274     /* High order half first, since we're doing MSB-first */
00275     n32 = (uint32) (i >> 32);
00276     n32 = htonl(n32);
00277     appendBinaryStringInfo(buf, (char *) &n32, 4);
00278 
00279     /* Now the low order half */
00280     n32 = (uint32) i;
00281     n32 = htonl(n32);
00282     appendBinaryStringInfo(buf, (char *) &n32, 4);
00283 }
00284 
00285 /* --------------------------------
00286  *      pq_sendfloat4   - append a float4 to a StringInfo buffer
00287  *
00288  * The point of this routine is to localize knowledge of the external binary
00289  * representation of float4, which is a component of several datatypes.
00290  *
00291  * We currently assume that float4 should be byte-swapped in the same way
00292  * as int4.  This rule is not perfect but it gives us portability across
00293  * most IEEE-float-using architectures.
00294  * --------------------------------
00295  */
00296 void
00297 pq_sendfloat4(StringInfo buf, float4 f)
00298 {
00299     union
00300     {
00301         float4      f;
00302         uint32      i;
00303     }           swap;
00304 
00305     swap.f = f;
00306     swap.i = htonl(swap.i);
00307 
00308     appendBinaryStringInfo(buf, (char *) &swap.i, 4);
00309 }
00310 
00311 /* --------------------------------
00312  *      pq_sendfloat8   - append a float8 to a StringInfo buffer
00313  *
00314  * The point of this routine is to localize knowledge of the external binary
00315  * representation of float8, which is a component of several datatypes.
00316  *
00317  * We currently assume that float8 should be byte-swapped in the same way
00318  * as int8.  This rule is not perfect but it gives us portability across
00319  * most IEEE-float-using architectures.
00320  * --------------------------------
00321  */
00322 void
00323 pq_sendfloat8(StringInfo buf, float8 f)
00324 {
00325     union
00326     {
00327         float8      f;
00328         int64       i;
00329     }           swap;
00330 
00331     swap.f = f;
00332     pq_sendint64(buf, swap.i);
00333 }
00334 
00335 /* --------------------------------
00336  *      pq_endmessage   - send the completed message to the frontend
00337  *
00338  * The data buffer is pfree()d, but if the StringInfo was allocated with
00339  * makeStringInfo then the caller must still pfree it.
00340  * --------------------------------
00341  */
00342 void
00343 pq_endmessage(StringInfo buf)
00344 {
00345     /* msgtype was saved in cursor field */
00346     (void) pq_putmessage(buf->cursor, buf->data, buf->len);
00347     /* no need to complain about any failure, since pqcomm.c already did */
00348     pfree(buf->data);
00349     buf->data = NULL;
00350 }
00351 
00352 
00353 /* --------------------------------
00354  *      pq_begintypsend     - initialize for constructing a bytea result
00355  * --------------------------------
00356  */
00357 void
00358 pq_begintypsend(StringInfo buf)
00359 {
00360     initStringInfo(buf);
00361     /* Reserve four bytes for the bytea length word */
00362     appendStringInfoCharMacro(buf, '\0');
00363     appendStringInfoCharMacro(buf, '\0');
00364     appendStringInfoCharMacro(buf, '\0');
00365     appendStringInfoCharMacro(buf, '\0');
00366 }
00367 
00368 /* --------------------------------
00369  *      pq_endtypsend   - finish constructing a bytea result
00370  *
00371  * The data buffer is returned as the palloc'd bytea value.  (We expect
00372  * that it will be suitably aligned for this because it has been palloc'd.)
00373  * We assume the StringInfoData is just a local variable in the caller and
00374  * need not be pfree'd.
00375  * --------------------------------
00376  */
00377 bytea *
00378 pq_endtypsend(StringInfo buf)
00379 {
00380     bytea      *result = (bytea *) buf->data;
00381 
00382     /* Insert correct length into bytea length word */
00383     Assert(buf->len >= VARHDRSZ);
00384     SET_VARSIZE(result, buf->len);
00385 
00386     return result;
00387 }
00388 
00389 
00390 /* --------------------------------
00391  *      pq_puttextmessage - generate a character set-converted message in one step
00392  *
00393  *      This is the same as the pqcomm.c routine pq_putmessage, except that
00394  *      the message body is a null-terminated string to which encoding
00395  *      conversion applies.
00396  * --------------------------------
00397  */
00398 void
00399 pq_puttextmessage(char msgtype, const char *str)
00400 {
00401     int         slen = strlen(str);
00402     char       *p;
00403 
00404     p = pg_server_to_client(str, slen);
00405     if (p != str)               /* actual conversion has been done? */
00406     {
00407         (void) pq_putmessage(msgtype, p, strlen(p) + 1);
00408         pfree(p);
00409         return;
00410     }
00411     (void) pq_putmessage(msgtype, str, slen + 1);
00412 }
00413 
00414 
00415 /* --------------------------------
00416  *      pq_putemptymessage - convenience routine for message with empty body
00417  * --------------------------------
00418  */
00419 void
00420 pq_putemptymessage(char msgtype)
00421 {
00422     (void) pq_putmessage(msgtype, NULL, 0);
00423 }
00424 
00425 
00426 /* --------------------------------
00427  *      pq_getmsgbyte   - get a raw byte from a message buffer
00428  * --------------------------------
00429  */
00430 int
00431 pq_getmsgbyte(StringInfo msg)
00432 {
00433     if (msg->cursor >= msg->len)
00434         ereport(ERROR,
00435                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00436                  errmsg("no data left in message")));
00437     return (unsigned char) msg->data[msg->cursor++];
00438 }
00439 
00440 /* --------------------------------
00441  *      pq_getmsgint    - get a binary integer from a message buffer
00442  *
00443  *      Values are treated as unsigned.
00444  * --------------------------------
00445  */
00446 unsigned int
00447 pq_getmsgint(StringInfo msg, int b)
00448 {
00449     unsigned int result;
00450     unsigned char n8;
00451     uint16      n16;
00452     uint32      n32;
00453 
00454     switch (b)
00455     {
00456         case 1:
00457             pq_copymsgbytes(msg, (char *) &n8, 1);
00458             result = n8;
00459             break;
00460         case 2:
00461             pq_copymsgbytes(msg, (char *) &n16, 2);
00462             result = ntohs(n16);
00463             break;
00464         case 4:
00465             pq_copymsgbytes(msg, (char *) &n32, 4);
00466             result = ntohl(n32);
00467             break;
00468         default:
00469             elog(ERROR, "unsupported integer size %d", b);
00470             result = 0;         /* keep compiler quiet */
00471             break;
00472     }
00473     return result;
00474 }
00475 
00476 /* --------------------------------
00477  *      pq_getmsgint64  - get a binary 8-byte int from a message buffer
00478  *
00479  * It is tempting to merge this with pq_getmsgint, but we'd have to make the
00480  * result int64 for all data widths --- that could be a big performance
00481  * hit on machines where int64 isn't efficient.
00482  * --------------------------------
00483  */
00484 int64
00485 pq_getmsgint64(StringInfo msg)
00486 {
00487     int64       result;
00488     uint32      h32;
00489     uint32      l32;
00490 
00491     pq_copymsgbytes(msg, (char *) &h32, 4);
00492     pq_copymsgbytes(msg, (char *) &l32, 4);
00493     h32 = ntohl(h32);
00494     l32 = ntohl(l32);
00495 
00496     result = h32;
00497     result <<= 32;
00498     result |= l32;
00499 
00500     return result;
00501 }
00502 
00503 /* --------------------------------
00504  *      pq_getmsgfloat4 - get a float4 from a message buffer
00505  *
00506  * See notes for pq_sendfloat4.
00507  * --------------------------------
00508  */
00509 float4
00510 pq_getmsgfloat4(StringInfo msg)
00511 {
00512     union
00513     {
00514         float4      f;
00515         uint32      i;
00516     }           swap;
00517 
00518     swap.i = pq_getmsgint(msg, 4);
00519     return swap.f;
00520 }
00521 
00522 /* --------------------------------
00523  *      pq_getmsgfloat8 - get a float8 from a message buffer
00524  *
00525  * See notes for pq_sendfloat8.
00526  * --------------------------------
00527  */
00528 float8
00529 pq_getmsgfloat8(StringInfo msg)
00530 {
00531     union
00532     {
00533         float8      f;
00534         int64       i;
00535     }           swap;
00536 
00537     swap.i = pq_getmsgint64(msg);
00538     return swap.f;
00539 }
00540 
00541 /* --------------------------------
00542  *      pq_getmsgbytes  - get raw data from a message buffer
00543  *
00544  *      Returns a pointer directly into the message buffer; note this
00545  *      may not have any particular alignment.
00546  * --------------------------------
00547  */
00548 const char *
00549 pq_getmsgbytes(StringInfo msg, int datalen)
00550 {
00551     const char *result;
00552 
00553     if (datalen < 0 || datalen > (msg->len - msg->cursor))
00554         ereport(ERROR,
00555                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00556                  errmsg("insufficient data left in message")));
00557     result = &msg->data[msg->cursor];
00558     msg->cursor += datalen;
00559     return result;
00560 }
00561 
00562 /* --------------------------------
00563  *      pq_copymsgbytes - copy raw data from a message buffer
00564  *
00565  *      Same as above, except data is copied to caller's buffer.
00566  * --------------------------------
00567  */
00568 void
00569 pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
00570 {
00571     if (datalen < 0 || datalen > (msg->len - msg->cursor))
00572         ereport(ERROR,
00573                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00574                  errmsg("insufficient data left in message")));
00575     memcpy(buf, &msg->data[msg->cursor], datalen);
00576     msg->cursor += datalen;
00577 }
00578 
00579 /* --------------------------------
00580  *      pq_getmsgtext   - get a counted text string (with conversion)
00581  *
00582  *      Always returns a pointer to a freshly palloc'd result.
00583  *      The result has a trailing null, *and* we return its strlen in *nbytes.
00584  * --------------------------------
00585  */
00586 char *
00587 pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
00588 {
00589     char       *str;
00590     char       *p;
00591 
00592     if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor))
00593         ereport(ERROR,
00594                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00595                  errmsg("insufficient data left in message")));
00596     str = &msg->data[msg->cursor];
00597     msg->cursor += rawbytes;
00598 
00599     p = pg_client_to_server(str, rawbytes);
00600     if (p != str)               /* actual conversion has been done? */
00601         *nbytes = strlen(p);
00602     else
00603     {
00604         p = (char *) palloc(rawbytes + 1);
00605         memcpy(p, str, rawbytes);
00606         p[rawbytes] = '\0';
00607         *nbytes = rawbytes;
00608     }
00609     return p;
00610 }
00611 
00612 /* --------------------------------
00613  *      pq_getmsgstring - get a null-terminated text string (with conversion)
00614  *
00615  *      May return a pointer directly into the message buffer, or a pointer
00616  *      to a palloc'd conversion result.
00617  * --------------------------------
00618  */
00619 const char *
00620 pq_getmsgstring(StringInfo msg)
00621 {
00622     char       *str;
00623     int         slen;
00624 
00625     str = &msg->data[msg->cursor];
00626 
00627     /*
00628      * It's safe to use strlen() here because a StringInfo is guaranteed to
00629      * have a trailing null byte.  But check we found a null inside the
00630      * message.
00631      */
00632     slen = strlen(str);
00633     if (msg->cursor + slen >= msg->len)
00634         ereport(ERROR,
00635                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00636                  errmsg("invalid string in message")));
00637     msg->cursor += slen + 1;
00638 
00639     return pg_client_to_server(str, slen);
00640 }
00641 
00642 /* --------------------------------
00643  *      pq_getmsgend    - verify message fully consumed
00644  * --------------------------------
00645  */
00646 void
00647 pq_getmsgend(StringInfo msg)
00648 {
00649     if (msg->cursor != msg->len)
00650         ereport(ERROR,
00651                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
00652                  errmsg("invalid message format")));
00653 }