Skip to content

Commit 0ac6298

Browse files
committed
Implement new-protocol binary I/O support in DataRow, Bind, and FunctionCall
messages. Binary I/O is now up and working, but only for a small set of datatypes (integers, text, bytea).
1 parent d85a0a6 commit 0ac6298

File tree

7 files changed

+435
-345
lines changed

7 files changed

+435
-345
lines changed

src/backend/access/common/printtup.c

Lines changed: 124 additions & 151 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.71 2003/05/08 18:16:36 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.72 2003/05/09 18:08:48 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -42,14 +42,19 @@ static void printtup_destroy(DestReceiver *self);
4242

4343
/* ----------------
4444
* Private state for a printtup destination object
45+
*
46+
* NOTE: finfo is the lookup info for either typoutput or typsend, whichever
47+
* we are using for this column.
4548
* ----------------
4649
*/
4750
typedef struct
4851
{ /* Per-attribute information */
49-
Oid typoutput; /* Oid for the attribute's type output fn */
52+
Oid typoutput; /* Oid for the type's text output fn */
53+
Oid typsend; /* Oid for the type's binary output fn */
5054
Oid typelem; /* typelem value to pass to the output fn */
5155
bool typisvarlena; /* is it varlena (ie possibly toastable)? */
52-
FmgrInfo finfo; /* Precomputed call info for typoutput */
56+
int16 format; /* format code for this column */
57+
FmgrInfo finfo; /* Precomputed call info for output fn */
5358
} PrinttupAttrInfo;
5459

5560
typedef struct
@@ -219,9 +224,13 @@ SendRowDescriptionMessage(TupleDesc typeinfo, List *targetlist, int16 *formats)
219224
pq_endmessage(&buf);
220225
}
221226

227+
/*
228+
* Get the lookup info that printtup() needs
229+
*/
222230
static void
223231
printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
224232
{
233+
int16 *formats = myState->portal->formats;
225234
int i;
226235

227236
if (myState->myinfo)
@@ -232,15 +241,31 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
232241
if (numAttrs <= 0)
233242
return;
234243
myState->myinfo = (PrinttupAttrInfo *)
235-
palloc(numAttrs * sizeof(PrinttupAttrInfo));
244+
palloc0(numAttrs * sizeof(PrinttupAttrInfo));
236245
for (i = 0; i < numAttrs; i++)
237246
{
238247
PrinttupAttrInfo *thisState = myState->myinfo + i;
248+
int16 format = (formats ? formats[i] : 0);
239249

240-
if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
241-
&thisState->typoutput, &thisState->typelem,
242-
&thisState->typisvarlena))
250+
thisState->format = format;
251+
if (format == 0)
252+
{
253+
getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
254+
&thisState->typoutput,
255+
&thisState->typelem,
256+
&thisState->typisvarlena);
243257
fmgr_info(thisState->typoutput, &thisState->finfo);
258+
}
259+
else if (format == 1)
260+
{
261+
getTypeBinaryOutputInfo(typeinfo->attrs[i]->atttypid,
262+
&thisState->typsend,
263+
&thisState->typelem,
264+
&thisState->typisvarlena);
265+
fmgr_info(thisState->typsend, &thisState->finfo);
266+
}
267+
else
268+
elog(ERROR, "Unsupported format code %d", format);
244269
}
245270
}
246271

@@ -252,7 +277,6 @@ static void
252277
printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
253278
{
254279
DR_printtup *myState = (DR_printtup *) self;
255-
int16 *formats = myState->portal->formats;
256280
StringInfoData buf;
257281
int natts = tuple->t_data->t_natts;
258282
int i;
@@ -274,58 +298,56 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
274298
for (i = 0; i < natts; ++i)
275299
{
276300
PrinttupAttrInfo *thisState = myState->myinfo + i;
277-
int16 format = (formats ? formats[i] : 0);
278301
Datum origattr,
279302
attr;
280303
bool isnull;
281-
char *outputstr;
282304

283305
origattr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
284306
if (isnull)
285307
{
286308
pq_sendint(&buf, -1, 4);
287309
continue;
288310
}
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)));
306311

