@@ -223,14 +223,15 @@ detoast_attr_slice(struct varlena *attr,
223223 else if (pg_add_s32_overflow (sliceoffset , slicelength , & slicelimit ))
224224 slicelength = slicelimit = -1 ;
225225
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 */
228228
229- if (VARATT_IS_EXTERNAL_ONDISK (attr ))
229+ if (VARATT_IS_EXTERNAL_ONDISK (attr ) ||
230+ VARATT_IS_EXTERNAL_ONDISK_INLINE (attr ))
230231 {
231232 struct varatt_external toast_pointer ;
232233
233- VARATT_EXTERNAL_GET_POINTER (toast_pointer , attr );
234+ VARATT_EXTERNAL_INLINE_GET_POINTER (toast_pointer , attr );
234235
235236 /* fast path for non-compressed external datums */
236237 if (!VARATT_EXTERNAL_IS_COMPRESSED (toast_pointer ))
@@ -381,9 +382,18 @@ create_detoast_iterator(struct varlena *attr)
381382
382383 if (inlineSize > 0 )
383384 {
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+ }
387397 }
388398
389399 return iter ;
@@ -464,13 +474,14 @@ toast_fetch_datum(struct varlena *attr)
464474 struct varlena * result ;
465475 struct varatt_external toast_pointer ;
466476 int32 attrsize ;
467- int32 inlineSize ;
477+ int32 inline_size ;
478+ char * detoast_ptr ;
468479
469480 if (!VARATT_IS_EXTERNAL_ONDISK (attr ) && !VARATT_IS_EXTERNAL_ONDISK_INLINE (attr ))
470481 elog (ERROR , "toast_fetch_datum shouldn't be called for non-ondisk datums" );
471482
472483 /* 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 );
474485 attrsize = VARATT_EXTERNAL_GET_EXTSIZE (toast_pointer );
475486
476487 result = (struct varlena * ) palloc (attrsize + VARHDRSZ );
@@ -484,8 +495,18 @@ toast_fetch_datum(struct varlena *attr)
484495 return result ; /* Probably shouldn't happen, but just in
485496 * case. */
486497
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+ }
489510
490511 /*
491512 * Open the toast relation and its indexes
@@ -494,8 +515,8 @@ toast_fetch_datum(struct varlena *attr)
494515
495516 /* Fetch all chunks */
496517 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 );
499520
500521 /* Close toast table */
501522 table_close (toastrel , AccessShareLock );
@@ -522,12 +543,14 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
522543 struct varlena * result ;
523544 struct varatt_external toast_pointer ;
524545 int32 attrsize ;
546+ int32 inline_size ;
525547
526- if (!VARATT_IS_EXTERNAL_ONDISK (attr )) /* FIXME */
548+ if (!VARATT_IS_EXTERNAL_ONDISK (attr ) &&
549+ !VARATT_IS_EXTERNAL_ONDISK_INLINE (attr ))
527550 elog (ERROR , "toast_fetch_datum_slice shouldn't be called for non-ondisk datums" );
528551
529552 /* 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 );
531554
532555 /*
533556 * 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,
567590 else
568591 SET_VARSIZE (result , slicelength + VARHDRSZ );
569592
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 )
571619 return result ; /* Can save a lot of work at this point! */
572620
573621 /* Open the toast relation */
574622 toastrel = table_open (toast_pointer .va_toastrelid , AccessShareLock );
575623
576624 /* Fetch all chunks */
577625 table_relation_fetch_toast_slice (toastrel , toast_pointer .va_valueid ,
578- attrsize , sliceoffset , slicelength ,
626+ attrsize - inline_size , sliceoffset , slicelength ,
579627 result );
580628
581629 /* Close toast table */
@@ -673,10 +721,9 @@ toast_raw_datum_size(Datum value)
673721 {
674722 /* va_rawsize is the size of the original datum -- including header */
675723 struct varatt_external toast_pointer ;
676- Size inlineSize ;
677724
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 ;
680727 }
681728 else if (VARATT_IS_EXTERNAL_INDIRECT (attr ))
682729 {
0 commit comments