PostgreSQL Source Code git master
brin_tuple.c
Go to the documentation of this file.
1/*
2 * brin_tuple.c
3 * Method implementations for tuples in BRIN indexes.
4 *
5 * Intended usage is that code outside this file only deals with
6 * BrinMemTuples, and convert to and from the on-disk representation through
7 * functions in this file.
8 *
9 * NOTES
10 *
11 * A BRIN tuple is similar to a heap tuple, with a few key differences. The
12 * first interesting difference is that the tuple header is much simpler, only
13 * containing its total length and a small area for flags. Also, the stored
14 * data does not match the relation tuple descriptor exactly: for each
15 * attribute in the descriptor, the index tuple carries an arbitrary number
16 * of values, depending on the opclass.
17 *
18 * Also, for each column of the index relation there are two null bits: one
19 * (hasnulls) stores whether any tuple within the page range has that column
20 * set to null; the other one (allnulls) stores whether the column values are
21 * all null. If allnulls is true, then the tuple data area does not contain
22 * values for that column at all; whereas it does if the hasnulls is set.
23 * Note the size of the null bitmask may not be the same as that of the
24 * datum array.
25 *
26 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
27 * Portions Copyright (c) 1994, Regents of the University of California
28 *
29 * IDENTIFICATION
30 * src/backend/access/brin/brin_tuple.c
31 */
32#include "postgres.h"
33
34#include "access/brin_tuple.h"
35#include "access/detoast.h"
36#include "access/heaptoast.h"
37#include "access/htup_details.h"
39#include "access/tupdesc.h"
40#include "access/tupmacs.h"
41#include "utils/datum.h"
42#include "utils/memutils.h"
43
44
45/*
46 * This enables de-toasting of index entries. Needed until VACUUM is
47 * smart enough to rebuild indexes from scratch.
48 */
49#define TOAST_INDEX_HACK
50
51
52static inline void brin_deconstruct_tuple(BrinDesc *brdesc,
53 char *tp, bits8 *nullbits, bool nulls,
54 Datum *values, bool *allnulls, bool *hasnulls);
55
56
57/*
58 * Return a tuple descriptor used for on-disk storage of BRIN tuples.
59 */
60static TupleDesc
62{
63 /* We cache these in the BrinDesc */
64 if (brdesc->bd_disktdesc == NULL)
65 {
66 int i;
67 int j;
68 AttrNumber attno = 1;
69 TupleDesc tupdesc;
70 MemoryContext oldcxt;
71
72 /* make sure it's in the bdesc's context */
73 oldcxt = MemoryContextSwitchTo(brdesc->bd_context);
74
75 tupdesc = CreateTemplateTupleDesc(brdesc->bd_totalstored);
76
77 for (i = 0; i < brdesc->bd_tupdesc->natts; i++)
78 {
79 for (j = 0; j < brdesc->bd_info[i]->oi_nstored; j++)
80 TupleDescInitEntry(tupdesc, attno++, NULL,
81 brdesc->bd_info[i]->oi_typcache[j]->type_id,
82 -1, 0);
83 }
84
86
87 brdesc->bd_disktdesc = tupdesc;
88 }
89
90 return brdesc->bd_disktdesc;
91}
92
93/*
94 * Generate a new on-disk tuple to be inserted in a BRIN index.
95 *
96 * See brin_form_placeholder_tuple if you touch this.
97 */
100 Size *size)
101{
102 Datum *values;
103 bool *nulls;
104 bool anynulls = false;
105 BrinTuple *rettuple;
106 int keyno;
107 int idxattno;
108 uint16 phony_infomask = 0;
109 bits8 *phony_nullbitmap;
110 Size len,
111 hoff,
112 data_len;
113 int i;
114
115#ifdef TOAST_INDEX_HACK
116 Datum *untoasted_values;
117 int nuntoasted = 0;
118#endif
119
120 Assert(brdesc->bd_totalstored > 0);
121
123 nulls = palloc0_array(bool, brdesc->bd_totalstored);
124 phony_nullbitmap = palloc_array(bits8, BITMAPLEN(brdesc->bd_totalstored));
125
126#ifdef TOAST_INDEX_HACK
127 untoasted_values = palloc_array(Datum, brdesc->bd_totalstored);
128#endif
129
130 /*
131 * Set up the values/nulls arrays for heap_fill_tuple
132 */
133 idxattno = 0;
134 for (keyno = 0; keyno < brdesc->bd_tupdesc->natts; keyno++)
135 {
136 int datumno;
137
138 /*
139 * "allnulls" is set when there's no nonnull value in any row in the
140 * column; when this happens, there is no data to store. Thus set the
141 * nullable bits for all data elements of this column and we're done.
142 */
143 if (tuple->bt_columns[keyno].bv_allnulls)
144 {
145 for (datumno = 0;
146 datumno < brdesc->bd_info[keyno]->oi_nstored;
147 datumno++)
148 nulls[idxattno++] = true;
149 anynulls = true;
150 continue;
151 }
152
153 /*
154 * The "hasnulls" bit is set when there are some null values in the
155 * data. We still need to store a real value, but the presence of
156 * this means we need a null bitmap.
157 */
158 if (tuple->bt_columns[keyno].bv_hasnulls)
159 anynulls = true;
160
161 /* If needed, serialize the values before forming the on-disk tuple. */
162 if (tuple->bt_columns[keyno].bv_serialize)
163 {
164 tuple->bt_columns[keyno].bv_serialize(brdesc,
165 tuple->bt_columns[keyno].bv_mem_value,
166 tuple->bt_columns[keyno].bv_values);
167 }
168
169 /*
170 * Now obtain the values of each stored datum. Note that some values
171 * might be toasted, and we cannot rely on the original heap values
172 * sticking around forever, so we must detoast them. Also try to
173 * compress them.
174 */
175 for (datumno = 0;
176 datumno < brdesc->bd_info[keyno]->oi_nstored;
177 datumno++)
178 {
179 Datum value = tuple->bt_columns[keyno].bv_values[datumno];
180
181#ifdef TOAST_INDEX_HACK
182
183 /* We must look at the stored type, not at the index descriptor. */
184 TypeCacheEntry *atttype = brdesc->bd_info[keyno]->oi_typcache[datumno];
185
186 /* Do we need to free the value at the end? */
187 bool free_value = false;
188
189 /* For non-varlena types we don't need to do anything special */
190 if (atttype->typlen != -1)
191 {
192 values[idxattno++] = value;
193 continue;
194 }
195
196 /*
197 * Do nothing if value is not of varlena type. We don't need to
198 * care about NULL values here, thanks to bv_allnulls above.
199 *
200 * If value is stored EXTERNAL, must fetch it so we are not
201 * depending on outside storage.
202 *
203 * XXX Is this actually true? Could it be that the summary is NULL
204 * even for range with non-NULL data? E.g. degenerate bloom filter
205 * may be thrown away, etc.
206 */
208 {
211 free_value = true;
212 }
213
214 /*
215 * If value is above size target, and is of a compressible
216 * datatype, try to compress it in-line.
217 */
220 (atttype->typstorage == TYPSTORAGE_EXTENDED ||
221 atttype->typstorage == TYPSTORAGE_MAIN))
222 {
223 Datum cvalue;
224 char compression;
226 keyno);
227
228 /*
229 * If the BRIN summary and indexed attribute use the same data
230 * type and it has a valid compression method, we can use the
231 * same compression method. Otherwise we have to use the
232 * default method.
233 */
234 if (att->atttypid == atttype->type_id)
235 compression = att->attcompression;
236 else
237 compression = InvalidCompressionMethod;
238
239 cvalue = toast_compress_datum(value, compression);
240
241 if (DatumGetPointer(cvalue) != NULL)
242 {
243 /* successful compression */
244 if (free_value)
246
247 value = cvalue;
248 free_value = true;
249 }
250 }
251
252 /*
253 * If we untoasted / compressed the value, we need to free it
254 * after forming the index tuple.
255 */
256 if (free_value)
257 untoasted_values[nuntoasted++] = value;
258
259#endif
260
261 values[idxattno++] = value;
262 }
263 }
264
265 /* Assert we did not overrun temp arrays */
266 Assert(idxattno <= brdesc->bd_totalstored);
267
268 /* compute total space needed */
270 if (anynulls)
271 {
272 /*
273 * We need a double-length bitmap on an on-disk BRIN index tuple; the
274 * first half stores the "allnulls" bits, the second stores
275 * "hasnulls".
276 */
277 len += BITMAPLEN(brdesc->bd_tupdesc->natts * 2);
278 }
279
280 len = hoff = MAXALIGN(len);
281
283 values, nulls);
284 len += data_len;
285
286 len = MAXALIGN(len);
287
288 rettuple = palloc0(len);
289 rettuple->bt_blkno = blkno;
290 rettuple->bt_info = hoff;
291
292 /* Assert that hoff fits in the space available */
293 Assert((rettuple->bt_info & BRIN_OFFSET_MASK) == hoff);
294
295 /*
296 * The infomask and null bitmap as computed by heap_fill_tuple are useless
297 * to us. However, that function will not accept a null infomask; and we
298 * need to pass a valid null bitmap so that it will correctly skip
299 * outputting null attributes in the data area.
300 */
302 values,
303 nulls,
304 (char *) rettuple + hoff,
305 data_len,
306 &phony_infomask,
307 phony_nullbitmap);
308
309 /* done with these */
310 pfree(values);
311 pfree(nulls);
312 pfree(phony_nullbitmap);
313
314#ifdef TOAST_INDEX_HACK
315 for (i = 0; i < nuntoasted; i++)
316 pfree(DatumGetPointer(untoasted_values[i]));
317#endif
318
319 /*
320 * Now fill in the real null bitmasks. allnulls first.
321 */
322 if (anynulls)
323 {
324 bits8 *bitP;
325 int bitmask;
326
327 rettuple->bt_info |= BRIN_NULLS_MASK;
328
329 /*
330 * Note that we reverse the sense of null bits in this module: we
331 * store a 1 for a null attribute rather than a 0. So we must reverse
332 * the sense of the att_isnull test in brin_deconstruct_tuple as well.
333 */
334 bitP = ((bits8 *) ((char *) rettuple + SizeOfBrinTuple)) - 1;
335 bitmask = HIGHBIT;
336 for (keyno = 0; keyno < brdesc->bd_tupdesc->natts; keyno++)
337 {
338 if (bitmask != HIGHBIT)
339 bitmask <<= 1;
340 else
341 {
342 bitP += 1;
343 *bitP = 0x0;
344 bitmask = 1;
345 }
346
347 if (!tuple->bt_columns[keyno].bv_allnulls)
348 continue;
349
350 *bitP |= bitmask;
351 }
352 /* hasnulls bits follow */
353 for (keyno = 0; keyno < brdesc->bd_tupdesc->natts; keyno++)
354 {
355 if (bitmask != HIGHBIT)
356 bitmask <<= 1;
357 else
358 {
359 bitP += 1;
360 *bitP = 0x0;
361 bitmask = 1;
362 }
363
364 if (!tuple->bt_columns[keyno].bv_hasnulls)
365 continue;
366
367 *bitP |= bitmask;
368 }
369 }
370
371 if (tuple->bt_placeholder)
372 rettuple->bt_info |= BRIN_PLACEHOLDER_MASK;
373
374 if (tuple->bt_empty_range)
375 rettuple->bt_info |= BRIN_EMPTY_RANGE_MASK;
376
377 *size = len;
378 return rettuple;
379}
380
381/*
382 * Generate a new on-disk tuple with no data values, marked as placeholder.
383 *
384 * This is a cut-down version of brin_form_tuple.
385 */
386BrinTuple *
388{
389 Size len;
390 Size hoff;
391 BrinTuple *rettuple;
392 int keyno;
393 bits8 *bitP;
394 int bitmask;
395
396 /* compute total space needed: always add nulls */
398 len += BITMAPLEN(brdesc->bd_tupdesc->natts * 2);
399 len = hoff = MAXALIGN(len);
400
401 rettuple = palloc0(len);
402 rettuple->bt_blkno = blkno;
403 rettuple->bt_info = hoff;
405
406 bitP = ((bits8 *) ((char *) rettuple + SizeOfBrinTuple)) - 1;
407 bitmask = HIGHBIT;
408 /* set allnulls true for all attributes */
409 for (keyno = 0; keyno < brdesc->bd_tupdesc->natts; keyno++)
410 {
411 if (bitmask != HIGHBIT)
412 bitmask <<= 1;
413 else
414 {
415 bitP += 1;
416 *bitP = 0x0;
417 bitmask = 1;
418 }
419
420 *bitP |= bitmask;
421 }
422 /* no need to set hasnulls */
423
424 *size = len;
425 return rettuple;
426}
427
428/*
429 * Free a tuple created by brin_form_tuple
430 */
431void
433{
434 pfree(tuple);
435}
436
437/*
438 * Given a brin tuple of size len, create a copy of it. If 'dest' is not
439 * NULL, its size is destsz, and can be used as output buffer; if the tuple
440 * to be copied does not fit, it is enlarged by repalloc, and the size is
441 * updated to match. This avoids palloc/free cycles when many brin tuples
442 * are being processed in loops.
443 */
444BrinTuple *
446{
447 if (!destsz || *destsz == 0)
448 dest = palloc(len);
449 else if (len > *destsz)
450 {
451 dest = repalloc(dest, len);
452 *destsz = len;
453 }
454
455 memcpy(dest, tuple, len);
456
457 return dest;
458}
459
460/*
461 * Return whether two BrinTuples are bitwise identical.
462 */
463bool
464brin_tuples_equal(const BrinTuple *a, Size alen, const BrinTuple *b, Size blen)
465{
466 if (alen != blen)
467 return false;
468 if (memcmp(a, b, alen) != 0)
469 return false;
470 return true;
471}
472
473/*
474 * Create a new BrinMemTuple from scratch, and initialize it to an empty
475 * state.
476 *
477 * Note: we don't provide any means to free a deformed tuple, so make sure to
478 * use a temporary memory context.
479 */
482{
483 BrinMemTuple *dtup;
484 long basesize;
485
486 basesize = MAXALIGN(sizeof(BrinMemTuple) +
487 sizeof(BrinValues) * brdesc->bd_tupdesc->natts);
488 dtup = palloc0(basesize + sizeof(Datum) * brdesc->bd_totalstored);
489
490 dtup->bt_values = palloc_array(Datum, brdesc->bd_totalstored);
491 dtup->bt_allnulls = palloc_array(bool, brdesc->bd_tupdesc->natts);
492 dtup->bt_hasnulls = palloc_array(bool, brdesc->bd_tupdesc->natts);
493
494 dtup->bt_empty_range = true;
495
497 "brin dtuple",
499
500 brin_memtuple_initialize(dtup, brdesc);
501
502 return dtup;
503}
504
505/*
506 * Reset a BrinMemTuple to initial state. We return the same tuple, for
507 * notational convenience.
508 */
511{
512 int i;
513 char *currdatum;
514
516
517 currdatum = (char *) dtuple +
518 MAXALIGN(sizeof(BrinMemTuple) +
519 sizeof(BrinValues) * brdesc->bd_tupdesc->natts);
520 for (i = 0; i < brdesc->bd_tupdesc->natts; i++)
521 {
522 dtuple->bt_columns[i].bv_attno = i + 1;
523 dtuple->bt_columns[i].bv_allnulls = true;
524 dtuple->bt_columns[i].bv_hasnulls = false;
525 dtuple->bt_columns[i].bv_values = (Datum *) currdatum;
526
527 dtuple->bt_columns[i].bv_mem_value = PointerGetDatum(NULL);
528 dtuple->bt_columns[i].bv_serialize = NULL;
529 dtuple->bt_columns[i].bv_context = dtuple->bt_context;
530
531 currdatum += sizeof(Datum) * brdesc->bd_info[i]->oi_nstored;
532 }
533
534 dtuple->bt_empty_range = true;
535
536 return dtuple;
537}
538
539/*
540 * Convert a BrinTuple back to a BrinMemTuple. This is the reverse of
541 * brin_form_tuple.
542 *
543 * As an optimization, the caller can pass a previously allocated 'dMemtuple'.
544 * This avoids having to allocate it here, which can be useful when this
545 * function is called many times in a loop. It is caller's responsibility
546 * that the given BrinMemTuple matches what we need here.
547 *
548 * Note we don't need the "on disk tupdesc" here; we rely on our own routine to
549 * deconstruct the tuple from the on-disk format.
550 */
553{
554 BrinMemTuple *dtup;
555 Datum *values;
556 bool *allnulls;
557 bool *hasnulls;
558 char *tp;
559 bits8 *nullbits;
560 int keyno;
561 int valueno;
562 MemoryContext oldcxt;
563
564 dtup = dMemtuple ? brin_memtuple_initialize(dMemtuple, brdesc) :
565 brin_new_memtuple(brdesc);
566
567 if (BrinTupleIsPlaceholder(tuple))
568 dtup->bt_placeholder = true;
569
570 /* ranges start as empty, depends on the BrinTuple */
571 if (!BrinTupleIsEmptyRange(tuple))
572 dtup->bt_empty_range = false;
573
574 dtup->bt_blkno = tuple->bt_blkno;
575
576 values = dtup->bt_values;
577 allnulls = dtup->bt_allnulls;
578 hasnulls = dtup->bt_hasnulls;
579
580 tp = (char *) tuple + BrinTupleDataOffset(tuple);
581
582 if (BrinTupleHasNulls(tuple))
583 nullbits = (bits8 *) ((char *) tuple + SizeOfBrinTuple);
584 else
585 nullbits = NULL;
587 tp, nullbits, BrinTupleHasNulls(tuple),
588 values, allnulls, hasnulls);
589
590 /*
591 * Iterate to assign each of the values to the corresponding item in the
592 * values array of each column. The copies occur in the tuple's context.
593 */
594 oldcxt = MemoryContextSwitchTo(dtup->bt_context);
595 for (valueno = 0, keyno = 0; keyno < brdesc->bd_tupdesc->natts; keyno++)
596 {
597 int i;
598
599 if (allnulls[keyno])
600 {
601 valueno += brdesc->bd_info[keyno]->oi_nstored;
602 continue;
603 }
604
605 /*
606 * We would like to skip datumCopy'ing the values datum in some cases,
607 * caller permitting ...
608 */
609 for (i = 0; i < brdesc->bd_info[keyno]->oi_nstored; i++)
610 dtup->bt_columns[keyno].bv_values[i] =
611 datumCopy(values[valueno++],
612 brdesc->bd_info[keyno]->oi_typcache[i]->typbyval,
613 brdesc->bd_info[keyno]->oi_typcache[i]->typlen);
614
615 dtup->bt_columns[keyno].bv_hasnulls = hasnulls[keyno];
616 dtup->bt_columns[keyno].bv_allnulls = false;
617
618 dtup->bt_columns[keyno].bv_mem_value = PointerGetDatum(NULL);
619 dtup->bt_columns[keyno].bv_serialize = NULL;
620 dtup->bt_columns[keyno].bv_context = dtup->bt_context;
621 }
622
623 MemoryContextSwitchTo(oldcxt);
624
625 return dtup;
626}
627
628/*
629 * brin_deconstruct_tuple
630 * Guts of attribute extraction from an on-disk BRIN tuple.
631 *
632 * Its arguments are:
633 * brdesc BRIN descriptor for the stored tuple
634 * tp pointer to the tuple data area
635 * nullbits pointer to the tuple nulls bitmask
636 * nulls "has nulls" bit in tuple infomask
637 * values output values, array of size brdesc->bd_totalstored
638 * allnulls output "allnulls", size brdesc->bd_tupdesc->natts
639 * hasnulls output "hasnulls", size brdesc->bd_tupdesc->natts
640 *
641 * Output arrays must have been allocated by caller.
642 */
643static inline void
645 char *tp, bits8 *nullbits, bool nulls,
646 Datum *values, bool *allnulls, bool *hasnulls)
647{
648 int attnum;
649 int stored;
650 TupleDesc diskdsc;
651 long off;
652
653 /*
654 * First iterate to natts to obtain both null flags for each attribute.
655 * Note that we reverse the sense of the att_isnull test, because we store
656 * 1 for a null value (rather than a 1 for a not null value as is the
657 * att_isnull convention used elsewhere.) See brin_form_tuple.
658 */
659 for (attnum = 0; attnum < brdesc->bd_tupdesc->natts; attnum++)
660 {
661 /*
662 * the "all nulls" bit means that all values in the page range for
663 * this column are nulls. Therefore there are no values in the tuple
664 * data area.
665 */
666 allnulls[attnum] = nulls && !att_isnull(attnum, nullbits);
667
668 /*
669 * the "has nulls" bit means that some tuples have nulls, but others
670 * have not-null values. Therefore we know the tuple contains data
671 * for this column.
672 *
673 * The hasnulls bits follow the allnulls bits in the same bitmask.
674 */
675 hasnulls[attnum] =
676 nulls && !att_isnull(brdesc->bd_tupdesc->natts + attnum, nullbits);
677 }
678
679 /*
680 * Iterate to obtain each attribute's stored values. Note that since we
681 * may reuse attribute entries for more than one column, we cannot cache
682 * offsets here.
683 */
684 diskdsc = brtuple_disk_tupdesc(brdesc);
685 stored = 0;
686 off = 0;
687 for (attnum = 0; attnum < brdesc->bd_tupdesc->natts; attnum++)
688 {
689 int datumno;
690
691 if (allnulls[attnum])
692 {
693 stored += brdesc->bd_info[attnum]->oi_nstored;
694 continue;
695 }
696
697 for (datumno = 0;
698 datumno < brdesc->bd_info[attnum]->oi_nstored;
699 datumno++)
700 {
701 CompactAttribute *thisatt = TupleDescCompactAttr(diskdsc, stored);
702
703 if (thisatt->attlen == -1)
704 {
705 off = att_pointer_alignby(off,
706 thisatt->attalignby,
707 -1,
708 tp + off);
709 }
710 else
711 {
712 /* not varlena, so safe to use att_nominal_alignby */
713 off = att_nominal_alignby(off, thisatt->attalignby);
714 }
715
716 values[stored++] = fetchatt(thisatt, tp + off);
717
718 off = att_addlength_pointer(off, thisatt->attlen, tp + off);
719 }
720 }
721}
int16 AttrNumber
Definition: attnum.h:21
uint32 BlockNumber
Definition: block.h:31
static Datum values[MAXATTR]
Definition: bootstrap.c:153
BrinTuple * brin_copy_tuple(BrinTuple *tuple, Size len, BrinTuple *dest, Size *destsz)
Definition: brin_tuple.c:445
static void brin_deconstruct_tuple(BrinDesc *brdesc, char *tp, bits8 *nullbits, bool nulls, Datum *values, bool *allnulls, bool *hasnulls)
Definition: brin_tuple.c:644
bool brin_tuples_equal(const BrinTuple *a, Size alen, const BrinTuple *b, Size blen)
Definition: brin_tuple.c:464
BrinTuple * brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple, Size *size)
Definition: brin_tuple.c:99
BrinMemTuple * brin_new_memtuple(BrinDesc *brdesc)
Definition: brin_tuple.c:481
void brin_free_tuple(BrinTuple *tuple)
Definition: brin_tuple.c:432
BrinTuple * brin_form_placeholder_tuple(BrinDesc *brdesc, BlockNumber blkno, Size *size)
Definition: brin_tuple.c:387
BrinMemTuple * brin_memtuple_initialize(BrinMemTuple *dtuple, BrinDesc *brdesc)
Definition: brin_tuple.c:510
BrinMemTuple * brin_deform_tuple(BrinDesc *brdesc, BrinTuple *tuple, BrinMemTuple *dMemtuple)
Definition: brin_tuple.c:552
static TupleDesc brtuple_disk_tupdesc(BrinDesc *brdesc)
Definition: brin_tuple.c:61
#define BRIN_EMPTY_RANGE_MASK
Definition: brin_tuple.h:86
#define BrinTupleIsEmptyRange(tup)
Definition: brin_tuple.h:93
#define BrinTupleDataOffset(tup)
Definition: brin_tuple.h:90
#define BRIN_OFFSET_MASK
Definition: brin_tuple.h:85
#define BrinTupleIsPlaceholder(tup)
Definition: brin_tuple.h:92
#define BRIN_PLACEHOLDER_MASK
Definition: brin_tuple.h:87
#define SizeOfBrinTuple
Definition: brin_tuple.h:80
#define BrinTupleHasNulls(tup)
Definition: brin_tuple.h:91
struct BrinValues BrinValues
#define BRIN_NULLS_MASK
Definition: brin_tuple.h:88
#define MAXALIGN(LEN)
Definition: c.h:824
uint8 bits8
Definition: c.h:559
uint16_t uint16
Definition: c.h:551
#define HIGHBIT
Definition: c.h:1152
size_t Size
Definition: c.h:624
Datum datumCopy(Datum value, bool typByVal, int typLen)
Definition: datum.c:132
struct varlena * detoast_external_attr(struct varlena *attr)
Definition: detoast.c:45
#define palloc_array(type, count)
Definition: fe_memutils.h:76
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
Assert(PointerIsAligned(start, uint64))
#define TOAST_INDEX_TARGET
Definition: heaptoast.h:68
Size heap_compute_data_size(TupleDesc tupleDesc, const Datum *values, const bool *isnull)
Definition: heaptuple.c:219
void heap_fill_tuple(TupleDesc tupleDesc, const Datum *values, const bool *isnull, char *data, Size data_size, uint16 *infomask, bits8 *bit)
Definition: heaptuple.c:401
static int BITMAPLEN(int NATTS)
Definition: htup_details.h:594
static struct @171 value
int b
Definition: isn.c:74
int a
Definition: isn.c:73
int j
Definition: isn.c:78
int i
Definition: isn.c:77
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:400
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1610
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc0(Size size)
Definition: mcxt.c:1395
void * palloc(Size size)
Definition: mcxt.c:1365
MemoryContext CurrentMemoryContext
Definition: mcxt.c:160
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
int16 attnum
Definition: pg_attribute.h:74
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:202
const void size_t len
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:332
uint64_t Datum
Definition: postgres.h:70
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:322
int bd_totalstored
Definition: brin_internal.h:59
TupleDesc bd_tupdesc
Definition: brin_internal.h:53
BrinOpcInfo * bd_info[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:62
MemoryContext bd_context
Definition: brin_internal.h:47
TupleDesc bd_disktdesc
Definition: brin_internal.h:56
bool * bt_allnulls
Definition: brin_tuple.h:52
BrinValues bt_columns[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_tuple.h:55
MemoryContext bt_context
Definition: brin_tuple.h:49
BlockNumber bt_blkno
Definition: brin_tuple.h:48
Datum * bt_values
Definition: brin_tuple.h:51
bool * bt_hasnulls
Definition: brin_tuple.h:53
bool bt_placeholder
Definition: brin_tuple.h:46
bool bt_empty_range
Definition: brin_tuple.h:47
TypeCacheEntry * oi_typcache[FLEXIBLE_ARRAY_MEMBER]
Definition: brin_internal.h:37
uint16 oi_nstored
Definition: brin_internal.h:28
BlockNumber bt_blkno
Definition: brin_tuple.h:66
uint8 bt_info
Definition: brin_tuple.h:77
MemoryContext bv_context
Definition: brin_tuple.h:36
bool bv_hasnulls
Definition: brin_tuple.h:32
Datum bv_mem_value
Definition: brin_tuple.h:35
brin_serialize_callback_type bv_serialize
Definition: brin_tuple.h:37
Datum * bv_values
Definition: brin_tuple.h:34
AttrNumber bv_attno
Definition: brin_tuple.h:31
bool bv_allnulls
Definition: brin_tuple.h:33
uint8 attalignby
Definition: tupdesc.h:80
int16 attlen
Definition: tupdesc.h:71
bool typbyval
Definition: typcache.h:40
int16 typlen
Definition: typcache.h:39
char typstorage
Definition: typcache.h:42
Definition: c.h:706
#define InvalidCompressionMethod
Datum toast_compress_datum(Datum value, char cmethod)
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:182
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:842
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160
static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:175
#define att_nominal_alignby(cur_offset, attalignby)
Definition: tupmacs.h:160
static bool att_isnull(int ATT, const bits8 *BITS)
Definition: tupmacs.h:26
#define att_addlength_pointer(cur_offset, attlen, attptr)
Definition: tupmacs.h:180
#define att_pointer_alignby(cur_offset, attalignby, attlen, attptr)
Definition: tupmacs.h:124
#define fetchatt(A, T)
Definition: tupmacs.h:44
static bool VARATT_IS_EXTENDED(const void *PTR)
Definition: varatt.h:410
static bool VARATT_IS_EXTERNAL(const void *PTR)
Definition: varatt.h:354
static Size VARSIZE(const void *PTR)
Definition: varatt.h:298