1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-12 05:01:15 +03:00

Revise backend libpq interfaces so that messages to the frontend

can be generated in a buffer and then sent to the frontend in a single
libpq call.  This solves problems with NOTICE and ERROR messages generated
in the middle of a data message or COPY OUT operation.
This commit is contained in:
Tom Lane
1999-04-25 03:19:27 +00:00
parent fc08814e00
commit 95cc41b81d
18 changed files with 1071 additions and 1028 deletions

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.25 1999/02/13 23:18:42 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.26 1999/04/25 03:19:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -39,6 +39,7 @@
#include "access/htup.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "access/printtup.h"
#include "utils/portal.h"
#include "utils/palloc.h"
@@ -137,8 +138,7 @@ BeginCommand(char *pname,
* send fe info on tuples we're about to send
* ----------------
*/
pq_putnchar("P", 1);/* new portal.. */
pq_putstr(pname); /* portal name */
pq_putmessage('P', pname, strlen(pname)+1);
/* ----------------
* if this is a retrieve, then we send back the tuple
@@ -148,17 +148,24 @@ BeginCommand(char *pname,
*/
if (operation == CMD_SELECT && !isIntoRel)
{
pq_putnchar("T", 1); /* type info to follow.. */
pq_putint(natts, 2); /* number of attributes in tuples */
StringInfoData buf;
pq_beginmessage(&buf);
pq_sendbyte(&buf, 'T'); /* tuple descriptor message type */
pq_sendint(&buf, natts, 2); /* # of attributes in tuples */
for (i = 0; i < natts; ++i)
{
pq_putstr(attrs[i]->attname.data);
pq_putint((int) attrs[i]->atttypid, sizeof(attrs[i]->atttypid));
pq_putint(attrs[i]->attlen, sizeof(attrs[i]->attlen));
pq_sendstring(&buf, attrs[i]->attname.data,
strlen(attrs[i]->attname.data));
pq_sendint(&buf, (int) attrs[i]->atttypid,
sizeof(attrs[i]->atttypid));
pq_sendint(&buf, attrs[i]->attlen,
sizeof(attrs[i]->attlen));
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
pq_putint(attrs[i]->atttypmod, sizeof(attrs[i]->atttypmod));
pq_sendint(&buf, attrs[i]->atttypmod,
sizeof(attrs[i]->atttypmod));
}
pq_endmessage(&buf);
}
break;
@@ -265,8 +272,8 @@ EndCommand(char *commandTag, CommandDest dest)
* tell the fe that the query is over
* ----------------
*/
sprintf(buf, "C%s%s", commandTag, CommandInfo);
pq_putstr(buf);
sprintf(buf, "%s%s", commandTag, CommandInfo);
pq_putmessage('C', buf, strlen(buf)+1);
CommandInfo[0] = '\0';
break;
@@ -293,18 +300,18 @@ void
SendCopyBegin(void)
{
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
pq_putnchar("H", 1); /* new way */
pq_putbytes("H", 1); /* new way */
else
pq_putnchar("B", 1); /* old way */
pq_putbytes("B", 1); /* old way */
}
void
ReceiveCopyBegin(void)
{
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
pq_putnchar("G", 1); /* new way */
pq_putbytes("G", 1); /* new way */
else
pq_putnchar("D", 1); /* old way */
pq_putbytes("D", 1); /* old way */
/* We *must* flush here to ensure FE knows it can send. */
pq_flush();
}
@@ -330,7 +337,7 @@ NullCommand(CommandDest dest)
* tell the fe that we saw an empty query string
* ----------------
*/
pq_putstr("I");
pq_putbytes("I", 1);
break;
case Local:
@@ -359,7 +366,7 @@ ReadyForQuery(CommandDest dest)
case RemoteInternal:
case Remote:
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
pq_putnchar("Z", 1);
pq_putbytes("Z", 1);
/* Flush output at end of cycle in any case. */
pq_flush();
break;

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.22 1999/02/13 23:18:44 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.23 1999/04/25 03:19:10 tgl Exp $
*
* NOTES
* This cruft is the server side of PQfn.
@@ -68,6 +68,7 @@
#include "utils/builtins.h" /* for oideq */
#include "tcop/fastpath.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "access/xact.h" /* for TransactionId/CommandId protos */
@@ -87,32 +88,36 @@ SendFunctionResult(Oid fid, /* function id */
int retlen /* the length according to the catalogs */
)
{
pq_putnchar("V", 1);
StringInfoData buf;
pq_beginmessage(&buf);
pq_sendbyte(&buf, 'V');
if (retlen != 0)
{
pq_putnchar("G", 1);
pq_sendbyte(&buf, 'G');
if (retbyval)
{ /* by-value */
pq_putint(retlen, 4);
pq_putint((int) (Datum) retval, retlen);
pq_sendint(&buf, retlen, 4);
pq_sendint(&buf, (int) (Datum) retval, retlen);
}
else
{ /* by-reference ... */
if (retlen < 0)
{ /* ... varlena */
pq_putint(VARSIZE(retval) - VARHDRSZ, VARHDRSZ);
pq_putnchar(VARDATA(retval), VARSIZE(retval) - VARHDRSZ);
pq_sendint(&buf, VARSIZE(retval) - VARHDRSZ, VARHDRSZ);
pq_sendbytes(&buf, VARDATA(retval), VARSIZE(retval) - VARHDRSZ);
}
else
{ /* ... fixed */
pq_putint(retlen, 4);
pq_putnchar(retval, retlen);
pq_sendint(&buf, retlen, 4);
pq_sendbytes(&buf, retval, retlen);
}
}
}
pq_putnchar("0", 1);
pq_sendbyte(&buf, '0');
pq_endmessage(&buf);
}
/*
@@ -276,6 +281,7 @@ HandleFunctionRequest()
Oid fid;
int argsize;
int nargs;
int tmp;
char *arg[8];
char *retval;
int i;
@@ -283,8 +289,9 @@ HandleFunctionRequest()
char *p;
struct fp_info *fip;
fid = (Oid) pq_getint(4); /* function oid */
nargs = pq_getint(4); /* # of arguments */
pq_getint(&tmp, 4); /* function oid */
fid = (Oid) tmp;
pq_getint(&nargs, 4); /* # of arguments */
/*
* This is where the one-back caching is done. If you want to save
@@ -311,13 +318,14 @@ HandleFunctionRequest()
arg[i] = (char *) NULL;
else
{
argsize = pq_getint(4);
pq_getint(&argsize, 4);
Assert(argsize > 0);
if (fip->argbyval[i])
{ /* by-value */
Assert(argsize <= 4);
arg[i] = (char *) pq_getint(argsize);
pq_getint(&tmp, argsize);
arg[i] = (char *) tmp;
}
else
{ /* by-reference ... */
@@ -328,14 +336,14 @@ HandleFunctionRequest()
* 98 Jan 6 */
elog(ERROR, "HandleFunctionRequest: palloc failed");
VARSIZE(p) = argsize + VARHDRSZ;
pq_getnchar(VARDATA(p), 0, argsize);
pq_getbytes(VARDATA(p), argsize);
}
else
{ /* ... fixed */
/* XXX cross our fingers and trust "argsize" */
if (!(p = palloc(argsize + 1)))
elog(ERROR, "HandleFunctionRequest: palloc failed");
pq_getnchar(p, 0, argsize);
pq_getbytes(p, argsize);
}
palloced |= (1 << i);
arg[i] = p;

