Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c0a8c3a

Browse files
committed
Update 3.0 protocol support to match recent agreements about how to
handle multiple 'formats' for data I/O. Restructure CommandDest and DestReceiver stuff one more time (it's finally starting to look a bit clean though). Code now matches latest 3.0 protocol document as far as message formats go --- but there is no support for binary I/O yet.
1 parent 5e7a5c9 commit c0a8c3a

File tree

24 files changed

+999
-680
lines changed

24 files changed

+999
-680
lines changed

src/backend/access/common/printtup.c

Lines changed: 159 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1994, Regents of the University of California
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.70 2003/05/06 20:26:26 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.71 2003/05/08 18:16:36 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -20,12 +20,17 @@
2020
#include "libpq/libpq.h"
2121
#include "libpq/pqformat.h"
2222
#include "utils/lsyscache.h"
23+
#include "utils/portal.h"
2324

2425

2526
static void printtup_startup(DestReceiver *self, int operation,
26-
const char *portalName, TupleDesc typeinfo, List *targetlist);
27-
static void printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
28-
static void printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self);
27+
TupleDesc typeinfo);
28+
static void printtup(HeapTuple tuple, TupleDesc typeinfo,
29+
DestReceiver *self);
30+
static void printtup_20(HeapTuple tuple, TupleDesc typeinfo,
31+
DestReceiver *self);
32+
static void printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo,
33+
DestReceiver *self);
2934
static void printtup_shutdown(DestReceiver *self);
3035
static void printtup_destroy(DestReceiver *self);
3136

