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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy