Skip to content

Commit 412eb4e

Browse files
author
Nikita Glukhov
committed
TMP: in-place updates
1 parent b210613 commit 412eb4e

File tree

12 files changed

+645
-137
lines changed

12 files changed

+645
-137
lines changed

contrib/jsonb_toaster/expected/jsonb_toaster.out

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,120 @@ SELECT id, key, pg_column_size(value::text) FROM test_jsonb_toaster, jsonb_each(
123123
(100 rows)
124124

125125
DROP TABLE test_jsonb_toaster;
126+
create table test_jsonbz_arr (id int, js jsonb toaster jsonb_toaster);
127+
insert into test_jsonbz_arr
128+
select
129+
j id,
130+
jsonb_build_object(
131+
'a', jsonb_agg(repeat('a', pow(2, 6 + i)::int)),
132+
'b', 'foo'
133+
) js
134+
from
135+
generate_series(0, 19) j,
136+
generate_series(0, j) i
137+
group by j
138+
order by j;
139+
update test_jsonbz_arr set js = jsonb_set(js, '{a,0}', to_jsonb(repeat('b', 64)));
140+
select id, js->'a'->>0 from test_jsonbz_arr order by id;
141+
id | ?column?
142+
----+------------------------------------------------------------------
143+
0 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
144+
1 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
145+
2 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
146+
3 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
147+
4 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
148+
5 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
149+
6 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
150+
7 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
151+
8 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
152+
9 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
153+
10 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
154+
11 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
155+
12 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
156+
13 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
157+
14 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
158+
15 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
159+
16 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
160+
17 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
161+
18 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
162+
19 | bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
163+
(20 rows)
164+
165+
update test_jsonbz_arr set js = jsonb_set(js, '{a,0}', to_jsonb(repeat('c', 64)));
166+
select id, js->'a'->>0 from test_jsonbz_arr order by id;
167+
id | ?column?
168+
----+------------------------------------------------------------------
169+
0 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
170+
1 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
171+
2 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
172+
3 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
173+
4 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
174+
5 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
175+
6 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
176+
7 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
177+
8 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
178+
9 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
179+
10 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
180+
11 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
181+
12 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
182+
13 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
183+
14 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
184+
15 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
185+
16 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
186+
17 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
187+
18 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
188+
19 | cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
189+
(20 rows)
190+
191+
update test_jsonbz_arr set js = jsonb_set(js, '{a,0}', to_jsonb(repeat('d', 65)));
192+
select id, js->'a'->>0 from test_jsonbz_arr order by id;
193+
id | ?column?
194+
----+-------------------------------------------------------------------
195+
0 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
196+
1 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
197+
2 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
198+
3 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
199+
4 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
200+
5 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
201+
6 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
202+
7 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
203+
8 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
204+
9 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
205+
10 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
206+
11 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
207+
12 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
208+
13 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
209+
14 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
210+
15 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
211+
16 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
212+
17 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
213+
18 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
214+
19 | ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
215+
(20 rows)
216+
217+
update test_jsonbz_arr set js = jsonb_set(js, '{a,0}', to_jsonb(repeat('e', 65)));
218+
select id, js->'a'->>0 from test_jsonbz_arr order by id;
219+
id | ?column?
220+
----+-------------------------------------------------------------------
221+
0 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
222+
1 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
223+
2 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
224+
3 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
225+
4 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
226+
5 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
227+
6 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
228+
7 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
229+
8 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
230+
9 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
231+
10 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
232+
11 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
233+
12 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
234+
13 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
235+
14 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
236+
15 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
237+
16 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
238+
17 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
239+
18 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
240+
19 | eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
241+
(20 rows)
242+

contrib/jsonb_toaster/jsonb_toast_internals.c

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,11 @@
3131
#include "miscadmin.h"
3232
#include "utils/expandeddatum.h"
3333
#include "utils/fmgroids.h"
34+
#include "utils/memutils.h"
3435
#include "utils/rel.h"
3536
#include "utils/snapmgr.h"
3637
#include "utils/jsonb.h"
3738

38-
typedef struct varatt_external_diff
39-
{
40-
int32 va_diff_offset;
41-
char va_diff_data[FLEXIBLE_ARRAY_MEMBER];
42-
} varatt_external_diff;
43-
4439
char *
4540
jsonxWriteCustomToastPointerHeader(char *ptr, Oid toasterid, uint32 header,
4641
int datalen, int rawsize)
@@ -53,6 +48,14 @@ jsonxWriteCustomToastPointerHeader(char *ptr, Oid toasterid, uint32 header,
5348

5449
VARATT_CUSTOM_SET_TOASTERID(ptr, toasterid);
5550
VARATT_CUSTOM_SET_DATA_RAW_SIZE(ptr, rawsize);
51+
52+
if (size - hdrsize > VARATT_CUSTOM_MAX_DATA_SIZE)
53+
ereport(ERROR,
54+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
55+
errmsg("atribute length too large")));
56+
//elog(ERROR, "custom TOAST pointer data size exceeds maximal size: %d > %d",
57+
// (int)(size - hdrsize), VARATT_CUSTOM_MAX_DATA_SIZE);
58+
5659
VARATT_CUSTOM_SET_DATA_SIZE(ptr, size - hdrsize);
5760

5861
if (aligned_hdrsize != hdrsize)
@@ -135,15 +138,41 @@ jsonx_toast_make_pointer_compressed_chunks(Oid toasterid,
135138
return custom_ptr;
136139
}
137140

141+
struct varlena *
142+
jsonx_toast_make_pointer_diff(Oid toasterid,
143+
struct varatt_external *toast_pointer,
144+
int32 diff_offset, int32 diff_len,
145+
const void *diff_data)
146+
{
147+
JsonxPointerDiff *diff;
148+
char *data;
149+
int datalen =
150+
TOAST_POINTER_SIZE + offsetof(JsonxPointerDiff, data) + diff_len;
151+
152+
struct varlena *result =
153+
jsonx_toast_make_custom_pointer(toasterid, JSONX_POINTER_DIFF,
154+
datalen, toast_pointer->va_rawsize, &data);
155+
156+
SET_VARTAG_EXTERNAL(data, VARTAG_ONDISK);
157+
memcpy(VARDATA_EXTERNAL(data), toast_pointer, sizeof(*toast_pointer));
158+
159+
diff = (JsonxPointerDiff *)(data + TOAST_POINTER_SIZE);
160+
memcpy(&diff->offset, &diff_offset, sizeof(diff_offset));
161+
memcpy(diff->data, diff_data, diff_len);
162+
163+
return result;
164+
}
165+
138166
struct varlena *
139167
jsonxMakeToastPointer(JsonbToastedContainerPointerData *ptr)
140168
{
141-
if (ptr->ntids)
169+
if (ptr->ntids || ptr->has_diff)
142170
{
143171
char *data;
144-
uint32 header = ptr->ntids | (ptr->compressed_tids ?
145-
JSONX_POINTER_DIRECT_TIDS_COMP :
146-
JSONX_POINTER_DIRECT_TIDS);
172+
uint32 header = ptr->has_diff ? JSONX_POINTER_DIFF :
173+
ptr->ntids | (ptr->compressed_tids ?
174+
JSONX_POINTER_DIRECT_TIDS_COMP :
175+
JSONX_POINTER_DIRECT_TIDS);
147176
struct varlena *custom_ptr =
148177
jsonx_toast_make_custom_pointer(ptr->toasterid, header,
149178
TOAST_POINTER_SIZE + ptr->tail_size,
@@ -175,14 +204,17 @@ jsonxMakeToastPointer(JsonbToastedContainerPointerData *ptr)
175204
void
176205
jsonxWriteToastPointer(StringInfo buffer, JsonbToastedContainerPointerData *ptr)
177206
{
178-
if (ptr->ntids)
207+
if (ptr->ntids || ptr->has_diff)
179208
{
180209
char custom_ptr[JSONX_CUSTOM_PTR_HEADER_SIZE];
181210
char toast_ptr[TOAST_POINTER_SIZE];
182-
uint32 header = ptr->ntids | (ptr->compressed_tids ?
183-
JSONX_POINTER_DIRECT_TIDS_COMP :
184-
JSONX_POINTER_DIRECT_TIDS);
211+
uint32 header = ptr->has_diff ?
212+
JSONX_POINTER_DIFF :
213+
ptr->ntids | (ptr->compressed_tids ?
214+
JSONX_POINTER_DIRECT_TIDS_COMP :
215+
JSONX_POINTER_DIRECT_TIDS);
185216

217+
Assert(ptr->has_diff ^ ptr->ntids);
186218
Assert(!ptr->compressed_chunks);
187219

188220
jsonxWriteCustomToastPointerHeader(custom_ptr, ptr->toasterid, header,
@@ -241,6 +273,7 @@ jsonxInitToastedContainerPointer(JsonbToastedContainerPointerData *jbcptr,
241273
jbcptr->ntids = ntids;
242274
jbcptr->compressed_tids = compressed_tids;
243275
jbcptr->compressed_chunks = compressed_chunks;
276+
jbcptr->has_diff = false;
244277
jbcptr->toasterid = toasterid;
245278
jbcptr->container_offset = container_offset;
246279
}
@@ -1611,13 +1644,13 @@ jsonx_create_detoast_iterator(struct varlena *attr)
16111644

16121645
if (type == JSONX_POINTER_DIFF)
16131646
{
1614-
varatt_external_diff *diff = (varatt_external_diff *) inline_data;
1647+
JsonxPointerDiff *diff = (JsonxPointerDiff *) inline_data;
16151648

16161649
iter->diff.inline_data = inline_data;
16171650
iter->diff.inline_size = inline_size;
1618-
iter->diff.size = inline_size - offsetof(varatt_external_diff, va_diff_data);
1619-
iter->diff.offset = diff->va_diff_offset;
1620-
iter->diff.data = diff->va_diff_data; /* FIXME MemoryContext */
1651+
iter->diff.size = inline_size - offsetof(JsonxPointerDiff, data);
1652+
iter->diff.offset = diff->offset;
1653+
iter->diff.data = diff->data; /* FIXME MemoryContext */
16211654
}
16221655

16231656
return iter;
@@ -1726,12 +1759,12 @@ toast_apply_diff(struct varlena *attr, struct varlena *result,
17261759
if (VARATT_IS_EXTERNAL_ONDISK_INLINE_DIFF(attr))
17271760
{
17281761
struct varatt_external_versioned toast_pointer;
1729-
struct varatt_external_diff diff;
1762+
struct JsonxPointerDiff diff;
17301763
const char *inline_data = VARDATA_EXTERNAL_INLINE(attr);
17311764
/* Must copy to access aligned fields */
17321765
int32 inline_size = VARATT_EXTERNAL_INLINE_GET_POINTER(toast_pointer, attr);
17331766
int32 attrsize = VARATT_EXTERNAL_GET_EXTSIZE(toast_pointer.va_external);
1734-
Size data_offset = offsetof(varatt_external_diff, va_diff_data);
1767+
Size data_offset = offsetof(JsonxPointerDiff, data);
17351768
Size diff_size = inline_size - data_offset;
17361769
const char *diff_data = inline_data + data_offset;
17371770

@@ -1741,7 +1774,7 @@ toast_apply_diff(struct varlena *attr, struct varlena *result,
17411774
slicelength = attrsize - sliceoffset;
17421775

17431776
toast_apply_diff_internal(result, diff_data,
1744-
diff.va_diff_offset, diff_size,
1777+
diff.offset, diff_size,
17451778
sliceoffset, slicelength);
17461779
}
17471780
}

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