Skip to content

Commit 102f464

Browse files
author
Nikita Glukhov
committed
WIP: TOAST iterators
1 parent d03a62e commit 102f464

File tree

12 files changed

+800
-18
lines changed

12 files changed

+800
-18
lines changed

src/backend/access/common/detoast.c

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,111 @@ detoast_attr_slice(struct varlena *attr,
312312
return result;
313313
}
314314

315+
/* ----------
316+
* create_detoast_iterator -
317+
*
318+
* It only makes sense to initialize a de-TOAST iterator for external on-disk values.
319+
*
320+
* ----------
321+
*/
322+
DetoastIterator
323+
create_detoast_iterator(struct varlena *attr)
324+
{
325+
struct varatt_external toast_pointer;
326+
DetoastIterator iter;
327+
if (VARATT_IS_EXTERNAL_ONDISK(attr))
328+
{
329+
iter = (DetoastIterator) palloc0(sizeof(DetoastIteratorData));
330+
iter->done = false;
331+
iter->nrefs = 1;
332+
333+
/* This is an externally stored datum --- initialize fetch datum iterator */
334+
iter->fetch_datum_iterator = create_fetch_datum_iterator(attr);
335+
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
336+
if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
337+
{
338+
iter->compressed = true;
339+
340+
/* prepare buffer to received decompressed data */
341+
iter->buf = create_toast_buffer(toast_pointer.va_rawsize, false);
342+
343+
/* initialize state for pglz_decompress_iterate() */
344+
iter->ctrl = 0;
345+
iter->ctrlc = INVALID_CTRLC;
346+
}
347+
else
348+
{
349+
iter->compressed = false;
350+
351+
/* point the buffer directly at the raw data */
352+
iter->buf = iter->fetch_datum_iterator->buf;
353+
}
354+
return iter;
355+
}
356+
else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
357+
{
358+
/* indirect pointer --- dereference it */
359+
struct varatt_indirect redirect;
360+
361+
VARATT_EXTERNAL_GET_POINTER(redirect, attr);
362+
attr = (struct varlena *) redirect.pointer;
363+
364+
/* nested indirect Datums aren't allowed */
365+
Assert(!VARATT_IS_EXTERNAL_INDIRECT(attr));
366+
367+
/* recurse in case value is still extended in some other way */
368+
return create_detoast_iterator(attr);
369+
370+
}
371+
else if (VARATT_IS_COMPRESSED(attr))
372+
{
373+
ToastBuffer *buf;
374+
375+
iter = (DetoastIterator) palloc0(sizeof(DetoastIteratorData));
376+
iter->done = false;
377+
iter->nrefs = 1;
378+
379+
iter->fetch_datum_iterator = palloc0(sizeof(*iter->fetch_datum_iterator));
380+
iter->fetch_datum_iterator->buf = buf = create_toast_buffer(VARSIZE_ANY(attr), true);
381+
iter->fetch_datum_iterator->done = true;
382+
iter->compressed = true;
383+
384+
memcpy((void *) buf->buf, attr, VARSIZE_ANY(attr));
385+
buf->limit = (char *) buf->capacity;
386+
387+
/* prepare buffer to received decompressed data */
388+
iter->buf = create_toast_buffer(TOAST_COMPRESS_RAWSIZE(attr) + VARHDRSZ, false);
389+
390+
/* initialize state for pglz_decompress_iterate() */
391+
iter->ctrl = 0;
392+
iter->ctrlc = INVALID_CTRLC;
393+
return iter;
394+
}
395+
else
396+
/* in-line value -- no iteration used, even if it's compressed */
397+
return NULL;
398+
}
399+
400+
/* ----------
401+
* free_detoast_iterator -
402+
*
403+
* Free memory used by the de-TOAST iterator, including buffers and
404+
* fetch datum iterator.
405+
* ----------
406+
*/
407+
void
408+
free_detoast_iterator(DetoastIterator iter)
409+
{
410+
if (iter == NULL)
411+
return;
412+
if (--iter->nrefs > 0)
413+
return;
414+
if (iter->compressed)
415+
free_toast_buffer(iter->buf);
416+
free_fetch_datum_iterator(iter->fetch_datum_iterator);
417+
pfree(iter);
418+
}
419+
315420
/* ----------
316421
* toast_fetch_datum -
317422
*

0 commit comments

Comments
 (0)