@@ -312,6 +312,111 @@ detoast_attr_slice(struct varlena *attr,
312
312
return result ;
313
313
}
314
314
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
+
315
420
/* ----------
316
421
* toast_fetch_datum -
317
422
*
0 commit comments