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

Commitce242ae

Browse files
committed
tableam: New callback relation_fetch_toast_slice.
Instead of always calling heap_fetch_toast_slice during detoasting,invoke a table AM callback which, when the toast table is a heaptable, will be heap_fetch_toast_slice.This makes it possible for a table AM other than heap to be usedas a TOAST table. It also completes the series of commits intendedto improve the interaction of tableam with TOAST that began withcommit8b94dab; detoast.c isnow, hopefully, fully AM-independent.Patch by me, reviewed by Andres Freund and Peter Eisentraut.Discussion:http://postgr.es/m/CA+TgmoZv-=2iWM4jcw5ZhJeL18HF96+W1yJeYrnGMYdkFFnEpQ@mail.gmail.com
1 parent83322e3 commitce242ae

File tree

5 files changed

+245
-193
lines changed

5 files changed

+245
-193
lines changed

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

Lines changed: 6 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,17 @@
1414
#include"postgres.h"
1515

1616
#include"access/detoast.h"
17-
#include"access/genam.h"
18-
#include"access/heaptoast.h"
1917
#include"access/table.h"
18+
#include"access/tableam.h"
2019
#include"access/toast_internals.h"
2120
#include"common/pg_lzcompress.h"
2221
#include"utils/expandeddatum.h"
23-
#include"utils/fmgroids.h"
2422
#include"utils/rel.h"
2523

2624
staticstructvarlena*toast_fetch_datum(structvarlena*attr);
2725
staticstructvarlena*toast_fetch_datum_slice(structvarlena*attr,
2826
int32sliceoffset,
2927
int32slicelength);
30-
staticvoidheap_fetch_toast_slice(Relationtoastrel,Oidvalueid,
31-
int32attrsize,int32sliceoffset,
32-
int32slicelength,structvarlena*result);
3328
staticstructvarlena*toast_decompress_datum(structvarlena*attr);
3429
staticstructvarlena*toast_decompress_datum_slice(structvarlena*attr,int32slicelength);
3530

@@ -356,8 +351,8 @@ toast_fetch_datum(struct varlena *attr)
356351
toastrel=table_open(toast_pointer.va_toastrelid,AccessShareLock);
357352

358353
/* Fetch all chunks */
359-
heap_fetch_toast_slice(toastrel,toast_pointer.va_valueid,attrsize,0,
360-
attrsize,result);
354+
table_relation_fetch_toast_slice(toastrel,toast_pointer.va_valueid,
355+
attrsize,0,attrsize,result);
361356

362357
/* Close toast table */
363358
table_close(toastrel,AccessShareLock);
@@ -431,198 +426,16 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
431426
toastrel=table_open(toast_pointer.va_toastrelid,AccessShareLock);
432427

433428
/* Fetch all chunks */
434-
heap_fetch_toast_slice(toastrel,toast_pointer.va_valueid,attrsize,
435-
sliceoffset,slicelength,result);
429+
table_relation_fetch_toast_slice(toastrel,toast_pointer.va_valueid,
430+
attrsize,sliceoffset,slicelength,
431+
result);
436432

437433
/* Close toast table */
438434
table_close(toastrel,AccessShareLock);
439435

440436
returnresult;
441437
}
442438

443-
/*
444-
* Fetch a TOAST slice from a heap table.
445-
*
446-
* toastrel is the relation from which chunks are to be fetched.
447-
* valueid identifies the TOAST value from which chunks are being fetched.
448-
* attrsize is the total size of the TOAST value.
449-
* sliceoffset is the byte offset within the TOAST value from which to fetch.
450-
* slicelength is the number of bytes to be fetched from the TOAST value.
451-
* result is the varlena into which the results should be written.
452-
*/
453-
staticvoid
454-
heap_fetch_toast_slice(Relationtoastrel,Oidvalueid,int32attrsize,
455-
int32sliceoffset,int32slicelength,
456-
structvarlena*result)
457-
{
458-
Relation*toastidxs;
459-
ScanKeyDatatoastkey[3];
460-
TupleDesctoasttupDesc=toastrel->rd_att;
461-
intnscankeys;
462-
SysScanDesctoastscan;
463-
HeapTuplettup;
464-
int32expectedchunk;
465-
int32totalchunks= ((attrsize-1) /TOAST_MAX_CHUNK_SIZE)+1;
466-
intstartchunk;
467-
intendchunk;
468-
intnum_indexes;
469-
intvalidIndex;
470-
SnapshotDataSnapshotToast;
471-
472-
/* Look for the valid index of toast relation */
473-
validIndex=toast_open_indexes(toastrel,
474-
AccessShareLock,
475-
&toastidxs,
476-
&num_indexes);
477-
478-
startchunk=sliceoffset /TOAST_MAX_CHUNK_SIZE;
479-
endchunk= (sliceoffset+slicelength-1) /TOAST_MAX_CHUNK_SIZE;
480-
Assert(endchunk <=totalchunks);
481-
482-
/*
483-
* Setup a scan key to fetch from the index. This is either two keys or
484-
* three depending on the number of chunks.
485-
*/
486-
ScanKeyInit(&toastkey[0],
487-
(AttrNumber)1,
488-
BTEqualStrategyNumber,F_OIDEQ,
489-
ObjectIdGetDatum(valueid));
490-
491-
/*
492-
* No additional condition if fetching all chunks. Otherwise, use an
493-
* equality condition for one chunk, and a range condition otherwise.
494-
*/
495-
if (startchunk==0&&endchunk==totalchunks-1)
496-
nscankeys=1;
497-
elseif (startchunk==endchunk)
498-
{
499-
ScanKeyInit(&toastkey[1],
500-
(AttrNumber)2,
501-
BTEqualStrategyNumber,F_INT4EQ,
502-
Int32GetDatum(startchunk));
503-
nscankeys=2;
504-
}
505-
else
506-
{
507-
ScanKeyInit(&toastkey[1],
508-
(AttrNumber)2,
509-
BTGreaterEqualStrategyNumber,F_INT4GE,
510-
Int32GetDatum(startchunk));
511-
ScanKeyInit(&toastkey[2],
512-
(AttrNumber)2,
513-
BTLessEqualStrategyNumber,F_INT4LE,
514-
Int32GetDatum(endchunk));
515-
nscankeys=3;
516-
}
517-
518-
/* Prepare for scan */
519-
init_toast_snapshot(&SnapshotToast);
520-
toastscan=systable_beginscan_ordered(toastrel,toastidxs[validIndex],
521-
&SnapshotToast,nscankeys,toastkey);
522-
523-
/*
524-
* Read the chunks by index
525-
*
526-
* The index is on (valueid, chunkidx) so they will come in order
527-
*/
528-
expectedchunk=startchunk;
529-
while ((ttup=systable_getnext_ordered(toastscan,ForwardScanDirection))!=NULL)
530-
{
531-
int32curchunk;
532-
Pointerchunk;
533-
boolisnull;
534-
char*chunkdata;
535-
int32chunksize;
536-
int32expected_size;
537-
int32chcpystrt;
538-
int32chcpyend;
539-
540-
/*
541-
* Have a chunk, extract the sequence number and the data
542-
*/
543-
curchunk=DatumGetInt32(fastgetattr(ttup,2,toasttupDesc,&isnull));
544-
Assert(!isnull);
545-
chunk=DatumGetPointer(fastgetattr(ttup,3,toasttupDesc,&isnull));
546-
Assert(!isnull);
547-
if (!VARATT_IS_EXTENDED(chunk))
548-
{
549-
chunksize=VARSIZE(chunk)-VARHDRSZ;
550-
chunkdata=VARDATA(chunk);
551-
}
552-
elseif (VARATT_IS_SHORT(chunk))
553-
{
554-
/* could happen due to heap_form_tuple doing its thing */
555-
chunksize=VARSIZE_SHORT(chunk)-VARHDRSZ_SHORT;
556-
chunkdata=VARDATA_SHORT(chunk);
557-
}
558-
else
559-
{
560-
/* should never happen */
561-
elog(ERROR,"found toasted toast chunk for toast value %u in %s",
562-
valueid,RelationGetRelationName(toastrel));
563-
chunksize=0;/* keep compiler quiet */
564-
chunkdata=NULL;
565-
}
566-
567-
/*
568-
* Some checks on the data we've found
569-
*/
570-
if (curchunk!=expectedchunk)
571-
ereport(ERROR,
572-
(errcode(ERRCODE_DATA_CORRUPTED),
573-
errmsg_internal("unexpected chunk number %d (expected %d) for toast value %u in %s",
574-
curchunk,expectedchunk,valueid,
575-
RelationGetRelationName(toastrel))));
576-
if (curchunk>endchunk)
577-
ereport(ERROR,
578-
(errcode(ERRCODE_DATA_CORRUPTED),
579-
errmsg_internal("unexpected chunk number %d (out of range %d..%d) for toast value %u in %s",
580-
curchunk,
581-
startchunk,endchunk,valueid,
582-
RelationGetRelationName(toastrel))));
583-
expected_size=curchunk<totalchunks-1 ?TOAST_MAX_CHUNK_SIZE
584-
:attrsize- ((totalchunks-1)*TOAST_MAX_CHUNK_SIZE);
585-
if (chunksize!=expected_size)
586-
ereport(ERROR,
587-
(errcode(ERRCODE_DATA_CORRUPTED),
588-
errmsg_internal("unexpected chunk size %d (expected %d) in chunk %d of %d for toast value %u in %s",
589-
chunksize,expected_size,
590-
curchunk,totalchunks,valueid,
591-
RelationGetRelationName(toastrel))));
592-
593-
/*
594-
* Copy the data into proper place in our result
595-
*/
596-
chcpystrt=0;
597-
chcpyend=chunksize-1;
598-
if (curchunk==startchunk)
599-
chcpystrt=sliceoffset %TOAST_MAX_CHUNK_SIZE;
600-
if (curchunk==endchunk)
601-
chcpyend= (sliceoffset+slicelength-1) %TOAST_MAX_CHUNK_SIZE;
602-
603-
memcpy(VARDATA(result)+
604-
(curchunk*TOAST_MAX_CHUNK_SIZE-sliceoffset)+chcpystrt,
605-
chunkdata+chcpystrt,
606-
(chcpyend-chcpystrt)+1);
607-
608-
expectedchunk++;
609-
}
610-
611-
/*
612-
* Final checks that we successfully fetched the datum
613-
*/
614-
if (expectedchunk!= (endchunk+1))
615-
ereport(ERROR,
616-
(errcode(ERRCODE_DATA_CORRUPTED),
617-
errmsg_internal("missing chunk number %d for toast value %u in %s",
618-
expectedchunk,valueid,
619-
RelationGetRelationName(toastrel))));
620-
621-
/* End scan and close indexes. */
622-
systable_endscan_ordered(toastscan);
623-
toast_close_indexes(toastidxs,num_indexes,AccessShareLock);
624-
}
625-
626439
/* ----------
627440
* toast_decompress_datum -
628441
*

‎src/backend/access/heap/heapam_handler.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2545,6 +2545,7 @@ static const TableAmRoutine heapam_methods = {
25452545
.relation_size=table_block_relation_size,
25462546
.relation_needs_toast_table=heapam_relation_needs_toast_table,
25472547
.relation_toast_am=heapam_relation_toast_am,
2548+
.relation_fetch_toast_slice=heap_fetch_toast_slice,
25482549

25492550
.relation_estimate_size=heapam_estimate_rel_size,
25502551

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp