mirror of
https://github.com/postgres/postgres.git
synced 2025-08-25 20:23:07 +03:00
Remove server and libpq support for old FE/BE protocol version 2.
Protocol version 3 was introduced in PostgreSQL 7.4. There shouldn't be many clients or servers left out there without version 3 support. But as a courtesy, I kept just enough of the old protocol support that we can still send the "unsupported protocol version" error in v2 format, so that old clients can display the message properly. Likewise, libpq still understands v2 ErrorResponse messages when establishing a connection. The impetus to do this now is that I'm working on a patch to COPY FROM, to always prefetch some data. We cannot do that safely with the old protocol, because it requires parsing the input one byte at a time to detect the end-of-copy marker. Reviewed-by: Tom Lane, Alvaro Herrera, John Naylor Discussion: https://www.postgresql.org/message-id/9ec25819-0a8a-d51a-17dc-4150bb3cca3b%40iki.fi
This commit is contained in:
@@ -27,16 +27,9 @@
|
||||
static void printtup_startup(DestReceiver *self, int operation,
|
||||
TupleDesc typeinfo);
|
||||
static bool printtup(TupleTableSlot *slot, DestReceiver *self);
|
||||
static bool printtup_20(TupleTableSlot *slot, DestReceiver *self);
|
||||
static bool printtup_internal_20(TupleTableSlot *slot, DestReceiver *self);
|
||||
static void printtup_shutdown(DestReceiver *self);
|
||||
static void printtup_destroy(DestReceiver *self);
|
||||
|
||||
static void SendRowDescriptionCols_2(StringInfo buf, TupleDesc typeinfo,
|
||||
List *targetlist, int16 *formats);
|
||||
static void SendRowDescriptionCols_3(StringInfo buf, TupleDesc typeinfo,
|
||||
List *targetlist, int16 *formats);
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* printtup / debugtup support
|
||||
* ----------------------------------------------------------------
|
||||
@@ -112,19 +105,6 @@ SetRemoteDestReceiverParams(DestReceiver *self, Portal portal)
|
||||
myState->pub.mydest == DestRemoteExecute);
|
||||
|
||||
myState->portal = portal;
|
||||
|
||||
if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
|
||||
{
|
||||
/*
|
||||
* In protocol 2.0 the Bind message does not exist, so there is no way
|
||||
* for the columns to have different print formats; it's sufficient to
|
||||
* look at the first one.
|
||||
*/
|
||||
if (portal->formats && portal->formats[0] != 0)
|
||||
myState->pub.receiveSlot = printtup_internal_20;
|
||||
else
|
||||
myState->pub.receiveSlot = printtup_20;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -149,21 +129,6 @@ printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
|
||||
"printtup",
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
|
||||
if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
|
||||
{
|
||||
/*
|
||||
* Send portal name to frontend (obsolete cruft, gone in proto 3.0)
|
||||
*
|
||||
* If portal name not specified, use "blank" portal.
|
||||
*/
|
||||
const char *portalName = portal->name;
|
||||
|
||||
if (portalName == NULL || portalName[0] == '\0')
|
||||
portalName = "blank";
|
||||
|
||||
pq_puttextmessage('P', portalName);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are supposed to emit row descriptions, then send the tuple
|
||||
* descriptor of the tuples.
|
||||
@@ -202,31 +167,14 @@ SendRowDescriptionMessage(StringInfo buf, TupleDesc typeinfo,
|
||||
List *targetlist, int16 *formats)
|
||||
{
|
||||
int natts = typeinfo->natts;
|
||||
int proto = PG_PROTOCOL_MAJOR(FrontendProtocol);
|
||||
int i;
|
||||
ListCell *tlist_item = list_head(targetlist);
|
||||
|
||||
/* tuple descriptor message type */
|
||||
pq_beginmessage_reuse(buf, 'T');
|
||||
/* # of attrs in tuples */
|
||||
pq_sendint16(buf, natts);
|
||||
|
||||
if (proto >= 3)
|
||||
SendRowDescriptionCols_3(buf, typeinfo, targetlist, formats);
|
||||
else
|
||||
SendRowDescriptionCols_2(buf, typeinfo, targetlist, formats);
|
||||
|
||||
pq_endmessage_reuse(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send description for each column when using v3+ protocol
|
||||
*/
|
||||
static void
|
||||
SendRowDescriptionCols_3(StringInfo buf, TupleDesc typeinfo, List *targetlist, int16 *formats)
|
||||
{
|
||||
int natts = typeinfo->natts;
|
||||
int i;
|
||||
ListCell *tlist_item = list_head(targetlist);
|
||||
|
||||
/*
|
||||
* Preallocate memory for the entire message to be sent. That allows to
|
||||
* use the significantly faster inline pqformat.h functions and to avoid
|
||||
@@ -291,33 +239,8 @@ SendRowDescriptionCols_3(StringInfo buf, TupleDesc typeinfo, List *targetlist, i
|
||||
pq_writeint32(buf, atttypmod);
|
||||
pq_writeint16(buf, format);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send description for each column when using v2 protocol
|
||||
*/
|
||||
static void
|
||||
SendRowDescriptionCols_2(StringInfo buf, TupleDesc typeinfo, List *targetlist, int16 *formats)
|
||||
{
|
||||
int natts = typeinfo->natts;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < natts; ++i)
|
||||
{
|
||||
Form_pg_attribute att = TupleDescAttr(typeinfo, i);
|
||||
Oid atttypid = att->atttypid;
|
||||
int32 atttypmod = att->atttypmod;
|
||||
|
||||
/* If column is a domain, send the base type and typmod instead */
|
||||
atttypid = getBaseTypeAndTypmod(atttypid, &atttypmod);
|
||||
|
||||
pq_sendstring(buf, NameStr(att->attname));
|
||||
/* column ID only info appears in protocol 3.0 and up */
|
||||
pq_sendint32(buf, atttypid);
|
||||
pq_sendint16(buf, att->attlen);
|
||||
pq_sendint32(buf, atttypmod);
|
||||
/* format info only appears in protocol 3.0 and up */
|
||||
}
|
||||
pq_endmessage_reuse(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -371,7 +294,7 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* printtup --- print a tuple in protocol 3.0
|
||||
* printtup --- send a tuple to the client
|
||||
* ----------------
|
||||
*/
|
||||
static bool
|
||||
@@ -455,84 +378,6 @@ printtup(TupleTableSlot *slot, DestReceiver *self)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* printtup_20 --- print a tuple in protocol 2.0
|
||||
* ----------------
|
||||
*/
|
||||
static bool
|
||||
printtup_20(TupleTableSlot *slot, DestReceiver *self)
|
||||
{
|
||||
TupleDesc typeinfo = slot->tts_tupleDescriptor;
|
||||
DR_printtup *myState = (DR_printtup *) self;
|
||||
MemoryContext oldcontext;
|
||||
StringInfo buf = &myState->buf;
|
||||
int natts = typeinfo->natts;
|
||||
int i,
|
||||
j,
|
||||
k;
|
||||
|
||||
/* Set or update my derived attribute info, if needed */
|
||||
if (myState->attrinfo != typeinfo || myState->nattrs != natts)
|
||||
printtup_prepare_info(myState, typeinfo, natts);
|
||||
|
||||
/* Make sure the tuple is fully deconstructed */
|
||||
slot_getallattrs(slot);
|
||||
|
||||
/* Switch into per-row context so we can recover memory below */
|
||||
oldcontext = MemoryContextSwitchTo(myState->tmpcontext);
|
||||
|
||||
/*
|
||||
* tell the frontend to expect new tuple data (in ASCII style)
|
||||
*/
|
||||
pq_beginmessage_reuse(buf, 'D');
|
||||
|
||||
/*
|
||||
* send a bitmap of which attributes are not null
|
||||
*/
|
||||
j = 0;
|
||||
k = 1 << 7;
|
||||
for (i = 0; i < natts; ++i)
|
||||
{
|
||||
if (!slot->tts_isnull[i])
|
||||
j |= k; /* set bit if not null */
|
||||
k >>= 1;
|
||||
if (k == 0) /* end of byte? */
|
||||
{
|
||||
pq_sendint8(buf, j);
|
||||
j = 0;
|
||||
k = 1 << 7;
|
||||
}
|
||||
}
|
||||
if (k != (1 << 7)) /* flush last partial byte */
|
||||
pq_sendint8(buf, j);
|
||||
|
||||
/*
|
||||
* send the attributes of this tuple
|
||||
*/
|
||||
for (i = 0; i < natts; ++i)
|
||||
{
|
||||
PrinttupAttrInfo *thisState = myState->myinfo + i;
|
||||
Datum attr = slot->tts_values[i];
|
||||
char *outputstr;
|
||||
|
||||
if (slot->tts_isnull[i])
|
||||
continue;
|
||||
|
||||
Assert(thisState->format == 0);
|
||||
|
||||
outputstr = OutputFunctionCall(&thisState->finfo, attr);
|
||||
pq_sendcountedtext(buf, outputstr, strlen(outputstr), true);
|
||||
}
|
||||
|
||||
pq_endmessage_reuse(buf);
|
||||
|
||||
/* Return to caller's context, and flush row's temporary memory */
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
MemoryContextReset(myState->tmpcontext);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* printtup_shutdown
|
||||
* ----------------
|
||||
@@ -638,88 +483,3 @@ debugtup(TupleTableSlot *slot, DestReceiver *self)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* printtup_internal_20 --- print a binary tuple in protocol 2.0
|
||||
*
|
||||
* We use a different message type, i.e. 'B' instead of 'D' to
|
||||
* indicate a tuple in internal (binary) form.
|
||||
*
|
||||
* This is largely same as printtup_20, except we use binary formatting.
|
||||
* ----------------
|
||||
*/
|
||||
static bool
|
||||
printtup_internal_20(TupleTableSlot *slot, DestReceiver *self)
|
||||
{
|
||||
TupleDesc typeinfo = slot->tts_tupleDescriptor;
|
||||
DR_printtup *myState = (DR_printtup *) self;
|
||||
MemoryContext oldcontext;
|
||||
StringInfo buf = &myState->buf;
|
||||
int natts = typeinfo->natts;
|
||||
int i,
|
||||
j,
|
||||
k;
|
||||
|
||||
/* Set or update my derived attribute info, if needed */
|
||||
if (myState->attrinfo != typeinfo || myState->nattrs != natts)
|
||||
printtup_prepare_info(myState, typeinfo, natts);
|
||||
|
||||
/* Make sure the tuple is fully deconstructed */
|
||||
slot_getallattrs(slot);
|
||||
|
||||
/* Switch into per-row context so we can recover memory below */
|
||||
oldcontext = MemoryContextSwitchTo(myState->tmpcontext);
|
||||
|
||||
/*
|
||||
* tell the frontend to expect new tuple data (in binary style)
|
||||
*/
|
||||
pq_beginmessage_reuse(buf, 'B');
|
||||
|
||||
/*
|
||||
* send a bitmap of which attributes are not null
|
||||
*/
|
||||
j = 0;
|
||||
k = 1 << 7;
|
||||
for (i = 0; i < natts; ++i)
|
||||
{
|
||||
if (!slot->tts_isnull[i])
|
||||
j |= k; /* set bit if not null */
|
||||
k >>= 1;
|
||||
if (k == 0) /* end of byte? */
|
||||
{
|
||||
pq_sendint8(buf, j);
|
||||
j = 0;
|
||||
k = 1 << 7;
|
||||
}
|
||||
}
|
||||
if (k != (1 << 7)) /* flush last partial byte */
|
||||
pq_sendint8(buf, j);
|
||||
|
||||
/*
|
||||
* send the attributes of this tuple
|
||||
*/
|
||||
for (i = 0; i < natts; ++i)
|
||||
{
|
||||
PrinttupAttrInfo *thisState = myState->myinfo + i;
|
||||
Datum attr = slot->tts_values[i];
|
||||
bytea *outputbytes;
|
||||
|
||||
if (slot->tts_isnull[i])
|
||||
continue;
|
||||
|
||||
Assert(thisState->format == 1);
|
||||
|
||||
outputbytes = SendFunctionCall(&thisState->finfo, attr);
|
||||
pq_sendint32(buf, VARSIZE(outputbytes) - VARHDRSZ);
|
||||
pq_sendbytes(buf, VARDATA(outputbytes),
|
||||
VARSIZE(outputbytes) - VARHDRSZ);
|
||||
}
|
||||
|
||||
pq_endmessage_reuse(buf);
|
||||
|
||||
/* Return to caller's context, and flush row's temporary memory */
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
MemoryContextReset(myState->tmpcontext);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Reference in New Issue
Block a user