Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 33e2b76

Browse files
author
Nikita Glukhov
committed
TOAST iterators
1 parent 86b1afa commit 33e2b76

File tree

11 files changed

+866
-28
lines changed

11 files changed

+866
-28
lines changed

src/backend/access/common/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ include $(top_builddir)/src/Makefile.global
1515
OBJS = \
1616
attmap.o \
1717
bufmask.o \
18+
detoast.o \
1819
heaptuple.o \
1920
indextuple.o \
2021
printsimple.o \

src/backend/access/common/detoast.c

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* detoast.c
4+
* Retrieve compressed or external variable size attributes.
5+
*
6+
* Copyright (c) 2000-2022, PostgreSQL Global Development Group
7+
*
8+
* IDENTIFICATION
9+
* src/backend/access/common/detoast.c
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
14+
#include "postgres.h"
15+
16+
#include "access/detoast.h"
17+
#include "access/table.h"
18+
#include "access/tableam.h"
19+
#include "access/toast_internals.h"
20+
#include "common/int.h"
21+
#include "common/pg_lzcompress.h"
22+
#include "utils/expandeddatum.h"
23+
#include "utils/rel.h"
24+
#include "access/toasterapi.h"
25+
26+
/* ----------
27+
* create_detoast_iterator -
28+
*
29+
* It only makes sense to initialize a de-TOAST iterator for external on-disk values.
30+
*
31+
* ----------
32+
*/
33+
DetoastIterator
34+
create_detoast_iterator(struct varlena *attr)
35+
{
36+
struct varatt_external toast_pointer;
37+
DetoastIterator iter;
38+
if (VARATT_IS_EXTERNAL_ONDISK(attr))
39+
{
40+
FetchDatumIterator fetch_iter;
41+
42+
iter = (DetoastIterator) palloc0(sizeof(DetoastIteratorData));
43+
iter->done = false;
44+
iter->nrefs = 1;
45+
46+
/* This is an externally stored datum --- initialize fetch datum iterator */
47+
iter->fetch_datum_iterator = fetch_iter = create_fetch_datum_iterator(attr);
48+
VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr);
49+
if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer))
50+
{
51+
iter->compressed = true;
52+
53+
/* prepare buffer to received decompressed data */
54+
iter->buf = create_toast_buffer(toast_pointer.va_rawsize, false);
55+
56+
/* initialize state for pglz_decompress_iterate() */
57+
iter->ctrl = 0;
58+
iter->ctrlc = INVALID_CTRLC;
59+
}
60+
else
61+
{
62+
iter->compressed = false;
63+
64+
/* point the buffer directly at the raw data */
65+
iter->buf = fetch_iter->buf;
66+
}
67+
return iter;
68+
}
69+
else if (VARATT_IS_EXTERNAL_INDIRECT(attr))
70+
{
71+
/* indirect pointer --- dereference it */
72+
struct varatt_indirect redirect;
73+
74+
VARATT_EXTERNAL_GET_POINTER(redirect, attr);
75+
attr = (struct varlena *) redirect.pointer;
76+
77+
/* nested indirect Datums aren't allowed */
78+
Assert(!VARATT_IS_EXTERNAL_INDIRECT(attr));
79+
80+
/* recurse in case value is still extended in some other way */
81+
return create_detoast_iterator(attr);
82+
83+
}
84+
else if (VARATT_IS_COMPRESSED(attr))
85+
{
86+
ToastBuffer *buf;
87+
88+
iter = (DetoastIterator) palloc0(sizeof(DetoastIteratorData));
89+
iter->done = false;
90+
iter->nrefs = 1;
91+
92+
iter->fetch_datum_iterator = palloc0(sizeof(*iter->fetch_datum_iterator));
93+
iter->fetch_datum_iterator->buf = buf = create_toast_buffer(VARSIZE_ANY(attr), true);
94+
iter->fetch_datum_iterator->done = true;
95+
iter->compressed = true;
96+
97+
memcpy((void *) buf->buf, attr, VARSIZE_ANY(attr));
98+
buf->limit = (char *) buf->capacity;
99+
100+
/* prepare buffer to received decompressed data */
101+
iter->buf = create_toast_buffer(TOAST_COMPRESS_EXTSIZE(attr) + VARHDRSZ, false);
102+
103+
/* initialize state for pglz_decompress_iterate() */
104+
iter->ctrl = 0;
105+
iter->ctrlc = INVALID_CTRLC;
106+
return iter;
107+
}
108+
else
109+
/* in-line value -- no iteration used, even if it's compressed */
110+
return NULL;
111+
}
112+
113+
/* ----------
114+
* free_detoast_iterator -
115+
*
116+
* Free memory used by the de-TOAST iterator, including buffers and
117+
* fetch datum iterator.
118+
* ----------
119+
*/
120+
void
121+
free_detoast_iterator(DetoastIterator iter)
122+
{
123+
if (iter == NULL)
124+
return;
125+
if (--iter->nrefs > 0)
126+
return;
127+
if (iter->compressed)
128+
free_toast_buffer(iter->buf);
129+
free_fetch_datum_iterator(iter->fetch_datum_iterator);
130+
pfree(iter);
131+
}

0 commit comments

Comments
 (0)