Skip to content

Commit 95cc41b

Browse files
committed
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.
1 parent fc08814 commit 95cc41b

File tree

18 files changed

+1064
-1021
lines changed

18 files changed

+1064
-1021
lines changed

src/backend/access/common/printtup.c

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,25 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.42 1999/02/13 23:14:12 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.43 1999/04/25 03:19:23 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515

1616
#include <string.h>
17-
#include <postgres.h>
1817

19-
#include <fmgr.h>
20-
#include <access/heapam.h>
21-
#include <access/printtup.h>
22-
#include <catalog/pg_type.h>
23-
#include <libpq/libpq.h>
24-
#include <utils/syscache.h>
18+
#include "postgres.h"
19+
20+
#include "fmgr.h"
21+
#include "access/heapam.h"
22+
#include "access/printtup.h"
23+
#include "catalog/pg_type.h"
24+
#include "libpq/libpq.h"
25+
#include "libpq/pqformat.h"
26+
#include "utils/syscache.h"
2527

2628
#ifdef MULTIBYTE
27-
#include <mb/pg_wchar.h>
29+
#include "mb/pg_wchar.h"
2830
#endif
2931

3032
static void printtup_setup(DestReceiver* self, TupleDesc typeinfo);
@@ -152,6 +154,7 @@ static void
152154
printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
153155
{
154156
DR_printtup *myState = (DR_printtup*) self;
157+
StringInfoData buf;
155158
int i,
156159
j,
157160
k,
@@ -172,7 +175,8 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
172175
* tell the frontend to expect new tuple data (in ASCII style)
173176
* ----------------
174177
*/
175-
pq_putnchar("D", 1);
178+
pq_beginmessage(&buf);
179+
pq_sendbyte(&buf, 'D');
176180

177181
/* ----------------
178182
* send a bitmap of which attributes are not null
@@ -187,13 +191,13 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
187191
k >>= 1;
188192
if (k == 0) /* end of byte? */
189193
{
190-
pq_putint(j, 1);
194+
pq_sendint(&buf, j, 1);
191195
j = 0;
192196
k = 1 << 7;
193197
}
194198
}
195199
if (k != (1 << 7)) /* flush last partial byte */
196-
pq_putint(j, 1);
200+
pq_sendint(&buf, j, 1);
197201

198202
/* ----------------
199203
* send the attributes of this tuple
@@ -212,23 +216,25 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
212216
#ifdef MULTIBYTE
213217
p = pg_server_to_client(outputstr, strlen(outputstr));
214218
outputlen = strlen(p);
215-
pq_putint(outputlen + VARHDRSZ, VARHDRSZ);
216-
pq_putnchar(p, outputlen);
219+
pq_sendint(&buf, outputlen + VARHDRSZ, VARHDRSZ);
220+
pq_sendbytes(&buf, p, outputlen);
217221
#else
218222
outputlen = strlen(outputstr);
219-
pq_putint(outputlen + VARHDRSZ, VARHDRSZ);
220-
pq_putnchar(outputstr, outputlen);
223+
pq_sendint(&buf, outputlen + VARHDRSZ, VARHDRSZ);
224+
pq_sendbytes(&buf, outputstr, outputlen);
221225
#endif
222226
pfree(outputstr);
223227
}
224228
else
225229
{
226230
outputstr = "<unprintable>";
227231
outputlen = strlen(outputstr);
228-
pq_putint(outputlen + VARHDRSZ, VARHDRSZ);
229-
pq_putnchar(outputstr, outputlen);
232+
pq_sendint(&buf, outputlen + VARHDRSZ, VARHDRSZ);
233+
pq_sendbytes(&buf, outputstr, outputlen);
230234
}
231235
}
236+
237+
pq_endmessage(&buf);
232238
}
233239

234240
/* ----------------
@@ -325,6 +331,7 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
325331
void
326332
printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
327333
{
334+
StringInfoData buf;
328335
int i,
329336
j,
330337
k;
@@ -335,7 +342,8 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
335342
* tell the frontend to expect new tuple data (in binary style)
336343
* ----------------
337344
*/
338-
pq_putnchar("B", 1);
345+
pq_beginmessage(&buf);
346+
pq_sendbyte(&buf, 'B');
339347

340348
/* ----------------
341349
* send a bitmap of which attributes are not null
@@ -350,13 +358,13 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
350358
k >>= 1;
351359
if (k == 0) /* end of byte? */
352360
{
353-
pq_putint(j, 1);
361+
pq_sendint(&buf, j, 1);
354362
j = 0;
355363
k = 1 << 7;
356364
}
357365
}
358366
if (k != (1 << 7)) /* flush last partial byte */
359-
pq_putint(j, 1);
367+
pq_sendint(&buf, j, 1);
360368

361369
/* ----------------
362370
* send the attributes of this tuple
@@ -378,8 +386,8 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
378386
/* variable length, assume a varlena structure */
379387
len = VARSIZE(attr) - VARHDRSZ;
380388

381-
pq_putint(len, VARHDRSZ);
382-
pq_putnchar(VARDATA(attr), len);
389+
pq_sendint(&buf, len, VARHDRSZ);
390+
pq_sendbytes(&buf, VARDATA(attr), len);
383391

384392
#ifdef IPORTAL_DEBUG
385393
{
@@ -399,20 +407,20 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
399407
int16 i16;
400408
int32 i32;
401409

402-
pq_putint(len, sizeof(int32));
410+
pq_sendint(&buf, len, sizeof(int32));
403411
switch (len)
404412
{
405413
case sizeof(int8):
406414
i8 = DatumGetChar(attr);
407-
pq_putnchar((char *) &i8, len);
415+
pq_sendbytes(&buf, (char *) &i8, len);
408416
break;
409417
case sizeof(int16):
410418
i16 = DatumGetInt16(attr);
411-
pq_putnchar((char *) &i16, len);
419+
pq_sendbytes(&buf, (char *) &i16, len);
412420
break;
413421
case sizeof(int32):
414422
i32 = DatumGetInt32(attr);
415-
pq_putnchar((char *) &i32, len);
423+
pq_sendbytes(&buf, (char *) &i32, len);
416424
break;
417425
}
418426
#ifdef IPORTAL_DEBUG
@@ -421,8 +429,8 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
421429
}
422430
else
423431
{
424-
pq_putint(len, sizeof(int32));
425-
pq_putnchar(DatumGetPointer(attr), len);
432+
pq_sendint(&buf, len, sizeof(int32));
433+
pq_sendbytes(&buf, DatumGetPointer(attr), len);
426434
#ifdef IPORTAL_DEBUG
427435
fprintf(stderr, "byref length %d data %x\n", len,
428436
DatumGetPointer(attr));
@@ -431,4 +439,6 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
431439
}
432440
}
433441
}
442+
443+
pq_endmessage(&buf);
434444
}

src/backend/commands/async.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Copyright (c) 1994, Regents of the University of California
77
*
88
* IDENTIFICATION
9-
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.44 1999/02/13 23:15:00 momjian Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.45 1999/04/25 03:19:08 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -94,6 +94,7 @@
9494
#include "fmgr.h"
9595
#include "lib/dllist.h"
9696
#include "libpq/libpq.h"
97+
#include "libpq/pqformat.h"
9798
#include "miscadmin.h"
9899
#include "storage/bufmgr.h"
99100
#include "storage/lmgr.h"
@@ -798,9 +799,12 @@ NotifyMyFrontEnd(char *relname, int32 listenerPID)
798799
{
799800
if (whereToSendOutput == Remote)
800801
{
801-
pq_putnchar("A", 1);
802-
pq_putint(listenerPID, sizeof(int32));
803-
pq_putstr(relname);
802+
StringInfoData buf;
803+
pq_beginmessage(&buf);
804+
pq_sendbyte(&buf, 'A');
805+
pq_sendint(&buf, listenerPID, sizeof(int32));
806+
pq_sendstring(&buf, relname, strlen(relname));
807+
pq_endmessage(&buf);
804808
/* NOTE: we do not do pq_flush() here. For a self-notify, it will
805809
* happen at the end of the transaction, and for incoming notifies
806810
* ProcessIncomingNotify will do it after finding all the notifies.

src/backend/commands/copy.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
*
88
* IDENTIFICATION
9-
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.73 1999/02/13 23:15:04 momjian Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.74 1999/04/25 03:19:09 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -89,12 +89,14 @@ inline void CopyDonePeek(FILE *fp, int c, int pickup);
8989
*
9090
* CopySendString does the same for null-terminated strings
9191
* CopySendChar does the same for single characters
92+
*
93+
* NB: no data conversion is applied by these functions
9294
*/
9395
inline void CopySendData(void *databuf, int datasize, FILE *fp) {
9496
if (!fp)
95-
pq_putnchar(databuf, datasize);
97+
pq_putbytes((char*) databuf, datasize);
9698
else
97-
fwrite(databuf, datasize, 1, fp);
99+
fwrite(databuf, datasize, 1, fp);
98100
}
99101

100102
inline void CopySendString(char *str, FILE *fp) {
@@ -112,17 +114,24 @@ inline void CopySendChar(char c, FILE *fp) {
112114
*
113115
* CopyGetChar does the same for single characters
114116
* CopyGetEof checks if it's EOF on the input
117+
*
118+
* NB: no data conversion is applied by these functions
115119
*/
116120
inline void CopyGetData(void *databuf, int datasize, FILE *fp) {
117121
if (!fp)
118-
pq_getnchar(databuf, 0, datasize);
122+
pq_getbytes((char*) databuf, datasize);
119123
else
120124
fread(databuf, datasize, 1, fp);
121125
}
122126

123127
inline int CopyGetChar(FILE *fp) {
124128
if (!fp)
125-
return pq_getchar();
129+
{
130+
unsigned char ch;
131+
if (pq_getbytes((char*) &ch, 1))
132+
return EOF;
133+
return ch;
134+
}
126135
else
127136
return getc(fp);
128137
}
@@ -143,7 +152,7 @@ inline int CopyGetEof(FILE *fp) {
143152
*/
144153
inline int CopyPeekChar(FILE *fp) {
145154
if (!fp)
146-
return pq_peekchar();
155+
return pq_peekbyte();
147156
else
148157
return getc(fp);
149158
}
@@ -153,7 +162,7 @@ inline void CopyDonePeek(FILE *fp, int c, int pickup) {
153162
if (pickup) {
154163
/* We want to pick it up - just receive again into dummy buffer */
155164
char c;
156-
pq_getnchar(&c, 0, 1);
165+
pq_getbytes(&c, 1);
157166
}
158167
/* If we didn't want to pick it up, just leave it where it sits */
159168
}
@@ -216,7 +225,10 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
216225
* descriptor leak. bjm 1998/08/29
217226
*/
218227
if (file_opened)
228+
{
219229
FreeFile(fp);
230+
file_opened = false;
231+
}
220232

221233
rel = heap_openr(relname);
222234
if (rel == NULL)
@@ -271,6 +283,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
271283
if (IsUnderPostmaster)
272284
{
273285
SendCopyBegin();
286+
pq_startcopyout();
274287
fp = NULL;
275288
}
276289
else
@@ -301,9 +314,12 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
301314
FreeFile(fp);
302315
file_opened = false;
303316
}
304-
else if (!from && !binary)
317+
else if (!from)
305318
{
306-
CopySendData("\\.\n",3,fp);
319+
if (!binary)
320+
CopySendData("\\.\n",3,fp);
321+
if (IsUnderPostmaster)
322+
pq_endcopyout(false);
307323
}
308324
}
309325
}

src/backend/commands/explain.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Copyright (c) 1994-5, Regents of the University of California
66
*
7-
* $Id: explain.c,v 1.34 1999/04/23 21:23:48 momjian Exp $
7+
* $Id: explain.c,v 1.35 1999/04/25 03:19:09 tgl Exp $
88
*
99
*/
1010
#include <stdio.h>
@@ -350,18 +350,13 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es)
350350
static char *
351351
Explain_PlanToString(Plan *plan, ExplainState *es)
352352
{
353-
StringInfo str;
354-
char *s;
353+
StringInfoData str;
355354

356-
if (plan == NULL)
357-
return "";
358-
Assert(plan != NULL);
359-
str = makeStringInfo();
360-
explain_outNode(str, plan, 0, es);
361-
s = str->data;
362-
pfree(str);
363-
364-
return s;
355+
/* see stringinfo.h for an explanation of this maneuver */
356+
initStringInfo(&str);
357+
if (plan != NULL)
358+
explain_outNode(&str, plan, 0, es);
359+
return str.data;
365360
}
366361

367362
/*

0 commit comments

Comments
 (0)