PostgreSQL Source Code: src/backend/access/heap/heaptoast.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
26
33#include "utils/fmgroids.h"
34
35
36
37
38
39
40
41
42void
44{
48
49
50
51
52
53 Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
54 rel->rd_rel->relkind == RELKIND_MATVIEW);
55
56
57
58
59
60
61
62
63
64
65
66
67 tupleDesc = rel->rd_att;
68
71
72
74}
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
98{
101 int numAttrs;
102
103 Size maxDataLen;
105
112
113
114
115
116
117
118
119 options &= ~HEAP_INSERT_SPECULATIVE;
120
121
122
123
124
125 Assert(rel->rd_rel->relkind == RELKIND_RELATION ||
126 rel->rd_rel->relkind == RELKIND_MATVIEW);
127
128
129
130
131 tupleDesc = rel->rd_att;
132 numAttrs = tupleDesc->natts;
133
135 heap_deform_tuple(newtup, tupleDesc, toast_values, toast_isnull);
136 if (oldtup != NULL)
137 heap_deform_tuple(oldtup, tupleDesc, toast_oldvalues, toast_oldisnull);
138
139
140
141
142
146 if (oldtup == NULL)
147 {
150 }
151 else
152 {
155 }
158
159
160
161
162
163
164
165
166
167
168
169
170
171
176
178
179
180
181
182
183
185 toast_values, toast_isnull) > maxDataLen)
186 {
187 int biggest_attno;
188
190 if (biggest_attno < 0)
191 break;
192
193
194
195
198 else
199 {
200
201
202
203
205 }
206
207
208
209
210
211
212
213
214
215 if (toast_attr[biggest_attno].tai_size > maxDataLen &&
218 }
219
220
221
222
223
224
226 toast_values, toast_isnull) > maxDataLen &&
228 {
229 int biggest_attno;
230
232 if (biggest_attno < 0)
233 break;
235 }
236
237
238
239
240
242 toast_values, toast_isnull) > maxDataLen)
243 {
244 int biggest_attno;
245
247 if (biggest_attno < 0)
248 break;
249
251 }
252
253
254
255
256
257
259
261 toast_values, toast_isnull) > maxDataLen &&
263 {
264 int biggest_attno;
265
267 if (biggest_attno < 0)
268 break;
269
271 }
272
273
274
275
276
278 {
281 int32 new_header_len;
282 int32 new_data_len;
283 int32 new_tuple_len;
284
285
286
287
288
289
290
291
292
293
294
297 new_header_len += BITMAPLEN(numAttrs);
298 new_header_len = MAXALIGN(new_header_len);
300 toast_values, toast_isnull);
301 new_tuple_len = new_header_len + new_data_len;
302
303
304
305
307 result_tuple->t_len = new_tuple_len;
311 result_tuple->t_data = new_data;
312
313
314
315
318 new_data->t_hoff = new_header_len;
319
320
322 toast_values,
323 toast_isnull,
324 (char *) new_data + new_header_len,
325 new_data_len,
328 new_data->t_bits : NULL);
329 }
330 else
331 result_tuple = newtup;
332
334
335 return result_tuple;
336}
337
338
339
340
341
342
343
344
345
346
347
348
351{
353 int numAttrs = tupleDesc->natts;
354 int i;
358
359
360
361
364
365 memset(toast_free, 0, numAttrs * sizeof(bool));
366
367 for (i = 0; i < numAttrs; i++)
368 {
369
370
371
373 {
374 struct varlena *new_value;
375
378 {
381 toast_free[i] = true;
382 }
383 }
384 }
385
386
387
388
389 new_tuple = heap_form_tuple(tupleDesc, toast_values, toast_isnull);
390
391
392
393
394
395
398
407
408
409
410
411 for (i = 0; i < numAttrs; i++)
412 if (toast_free[i])
414
415 return new_tuple;
416}
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
452{
454 int32 new_header_len;
455 int32 new_data_len;
456 int32 new_tuple_len;
458 int numAttrs = tupleDesc->natts;
459 int i;
460 bool has_nulls = false;
464
465
466 tmptup.t_len = tup_len;
470
471
472
473
475 heap_deform_tuple(&tmptup, tupleDesc, toast_values, toast_isnull);
476
477 memset(toast_free, 0, numAttrs * sizeof(bool));
478
479 for (i = 0; i < numAttrs; i++)
480 {
481
482
483
484 if (toast_isnull[i])
485 has_nulls = true;
487 {
488 struct varlena *new_value;
489
493 {
496 toast_free[i] = true;
497 }
498 }
499 }
500
501
502
503
504
505
506
508 if (has_nulls)
509 new_header_len += BITMAPLEN(numAttrs);
510 new_header_len = MAXALIGN(new_header_len);
512 toast_values, toast_isnull);
513 new_tuple_len = new_header_len + new_data_len;
514
516
517
518
519
522 new_data->t_hoff = new_header_len;
523
524
528
529
531 toast_values,
532 toast_isnull,
533 (char *) new_data + new_header_len,
534 new_data_len,
536 has_nulls ? new_data->t_bits : NULL);
537
538
539
540
541 for (i = 0; i < numAttrs; i++)
542 if (toast_free[i])
544
546}
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
565 bool *isnull)
566{
568 int numAttrs = tupleDesc->natts;
569 int num_to_free;
570 int i;
573
574
575
576
577
579 memcpy(new_values, values, numAttrs * sizeof(Datum));
580
581 num_to_free = 0;
582 for (i = 0; i < numAttrs; i++)
583 {
584
585
586
588 {
589 struct varlena *new_value;
590
593 {
596 freeable_values[num_to_free++] = (Pointer) new_value;
597 }
598 }
599 }
600
601
602
603
604 new_tuple = heap_form_tuple(tupleDesc, new_values, isnull);
605
606
607
608
609 for (i = 0; i < num_to_free; i++)
610 pfree(freeable_values[i]);
611
612 return new_tuple;
613}
614
615
616
617
618
619
620
621
622
623
624
625void
627 int32 sliceoffset, int32 slicelength,
629{
633 int nscankeys;
636 int32 expectedchunk;
638 int startchunk;
639 int endchunk;
640 int num_indexes;
641 int validIndex;
642
643
646 &toastidxs,
647 &num_indexes);
648
651 Assert(endchunk <= totalchunks);
652
653
658
659
660
661
662
663 if (startchunk == 0 && endchunk == totalchunks - 1)
664 nscankeys = 1;
665 else if (startchunk == endchunk)
666 {
671 nscankeys = 2;
672 }
673 else
674 {
683 nscankeys = 3;
684 }
685
686
689
690
691
692
693
694
695 expectedchunk = startchunk;
697 {
700 bool isnull;
701 char *chunkdata;
703 int32 expected_size;
706
707
708
709
715 {
717 chunkdata = VARDATA(chunk);
718 }
720 {
721
724 }
725 else
726 {
727
728 elog(ERROR, "found toasted toast chunk for toast value %u in %s",
730 chunksize = 0;
731 chunkdata = NULL;
732 }
733
734
735
736
737 if (curchunk != expectedchunk)
740 errmsg_internal("unexpected chunk number %d (expected %d) for toast value %u in %s",
741 curchunk, expectedchunk, valueid,
743 if (curchunk > endchunk)
746 errmsg_internal("unexpected chunk number %d (out of range %d..%d) for toast value %u in %s",
747 curchunk,
748 startchunk, endchunk, valueid,
752 if (chunksize != expected_size)
755 errmsg_internal("unexpected chunk size %d (expected %d) in chunk %d of %d for toast value %u in %s",
756 chunksize, expected_size,
757 curchunk, totalchunks, valueid,
759
760
761
762
763 chcpystrt = 0;
764 chcpyend = chunksize - 1;
765 if (curchunk == startchunk)
767 if (curchunk == endchunk)
769
772 chunkdata + chcpystrt,
773 (chcpyend - chcpystrt) + 1);
774
775 expectedchunk++;
776 }
777
778
779
780
781 if (expectedchunk != (endchunk + 1))
784 errmsg_internal("missing chunk number %d for toast value %u in %s",
785 expectedchunk, valueid,
787
788
791}
static Datum values[MAXATTR]
struct varlena * detoast_attr(struct varlena *attr)
struct varlena * detoast_external_attr(struct varlena *attr)
int errmsg_internal(const char *fmt,...)
int errcode(int sqlerrcode)
#define ereport(elevel,...)
SysScanDesc systable_beginscan_ordered(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key)
void systable_endscan_ordered(SysScanDesc sysscan)
HeapTuple systable_getnext_ordered(SysScanDesc sysscan, ScanDirection direction)
Assert(PointerIsAligned(start, uint64))
void heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize, int32 sliceoffset, int32 slicelength, struct varlena *result)
void heap_toast_delete(Relation rel, HeapTuple oldtup, bool is_speculative)
HeapTuple heap_toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, int options)
HeapTuple toast_build_flattened_tuple(TupleDesc tupleDesc, Datum *values, bool *isnull)
HeapTuple toast_flatten_tuple(HeapTuple tup, TupleDesc tupleDesc)
Datum toast_flatten_tuple_to_datum(HeapTupleHeader tup, uint32 tup_len, TupleDesc tupleDesc)
#define TOAST_TUPLE_TARGET
#define TOAST_TUPLE_TARGET_MAIN
#define TOAST_MAX_CHUNK_SIZE
Size heap_compute_data_size(TupleDesc tupleDesc, const Datum *values, const bool *isnull)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_fill_tuple(TupleDesc tupleDesc, const Datum *values, const bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
HeapTupleData * HeapTuple
HeapTupleHeaderData * HeapTupleHeader
#define SizeofHeapTupleHeader
static void HeapTupleHeaderSetTypMod(HeapTupleHeaderData *tup, int32 typmod)
static int BITMAPLEN(int NATTS)
static void HeapTupleHeaderSetTypeId(HeapTupleHeaderData *tup, Oid datum_typeid)
#define MaxTupleAttributeNumber
static void HeapTupleHeaderSetDatumLength(HeapTupleHeaderData *tup, uint32 len)
#define HeapTupleHeaderSetNatts(tup, natts)
#define MaxHeapAttributeNumber
static Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
static void ItemPointerSetInvalid(ItemPointerData *pointer)
void pfree(void *pointer)
void * palloc0(Size size)
#define ERRCODE_DATA_CORRUPTED
static Datum PointerGetDatum(const void *X)
static Datum ObjectIdGetDatum(Oid X)
static Pointer DatumGetPointer(Datum X)
static Datum Int32GetDatum(int32 X)
static int32 DatumGetInt32(Datum X)
#define RelationGetRelationName(relation)
#define RelationGetToastTupleTarget(relation, defaulttarg)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
#define BTEqualStrategyNumber
#define BTLessEqualStrategyNumber
#define BTGreaterEqualStrategyNumber
void toast_tuple_init(ToastTupleContext *ttc)
void toast_delete_external(Relation rel, const Datum *values, const bool *isnull, bool is_speculative)
void toast_tuple_try_compression(ToastTupleContext *ttc, int attribute)
void toast_tuple_externalize(ToastTupleContext *ttc, int attribute, int options)
void toast_tuple_cleanup(ToastTupleContext *ttc)
int toast_tuple_find_biggest_attribute(ToastTupleContext *ttc, bool for_compression, bool check_main)
#define TOAST_NEEDS_CHANGE
#define TOASTCOL_INCOMPRESSIBLE
void toast_close_indexes(Relation *toastidxs, int num_indexes, LOCKMODE lock)
int toast_open_indexes(Relation toastrel, LOCKMODE lock, Relation **toastidxs, int *num_indexes)
Snapshot get_toast_snapshot(void)
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
#define VARSIZE_SHORT(PTR)
#define VARATT_IS_EXTENDED(PTR)
#define VARATT_IS_SHORT(PTR)
#define VARATT_IS_COMPRESSED(PTR)
#define VARATT_IS_EXTERNAL(PTR)
#define VARDATA_SHORT(PTR)