Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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

+159-69
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)