Skip to content

Commit 95ea57f

Browse files
author
Nikita Glukhov
committed
WIP: bytea append TOAST
1 parent 98c5e45 commit 95ea57f

File tree

7 files changed

+284
-82
lines changed

7 files changed

+284
-82
lines changed

src/backend/access/common/detoast.c

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)