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-
4439char *
4540jsonxWriteCustomToastPointerHeader (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+
138166struct varlena *
139167jsonxMakeToastPointer (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)
175204void
176205jsonxWriteToastPointer (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