1
0
mirror of https://github.com/postgres/postgres.git synced 2026-01-13 12:22:55 +03:00

Second round of FE/BE protocol changes. Frontend->backend messages now

have length counts, and COPY IN data is packetized into messages.
This commit is contained in:
Tom Lane
2003-04-19 00:02:30 +00:00
parent 54b38d293e
commit bd8d441775
24 changed files with 1337 additions and 982 deletions

View File

@@ -8,15 +8,17 @@
* formatting/conversion routines that are needed to produce valid messages.
* Note in particular the distinction between "raw data" and "text"; raw data
* is message protocol characters and binary values that are not subject to
* character set conversion, while text is converted by character encoding rules.
* character set conversion, while text is converted by character encoding
* rules.
*
* Incoming messages are read directly off the wire, as it were, but there
* are still data-conversion tasks to be performed.
* Incoming messages are similarly read into a StringInfo buffer, via
* pq_getmessage, and then parsed and converted from that using the routines
* in this module.
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pqformat.c,v 1.26 2003/04/02 00:49:28 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/pqformat.c,v 1.27 2003/04/19 00:02:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -37,12 +39,13 @@
* Special-case message output:
* pq_puttextmessage - generate a character set-converted message in one step
*
* Message input:
* pq_getint - get an integer from connection
* pq_getstr_bounded - get a null terminated string from connection
* pq_getstr_bounded performs character set conversion on the collected
* string. Use the raw pqcomm.c routines pq_getstring or pq_getbytes
* to fetch data without conversion.
* Message parsing after input:
* pq_getmsgbyte - get a raw byte from a message buffer
* pq_getmsgint - get a binary integer from a message buffer
* pq_getmsgbytes - get raw data from a message buffer
* pq_copymsgbytes - copy raw data from a message buffer
* pq_getmsgstring - get a null-terminated text string (with conversion)
* pq_getmsgend - verify message fully consumed
*/
#include "postgres.h"
@@ -206,16 +209,29 @@ pq_puttextmessage(char msgtype, const char *str)
return pq_putmessage(msgtype, str, slen + 1);
}
/* --------------------------------
* pq_getint - get an integer from connection
*
* returns 0 if OK, EOF if trouble
* pq_getmsgbyte - get a raw byte from a message buffer
* --------------------------------
*/
int
pq_getint(int *result, int b)
pq_getmsgbyte(StringInfo msg)
{
int status;
if (msg->cursor >= msg->len)
elog(ERROR, "pq_getmsgbyte: no data left in message");
return (unsigned char) msg->data[msg->cursor++];
}
/* --------------------------------
* pq_getmsgint - get a binary integer from a message buffer
*
* Values are treated as unsigned.
* --------------------------------
*/
unsigned int
pq_getmsgint(StringInfo msg, int b)
{
unsigned int result;
unsigned char n8;
uint16 n16;
uint32 n32;
@@ -223,59 +239,93 @@ pq_getint(int *result, int b)
switch (b)
{
case 1:
status = pq_getbytes((char *) &n8, 1);
*result = (int) n8;
pq_copymsgbytes(msg, (char *) &n8, 1);
result = n8;
break;
case 2:
status = pq_getbytes((char *) &n16, 2);
*result = (int) (ntohs(n16));
pq_copymsgbytes(msg, (char *) &n16, 2);
result = ntohs(n16);
break;
case 4:
status = pq_getbytes((char *) &n32, 4);
*result = (int) (ntohl(n32));
pq_copymsgbytes(msg, (char *) &n32, 4);
result = ntohl(n32);
break;
default:
/*
* if we elog(ERROR) here, we will lose sync with the
* frontend, so just complain to postmaster log instead...
*/
elog(COMMERROR, "pq_getint: unsupported size %d", b);
status = EOF;
*result = 0;
elog(ERROR, "pq_getmsgint: unsupported size %d", b);
result = 0; /* keep compiler quiet */
break;
}
return status;
return result;
}
/* --------------------------------
* pq_getstr_bounded - get a null terminated string from connection
* pq_getmsgbytes - get raw data from a message buffer
*
* The return value is placed in an expansible StringInfo.
* Note that space allocation comes from the current memory context!
*
* The maxlen parameter is interpreted as per pq_getstring.
*
* returns 0 if OK, EOF if trouble
* Returns a pointer directly into the message buffer; note this
* may not have any particular alignment.
* --------------------------------
*/
int
pq_getstr_bounded(StringInfo s, int maxlen)
const char *
pq_getmsgbytes(StringInfo msg, int datalen)
{
int result;
char *p;
result = pq_getstring(s, maxlen);
p = (char *) pg_client_to_server((unsigned char *) s->data, s->len);
if (p != s->data) /* actual conversion has been done? */
{
/* reset s to empty, and append the new string p */
s->len = 0;
s->data[0] = '\0';
appendBinaryStringInfo(s, p, strlen(p));
pfree(p);
}
const char *result;
if (datalen > (msg->len - msg->cursor))
elog(ERROR, "pq_getmsgbytes: insufficient data left in message");
result = &msg->data[msg->cursor];
msg->cursor += datalen;
return result;
}
/* --------------------------------
* pq_copymsgbytes - copy raw data from a message buffer
*
* Same as above, except data is copied to caller's buffer.
* --------------------------------
*/
void
pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
{
if (datalen > (msg->len - msg->cursor))
elog(ERROR, "pq_copymsgbytes: insufficient data left in message");
memcpy(buf, &msg->data[msg->cursor], datalen);
msg->cursor += datalen;
}
/* --------------------------------
* pq_getmsgstring - get a null-terminated text string (with conversion)
*
* May return a pointer directly into the message buffer, or a pointer
* to a palloc'd conversion result.
* --------------------------------
*/
const char *
pq_getmsgstring(StringInfo msg)
{
char *str;
int slen;
str = &msg->data[msg->cursor];
/*
* It's safe to use strlen() here because a StringInfo is guaranteed
* to have a trailing null byte. But check we found a null inside
* the message.
*/
slen = strlen(str);
if (msg->cursor + slen >= msg->len)
elog(ERROR, "pq_getmsgstring: invalid string in message");
msg->cursor += slen + 1;
return (const char *) pg_client_to_server((unsigned char *) str, slen);
}
/* --------------------------------
* pq_getmsgend - verify message fully consumed
* --------------------------------
*/
void
pq_getmsgend(StringInfo msg)
{
if (msg->cursor != msg->len)
elog(ERROR, "pq_getmsgend: invalid message format");
}