307-
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
312+
/*
313+
* If we have a toasted datum, forcibly detoast it here to
314+
* avoid memory leakage inside the type's output routine.
315+
*/
316+
if (thisState->typisvarlena)
317+
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
318+
else
319+
attr = origattr;
308320

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+
if (thisState->format == 0)
321322
{
322-
/* XXX something similar to above */
323-
elog(ERROR, "Binary transmission not implemented yet");
323+
/* Text output */
324+
char *outputstr;
325+
326+
outputstr = DatumGetCString(FunctionCall3(&thisState->finfo,
327+
attr,
328+
ObjectIdGetDatum(thisState->typelem),
329+
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
330+
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
331+
pfree(outputstr);
324332
}
325333
else
326334
{
327-
elog(ERROR, "Invalid format code %d", format);
335+
/* Binary output */
336+
bytea *outputbytes;
337+
338+
outputbytes = DatumGetByteaP(FunctionCall2(&thisState->finfo,
339+
attr,
340+
ObjectIdGetDatum(thisState->typelem)));
341+
/* We assume the result will not have been toasted */
342+
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
343+
pq_sendbytes(&buf, VARDATA(outputbytes),
344+
VARSIZE(outputbytes) - VARHDRSZ);
345+
pfree(outputbytes);
328346
}
347+
348+
/* Clean up detoasted copy, if any */
349+
if (attr != origattr)
350+
pfree(DatumGetPointer(attr));
329351
}
330352

331353
pq_endmessage(&buf);
@@ -388,34 +410,28 @@ printtup_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
388410
origattr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
389411
if (isnull)
390412
continue;
391-
if (OidIsValid(thisState->typoutput))
392-
{
393-
/*
394-
* If we have a toasted datum, forcibly detoast it here to
395-
* avoid memory leakage inside the type's output routine.
396-
*/
397-
if (thisState->typisvarlena)
398-
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
399-
else
400-
attr = origattr;
401413

402-
outputstr = DatumGetCString(FunctionCall3(&thisState->finfo,
403-
attr,
414+
Assert(thisState->format == 0);
415+
416+
/*
417+
* If we have a toasted datum, forcibly detoast it here to
418+
* avoid memory leakage inside the type's output routine.
419+
*/
420+
if (thisState->typisvarlena)
421+
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
422+
else
423+
attr = origattr;
424+
425+
outputstr = DatumGetCString(FunctionCall3(&thisState->finfo,
426+
attr,
404427
ObjectIdGetDatum(thisState->typelem),
405428
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
429+
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), true);
430+
pfree(outputstr);
406431

407-
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), true);
408-
409-
/* Clean up detoasted copy, if any */
410-
if (attr != origattr)
411-
pfree(DatumGetPointer(attr));
412-
pfree(outputstr);
413-
}
414-
else
415-
{
416-
outputstr = "<unprintable>";
417-
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), true);
418-
}
432+
/* Clean up detoasted copy, if any */
433+
if (attr != origattr)
434+
pfree(DatumGetPointer(attr));
419435
}
420436

421437
pq_endmessage(&buf);
@@ -508,30 +524,29 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
508524
origattr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
509525
if (isnull)
510526
continue;
511-
if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
512-
&typoutput, &typelem, &typisvarlena))
513-
{
514-
/*
515-
* If we have a toasted datum, forcibly detoast it here to
516-
* avoid memory leakage inside the type's output routine.
517-
*/
518-
if (typisvarlena)
519-
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
520-
else
521-
attr = origattr;
527+
getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
528+
&typoutput, &typelem, &typisvarlena);
529+
/*
530+
* If we have a toasted datum, forcibly detoast it here to
531+
* avoid memory leakage inside the type's output routine.
532+
*/
533+
if (typisvarlena)
534+
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
535+
else
536+
attr = origattr;
522537