@@ -50,6 +55,7 @@ typedef struct
5055
typedef struct
5156
{
5257
DestReceiver pub; /* publicly-known function pointers */
58+
Portal portal; /* the Portal we are printing from */
5359
bool sendDescrip; /* send RowDescription at startup? */
5460
TupleDesc attrinfo; /* The attr info we are set up for */
5561
int nattrs;
@@ -61,43 +67,33 @@ typedef struct
6167
* ----------------
6268
*/
6369
DestReceiver *
64-
printtup_create_DR(CommandDest dest)
70+
printtup_create_DR(CommandDest dest, Portal portal)
6571
{
6672
DR_printtup *self = (DR_printtup *) palloc(sizeof(DR_printtup));
67-
bool isBinary;
68-
bool sendDescrip;
6973

70-
switch (dest)
74+
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
75+
self->pub.receiveTuple = printtup;
76+
else
7177
{
72-
case Remote:
73-
isBinary = false;
74-
sendDescrip = true;
75-
break;
76-
case RemoteInternal:
77-
isBinary = true;
78-
sendDescrip = true;
79-
break;
80-
case RemoteExecute:
81-
isBinary = false;
82-
sendDescrip = false; /* no T message for Execute */
83-
break;
84-
case RemoteExecuteInternal:
85-
isBinary = true;
86-
sendDescrip = false; /* no T message for Execute */
87-
break;
88-
89-
default:
90-
elog(ERROR, "printtup_create_DR: unsupported dest");
91-
return NULL;
78+
/*
79+
* In protocol 2.0 the Bind message does not exist, so there is
80+
* no way for the columns to have different print formats; it's
81+
* sufficient to look at the first one.
82+
*/
83+
if (portal->formats && portal->formats[0] != 0)
84+
self->pub.receiveTuple = printtup_internal_20;
85+
else
86+
self->pub.receiveTuple = printtup_20;
9287
}
93-
94-
self->pub.receiveTuple = isBinary ? printtup_internal : printtup;
9588
self->pub.startup = printtup_startup;
9689
self->pub.shutdown = printtup_shutdown;
9790
self->pub.destroy = printtup_destroy;
9891
self->pub.mydest = dest;
9992

100-
self->sendDescrip = sendDescrip;
93+
self->portal = portal;
94+
95+
/* Send T message automatically if Remote, but not if RemoteExecute */
96+
self->sendDescrip = (dest == Remote);
10197

10298
self->attrinfo = NULL;
10399
self->nattrs = 0;
@@ -107,10 +103,10 @@ printtup_create_DR(CommandDest dest)
107103
}
108104

109105
static void
110-
printtup_startup(DestReceiver *self, int operation,
111-
const char *portalName, TupleDesc typeinfo, List *targetlist)
106+
printtup_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
112107
{
113108
DR_printtup *myState = (DR_printtup *) self;
109+
Portal portal = myState->portal;
114110

115111
if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
116112
{
@@ -119,7 +115,9 @@ printtup_startup(DestReceiver *self, int operation,
119115
*
120116
* If portal name not specified, use "blank" portal.
121117
*/
122-
if (portalName == NULL)
118+
const char *portalName = portal->name;
119+
120+
if (portalName == NULL || portalName[0] == '\0')
123121
portalName = "blank";
124122

125123
pq_puttextmessage('P', portalName);
@@ -130,7 +128,16 @@ printtup_startup(DestReceiver *self, int operation,
130128
* then we send back the tuple descriptor of the tuples.
131129
*/
132130
if (operation == CMD_SELECT && myState->sendDescrip)
133-
SendRowDescriptionMessage(typeinfo, targetlist);
131+
{
132+
List *targetlist;
133+
134+
if (portal->strategy == PORTAL_ONE_SELECT)
135+
targetlist = ((Query *) lfirst(portal->parseTrees))->targetList;
136+
else
137+
targetlist = NIL;
138+
139+
SendRowDescriptionMessage(typeinfo, targetlist, portal->formats);
140+
}
134141

135142
/* ----------------
136143
* We could set up the derived attr info at this time, but we postpone it
@@ -150,11 +157,13 @@ printtup_startup(DestReceiver *self, int operation,
150157
* Notes: the TupleDesc has typically been manufactured by ExecTypeFromTL()
151158
* or some similar function; it does not contain a full set of fields.
152159
* The targetlist will be NIL when executing a utility function that does
153-
* not have a plan. If the targetlist isn't NIL then it is a Plan node's
154-
* targetlist; it is up to us to ignore resjunk columns in it.
160+
* not have a plan. If the targetlist isn't NIL then it is a Query node's
161+
* targetlist; it is up to us to ignore resjunk columns in it. The formats[]
162+
* array pointer might be NULL (if we are doing Describe on a prepared stmt);
163+
* send zeroes for the format codes in that case.
155164
*/
156165
void
157-
SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist)
166+
SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats)
158167
{
159168
Form_pg_attribute *attrs = typeinfo->attrs;
160169
int natts = typeinfo->natts;
@@ -198,6 +207,14 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist)
198207
if (proto >= 2)
199208
pq_sendint(&buf, attrs[i]->atttypmod,
200209
sizeof(attrs[i]->atttypmod));
210+
/* format info appears in protocol 3.0 and up */
211+
if (proto >= 3)
212+
{
213+
if (formats)
214+
pq_sendint(&buf, formats[i], 2);
215+
else
216+
pq_sendint(&buf, 0, 2);
217+
}
201218
}
202219
pq_endmessage(&buf);
203220
}
@@ -228,11 +245,98 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
228245
}
229246