View File

@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.107 1999/04/20 02:19:53 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.108 1999/04/25 03:19:10 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -52,6 +52,7 @@
#include "executor/execdebug.h"
#include "executor/executor.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "libpq/libpq-be.h"
#include "libpq/pqsignal.h"
#include "nodes/pg_list.h"
@@ -304,15 +305,15 @@ InteractiveBackend(char *inBuf)
static char
SocketBackend(char *inBuf)
{
char qtype[2];
char qtype;
char result = '\0';
/* ----------------
* get input from the frontend
* ----------------
*/
strcpy(qtype, "?");
if (pq_getnchar(qtype, 0, 1) == EOF)
qtype = '?';
if (pq_getbytes(&qtype, 1) == EOF)
{
/* ------------
* when front-end applications quits/dies
@@ -321,7 +322,7 @@ SocketBackend(char *inBuf)
proc_exit(0);
}
switch (*qtype)
switch (qtype)
{
/* ----------------
* 'Q': user entered a query
@@ -358,7 +359,7 @@ SocketBackend(char *inBuf)
* ----------------
*/
default:
elog(FATAL, "Socket command type %c unknown\n", *qtype);
elog(FATAL, "Socket command type %c unknown", qtype);
break;
}
return result;
@@ -1461,7 +1462,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
Portfd = open(NULL_DEV, O_RDWR | O_BINARY, 0666);
#endif
}
pq_init(Portfd);
pq_init(); /* reset libpq */
whereToSendOutput = Remote;
}
else
@@ -1521,16 +1522,19 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
if (whereToSendOutput == Remote &&
PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
{
pq_putnchar("K", 1);
pq_putint((int32) MyProcPid, sizeof(int32));
pq_putint((int32) MyCancelKey, sizeof(int32));
StringInfoData buf;
pq_beginmessage(&buf);
pq_sendbyte(&buf, 'K');
pq_sendint(&buf, (int32) MyProcPid, sizeof(int32));
pq_sendint(&buf, (int32) MyCancelKey, sizeof(int32));
pq_endmessage(&buf);
/* Need not flush since ReadyForQuery will do it. */
}
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
puts("$Revision: 1.107 $ $Date: 1999/04/20 02:19:53 $\n");
puts("$Revision: 1.108 $ $Date: 1999/04/25 03:19:10 $\n");
}
/* ----------------