Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit217d156

Browse files
committed
Make tuple receive/print routines TOAST-aware. Formerly, printtup would
leak memory when printing a toasted attribute, and printtup_internaldidn't work at all...
1 parentf5371fe commit217d156

File tree

4 files changed

+172
-108
lines changed

4 files changed

+172
-108
lines changed

‎src/backend/access/common/printtup.c

Lines changed: 135 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,10 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.54 2000/11/16 22:30:15 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.55 2000/12/01 22:10:31 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
16-
17-
1816
#include"postgres.h"
1917

2018
#include"access/heapam.h"
@@ -25,6 +23,7 @@
2523

2624
staticvoidprinttup_setup(DestReceiver*self,TupleDesctypeinfo);
2725
staticvoidprinttup(HeapTupletuple,TupleDesctypeinfo,DestReceiver*self);
26+
staticvoidprinttup_internal(HeapTupletuple,TupleDesctypeinfo,DestReceiver*self);
2827
staticvoidprinttup_cleanup(DestReceiver*self);
2928

3029
/* ----------------------------------------------------------------
@@ -33,15 +32,12 @@ static void printtup_cleanup(DestReceiver *self);
3332
*/
3433

3534
/* ----------------
36-
*getTypeOutAndElem -- get both typoutput and typelem for a type
37-
*
38-
* We used to fetch these with two separate function calls,
39-
* typtoout() and gettypelem(), which each called SearchSysCache.
40-
* This way takes half the time.
35+
*getTypeOutputInfo -- get info needed for printing values of a type
4136
* ----------------
4237
*/
43-
int
44-
getTypeOutAndElem(Oidtype,Oid*typOutput,Oid*typElem)
38+
bool
39+
getTypeOutputInfo(Oidtype,Oid*typOutput,Oid*typElem,
40+
bool*typIsVarlena)
4541
{
4642
HeapTupletypeTuple;
4743
Form_pg_typept;
@@ -50,11 +46,12 @@ getTypeOutAndElem(Oid type, Oid *typOutput, Oid *typElem)
5046
ObjectIdGetDatum(type),
5147
0,0,0);
5248
if (!HeapTupleIsValid(typeTuple))
53-
elog(ERROR,"getTypeOutAndElem: Cache lookup of type %u failed",type);
49+
elog(ERROR,"getTypeOutputInfo: Cache lookup of type %u failed",type);
5450
pt= (Form_pg_type)GETSTRUCT(typeTuple);
5551

5652
*typOutput=pt->typoutput;
5753
*typElem=pt->typelem;
54+
*typIsVarlena= (!pt->typbyval)&& (pt->typlen==-1);
5855
ReleaseSysCache(typeTuple);
5956
returnOidIsValid(*typOutput);
6057
}
@@ -67,6 +64,7 @@ typedef struct
6764
{/* Per-attribute information */
6865
Oidtypoutput;/* Oid for the attribute's type output fn */
6966
Oidtypelem;/* typelem value to pass to the output fn */
67+
booltypisvarlena;/* is it varlena (ie possibly toastable)? */
7068
FmgrInfofinfo;/* Precomputed call info for typoutput */
7169
}PrinttupAttrInfo;
7270