230247
/* ----------------
231-
* printtup
248+
* printtup --- print a tuple in protocol 3.0
232249
* ----------------
233250
*/
234251
static void
235252
printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
253+
{
254+
DR_printtup *myState = (DR_printtup *) self;
255+
int16 *formats = myState->portal->formats;
256+
StringInfoData buf;
257+
int natts = tuple->t_data->t_natts;
258+
int i;
259+
260+
/* Set or update my derived attribute info, if needed */
261+
if (myState->attrinfo != typeinfo || myState->nattrs != natts)
262+
printtup_prepare_info(myState, typeinfo, natts);
263+
264+
/*
265+
* Prepare a DataRow message
266+
*/
267+
pq_beginmessage(&buf, 'D');
268+
269+
pq_sendint(&buf, natts, 2);
270+
271+
/*
272+
* send the attributes of this tuple
273+
*/
274+
for (i = 0; i < natts; ++i)
275+
{
276+
PrinttupAttrInfo *thisState = myState->myinfo + i;
277+
int16 format = (formats ? formats[i] : 0);
278+
Datum origattr,
279+
attr;
280+
bool isnull;
281+
char *outputstr;
282+
283+
origattr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
284+
if (isnull)
285+
{
286+
pq_sendint(&buf, -1, 4);
287+
continue;
288+
}
289+
if (format == 0)
290+
{
291+
if (OidIsValid(thisState->typoutput))
292+
{
293+
/*
294+
* If we have a toasted datum, forcibly detoast it here to
295+
* avoid memory leakage inside the type's output routine.
296+
*/
297+
if (thisState->typisvarlena)
298+
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
299+
else
300+
attr = origattr;
301+
302+
outputstr = DatumGetCString(FunctionCall3(&thisState->finfo,
303+
attr,
304+
ObjectIdGetDatum(thisState->typelem),
305+
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
306+
307+
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
308+
309+
/* Clean up detoasted copy, if any */
310+
if (attr != origattr)
311+
pfree(DatumGetPointer(attr));
312+
pfree(outputstr);
313+
}
314+
else
315+
{
316+
outputstr = "<unprintable>";
317+
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
318+
}
319+
}
320+
else if (format == 1)
321+
{
322+
/* XXX something similar to above */
323+
elog(ERROR, "Binary transmission not implemented yet");
324+
}
325+
else
326+
{
327+
elog(ERROR, "Invalid format code %d", format);
328+
}
329+
}
330+
331+
pq_endmessage(&buf);
332+
}
333+
334+
/* ----------------
335+
* printtup_20 --- print a tuple in protocol 2.0
336+
* ----------------
337+
*/
338+
static void
339+
printtup_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
236340
{
237341
DR_printtup *myState = (DR_printtup *) self;
238342
StringInfoData buf;
@@ -300,7 +404,7 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
300404
ObjectIdGetDatum(thisState->typelem),
301405
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
302406

303-
pq_sendcountedtext(&buf, outputstr, strlen(outputstr));
407+
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), true);
304408

305409
/* Clean up detoasted copy, if any */
306410
if (attr != origattr)
@@ -310,7 +414,7 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
310414
else
311415
{
312416
outputstr = "<unprintable>";
313-
pq_sendcountedtext(&buf, outputstr, strlen(outputstr));
417+
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), true);
314418
}
315419
}
316420

@@ -363,38 +467,23 @@ printatt(unsigned attributeId,
363467
attributeP->attbyval ? 't' : 'f');
364468
}
365469

366-
/* ----------------
367-
* showatts
368-
* ----------------
369-
*/
370-
static void
371-
showatts(const char *name, TupleDesc tupleDesc)
372-
{
373-
int natts = tupleDesc->natts;
374-
Form_pg_attribute *attinfo = tupleDesc->attrs;
375-
int i;
376-
377-
puts(name);
378-
for (i = 0; i < natts; ++i)
379-
printatt((unsigned) i + 1, attinfo[i], (char *) NULL);
380-
printf("\t----\n");
381-
}
382-
383470
/* ----------------
384471
* debugStartup - prepare to print tuples for an interactive backend
385472
* ----------------
386473
*/
387474
void
388-
debugStartup(DestReceiver *self, int operation,
389-
const char *portalName, TupleDesc typeinfo, List *targetlist)
475+
debugStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
390476
{
477+
int natts = typeinfo->natts;
478+
Form_pg_attribute *attinfo = typeinfo->attrs;
479+
int i;
480+
391481
/*
392482
* show the return type of the tuples
393483
*/
394-
if (portalName == NULL)
395-
portalName = "blank";
396-
397-
showatts(portalName, typeinfo);
484+
for (i = 0; i < natts; ++i)
485+
printatt((unsigned) i + 1, attinfo[i], (char *) NULL);
486+
printf("\t----\n");
398487
}
399488

400489
/* ----------------
@@ -448,15 +537,16 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
448537
}
449538

450539
/* ----------------
451-
* printtup_internal
452-
* We use a different data prefix, e.g. 'B' instead of 'D' to
453-
* indicate a tuple in internal (binary) form.
540+
* printtup_internal_20 --- print a binary tuple in protocol 2.0
541+
*
542+
* We use a different message type, i.e. 'B' instead of 'D' to
543+
* indicate a tuple in internal (binary) form.
454544
*
455-
* This is largely same as printtup, except we don't use the typout func.
545+
* This is largely same as printtup_20, except we don't use the typout func.
456546
* ----------------
457547
*/
458548
static void
459-
printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
549+
printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
460550
{
461551
DR_printtup *myState = (DR_printtup *) self;
462552
StringInfoData buf;

0 commit comments

Comments
 (0)