523-
value = DatumGetCString(OidFunctionCall3(typoutput,
524-
attr,
525-
ObjectIdGetDatum(typelem),
538+
value = DatumGetCString(OidFunctionCall3(typoutput,
539+
attr,
540+
ObjectIdGetDatum(typelem),
526541
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
527542

528-
printatt((unsigned) i + 1, typeinfo->attrs[i], value);
543+
printatt((unsigned) i + 1, typeinfo->attrs[i], value);
529544

530-
/* Clean up detoasted copy, if any */
531-
if (attr != origattr)
532-
pfree(DatumGetPointer(attr));
533-
pfree(value);
534-
}
545+
pfree(value);
546+
547+
/* Clean up detoasted copy, if any */
548+
if (attr != origattr)
549+
pfree(DatumGetPointer(attr));
535550
}
536551
printf("\t----\n");
537552
}
@@ -542,7 +557,7 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
542557
* We use a different message type, i.e. 'B' instead of 'D' to
543558
* indicate a tuple in internal (binary) form.
544559
*
545-
* This is largely same as printtup_20, except we don't use the typout func.
560+
* This is largely same as printtup_20, except we use binary formatting.
546561
* ----------------
547562
*/
548563
static void
@@ -587,83 +602,41 @@ printtup_internal_20(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
587602
/*
588603
* send the attributes of this tuple
589604
*/
590-
#ifdef IPORTAL_DEBUG
591-
fprintf(stderr, "sending tuple with %d atts\n", natts);
592-
#endif
593-
594605
for (i = 0; i < natts; ++i)
595606
{
596607
PrinttupAttrInfo *thisState = myState->myinfo + i;
597608
Datum origattr,
598609
attr;
599610
bool isnull;
600-
int32 len;
611+
bytea *outputbytes;
601612

602613
origattr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
603614
if (isnull)
604615
continue;
605-
/* send # of bytes, and opaque data */
606-
if (thisState->typisvarlena)
607-
{
608-
/*
609-
* If we have a toasted datum, must detoast before sending.
610-
*/
611-
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
612-
613-
len = VARSIZE(attr) - VARHDRSZ;
614616

615-
pq_sendint(&buf, len, VARHDRSZ);
616-
pq_sendbytes(&buf, VARDATA(attr), len);
617+
Assert(thisState->format == 1);
617618

618-
#ifdef IPORTAL_DEBUG
619-
{
620-
char *d = VARDATA(attr);
621-
622-
fprintf(stderr, "length %d data %x %x %x %x\n",
623-
len, *d, *(d + 1), *(d + 2), *(d + 3));
624-
}
625-
#endif
626-
627-
/* Clean up detoasted copy, if any */
628-
if (attr != origattr)
629-
pfree(DatumGetPointer(attr));
630-
}
619+
/*
620+
* If we have a toasted datum, forcibly detoast it here to
621+
* avoid memory leakage inside the type's output routine.
622+
*/
623+
if (thisState->typisvarlena)
624+
attr = PointerGetDatum(PG_DETOAST_DATUM(origattr));
631625
else
632-
{
633-
/* fixed size or cstring */
634626
attr = origattr;
635-
len = typeinfo->attrs[i]->attlen;
636-
if (len <= 0)
637-
{
638-
/* it's a cstring */
639-
Assert(len == -2 && !typeinfo->attrs[i]->attbyval);
640-
len = strlen(DatumGetCString(attr)) + 1;
641-
}
642-
pq_sendint(&buf, len, sizeof(int32));
643-
if (typeinfo->attrs[i]->attbyval)
644-
{
645-
Datum datumBuf;
646-
647-
/*
648-
* We need this horsing around because we don't know how
649-
* shorter data values are aligned within a Datum.
650-
*/
651-
store_att_byval(&datumBuf, attr, len);
652-
pq_sendbytes(&buf, (char *) &datumBuf, len);
653-
#ifdef IPORTAL_DEBUG
654-
fprintf(stderr, "byval length %d data %ld\n", len,
655-
(long) attr);
656-
#endif
657-
}
658-
else
659-
{
660-
pq_sendbytes(&buf, DatumGetPointer(attr), len);
661-
#ifdef IPORTAL_DEBUG
662-
fprintf(stderr, "byref length %d data %p\n", len,
663-
DatumGetPointer(attr));
664-
#endif
665-
}
666-
}
627+
628+
outputbytes = DatumGetByteaP(FunctionCall2(&thisState->finfo,
629+
attr,
630+
ObjectIdGetDatum(thisState->typelem)));
631+
/* We assume the result will not have been toasted */
632+
pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4);
633+
pq_sendbytes(&buf, VARDATA(outputbytes),
634+
VARSIZE(outputbytes) - VARHDRSZ);
635+
pfree(outputbytes);
636+
637+
/* Clean up detoasted copy, if any */
638+
if (attr != origattr)
639+
pfree(DatumGetPointer(attr));
667640
}
668641

669642
pq_endmessage(&buf);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy