1919#include "access/heaptoast.h"
2020#include "access/table.h"
2121#include "access/toast_internals.h"
22+ #include "access/generic_toaster.h"
2223#include "catalog/toasting.h"
2324#include "access/xact.h"
2425#include "catalog/catalog.h"
@@ -165,9 +166,22 @@ toast_save_datum_ext(Relation rel, Oid toasterid, Datum value,
165166 {
166167 struct varatt_external old_toast_pointer ;
167168
168- Assert (VARATT_IS_EXTERNAL_ONDISK (oldexternal ));
169+ /* New case - Generic TOAST working with Custom pointer */
170+ if (VARATT_IS_CUSTOM (oldexternal ))
171+ {
172+ ExternalToastData data ;
173+ VARATT_CUSTOM_GET_EXTERNAL_DATA (PointerGetDatum (oldexternal ), data );
174+ old_toast_pointer .va_toastrelid = get_uint32align16 (& data .va_toastrelid );
175+ old_toast_pointer .va_valueid = get_uint32align16 (& data .va_valueid );
176+ }
177+ else
178+ {
179+ Assert (VARATT_IS_EXTERNAL_ONDISK (oldexternal ));
180+ VARATT_EXTERNAL_GET_POINTER (old_toast_pointer , oldexternal );
181+ }
169182 /* Must copy to access aligned fields */
170- VARATT_EXTERNAL_GET_POINTER (old_toast_pointer , oldexternal );
183+ /* VARATT_EXTERNAL_GET_POINTER(old_toast_pointer, oldexternal); */
184+ /* XXX if (old_toast_pointer.va_toastrelid == rel->rd_toastoid) */
171185 if (old_toast_pointer .va_toastrelid == real_toastrelid )
172186 {
173187 /* This value came from the old toast table; reuse its OID */
@@ -265,17 +279,34 @@ toast_delete_datum(Datum value, bool is_speculative)
265279 int num_indexes ;
266280 int validIndex ;
267281 SnapshotData SnapshotToast ;
282+ ExternalToastData data ;
283+ Oid va_toastrelid ;
284+ Oid va_valueid ;
268285
269- if (!VARATT_IS_EXTERNAL_ONDISK (attr ))
286+ if (!VARATT_IS_EXTERNAL_ONDISK (attr ) && ! VARATT_IS_CUSTOM ( attr ) )
270287 return ;
271288
272289 /* Must copy to access aligned fields */
273- VARATT_EXTERNAL_GET_POINTER (toast_pointer , attr );
290+ if (VARATT_IS_CUSTOM (attr ))
291+ {
292+ /* process custom Toast Pointer */
293+ VARATT_CUSTOM_GET_EXTERNAL_DATA (attr , data );
294+
295+ va_toastrelid = get_uint32align16 (& data .va_toastrelid );
296+ va_valueid = get_uint32align16 (& data .va_valueid );
297+ }
298+ else
299+ {
300+ VARATT_EXTERNAL_GET_POINTER (toast_pointer , attr );
301+
302+ va_toastrelid = toast_pointer .va_toastrelid ;
303+ va_valueid = toast_pointer .va_valueid ;
304+ }
274305
275306 /*
276307 * Open the toast relation and its indexes
277308 */
278- toastrel = table_open (toast_pointer . va_toastrelid , RowExclusiveLock );
309+ toastrel = table_open (va_toastrelid , RowExclusiveLock );
279310
280311 /* Fetch valid relation used for process */
281312 validIndex = toast_open_indexes (toastrel ,
@@ -289,7 +320,7 @@ toast_delete_datum(Datum value, bool is_speculative)
289320 ScanKeyInit (& toastkey ,
290321 (AttrNumber ) 1 ,
291322 BTEqualStrategyNumber , F_OIDEQ ,
292- ObjectIdGetDatum (toast_pointer . va_valueid ));
323+ ObjectIdGetDatum (va_valueid ));
293324
294325 /*
295326 * Find all the chunks. (We don't actually care whether we see them in
@@ -405,19 +436,43 @@ toast_fetch_datum(struct varlena *attr)
405436 Relation toastrel ;
406437 struct varlena * result ;
407438 struct varatt_external toast_pointer ;
439+ ExternalToastData data ;
440+ Oid va_toastrelid ;
441+ Oid va_valueid ;
408442 int32 attrsize ;
443+ bool is_compressed = false;
409444
410- if (!VARATT_IS_EXTERNAL_ONDISK (attr ))
411- elog (ERROR , "toast_fetch_datum shouldn't be called for non-ondisk datums" );
445+ if (!VARATT_IS_EXTERNAL_ONDISK (attr ) && ! VARATT_IS_CUSTOM ( attr ) )
446+ elog (ERROR , "toast_fetch_datum_slice shouldn't be called for non-ondisk or non-custom datums" );
412447
413448 /* Must copy to access aligned fields */
414- VARATT_EXTERNAL_GET_POINTER (toast_pointer , attr );
449+ if (VARATT_IS_CUSTOM (attr ))
450+ {
451+ /* process custom Toast Pointer */
452+ VARATT_CUSTOM_GET_EXTERNAL_DATA (attr , data );
453+
454+ attrsize = get_uint32align16 (& data .va_extinfo );
455+ va_toastrelid = get_uint32align16 (& data .va_toastrelid );
456+ va_valueid = get_uint32align16 (& data .va_valueid );
457+
458+ if (VARATT_CUSTOM_EXTERNAL_IS_COMPRESSED (attr , attrsize ))
459+ is_compressed = true;
460+ }
461+ else
462+ {
463+ VARATT_EXTERNAL_GET_POINTER (toast_pointer , attr );
415464
416- attrsize = VARATT_EXTERNAL_GET_EXTSIZE (toast_pointer );
465+ va_toastrelid = toast_pointer .va_toastrelid ;
466+ va_valueid = toast_pointer .va_valueid ;
467+
468+ attrsize = VARATT_EXTERNAL_GET_EXTSIZE (toast_pointer );
469+ if (VARATT_EXTERNAL_IS_COMPRESSED (toast_pointer ))
470+ is_compressed = true;
471+ }
417472
418473 result = (struct varlena * ) palloc (attrsize + VARHDRSZ );
419474
420- if (VARATT_EXTERNAL_IS_COMPRESSED ( toast_pointer ) )
475+ if (is_compressed )
421476 SET_VARSIZE_COMPRESSED (result , attrsize + VARHDRSZ );
422477 else
423478 SET_VARSIZE (result , attrsize + VARHDRSZ );
@@ -429,10 +484,10 @@ toast_fetch_datum(struct varlena *attr)
429484 /*
430485 * Open the toast relation and its indexes
431486 */
432- toastrel = table_open (toast_pointer . va_toastrelid , AccessShareLock );
487+ toastrel = table_open (va_toastrelid , AccessShareLock );
433488
434489 /* Fetch all chunks */
435- toast_fetch_toast_slice (toastrel , toast_pointer . va_valueid ,
490+ toast_fetch_toast_slice (toastrel , va_valueid ,
436491 attr , attrsize , 0 , attrsize , result , 0 ,
437492 NULL , NULL );
438493
@@ -460,22 +515,47 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
460515 Relation toastrel ;
461516 struct varlena * result ;
462517 struct varatt_external toast_pointer ;
518+ ExternalToastData data ;
519+ Oid va_toastrelid ;
520+ Oid va_valueid ;
463521 int32 attrsize ;
522+ bool is_compressed = false;
464523
465- if (!VARATT_IS_EXTERNAL_ONDISK (attr ))
466- elog (ERROR , "toast_fetch_datum_slice shouldn't be called for non-ondisk datums" );
524+ if (!( VARATT_IS_EXTERNAL_ONDISK (attr ) || VARATT_IS_CUSTOM ( attr ) ))
525+ elog (ERROR , "toast_fetch_datum_slice shouldn't be called for non-ondisk or non-custom datums" );
467526
468527 /* Must copy to access aligned fields */
469- VARATT_EXTERNAL_GET_POINTER (toast_pointer , attr );
528+ if (VARATT_IS_CUSTOM (attr ))
529+ {
530+ /* process custom Toast Pointer */
531+ VARATT_CUSTOM_GET_EXTERNAL_DATA (attr , data );
470532
471- /*
472- * It's nonsense to fetch slices of a compressed datum unless when it's a
473- * prefix -- this isn't lo_* we can't return a compressed datum which is
474- * meaningful to toast later.
475- */
476- Assert (!VARATT_EXTERNAL_IS_COMPRESSED (toast_pointer ) || 0 == sliceoffset );
533+ attrsize = get_uint32align16 (& data .va_extinfo );
534+ va_toastrelid = get_uint32align16 (& data .va_toastrelid );
535+ va_valueid = get_uint32align16 (& data .va_valueid );
536+
537+ if (VARATT_CUSTOM_EXTERNAL_IS_COMPRESSED (attr , attrsize ) && slicelength > 0 )
538+ is_compressed = true;
539+ }
540+ else
541+ {
542+ VARATT_EXTERNAL_GET_POINTER (toast_pointer , attr );
543+
544+ va_toastrelid = toast_pointer .va_toastrelid ;
545+ va_valueid = toast_pointer .va_valueid ;
546+
547+ /*
548+ * It's nonsense to fetch slices of a compressed datum unless when it's a
549+ * prefix -- this isn't lo_* we can't return a compressed datum which is
550+ * meaningful to toast later.
551+ */
552+ Assert (!VARATT_EXTERNAL_IS_COMPRESSED (toast_pointer ) || 0 == sliceoffset );
553+
554+ attrsize = VARATT_EXTERNAL_GET_EXTSIZE (toast_pointer );
555+ if (VARATT_EXTERNAL_IS_COMPRESSED (toast_pointer ) && slicelength > 0 )
556+ is_compressed = true;
557+ }
477558
478- attrsize = VARATT_EXTERNAL_GET_EXTSIZE (toast_pointer );
479559
480560 if (sliceoffset >= attrsize )
481561 {
@@ -488,7 +568,8 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
488568 * space required by va_tcinfo, which is stored at the beginning as an
489569 * int32 value.
490570 */
491- if (VARATT_EXTERNAL_IS_COMPRESSED (toast_pointer ) && slicelength > 0 )
571+ /* if (VARATT_EXTERNAL_IS_COMPRESSED(toast_pointer) && slicelength > 0) */
572+ if (is_compressed )
492573 slicelength = slicelength + sizeof (int32 );
493574
494575 /*
@@ -501,7 +582,7 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
501582
502583 result = (struct varlena * ) palloc (slicelength + VARHDRSZ );
503584
504- if ( VARATT_EXTERNAL_IS_COMPRESSED ( toast_pointer ) )
585+ if ( is_compressed )
505586 SET_VARSIZE_COMPRESSED (result , slicelength + VARHDRSZ );
506587 else
507588 SET_VARSIZE (result , slicelength + VARHDRSZ );
@@ -510,10 +591,10 @@ toast_fetch_datum_slice(struct varlena *attr, int32 sliceoffset,
510591 return result ; /* Can save a lot of work at this point! */
511592
512593 /* Open the toast relation */
513- toastrel = table_open (toast_pointer . va_toastrelid , AccessShareLock );
594+ toastrel = table_open (va_toastrelid , AccessShareLock );
514595
515596 /* Fetch all chunks */
516- toast_fetch_toast_slice (toastrel , toast_pointer . va_valueid ,
597+ toast_fetch_toast_slice (toastrel , va_valueid ,
517598 attr , attrsize , sliceoffset , slicelength ,
518599 result , 0 , NULL , NULL );
519600
0 commit comments