|
14 | 14 | #include"postgres.h"
|
15 | 15 |
|
16 | 16 | #include"access/detoast.h"
|
17 |
| -#include"access/genam.h" |
18 |
| -#include"access/heaptoast.h" |
19 | 17 | #include"access/table.h"
|
| 18 | +#include"access/tableam.h" |
20 | 19 | #include"access/toast_internals.h"
|
21 | 20 | #include"common/pg_lzcompress.h"
|
22 | 21 | #include"utils/expandeddatum.h"
|
23 |
| -#include"utils/fmgroids.h" |
24 | 22 | #include"utils/rel.h"
|
25 | 23 |
|
26 | 24 | staticstructvarlena*toast_fetch_datum(structvarlena*attr);
|
27 | 25 | staticstructvarlena*toast_fetch_datum_slice(structvarlena*attr,
|
28 | 26 | int32sliceoffset,
|
29 | 27 | int32slicelength);
|
30 |
| -staticvoidheap_fetch_toast_slice(Relationtoastrel,Oidvalueid, |
31 |
| -int32attrsize,int32sliceoffset, |
32 |
| -int32slicelength,structvarlena*result); |
33 | 28 | staticstructvarlena*toast_decompress_datum(structvarlena*attr);
|
34 | 29 | staticstructvarlena*toast_decompress_datum_slice(structvarlena*attr,int32slicelength);
|
35 | 30 |
|
@@ -356,8 +351,8 @@ toast_fetch_datum(struct varlena *attr)
|
356 | 351 | toastrel=table_open(toast_pointer.va_toastrelid,AccessShareLock);
|
357 | 352 |
|
358 | 353 | /* 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); |
361 | 356 |
|
362 | 357 | /* Close toast table */
|
363 | 358 | table_close(toastrel,AccessShareLock);
|
@@ -431,198 +426,16 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
|
431 | 426 | toastrel=table_open(toast_pointer.va_toastrelid,AccessShareLock);
|
432 | 427 |
|
433 | 428 | /* 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); |
436 | 432 |
|
437 | 433 | /* Close toast table */
|
438 | 434 | table_close(toastrel,AccessShareLock);
|
439 | 435 |
|
440 | 436 | returnresult;
|
441 | 437 | }
|
442 | 438 |
|
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 |
| - |
626 | 439 | /* ----------
|
627 | 440 | * toast_decompress_datum -
|
628 | 441 | *
|
|