@@ -223,14 +223,15 @@ detoast_attr_slice(struct varlena *attr,
223
223
else if (pg_add_s32_overflow (sliceoffset ,slicelength ,& slicelimit ))
224
224
slicelength = slicelimit = -1 ;
225
225
226
- if (VARATT_IS_EXTERNAL_ONDISK_INLINE (attr ))
227
- elog (ERROR ,"slicing of chunked attributes is not yet supported" );/* FIXME */
226
+ // if (VARATT_IS_EXTERNAL_ONDISK_INLINE(attr))
227
+ // elog(ERROR, "slicing of chunked attributes is not yet supported"); /* FIXME */
228
228
229
- if (VARATT_IS_EXTERNAL_ONDISK (attr ))
229
+ if (VARATT_IS_EXTERNAL_ONDISK (attr )||
230
+ VARATT_IS_EXTERNAL_ONDISK_INLINE (attr ))
230
231
{
231
232
struct varatt_external toast_pointer ;
232
233
233
- VARATT_EXTERNAL_GET_POINTER (toast_pointer ,attr );
234
+ VARATT_EXTERNAL_INLINE_GET_POINTER (toast_pointer ,attr );
234
235
235
236
/* fast path for non-compressed external datums */
236
237
if (!VARATT_EXTERNAL_IS_COMPRESSED (toast_pointer ))
@@ -381,9 +382,18 @@ create_detoast_iterator(struct varlena *attr)
381
382
382
383
if (inlineSize > 0 )
383
384
{
384
- memcpy ((void * )fetch_iter -> buf -> limit ,
385
- VARDATA_EXTERNAL_INLINE (attr ),inlineSize );
386
- fetch_iter = - > buf -> limit += inlineSize ;
385
+ if (VARATT_IS_EXTERNAL_ONDISK_INLINE_HEAD (attr ))
386
+ {
387
+ memcpy ((void * )fetch_iter -> buf -> limit ,
388
+ VARDATA_EXTERNAL_INLINE (attr ),inlineSize );
389
+ fetch_iter -> buf -> limit += inlineSize ;
390
+ }
391
+ else
392
+ {
393
+ memcpy (fetch_iter -> buf -> limit + fetch_iter -> ressize ,
394
+ VARDATA_EXTERNAL_INLINE (attr ),inlineSize );
395
+ fetch_iter -> tail_size = inlineSize ;
396
+ }
387
397
}
388
398
389
399
return iter ;
@@ -464,13 +474,14 @@ toast_fetch_datum(struct varlena *attr)
464
474
struct varlena * result ;
465
475
struct varatt_external toast_pointer ;
466
476
int32 attrsize ;
467
- int32 inlineSize ;
477
+ int32 inline_size ;
478
+ char * detoast_ptr ;
468
479
469
480
if (!VARATT_IS_EXTERNAL_ONDISK (attr )&& !VARATT_IS_EXTERNAL_ONDISK_INLINE (attr ))
470
481
elog (ERROR ,"toast_fetch_datum shouldn't be called for non-ondisk datums" );
471
482
472
483
/* Must copy to access aligned fields */
473
- inlineSize = VARATT_EXTERNAL_INLINE_GET_POINTER (toast_pointer ,attr );
484
+ inline_size = VARATT_EXTERNAL_INLINE_GET_POINTER (toast_pointer ,attr );
474
485
attrsize = VARATT_EXTERNAL_GET_EXTSIZE (toast_pointer );
475
486
476
487
result = (struct varlena * )palloc (attrsize + VARHDRSZ );
@@ -484,8 +495,18 @@ toast_fetch_datum(struct varlena *attr)
484
495
return result ;/* Probably shouldn't happen, but just in
485
496
* case. */
486
497
487
- if (inlineSize )
488
- memcpy (VARDATA (result ),VARDATA_EXTERNAL_INLINE (attr ),inlineSize );
498
+ detoast_ptr = (char * )result ;
499
+
500
+ if (inline_size )
501
+ {
502
+ if (VARATT_IS_EXTERNAL_ONDISK_INLINE_TAIL (attr ))
503
+ memcpy (VARDATA (result )+ attrsize - inline_size ,VARDATA_EXTERNAL_INLINE (attr ),inline_size );
504
+ else
505
+ {
506
+ memcpy (VARDATA (result ),VARDATA_EXTERNAL_INLINE (attr ),inline_size );
507
+ detoast_ptr += inline_size ;
508
+ }
509
+ }
489
510
490
511
/*
491
512
* Open the toast relation and its indexes
@@ -494,8 +515,8 @@ toast_fetch_datum(struct varlena *attr)
494
515
495
516
/* Fetch all chunks */
496
517
table_relation_fetch_toast_slice (toastrel ,toast_pointer .va_valueid ,
497
- attrsize - inlineSize ,0 ,attrsize - inlineSize ,
498
- (struct varlena * )(( char * ) result + inlineSize ) );
518
+ attrsize - inline_size ,0 ,attrsize - inline_size ,
519
+ (struct varlena * )detoast_ptr );
499
520
500
521
/* Close toast table */
501
522
table_close (toastrel ,AccessShareLock );
@@ -522,12 +543,14 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
522
543
struct varlena * result ;
523
544
struct varatt_external toast_pointer ;
524
545
int32 attrsize ;
546
+ int32 inline_size ;
525
547
526
- if (!VARATT_IS_EXTERNAL_ONDISK (attr ))/* FIXME */
548
+ if (!VARATT_IS_EXTERNAL_ONDISK (attr )&&
549
+ !VARATT_IS_EXTERNAL_ONDISK_INLINE (attr ))
527
550
elog (ERROR ,"toast_fetch_datum_slice shouldn't be called for non-ondisk datums" );
528
551
529
552
/* Must copy to access aligned fields */
530
- VARATT_EXTERNAL_GET_POINTER (toast_pointer ,attr );
553
+ inline_size = VARATT_EXTERNAL_INLINE_GET_POINTER (toast_pointer ,attr );
531
554
532
555
/*
533
556
* It's nonsense to fetch slices of a compressed datum unless when it's a
@@ -567,15 +590,40 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
567
590
else
568
591
SET_VARSIZE (result ,slicelength + VARHDRSZ );
569
592
570
- if (slicelength == 0 )
593
+ if (VARATT_IS_EXTERNAL_ONDISK_INLINE_HEAD (attr ))
594
+ {
595
+ int32 size = Min (slicelength ,inline_size - sliceoffset );
596
+
597
+ if (size > 0 )
598
+ memcpy (VARDATA (result ),VARDATA_EXTERNAL_INLINE (attr )+ sliceoffset ,size );
599
+ slicelength -= size ;
600
+ sliceoffset = size ;
601
+ }
602
+ else if (VARATT_IS_EXTERNAL_ONDISK_INLINE_TAIL (attr ))
603
+ {
604
+ if (sliceoffset + slicelength > attrsize - inline_size )
605
+ {
606
+ int32 size = Min (sliceoffset + slicelength - (attrsize - inline_size ),inline_size );
607
+ int32 inline_offset = Max (0 ,sliceoffset - (attrsize - inline_size ));
608
+
609
+ size = Min (size ,slicelength );
610
+
611
+ memcpy (VARDATA (result )+ slicelength - size ,
612
+ VARDATA_EXTERNAL_INLINE (attr )+ inline_offset ,size );
613
+
614
+ slicelength -= size ;
615
+ }
616
+ }
617
+
618
+ if (slicelength <=0 )
571
619
return result ;/* Can save a lot of work at this point! */
572
620
573
621
/* Open the toast relation */
574
622
toastrel = table_open (toast_pointer .va_toastrelid ,AccessShareLock );
575
623
576
624
/* Fetch all chunks */
577
625
table_relation_fetch_toast_slice (toastrel ,toast_pointer .va_valueid ,
578
- attrsize ,sliceoffset ,slicelength ,
626
+ attrsize - inline_size ,sliceoffset ,slicelength ,
579
627
result );
580
628
581
629
/* Close toast table */
@@ -673,10 +721,9 @@ toast_raw_datum_size(Datum value)
673
721
{
674
722
/* va_rawsize is the size of the original datum -- including header */
675
723
struct varatt_external toast_pointer ;
676
- Size inlineSize ;
677
724
678
- inlineSize = VARATT_EXTERNAL_INLINE_GET_POINTER (toast_pointer ,attr );
679
- result = toast_pointer .va_rawsize + inlineSize ;
725
+ VARATT_EXTERNAL_INLINE_GET_POINTER (toast_pointer ,attr );
726
+ result = toast_pointer .va_rawsize ;
680
727
}
681
728
else if (VARATT_IS_EXTERNAL_INDIRECT (attr ))
682
729
{