@@ -83,11 +81,11 @@ typedef struct
8381
* ----------------
8482
*/
8583
DestReceiver*
86-
printtup_create_DR()
84+
printtup_create_DR(boolisBinary)
8785
{
8886
DR_printtup*self= (DR_printtup*)palloc(sizeof(DR_printtup));
8987

90-
self->pub.receiveTuple=printtup;
88+
self->pub.receiveTuple=isBinary ?printtup_internal :printtup;
9189
self->pub.setup=printtup_setup;
9290
self->pub.cleanup=printtup_cleanup;
9391

@@ -132,8 +130,9 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
132130
{
133131
PrinttupAttrInfo*thisState=myState->myinfo+i;
134132

135-
if (getTypeOutAndElem((Oid)typeinfo->attrs[i]->atttypid,
136-
&thisState->typoutput,&thisState->typelem))
133+
if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
134+
&thisState->typoutput,&thisState->typelem,
135+
&thisState->typisvarlena))
137136
fmgr_info(thisState->typoutput,&thisState->finfo);
138137
}
139138
}
@@ -147,17 +146,14 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
147146
{
148147
DR_printtup*myState= (DR_printtup*)self;
149148
StringInfoDatabuf;
149+
intnatts=tuple->t_data->t_natts;
150150
inti,
151151
j,
152152
k;
153-
char*outputstr;
154-
Datumattr;
155-
boolisnull;
156153

157154
/* Set or update my derived attribute info, if needed */
158-
if (myState->attrinfo!=typeinfo||
159-
myState->nattrs!=tuple->t_data->t_natts)
160-
printtup_prepare_info(myState,typeinfo,tuple->t_data->t_natts);
155+
if (myState->attrinfo!=typeinfo||myState->nattrs!=natts)
156+
printtup_prepare_info(myState,typeinfo,natts);
161157

162158
/* ----------------
163159
*tell the frontend to expect new tuple data (in ASCII style)
@@ -172,7 +168,7 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
172168
*/
173169
j=0;
174170
k=1 <<7;
175-
for (i=0;i<tuple->t_data->t_natts;++i)
171+
for (i=0;i<natts;++i)
176172
{
177173
if (!heap_attisnull(tuple,i+1))
178174
j |=k;/* set bit if not null */
@@ -191,20 +187,38 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
191187
*send the attributes of this tuple
192188
* ----------------
193189
*/
194-
for (i=0;i<tuple->t_data->t_natts;++i)
190+
for (i=0;i<natts;++i)
195191
{
196192
PrinttupAttrInfo*thisState=myState->myinfo+i;
193+
Datumorigattr,
194+
attr;
195+
boolisnull;
196+
char*outputstr;
197197

198-
attr=heap_getattr(tuple,i+1,typeinfo,&isnull);
198+
origattr=heap_getattr(tuple,i+1,typeinfo,&isnull);
199199
if (isnull)
200200
continue;
201201
if (OidIsValid(thisState->typoutput))
202202
{
203+
/*
204+
* If we have a toasted datum, forcibly detoast it here to avoid
205+
* memory leakage inside the type's output routine.
206+
*/
207+
if (thisState->typisvarlena)
208+
attr=PointerGetDatum(PG_DETOAST_DATUM(origattr));
209+
else
210+
attr=origattr;
211+
203212
outputstr=DatumGetCString(FunctionCall3(&thisState->finfo,
204213
attr,
205214
ObjectIdGetDatum(thisState->typelem),
206215
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
216+
207217
pq_sendcountedtext(&buf,outputstr,strlen(outputstr));
218+
219+
/* Clean up detoasted copy, if any */
220+
if (attr!=origattr)
221+
pfree(DatumGetPointer(attr));
208222
pfree(outputstr);
209223
}
210224
else
@@ -276,26 +290,43 @@ showatts(char *name, TupleDesc tupleDesc)
276290
void
277291
debugtup(HeapTupletuple,TupleDesctypeinfo,DestReceiver*self)
278292
{
293+
intnatts=tuple->t_data->t_natts;
279294
inti;
280-
Datumattr;
295+
Datumorigattr,
296+
attr;
281297
char*value;
282298
boolisnull;
283299
Oidtypoutput,
284300
typelem;
301+
booltypisvarlena;
285302

286-
for (i=0;i<tuple->t_data->t_natts;++i)
303+
for (i=0;i<natts;++i)
287304
{
288-
attr=heap_getattr(tuple,i+1,typeinfo,&isnull);
305+
origattr=heap_getattr(tuple,i+1,typeinfo,&isnull);
289306
if (isnull)
290307
continue;
291-
if (getTypeOutAndElem((Oid)typeinfo->attrs[i]->atttypid,
292-
&typoutput,&typelem))
308+
if (getTypeOutputInfo(typeinfo->attrs[i]->atttypid,
309+
&typoutput,&typelem,&typisvarlena))
293310
{
311+
/*
312+
* If we have a toasted datum, forcibly detoast it here to avoid
313+
* memory leakage inside the type's output routine.
314+
*/
315+
if (typisvarlena)
316+
attr=PointerGetDatum(PG_DETOAST_DATUM(origattr));
317+
else
318+
attr=origattr;
319+
294320
value=DatumGetCString(OidFunctionCall3(typoutput,
295321
attr,
296322
ObjectIdGetDatum(typelem),
297323
Int32GetDatum(typeinfo->attrs[i]->atttypmod)));
324+
298325
printatt((unsigned)i+1,typeinfo->attrs[i],value);
326+
327+
/* Clean up detoasted copy, if any */
328+
if (attr!=origattr)
329+
pfree(DatumGetPointer(attr));
299330
pfree(value);
300331
}
301332
}
@@ -307,19 +338,22 @@ debugtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
307338
*We use a different data prefix, e.g. 'B' instead of 'D' to
308339
*indicate a tuple in internal (binary) form.
309340
*
310-
*This is same as printtup, except we don't use the typout func,
311-
*and therefore have no need for persistent state.
341+
*This is largely same as printtup, except we don't use the typout func.
312342
* ----------------
313343
*/
314-
void
344+
staticvoid
315345
printtup_internal(HeapTupletuple,TupleDesctypeinfo,DestReceiver*self)
316346
{
347+
DR_printtup*myState= (DR_printtup*)self;
317348
StringInfoDatabuf;
349+
intnatts=tuple->t_data->t_natts;
318350
inti,
319351
j,
320352
k;
321-
Datumattr;
322-
boolisnull;
353+
354+
/* Set or update my derived attribute info, if needed */
355+
if (myState->attrinfo!=typeinfo||myState->nattrs!=natts)
356+
printtup_prepare_info(myState,typeinfo,natts);
323357

324358
/* ----------------
325359
*tell the frontend to expect new tuple data (in binary style)
@@ -334,7 +368,7 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
334368
*/
335369
j=0;
336370
k=1 <<7;
337-
for (i=0;i<tuple->t_data->t_natts;++i)
371+
for (i=0;i<natts;++i)
338372
{
339373
if (!heap_attisnull(tuple,i+1))
340374
j |=k;/* set bit if not null */
@@ -354,71 +388,87 @@ printtup_internal(HeapTuple tuple, TupleDesc typeinfo, DestReceiver *self)
354388
* ----------------
355389
*/
356390
#ifdefIPORTAL_DEBUG
357-
fprintf(stderr,"sending tuple with %d atts\n",tuple->t_data->t_natts);
391+
fprintf(stderr,"sending tuple with %d atts\n",natts);
358392
#endif
359-
for (i=0;i<tuple->t_data->t_natts;++i)
393+
394+
for (i=0;i<natts;++i)
360395
{
361-
int32len=typeinfo->attrs[i]->attlen;
396+
PrinttupAttrInfo*thisState=myState->myinfo+i;
397+
Datumorigattr,
398+
attr;
399+
boolisnull;
400+
int32len;
362401

363-
attr=heap_getattr(tuple,i+1,typeinfo,&isnull);
364-
if (!isnull)
402+
origattr=heap_getattr(tuple,i+1,typeinfo,&isnull);
403+
if (isnull)
404+
continue;
405+
/* send # of bytes, and opaque data */
406+
if (thisState->typisvarlena)
365407
{
366-
/* # of bytes, and opaque data */
367-
if (len==-1)
368-
{
369-
/* variable length, assume a varlena structure */
370-
len=VARSIZE(attr)-VARHDRSZ;
408+
/*
409+
* If we have a toasted datum, must detoast before sending.
410+
*/
411+
attr=PointerGetDatum(PG_DETOAST_DATUM(origattr));
412+
413+
len=VARSIZE(attr)-VARHDRSZ;
371414

372-
pq_sendint(&buf,len,VARHDRSZ);
373-
pq_sendbytes(&buf,VARDATA(attr),len);
415+
pq_sendint(&buf,len,VARHDRSZ);
416+
pq_sendbytes(&buf,VARDATA(attr),len);
374417

375418
#ifdefIPORTAL_DEBUG
376-
{
377-
char*d=VARDATA(attr);
419+
{
420+
char*d=VARDATA(attr);
378421

379-
fprintf(stderr,"length %d data %x%x%x%x\n",
380-
len,*d,*(d+1),*(d+2),*(d+3));
381-
}
382-
#endif
422+
fprintf(stderr,"length %d data %x %x %x %x\n",
423+
len,*d,*(d+1),*(d+2),*(d+3));
383424
}
384-
else
425+
#endif
426+
427+
/* Clean up detoasted copy, if any */
428+
if (attr!=origattr)
429+
pfree(DatumGetPointer(attr));
430+
}
431+
else
432+
{
433+
/* fixed size */
434+
attr=origattr;
435+
len=typeinfo->attrs[i]->attlen;
436+
pq_sendint(&buf,len,sizeof(int32));
437+
if (typeinfo->attrs[i]->attbyval)
385438
{
386-
/* fixed size */
387-
if (typeinfo->attrs[i]->attbyval)
439+
int8i8;
440+
int16i16;
441+
int32i32;
442+
443+
switch (len)
388444
{
389-
int8i8;
390-
int16i16;
391-
int32i32;
392-
393-
pq_sendint(&buf,len,sizeof(int32));
394-
switch (len)
395-
{
396-
casesizeof(int8):
397-
i8=DatumGetChar(attr);
398-
pq_sendbytes(&buf, (char*)&i8,len);
399-
break;
400-
casesizeof(int16):
401-
i16=DatumGetInt16(attr);
402-
pq_sendbytes(&buf, (char*)&i16,len);
403-
break;
404-
casesizeof(int32):
405-
i32=DatumGetInt32(attr);
406-
pq_sendbytes(&buf, (char*)&i32,len);
407-
break;
408-
}
445+
casesizeof(int8):
446+
i8=DatumGetChar(attr);
447+
pq_sendbytes(&buf, (char*)&i8,len);
448+
break;
449+
casesizeof(int16):
450+
i16=DatumGetInt16(attr);
451+
pq_sendbytes(&buf, (char*)&i16,len);
452+
break;
453+
casesizeof(int32):
454+
i32=DatumGetInt32(attr);
455+
pq_sendbytes(&buf, (char*)&i32,len);
456+
break;
457+
default:
458+
elog(ERROR,"printtup_internal: unexpected typlen");
459+
break;
460+
}
409461
#ifdefIPORTAL_DEBUG
410-
fprintf(stderr,"byval length %d data %d\n",len,attr);
462+
fprintf(stderr,"byval length %d data %d\n",len,attr);
411463
#endif
412-
}
413-
else
414-
{
415-
pq_sendint(&buf,len,sizeof(int32));
416-
pq_sendbytes(&buf,DatumGetPointer(attr),len);
464+
}
465+
else
466+
{
467+
pq_sendbytes(&buf,DatumGetPointer(attr),len);
417468
#ifdefIPORTAL_DEBUG
418-
fprintf(stderr,"byref length %d data %x\n",len,
419-
DatumGetPointer(attr));
469+
fprintf(stderr,"byref length %d data %p\n",len,
470+
DatumGetPointer(attr));
420471
#endif
421-
}
422472
}
423473
}
424474
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp