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

Commitd5406de

Browse files
committed
Code cleanup for toast_fetch_datum and toast_fetch_datum_slice.
Rework some of the checks for bad TOAST chunks to be a bit simplerand easier to understand. These checks verify that (1) we get alland only the chunk numbers we expect to see and (2) each chunk hasthe expected size. However, the existing code was a bit hard tounderstand, at least for me; try to make it clearer.As part of that, have toast_fetch_datum_slice check the relationshipbetween endchunk and totalchunks only with an Assert() rather thanchecking every chunk number against both values. There's no need tocheck that relationship in production builds because it's not afunction of whether on-disk corruption is present; it's just aquestion of whether the code does the right math.Also, have toast_fetch_datum_slice() use ereport(ERROR) rather thanelog(ERROR). Commitfd6ec93 madethe two functions inconsistent with each other.Rename assorted variables for better clarity and consistency, andmove assorted variables from function scope to the function's mainloop. Remove a few variables that are used only once entirely.Patch by me, reviewed by Peter Eisentraut.Discussion:http://postgr.es/m/CA+TgmobBzxwFojJ0zV0Own3dr09y43hp+OzU2VW+nos4PMXWEg@mail.gmail.com
1 parentda41d71 commitd5406de

File tree

1 file changed

+102
-118
lines changed

1 file changed

+102
-118
lines changed

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

Lines changed: 102 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525

2626
staticstructvarlena*toast_fetch_datum(structvarlena*attr);
2727
staticstructvarlena*toast_fetch_datum_slice(structvarlena*attr,
28-
int32sliceoffset,int32length);
28+
int32sliceoffset,
29+
int32slicelength);
2930
staticstructvarlena*toast_decompress_datum(structvarlena*attr);
3031
staticstructvarlena*toast_decompress_datum_slice(structvarlena*attr,int32slicelength);
3132

@@ -331,14 +332,9 @@ toast_fetch_datum(struct varlena *attr)
331332
TupleDesctoasttupDesc;
332333
structvarlena*result;
333334
structvaratt_externaltoast_pointer;
334-
int32ressize;
335-
int32residx,
336-
nextidx;
337-
int32numchunks;
338-
Pointerchunk;
339-
boolisnull;
340-
char*chunkdata;
341-
int32chunksize;
335+
int32attrsize;
336+
int32expectedchunk;
337+
int32totalchunks;
342338
intnum_indexes;
343339
intvalidIndex;
344340
SnapshotDataSnapshotToast;
@@ -349,15 +345,15 @@ toast_fetch_datum(struct varlena *attr)
349345
/* Must copy to access aligned fields */
350346
VARATT_EXTERNAL_GET_POINTER(toast_pointer,attr);
351347

352-
ressize=toast_pointer.va_extsize;
353-
numchunks= ((ressize-1) /TOAST_MAX_CHUNK_SIZE)+1;
348+
attrsize=toast_pointer.va_extsize;
349+
totalchunks= ((attrsize-1) /TOAST_MAX_CHUNK_SIZE)+1;
354350

355-
result= (structvarlena*)palloc(ressize+VARHDRSZ);
351+
result= (structvarlena*)palloc(attrsize+VARHDRSZ);
356352

357353
if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
358-
SET_VARSIZE_COMPRESSED(result,ressize+VARHDRSZ);
354+
SET_VARSIZE_COMPRESSED(result,attrsize+VARHDRSZ);
359355
else
360-
SET_VARSIZE(result,ressize+VARHDRSZ);
356+
SET_VARSIZE(result,attrsize+VARHDRSZ);
361357

362358
/*
363359
* Open the toast relation and its indexes
@@ -386,17 +382,24 @@ toast_fetch_datum(struct varlena *attr)
386382
* see the chunks in chunkidx order, even though we didn't explicitly ask
387383
* for it.
388384
*/
389-
nextidx=0;
385+
expectedchunk=0;
390386

391387
init_toast_snapshot(&SnapshotToast);
392388
toastscan=systable_beginscan_ordered(toastrel,toastidxs[validIndex],
393389
&SnapshotToast,1,&toastkey);
394390
while ((ttup=systable_getnext_ordered(toastscan,ForwardScanDirection))!=NULL)
395391
{
392+
int32curchunk;
393+
Pointerchunk;
394+
boolisnull;
395+
char*chunkdata;
396+
int32chunksize;
397+
int32expected_size;
398+
396399
/*
397400
* Have a chunk, extract the sequence number and the data
398401
*/
399-
residx=DatumGetInt32(fastgetattr(ttup,2,toasttupDesc,&isnull));
402+
curchunk=DatumGetInt32(fastgetattr(ttup,2,toasttupDesc,&isnull));
400403
Assert(!isnull);
401404
chunk=DatumGetPointer(fastgetattr(ttup,3,toasttupDesc,&isnull));
402405
Assert(!isnull);
@@ -424,63 +427,50 @@ toast_fetch_datum(struct varlena *attr)
424427
/*
425428
* Some checks on the data we've found
426429
*/
427-
if (residx!=nextidx)
430+
if (curchunk!=expectedchunk)
428431
ereport(ERROR,
429432
(errcode(ERRCODE_DATA_CORRUPTED),
430433
errmsg_internal("unexpected chunk number %d (expected %d) for toast value %u in %s",
431-
residx,nextidx,
434+
curchunk,expectedchunk,
432435
toast_pointer.va_valueid,
433436
RelationGetRelationName(toastrel))));
434-
if (residx<numchunks-1)
435-
{
436-
if (chunksize!=TOAST_MAX_CHUNK_SIZE)
437-
ereport(ERROR,
438-
(errcode(ERRCODE_DATA_CORRUPTED),
439-
errmsg_internal("unexpected chunk size %d (expected %d) in chunk %d of %d for toast value %u in %s",
440-
chunksize, (int)TOAST_MAX_CHUNK_SIZE,
441-
residx,numchunks,
442-
toast_pointer.va_valueid,
443-
RelationGetRelationName(toastrel))));
444-
}
445-
elseif (residx==numchunks-1)
446-
{
447-
if ((residx*TOAST_MAX_CHUNK_SIZE+chunksize)!=ressize)
448-
ereport(ERROR,
449-
(errcode(ERRCODE_DATA_CORRUPTED),
450-
errmsg_internal("unexpected chunk size %d (expected %d) in final chunk %d for toast value %u in %s",
451-
chunksize,
452-
(int) (ressize-residx*TOAST_MAX_CHUNK_SIZE),
453-
residx,
454-
toast_pointer.va_valueid,
455-
RelationGetRelationName(toastrel))));
456-
}
457-
else
437+
if (curchunk>totalchunks-1)
458438
ereport(ERROR,
459439
(errcode(ERRCODE_DATA_CORRUPTED),
460440
errmsg_internal("unexpected chunk number %d (out of range %d..%d) for toast value %u in %s",
461-
residx,
462-
0,numchunks-1,
441+
curchunk,
442+
0,totalchunks-1,
443+
toast_pointer.va_valueid,
444+
RelationGetRelationName(toastrel))));
445+
expected_size=curchunk<totalchunks-1 ?TOAST_MAX_CHUNK_SIZE
446+
:attrsize %TOAST_MAX_CHUNK_SIZE;
447+
if (chunksize!=expected_size)
448+
ereport(ERROR,
449+
(errcode(ERRCODE_DATA_CORRUPTED),
450+
errmsg_internal("unexpected chunk size %d (expected %d) in chunk %d of %d for toast value %u in %s",
451+
chunksize,expected_size,
452+
curchunk,totalchunks,
463453
toast_pointer.va_valueid,
464454
RelationGetRelationName(toastrel))));
465455

466456
/*
467457
* Copy the data into proper place in our result
468458
*/
469-
memcpy(VARDATA(result)+residx*TOAST_MAX_CHUNK_SIZE,
459+
memcpy(VARDATA(result)+curchunk*TOAST_MAX_CHUNK_SIZE,
470460
chunkdata,
471461
chunksize);
472462

473-
nextidx++;
463+
expectedchunk++;
474464
}
475465

476466
/*
477467
* Final checks that we successfully fetched the datum
478468
*/
479-
if (nextidx!=numchunks)
469+
if (expectedchunk!=totalchunks)
480470
ereport(ERROR,
481471
(errcode(ERRCODE_DATA_CORRUPTED),
482472
errmsg_internal("missing chunk number %d for toast value %u in %s",
483-
nextidx,
473+
expectedchunk,
484474
toast_pointer.va_valueid,
485475
RelationGetRelationName(toastrel))));
486476

@@ -506,7 +496,8 @@ toast_fetch_datum(struct varlena *attr)
506496
* ----------
507497
*/
508498
staticstructvarlena*
509-
toast_fetch_datum_slice(structvarlena*attr,int32sliceoffset,int32length)
499+
toast_fetch_datum_slice(structvarlena*attr,int32sliceoffset,
500+
int32slicelength)
510501
{
511502
Relationtoastrel;
512503
Relation*toastidxs;
@@ -518,20 +509,10 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset, int32 length)
518509
structvarlena*result;
519510
structvaratt_externaltoast_pointer;
520511
int32attrsize;
521-
int32residx;
522-
int32nextidx;
523-
intnumchunks;
512+
int32expectedchunk;
524513
intstartchunk;
525514
intendchunk;
526-
int32startoffset;
527-
int32endoffset;
528515
inttotalchunks;
529-
Pointerchunk;
530-
boolisnull;
531-
char*chunkdata;
532-
int32chunksize;
533-
int32chcpystrt;
534-
int32chcpyend;
535516
intnum_indexes;
536517
intvalidIndex;
537518
SnapshotDataSnapshotToast;
@@ -555,36 +536,33 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset, int32 length)
555536
if (sliceoffset >=attrsize)
556537
{
557538
sliceoffset=0;
558-
length=0;
539+
slicelength=0;
559540
}
560541

561542
/*
562543
* When fetching a prefix of a compressed external datum, account for the
563544
* rawsize tracking amount of raw data, which is stored at the beginning
564545
* as an int32 value).
565546
*/
566-
if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer)&&length>0)
567-
length=length+sizeof(int32);
547+
if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer)&&slicelength>0)
548+
slicelength=slicelength+sizeof(int32);
568549

569-
if (((sliceoffset+length)>attrsize)||length<0)
570-
length=attrsize-sliceoffset;
550+
if (((sliceoffset+slicelength)>attrsize)||slicelength<0)
551+
slicelength=attrsize-sliceoffset;
571552

572-
result= (structvarlena*)palloc(length+VARHDRSZ);
553+
result= (structvarlena*)palloc(slicelength+VARHDRSZ);
573554

574555
if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
575-
SET_VARSIZE_COMPRESSED(result,length+VARHDRSZ);
556+
SET_VARSIZE_COMPRESSED(result,slicelength+VARHDRSZ);
576557
else
577-
SET_VARSIZE(result,length+VARHDRSZ);
558+
SET_VARSIZE(result,slicelength+VARHDRSZ);
578559

579-
if (length==0)
560+
if (slicelength==0)
580561
returnresult;/* Can save a lot of work at this point! */
581562

582563
startchunk=sliceoffset /TOAST_MAX_CHUNK_SIZE;
583-
endchunk= (sliceoffset+length-1) /TOAST_MAX_CHUNK_SIZE;
584-
numchunks= (endchunk-startchunk)+1;
585-
586-
startoffset=sliceoffset %TOAST_MAX_CHUNK_SIZE;
587-
endoffset= (sliceoffset+length-1) %TOAST_MAX_CHUNK_SIZE;
564+
endchunk= (sliceoffset+slicelength-1) /TOAST_MAX_CHUNK_SIZE;
565+
Assert(endchunk<totalchunks);
588566

589567
/*
590568
* Open the toast relation and its indexes
@@ -610,7 +588,7 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset, int32 length)
610588
/*
611589
* Use equality condition for one chunk, a range condition otherwise:
612590
*/
613-
if (numchunks==1)
591+
if (startchunk==endchunk)
614592
{
615593
ScanKeyInit(&toastkey[1],
616594
(AttrNumber)2,
@@ -637,15 +615,24 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset, int32 length)
637615
* The index is on (valueid, chunkidx) so they will come in order
638616
*/
639617
init_toast_snapshot(&SnapshotToast);
640-
nextidx=startchunk;
618+
expectedchunk=startchunk;
641619
toastscan=systable_beginscan_ordered(toastrel,toastidxs[validIndex],
642620
&SnapshotToast,nscankeys,toastkey);
643621
while ((ttup=systable_getnext_ordered(toastscan,ForwardScanDirection))!=NULL)
644622
{
623+
int32curchunk;
624+
Pointerchunk;
625+
boolisnull;
626+
char*chunkdata;
627+
int32chunksize;
628+
int32expected_size;
629+
int32chcpystrt;
630+
int32chcpyend;
631+
645632
/*
646633
* Have a chunk, extract the sequence number and the data
647634
*/
648-
residx=DatumGetInt32(fastgetattr(ttup,2,toasttupDesc,&isnull));
635+
curchunk=DatumGetInt32(fastgetattr(ttup,2,toasttupDesc,&isnull));
649636
Assert(!isnull);
650637
chunk=DatumGetPointer(fastgetattr(ttup,3,toasttupDesc,&isnull));
651638
Assert(!isnull);
@@ -673,63 +660,60 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset, int32 length)
673660
/*
674661
* Some checks on the data we've found
675662
*/
676-
if ((residx!=nextidx)|| (residx>endchunk)|| (residx<startchunk))
677-
elog(ERROR,"unexpected chunk number %d (expected %d) for toast value %u in %s",
678-
residx,nextidx,
679-
toast_pointer.va_valueid,
680-
RelationGetRelationName(toastrel));
681-
if (residx<totalchunks-1)
682-
{
683-
if (chunksize!=TOAST_MAX_CHUNK_SIZE)
684-
elog(ERROR,"unexpected chunk size %d (expected %d) in chunk %d of %d for toast value %u in %s when fetching slice",
685-
chunksize, (int)TOAST_MAX_CHUNK_SIZE,
686-
residx,totalchunks,
687-
toast_pointer.va_valueid,
688-
RelationGetRelationName(toastrel));
689-
}
690-
elseif (residx==totalchunks-1)
691-
{
692-
if ((residx*TOAST_MAX_CHUNK_SIZE+chunksize)!=attrsize)
693-
elog(ERROR,"unexpected chunk size %d (expected %d) in final chunk %d for toast value %u in %s when fetching slice",
694-
chunksize,
695-
(int) (attrsize-residx*TOAST_MAX_CHUNK_SIZE),
696-
residx,
697-
toast_pointer.va_valueid,
698-
RelationGetRelationName(toastrel));
699-
}
700-
else
701-
elog(ERROR,"unexpected chunk number %d (out of range %d..%d) for toast value %u in %s",
702-
residx,
703-
0,totalchunks-1,
704-
toast_pointer.va_valueid,
705-
RelationGetRelationName(toastrel));
663+
if (curchunk!=expectedchunk)
664+
ereport(ERROR,
665+
(errcode(ERRCODE_DATA_CORRUPTED),
666+
errmsg_internal("unexpected chunk number %d (expected %d) for toast value %u in %s",
667+
curchunk,expectedchunk,
668+
toast_pointer.va_valueid,
669+
RelationGetRelationName(toastrel))));
670+
if (curchunk>endchunk)
671+
ereport(ERROR,
672+
(errcode(ERRCODE_DATA_CORRUPTED),
673+
errmsg_internal("unexpected chunk number %d (out of range %d..%d) for toast value %u in %s",
674+
curchunk,
675+
startchunk,endchunk,
676+
toast_pointer.va_valueid,
677+
RelationGetRelationName(toastrel))));
678+
expected_size=curchunk<totalchunks-1 ?TOAST_MAX_CHUNK_SIZE
679+
:attrsize %TOAST_MAX_CHUNK_SIZE;
680+
if (chunksize!=expected_size)
681+
ereport(ERROR,
682+
(errcode(ERRCODE_DATA_CORRUPTED),
683+
errmsg_internal("unexpected chunk size %d (expected %d) in chunk %d of %d for toast value %u in %s",
684+
chunksize,expected_size,
685+
curchunk,totalchunks,
686+
toast_pointer.va_valueid,
687+
RelationGetRelationName(toastrel))));
706688

707689
/*
708690
* Copy the data into proper place in our result
709691
*/
710692
chcpystrt=0;
711693
chcpyend=chunksize-1;
712-
if (residx==startchunk)
713-
chcpystrt=startoffset;
714-
if (residx==endchunk)
715-
chcpyend=endoffset;
694+
if (curchunk==startchunk)
695+
chcpystrt=sliceoffset %TOAST_MAX_CHUNK_SIZE;
696+
if (curchunk==endchunk)
697+
chcpyend=(sliceoffset+slicelength-1) %TOAST_MAX_CHUNK_SIZE;
716698

717699
memcpy(VARDATA(result)+
718-
(residx*TOAST_MAX_CHUNK_SIZE-sliceoffset)+chcpystrt,
700+
(curchunk*TOAST_MAX_CHUNK_SIZE-sliceoffset)+chcpystrt,
719701
chunkdata+chcpystrt,
720702
(chcpyend-chcpystrt)+1);
721703

722-
nextidx++;
704+
expectedchunk++;
723705
}
724706

725707
/*
726708
* Final checks that we successfully fetched the datum
727709
*/
728-
if (nextidx!= (endchunk+1))
729-
elog(ERROR,"missing chunk number %d for toast value %u in %s",
730-
nextidx,
731-
toast_pointer.va_valueid,
732-
RelationGetRelationName(toastrel));
710+
if (expectedchunk!= (endchunk+1))
711+
ereport(ERROR,
712+
(errcode(ERRCODE_DATA_CORRUPTED),
713+
errmsg_internal("missing chunk number %d for toast value %u in %s",
714+
expectedchunk,
715+
toast_pointer.va_valueid,
716+
RelationGetRelationName(toastrel))));
733717

734718
/*
735719
* End scan and close relations

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp