Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * heaptuple.c
4 : * This file contains heap tuple accessor and mutator routines, as well
5 : * as various tuple utilities.
6 : *
7 : * Some notes about varlenas and this code:
8 : *
9 : * Before Postgres 8.3 varlenas always had a 4-byte length header, and
10 : * therefore always needed 4-byte alignment (at least). This wasted space
11 : * for short varlenas, for example CHAR(1) took 5 bytes and could need up to
12 : * 3 additional padding bytes for alignment.
13 : *
14 : * Now, a short varlena (up to 126 data bytes) is reduced to a 1-byte header
15 : * and we don't align it. To hide this from datatype-specific functions that
16 : * don't want to deal with it, such a datum is considered "toasted" and will
17 : * be expanded back to the normal 4-byte-header format by pg_detoast_datum.
18 : * (In performance-critical code paths we can use pg_detoast_datum_packed
19 : * and the appropriate access macros to avoid that overhead.) Note that this
20 : * conversion is performed directly in heap_form_tuple, without invoking
21 : * heaptoast.c.
22 : *
23 : * This change will break any code that assumes it needn't detoast values
24 : * that have been put into a tuple but never sent to disk. Hopefully there
25 : * are few such places.
26 : *
27 : * Varlenas still have alignment INT (or DOUBLE) in pg_type/pg_attribute, since
28 : * that's the normal requirement for the untoasted format. But we ignore that
29 : * for the 1-byte-header format. This means that the actual start position
30 : * of a varlena datum may vary depending on which format it has. To determine
31 : * what is stored, we have to require that alignment padding bytes be zero.
32 : * (Postgres actually has always zeroed them, but now it's required!) Since
33 : * the first byte of a 1-byte-header varlena can never be zero, we can examine
34 : * the first byte after the previous datum to tell if it's a pad byte or the
35 : * start of a 1-byte-header varlena.
36 : *
37 : * Note that while formerly we could rely on the first varlena column of a
38 : * system catalog to be at the offset suggested by the C struct for the
39 : * catalog, this is now risky: it's only safe if the preceding field is
40 : * word-aligned, so that there will never be any padding.
41 : *
42 : * We don't pack varlenas whose attstorage is PLAIN, since the data type
43 : * isn't expecting to have to detoast values. This is used in particular
44 : * by oidvector and int2vector, which are used in the system catalogs
45 : * and we'd like to still refer to them via C struct offsets.
46 : *
47 : *
48 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
49 : * Portions Copyright (c) 1994, Regents of the University of California
50 : *
51 : *
52 : * IDENTIFICATION
53 : * src/backend/access/common/heaptuple.c
54 : *
55 : *-------------------------------------------------------------------------
56 : */
57 :
58 : #include "postgres.h"
59 :
60 : #include "access/heaptoast.h"
61 : #include "access/sysattr.h"
62 : #include "access/tupdesc_details.h"
63 : #include "executor/tuptable.h"
64 : #include "utils/expandeddatum.h"
65 :
66 :
67 : /* Does att's datatype allow packing into the 1-byte-header varlena format? */
68 : #define ATT_IS_PACKABLE(att) \
69 : ((att)->attlen == -1 && (att)->attstorage != TYPSTORAGE_PLAIN)
70 : /* Use this if it's already known varlena */
71 : #define VARLENA_ATT_IS_PACKABLE(att) \
72 : ((att)->attstorage != TYPSTORAGE_PLAIN)
73 :
74 :
75 : /* ----------------------------------------------------------------
76 : * misc support routines
77 : * ----------------------------------------------------------------
78 : */
79 :
80 : /*
81 : * Return the missing value of an attribute, or NULL if there isn't one.
82 : */
83 : Datum
84 358 : getmissingattr(TupleDesc tupleDesc,
85 : int attnum, bool *isnull)
86 : {
87 : Form_pg_attribute att;
88 :
89 : Assert(attnum <= tupleDesc->natts);
90 : Assert(attnum > 0);
91 :
92 358 : att = TupleDescAttr(tupleDesc, attnum - 1);
93 :
94 358 : if (att->atthasmissing)
95 : {
96 : AttrMissing *attrmiss;
97 :
98 : Assert(tupleDesc->constr);
99 : Assert(tupleDesc->constr->missing);
100 :
101 54 : attrmiss = tupleDesc->constr->missing + (attnum - 1);
102 :
103 54 : if (attrmiss->am_present)
104 : {
105 54 : *isnull = false;
106 54 : return attrmiss->am_value;
107 : }
108 : }
109 :
110 304 : *isnull = true;
111 304 : return PointerGetDatum(NULL);
112 : }
113 :
114 : /*
115 : * heap_compute_data_size
116 : * Determine size of the data area of a tuple to be constructed
117 : */
118 : Size
119 140716062 : heap_compute_data_size(TupleDesc tupleDesc,
120 : Datum *values,
121 : bool *isnull)
122 : {
123 140716062 : Size data_length = 0;
124 : int i;
125 140716062 : int numberOfAttributes = tupleDesc->natts;
126 :
127 615119270 : for (i = 0; i < numberOfAttributes; i++)
128 : {
129 : Datum val;
130 : Form_pg_attribute atti;
131 :
132 474403208 : if (isnull[i])
133 48150768 : continue;
134 :
135 426252440 : val = values[i];
136 426252440 : atti = TupleDescAttr(tupleDesc, i);
137 :
138 426252440 : if (ATT_IS_PACKABLE(atti) &&
139 37557736 : VARATT_CAN_MAKE_SHORT(DatumGetPointer(val)))
140 : {
141 : /*
142 : * we're anticipating converting to a short varlena header, so
143 : * adjust length and don't count any alignment
144 : */
145 29107420 : data_length += VARATT_CONVERTED_SHORT_SIZE(DatumGetPointer(val));
146 : }
147 397145020 : else if (atti->attlen == -1 &&
148 14289646 : VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val)))
149 : {
150 : /*
151 : * we want to flatten the expanded value so that the constructed
152 : * tuple doesn't depend on it
153 : */
154 2964 : data_length = att_align_nominal(data_length, atti->attalign);
155 2964 : data_length += EOH_get_flat_size(DatumGetEOHP(val));
156 : }
157 : else
158 : {
159 397142056 : data_length = att_align_datum(data_length, atti->attalign,
160 : atti->attlen, val);
161 397142056 : data_length = att_addlength_datum(data_length, atti->attlen,
162 : val);
163 : }
164 : }
165 :
166 140716062 : return data_length;
167 : }
168 :
169 : /*
170 : * Per-attribute helper for heap_fill_tuple and other routines building tuples.
171 : *
172 : * Fill in either a data value or a bit in the null bitmask
173 : */
174 : static inline void
175 446914082 : fill_val(Form_pg_attribute att,
176 : bits8 **bit,
177 : int *bitmask,
178 : char **dataP,
179 : uint16 *infomask,
180 : Datum datum,
181 : bool isnull)
182 : {
183 : Size data_length;
184 446914082 : char *data = *dataP;
185 :
186 : /*
187 : * If we're building a null bitmap, set the appropriate bit for the
188 : * current column value here.
189 : */
190 446914082 : if (bit != NULL)
191 : {
192 211523412 : if (*bitmask != HIGHBIT)
193 179078378 : *bitmask <<= 1;
194 : else
195 : {
196 32445034 : *bit += 1;
197 32445034 : **bit = 0x0;
198 32445034 : *bitmask = 1;
199 : }
200 :
201 211523412 : if (isnull)
202 : {
203 47325420 : *infomask |= HEAP_HASNULL;
204 47325420 : return;
205 : }
206 :
207 164197992 : **bit |= *bitmask;
208 : }
209 :
210 : /*
211 : * XXX we use the att_align macros on the pointer value itself, not on an
212 : * offset. This is a bit of a hack.
213 : */
214 399588662 : if (att->attbyval)
215 : {
216 : /* pass-by-value */
217 323473466 : data = (char *) att_align_nominal(data, att->attalign);
218 323473466 : store_att_byval(data, datum, att->attlen);
219 323473466 : data_length = att->attlen;
220 : }
221 76115196 : else if (att->attlen == -1)
222 : {
223 : /* varlena */
224 40750632 : Pointer val = DatumGetPointer(datum);
225 :
226 40750632 : *infomask |= HEAP_HASVARWIDTH;
227 40750632 : if (VARATT_IS_EXTERNAL(val))
228 : {
229 68592 : if (VARATT_IS_EXTERNAL_EXPANDED(val))
230 2964 : {
231 : /*
232 : * we want to flatten the expanded value so that the
233 : * constructed tuple doesn't depend on it
234 : */
235 2964 : ExpandedObjectHeader *eoh = DatumGetEOHP(datum);
236 :
237 2964 : data = (char *) att_align_nominal(data,
238 : att->attalign);
239 2964 : data_length = EOH_get_flat_size(eoh);
240 2964 : EOH_flatten_into(eoh, data, data_length);
241 : }
242 : else
243 : {
244 65628 : *infomask |= HEAP_HASEXTERNAL;
245 : /* no alignment, since it's short by definition */
246 65628 : data_length = VARSIZE_EXTERNAL(val);
247 65628 : memcpy(data, val, data_length);
248 : }
249 : }
250 40682040 : else if (VARATT_IS_SHORT(val))
251 : {
252 : /* no alignment for short varlenas */
253 5937268 : data_length = VARSIZE_SHORT(val);
254 5937268 : memcpy(data, val, data_length);
255 : }
256 34744772 : else if (VARLENA_ATT_IS_PACKABLE(att) &&
257 28955392 : VARATT_CAN_MAKE_SHORT(val))
258 : {
259 : /* convert to short varlena -- no alignment */
260 28179276 : data_length = VARATT_CONVERTED_SHORT_SIZE(val);
261 28179276 : SET_VARSIZE_SHORT(data, data_length);
262 28179276 : memcpy(data + 1, VARDATA(val), data_length - 1);
263 : }
264 : else
265 : {
266 : /* full 4-byte header varlena */
267 6565496 : data = (char *) att_align_nominal(data,
268 : att->attalign);
269 6565496 : data_length = VARSIZE(val);
270 6565496 : memcpy(data, val, data_length);
271 : }
272 : }
273 35364564 : else if (att->attlen == -2)
274 : {
275 : /* cstring ... never needs alignment */
276 7332346 : *infomask |= HEAP_HASVARWIDTH;
277 : Assert(att->attalign == TYPALIGN_CHAR);
278 7332346 : data_length = strlen(DatumGetCString(datum)) + 1;
279 7332346 : memcpy(data, DatumGetPointer(datum), data_length);
280 : }
281 : else
282 : {
283 : /* fixed-length pass-by-reference */
284 28032218 : data = (char *) att_align_nominal(data, att->attalign);
285 : Assert(att->attlen > 0);
286 28032218 : data_length = att->attlen;
287 28032218 : memcpy(data, DatumGetPointer(datum), data_length);
288 : }
289 :
290 399588662 : data += data_length;
291 399588662 : *dataP = data;
292 : }
293 :
294 : /*
295 : * heap_fill_tuple
296 : * Load data portion of a tuple from values/isnull arrays
297 : *
298 : * We also fill the null bitmap (if any) and set the infomask bits
299 : * that reflect the tuple's data contents.
300 : *
301 : * NOTE: it is now REQUIRED that the caller have pre-zeroed the data area.
302 : */
303 : void
304 120552168 : heap_fill_tuple(TupleDesc tupleDesc,
305 : Datum *values, bool *isnull,
306 : char *data, Size data_size,
307 : uint16 *infomask, bits8 *bit)
308 : {
309 : bits8 *bitP;
310 : int bitmask;
311 : int i;
312 120552168 : int numberOfAttributes = tupleDesc->natts;
313 :
314 : #ifdef USE_ASSERT_CHECKING
315 : char *start = data;
316 : #endif
317 :
318 120552168 : if (bit != NULL)
319 : {
320 11289904 : bitP = &bit[-1];
321 11289904 : bitmask = HIGHBIT;
322 : }
323 : else
324 : {
325 : /* just to keep compiler quiet */
326 109262264 : bitP = NULL;
327 109262264 : bitmask = 0;
328 : }
329 :
330 120552168 : *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTERNAL);
331 :
332 567466250 : for (i = 0; i < numberOfAttributes; i++)
333 : {
334 446914082 : Form_pg_attribute attr = TupleDescAttr(tupleDesc, i);
335 :
336 893828164 : fill_val(attr,
337 446914082 : bitP ? &bitP : NULL,
338 : &bitmask,
339 : &data,
340 : infomask,
341 446914082 : values ? values[i] : PointerGetDatum(NULL),
342 446914082 : isnull ? isnull[i] : true);
343 : }
344 :
345 : Assert((data - start) == data_size);
346 120552168 : }
347 :
348 :
349 : /* ----------------------------------------------------------------
350 : * heap tuple interface
351 : * ----------------------------------------------------------------
352 : */
353 :
354 : /* ----------------
355 : * heap_attisnull - returns true iff tuple attribute is not present
356 : * ----------------
357 : */
358 : bool
359 17659142 : heap_attisnull(HeapTuple tup, int attnum, TupleDesc tupleDesc)
360 : {
361 : /*
362 : * We allow a NULL tupledesc for relations not expected to have missing
363 : * values, such as catalog relations and indexes.
364 : */
365 : Assert(!tupleDesc || attnum <= tupleDesc->natts);
366 17659142 : if (attnum > (int) HeapTupleHeaderGetNatts(tup->t_data))
367 : {
368 0 : if (tupleDesc && TupleDescAttr(tupleDesc, attnum - 1)->atthasmissing)
369 0 : return false;
370 : else
371 0 : return true;
372 : }
373 :
374 17659142 : if (attnum > 0)
375 : {
376 17659142 : if (HeapTupleNoNulls(tup))
377 3040 : return false;
378 17656102 : return att_isnull(attnum - 1, tup->t_data->t_bits);
379 : }
380 :
381 0 : switch (attnum)
382 : {
383 0 : case TableOidAttributeNumber:
384 : case SelfItemPointerAttributeNumber:
385 : case MinTransactionIdAttributeNumber:
386 : case MinCommandIdAttributeNumber:
387 : case MaxTransactionIdAttributeNumber:
388 : case MaxCommandIdAttributeNumber:
389 : /* these are never null */
390 0 : break;
391 :
392 0 : default:
393 0 : elog(ERROR, "invalid attnum: %d", attnum);
394 : }
395 :
396 0 : return false;
397 : }
398 :
399 : /* ----------------
400 : * nocachegetattr
401 : *
402 : * This only gets called from fastgetattr() macro, in cases where
403 : * we can't use a cacheoffset and the value is not null.
404 : *
405 : * This caches attribute offsets in the attribute descriptor.
406 : *
407 : * An alternative way to speed things up would be to cache offsets
408 : * with the tuple, but that seems more difficult unless you take
409 : * the storage hit of actually putting those offsets into the
410 : * tuple you send to disk. Yuck.
411 : *
412 : * This scheme will be slightly slower than that, but should
413 : * perform well for queries which hit large #'s of tuples. After
414 : * you cache the offsets once, examining all the other tuples using
415 : * the same attribute descriptor will go much quicker. -cim 5/4/91
416 : *
417 : * NOTE: if you need to change this code, see also heap_deform_tuple.
418 : * Also see nocache_index_getattr, which is the same code for index
419 : * tuples.
420 : * ----------------
421 : */
422 : Datum
423 471869606 : nocachegetattr(HeapTuple tup,
424 : int attnum,
425 : TupleDesc tupleDesc)
426 : {
427 471869606 : HeapTupleHeader td = tup->t_data;
428 : char *tp; /* ptr to data part of tuple */
429 471869606 : bits8 *bp = td->t_bits; /* ptr to null bitmap in tuple */
430 471869606 : bool slow = false; /* do we have to walk attrs? */
431 : int off; /* current offset within data */
432 :
433 : /* ----------------
434 : * Three cases:
435 : *
436 : * 1: No nulls and no variable-width attributes.
437 : * 2: Has a null or a var-width AFTER att.
438 : * 3: Has nulls or var-widths BEFORE att.
439 : * ----------------
440 : */
441 :
442 471869606 : attnum--;
443 :
444 471869606 : if (!HeapTupleNoNulls(tup))
445 : {
446 : /*
447 : * there's a null somewhere in the tuple
448 : *
449 : * check to see if any preceding bits are null...
450 : */
451 439318870 : int byte = attnum >> 3;
452 439318870 : int finalbit = attnum & 0x07;
453 :
454 : /* check for nulls "before" final bit of last byte */
455 439318870 : if ((~bp[byte]) & ((1 << finalbit) - 1))
456 7882652 : slow = true;
457 : else
458 : {
459 : /* check for nulls in any "earlier" bytes */
460 : int i;
461 :
462 552257236 : for (i = 0; i < byte; i++)
463 : {
464 121422364 : if (bp[i] != 0xFF)
465 : {
466 601346 : slow = true;
467 601346 : break;
468 : }
469 : }
470 : }
471 : }
472 :
473 471869606 : tp = (char *) td + td->t_hoff;
474 :
475 471869606 : if (!slow)
476 : {
477 : Form_pg_attribute att;
478 :
479 : /*
480 : * If we get here, there are no nulls up to and including the target
481 : * attribute. If we have a cached offset, we can use it.
482 : */
483 463385608 : att = TupleDescAttr(tupleDesc, attnum);
484 463385608 : if (att->attcacheoff >= 0)
485 423880450 : return fetchatt(att, tp + att->attcacheoff);
486 :
487 : /*
488 : * Otherwise, check for non-fixed-length attrs up to and including
489 : * target. If there aren't any, it's safe to cheaply initialize the
490 : * cached offsets for these attrs.
491 : */
492 39505158 : if (HeapTupleHasVarWidth(tup))
493 : {
494 : int j;
495 :
496 127630368 : for (j = 0; j <= attnum; j++)
497 : {
498 127566472 : if (TupleDescAttr(tupleDesc, j)->attlen <= 0)
499 : {
500 39313682 : slow = true;
501 39313682 : break;
502 : }
503 : }
504 : }
505 : }
506 :
507 47989156 : if (!slow)
508 : {
509 191476 : int natts = tupleDesc->natts;
510 191476 : int j = 1;
511 :
512 : /*
513 : * If we get here, we have a tuple with no nulls or var-widths up to
514 : * and including the target attribute, so we can use the cached offset
515 : * ... only we don't have it yet, or we'd not have got here. Since
516 : * it's cheap to compute offsets for fixed-width columns, we take the
517 : * opportunity to initialize the cached offsets for *all* the leading
518 : * fixed-width columns, in hope of avoiding future visits to this
519 : * routine.
520 : */
521 191476 : TupleDescAttr(tupleDesc, 0)->attcacheoff = 0;
522 :
523 : /* we might have set some offsets in the slow path previously */
524 200244 : while (j < natts && TupleDescAttr(tupleDesc, j)->attcacheoff > 0)
525 8768 : j++;
526 :
527 191476 : off = TupleDescAttr(tupleDesc, j - 1)->attcacheoff +
528 191476 : TupleDescAttr(tupleDesc, j - 1)->attlen;
529 :
530 1864364 : for (; j < natts; j++)
531 : {
532 1768970 : Form_pg_attribute att = TupleDescAttr(tupleDesc, j);
533 :
534 1768970 : if (att->attlen <= 0)
535 96082 : break;
536 :
537 1672888 : off = att_align_nominal(off, att->attalign);
538 :
539 1672888 : att->attcacheoff = off;
540 :
541 1672888 : off += att->attlen;
542 : }
543 :
544 : Assert(j > attnum);
545 :
546 191476 : off = TupleDescAttr(tupleDesc, attnum)->attcacheoff;
547 : }
548 : else
549 : {
550 47797680 : bool usecache = true;
551 : int i;
552 :
553 : /*
554 : * Now we know that we have to walk the tuple CAREFULLY. But we still
555 : * might be able to cache some offsets for next time.
556 : *
557 : * Note - This loop is a little tricky. For each non-null attribute,
558 : * we have to first account for alignment padding before the attr,
559 : * then advance over the attr based on its length. Nulls have no
560 : * storage and no alignment padding either. We can use/set
561 : * attcacheoff until we reach either a null or a var-width attribute.
562 : */
563 47797680 : off = 0;
564 47797680 : for (i = 0;; i++) /* loop exit is at "break" */
565 281515368 : {
566 329313048 : Form_pg_attribute att = TupleDescAttr(tupleDesc, i);
567 :
568 329313048 : if (HeapTupleHasNulls(tup) && att_isnull(i, bp))
569 : {
570 26578274 : usecache = false;
571 26578274 : continue; /* this cannot be the target att */
572 : }
573 :
574 : /* If we know the next offset, we can skip the rest */
575 302734774 : if (usecache && att->attcacheoff >= 0)
576 204970636 : off = att->attcacheoff;
577 97764138 : else if (att->attlen == -1)
578 : {
579 : /*
580 : * We can only cache the offset for a varlena attribute if the
581 : * offset is already suitably aligned, so that there would be
582 : * no pad bytes in any case: then the offset will be valid for
583 : * either an aligned or unaligned value.
584 : */
585 34724838 : if (usecache &&
586 3527782 : off == att_align_nominal(off, att->attalign))
587 74894 : att->attcacheoff = off;
588 : else
589 : {
590 31122162 : off = att_align_pointer(off, att->attalign, -1,
591 : tp + off);
592 31122162 : usecache = false;
593 : }
594 : }
595 : else
596 : {
597 : /* not varlena, so safe to use att_align_nominal */
598 66567082 : off = att_align_nominal(off, att->attalign);
599 :
600 66567082 : if (usecache)
601 735616 : att->attcacheoff = off;
602 : }
603 :
604 302734774 : if (i == attnum)
605 47797680 : break;
606 :
607 254937094 : off = att_addlength_pointer(off, att->attlen, tp + off);
608 :
609 254937094 : if (usecache && att->attlen <= 0)
610 41546074 : usecache = false;
611 : }
612 : }
613 :
614 47989156 : return fetchatt(TupleDescAttr(tupleDesc, attnum), tp + off);
615 : }
616 :
617 : /* ----------------
618 : * heap_getsysattr
619 : *
620 : * Fetch the value of a system attribute for a tuple.
621 : *
622 : * This is a support routine for the heap_getattr macro. The macro
623 : * has already determined that the attnum refers to a system attribute.
624 : * ----------------
625 : */
626 : Datum
627 1270 : heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
628 : {
629 : Datum result;
630 :
631 : Assert(tup);
632 :
633 : /* Currently, no sys attribute ever reads as NULL. */
634 1270 : *isnull = false;
635 :
636 1270 : switch (attnum)
637 : {
638 4 : case SelfItemPointerAttributeNumber:
639 : /* pass-by-reference datatype */
640 4 : result = PointerGetDatum(&(tup->t_self));
641 4 : break;
642 1046 : case MinTransactionIdAttributeNumber:
643 1046 : result = TransactionIdGetDatum(HeapTupleHeaderGetRawXmin(tup->t_data));
644 1046 : break;
645 30 : case MaxTransactionIdAttributeNumber:
646 30 : result = TransactionIdGetDatum(HeapTupleHeaderGetRawXmax(tup->t_data));
647 30 : break;
648 186 : case MinCommandIdAttributeNumber:
649 : case MaxCommandIdAttributeNumber:
650 :
651 : /*
652 : * cmin and cmax are now both aliases for the same field, which
653 : * can in fact also be a combo command id. XXX perhaps we should
654 : * return the "real" cmin or cmax if possible, that is if we are
655 : * inside the originating transaction?
656 : */
657 186 : result = CommandIdGetDatum(HeapTupleHeaderGetRawCommandId(tup->t_data));
658 186 : break;
659 4 : case TableOidAttributeNumber:
660 4 : result = ObjectIdGetDatum(tup->t_tableOid);
661 4 : break;
662 0 : default:
663 0 : elog(ERROR, "invalid attnum: %d", attnum);
664 : result = 0; /* keep compiler quiet */
665 : break;
666 : }
667 1270 : return result;
668 : }
669 :
670 : /* ----------------
671 : * heap_copytuple
672 : *
673 : * returns a copy of an entire tuple
674 : *
675 : * The HeapTuple struct, tuple header, and tuple data are all allocated
676 : * as a single palloc() block.
677 : * ----------------
678 : */
679 : HeapTuple
680 24416634 : heap_copytuple(HeapTuple tuple)
681 : {
682 : HeapTuple newTuple;
683 :
684 24416634 : if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
685 0 : return NULL;
686 :
687 24416634 : newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
688 24416634 : newTuple->t_len = tuple->t_len;
689 24416634 : newTuple->t_self = tuple->t_self;
690 24416634 : newTuple->t_tableOid = tuple->t_tableOid;
691 24416634 : newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
692 24416634 : memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
693 24416634 : return newTuple;
694 : }
695 :
696 : /* ----------------
697 : * heap_copytuple_with_tuple
698 : *
699 : * copy a tuple into a caller-supplied HeapTuple management struct
700 : *
701 : * Note that after calling this function, the "dest" HeapTuple will not be
702 : * allocated as a single palloc() block (unlike with heap_copytuple()).
703 : * ----------------
704 : */
705 : void
706 0 : heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
707 : {
708 0 : if (!HeapTupleIsValid(src) || src->t_data == NULL)
709 : {
710 0 : dest->t_data = NULL;
711 0 : return;
712 : }
713 :
714 0 : dest->t_len = src->t_len;
715 0 : dest->t_self = src->t_self;
716 0 : dest->t_tableOid = src->t_tableOid;
717 0 : dest->t_data = (HeapTupleHeader) palloc(src->t_len);
718 0 : memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
719 : }
720 :
721 : /*
722 : * Expand a tuple which has fewer attributes than required. For each attribute
723 : * not present in the sourceTuple, if there is a missing value that will be
724 : * used. Otherwise the attribute will be set to NULL.
725 : *
726 : * The source tuple must have fewer attributes than the required number.
727 : *
728 : * Only one of targetHeapTuple and targetMinimalTuple may be supplied. The
729 : * other argument must be NULL.
730 : */
731 : static void
732 0 : expand_tuple(HeapTuple *targetHeapTuple,
733 : MinimalTuple *targetMinimalTuple,
734 : HeapTuple sourceTuple,
735 : TupleDesc tupleDesc)
736 : {
737 0 : AttrMissing *attrmiss = NULL;
738 : int attnum;
739 : int firstmissingnum;
740 0 : bool hasNulls = HeapTupleHasNulls(sourceTuple);
741 : HeapTupleHeader targetTHeader;
742 0 : HeapTupleHeader sourceTHeader = sourceTuple->t_data;
743 0 : int sourceNatts = HeapTupleHeaderGetNatts(sourceTHeader);
744 0 : int natts = tupleDesc->natts;
745 : int sourceNullLen;
746 : int targetNullLen;
747 0 : Size sourceDataLen = sourceTuple->t_len - sourceTHeader->t_hoff;
748 : Size targetDataLen;
749 : Size len;
750 : int hoff;
751 0 : bits8 *nullBits = NULL;
752 0 : int bitMask = 0;
753 : char *targetData;
754 : uint16 *infoMask;
755 :
756 : Assert((targetHeapTuple && !targetMinimalTuple)
757 : || (!targetHeapTuple && targetMinimalTuple));
758 :
759 : Assert(sourceNatts < natts);
760 :
761 0 : sourceNullLen = (hasNulls ? BITMAPLEN(sourceNatts) : 0);
762 :
763 0 : targetDataLen = sourceDataLen;
764 :
765 0 : if (tupleDesc->constr &&
766 0 : tupleDesc->constr->missing)
767 : {
768 : /*
769 : * If there are missing values we want to put them into the tuple.
770 : * Before that we have to compute the extra length for the values
771 : * array and the variable length data.
772 : */
773 0 : attrmiss = tupleDesc->constr->missing;
774 :
775 : /*
776 : * Find the first item in attrmiss for which we don't have a value in
777 : * the source. We can ignore all the missing entries before that.
778 : */
779 0 : for (firstmissingnum = sourceNatts;
780 : firstmissingnum < natts;
781 0 : firstmissingnum++)
782 : {
783 0 : if (attrmiss[firstmissingnum].am_present)
784 0 : break;
785 : else
786 0 : hasNulls = true;
787 : }
788 :
789 : /*
790 : * Now walk the missing attributes. If there is a missing value make
791 : * space for it. Otherwise, it's going to be NULL.
792 : */
793 0 : for (attnum = firstmissingnum;
794 : attnum < natts;
795 0 : attnum++)
796 : {
797 0 : if (attrmiss[attnum].am_present)
798 : {
799 0 : Form_pg_attribute att = TupleDescAttr(tupleDesc, attnum);
800 :
801 0 : targetDataLen = att_align_datum(targetDataLen,
802 : att->attalign,
803 : att->attlen,
804 : attrmiss[attnum].am_value);
805 :
806 0 : targetDataLen = att_addlength_pointer(targetDataLen,
807 : att->attlen,
808 : attrmiss[attnum].am_value);
809 : }
810 : else
811 : {
812 : /* no missing value, so it must be null */
813 0 : hasNulls = true;
814 : }
815 : }
816 : } /* end if have missing values */
817 : else
818 : {
819 : /*
820 : * If there are no missing values at all then NULLS must be allowed,
821 : * since some of the attributes are known to be absent.
822 : */
823 0 : hasNulls = true;
824 : }
825 :
826 0 : len = 0;
827 :
828 0 : if (hasNulls)
829 : {
830 0 : targetNullLen = BITMAPLEN(natts);
831 0 : len += targetNullLen;
832 : }
833 : else
834 0 : targetNullLen = 0;
835 :
836 : /*
837 : * Allocate and zero the space needed. Note that the tuple body and
838 : * HeapTupleData management structure are allocated in one chunk.
839 : */
840 0 : if (targetHeapTuple)
841 : {
842 0 : len += offsetof(HeapTupleHeaderData, t_bits);
843 0 : hoff = len = MAXALIGN(len); /* align user data safely */
844 0 : len += targetDataLen;
845 :
846 0 : *targetHeapTuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
847 0 : (*targetHeapTuple)->t_data
848 0 : = targetTHeader
849 0 : = (HeapTupleHeader) ((char *) *targetHeapTuple + HEAPTUPLESIZE);
850 0 : (*targetHeapTuple)->t_len = len;
851 0 : (*targetHeapTuple)->t_tableOid = sourceTuple->t_tableOid;
852 0 : (*targetHeapTuple)->t_self = sourceTuple->t_self;
853 :
854 0 : targetTHeader->t_infomask = sourceTHeader->t_infomask;
855 0 : targetTHeader->t_hoff = hoff;
856 0 : HeapTupleHeaderSetNatts(targetTHeader, natts);
857 0 : HeapTupleHeaderSetDatumLength(targetTHeader, len);
858 0 : HeapTupleHeaderSetTypeId(targetTHeader, tupleDesc->tdtypeid);
859 0 : HeapTupleHeaderSetTypMod(targetTHeader, tupleDesc->tdtypmod);
860 : /* We also make sure that t_ctid is invalid unless explicitly set */
861 0 : ItemPointerSetInvalid(&(targetTHeader->t_ctid));
862 0 : if (targetNullLen > 0)
863 0 : nullBits = (bits8 *) ((char *) (*targetHeapTuple)->t_data
864 : + offsetof(HeapTupleHeaderData, t_bits));
865 0 : targetData = (char *) (*targetHeapTuple)->t_data + hoff;
866 0 : infoMask = &(targetTHeader->t_infomask);
867 : }
868 : else
869 : {
870 0 : len += SizeofMinimalTupleHeader;
871 0 : hoff = len = MAXALIGN(len); /* align user data safely */
872 0 : len += targetDataLen;
873 :
874 0 : *targetMinimalTuple = (MinimalTuple) palloc0(len);
875 0 : (*targetMinimalTuple)->t_len = len;
876 0 : (*targetMinimalTuple)->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
877 0 : (*targetMinimalTuple)->t_infomask = sourceTHeader->t_infomask;
878 : /* Same macro works for MinimalTuples */
879 0 : HeapTupleHeaderSetNatts(*targetMinimalTuple, natts);
880 0 : if (targetNullLen > 0)
881 0 : nullBits = (bits8 *) ((char *) *targetMinimalTuple
882 0 : + offsetof(MinimalTupleData, t_bits));
883 0 : targetData = (char *) *targetMinimalTuple + hoff;
884 0 : infoMask = &((*targetMinimalTuple)->t_infomask);
885 : }
886 :
887 0 : if (targetNullLen > 0)
888 : {
889 0 : if (sourceNullLen > 0)
890 : {
891 : /* if bitmap pre-existed copy in - all is set */
892 0 : memcpy(nullBits,
893 : ((char *) sourceTHeader)
894 : + offsetof(HeapTupleHeaderData, t_bits),
895 : sourceNullLen);
896 0 : nullBits += sourceNullLen - 1;
897 : }
898 : else
899 : {
900 0 : sourceNullLen = BITMAPLEN(sourceNatts);
901 : /* Set NOT NULL for all existing attributes */
902 0 : memset(nullBits, 0xff, sourceNullLen);
903 :
904 0 : nullBits += sourceNullLen - 1;
905 :
906 0 : if (sourceNatts & 0x07)
907 : {
908 : /* build the mask (inverted!) */
909 0 : bitMask = 0xff << (sourceNatts & 0x07);
910 : /* Voila */
911 0 : *nullBits = ~bitMask;
912 : }
913 : }
914 :
915 0 : bitMask = (1 << ((sourceNatts - 1) & 0x07));
916 : } /* End if have null bitmap */
917 :
918 0 : memcpy(targetData,
919 0 : ((char *) sourceTuple->t_data) + sourceTHeader->t_hoff,
920 : sourceDataLen);
921 :
922 0 : targetData += sourceDataLen;
923 :
924 : /* Now fill in the missing values */
925 0 : for (attnum = sourceNatts; attnum < natts; attnum++)
926 : {
927 :
928 0 : Form_pg_attribute attr = TupleDescAttr(tupleDesc, attnum);
929 :
930 0 : if (attrmiss && attrmiss[attnum].am_present)
931 : {
932 0 : fill_val(attr,
933 0 : nullBits ? &nullBits : NULL,
934 : &bitMask,
935 : &targetData,
936 : infoMask,
937 0 : attrmiss[attnum].am_value,
938 : false);
939 : }
940 : else
941 : {
942 0 : fill_val(attr,
943 : &nullBits,
944 : &bitMask,
945 : &targetData,
946 : infoMask,
947 : (Datum) 0,
948 : true);
949 : }
950 : } /* end loop over missing attributes */
951 0 : }
952 :
953 : /*
954 : * Fill in the missing values for a minimal HeapTuple
955 : */
956 : MinimalTuple
957 0 : minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
958 : {
959 : MinimalTuple minimalTuple;
960 :
961 0 : expand_tuple(NULL, &minimalTuple, sourceTuple, tupleDesc);
962 0 : return minimalTuple;
963 : }
964 :
965 : /*
966 : * Fill in the missing values for an ordinary HeapTuple
967 : */
968 : HeapTuple
969 0 : heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc)
970 : {
971 : HeapTuple heapTuple;
972 :
973 0 : expand_tuple(&heapTuple, NULL, sourceTuple, tupleDesc);
974 0 : return heapTuple;
975 : }
976 :
977 : /* ----------------
978 : * heap_copy_tuple_as_datum
979 : *
980 : * copy a tuple as a composite-type Datum
981 : * ----------------
982 : */
983 : Datum
984 78632 : heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
985 : {
986 : HeapTupleHeader td;
987 :
988 : /*
989 : * If the tuple contains any external TOAST pointers, we have to inline
990 : * those fields to meet the conventions for composite-type Datums.
991 : */
992 78632 : if (HeapTupleHasExternal(tuple))
993 0 : return toast_flatten_tuple_to_datum(tuple->t_data,
994 : tuple->t_len,
995 : tupleDesc);
996 :
997 : /*
998 : * Fast path for easy case: just make a palloc'd copy and insert the
999 : * correct composite-Datum header fields (since those may not be set if
1000 : * the given tuple came from disk, rather than from heap_form_tuple).
1001 : */
1002 78632 : td = (HeapTupleHeader) palloc(tuple->t_len);
1003 78632 : memcpy((char *) td, (char *) tuple->t_data, tuple->t_len);
1004 :
1005 78632 : HeapTupleHeaderSetDatumLength(td, tuple->t_len);
1006 78632 : HeapTupleHeaderSetTypeId(td, tupleDesc->tdtypeid);
1007 78632 : HeapTupleHeaderSetTypMod(td, tupleDesc->tdtypmod);
1008 :
1009 78632 : return PointerGetDatum(td);
1010 : }
1011 :
1012 : /*
1013 : * heap_form_tuple
1014 : * construct a tuple from the given values[] and isnull[] arrays,
1015 : * which are of the length indicated by tupleDescriptor->natts
1016 : *
1017 : * The result is allocated in the current memory context.
1018 : */
1019 : HeapTuple
1020 33687114 : heap_form_tuple(TupleDesc tupleDescriptor,
1021 : Datum *values,
1022 : bool *isnull)
1023 : {
1024 : HeapTuple tuple; /* return tuple */
1025 : HeapTupleHeader td; /* tuple data */
1026 : Size len,
1027 : data_len;
1028 : int hoff;
1029 33687114 : bool hasnull = false;
1030 33687114 : int numberOfAttributes = tupleDescriptor->natts;
1031 : int i;
1032 :
1033 33687114 : if (numberOfAttributes > MaxTupleAttributeNumber)
1034 0 : ereport(ERROR,
1035 : (errcode(ERRCODE_TOO_MANY_COLUMNS),
1036 : errmsg("number of columns (%d) exceeds limit (%d)",
1037 : numberOfAttributes, MaxTupleAttributeNumber)));
1038 :
1039 : /*
1040 : * Check for nulls
1041 : */
1042 260525888 : for (i = 0; i < numberOfAttributes; i++)
1043 : {
1044 237559684 : if (isnull[i])
1045 : {
1046 10720910 : hasnull = true;
1047 10720910 : break;
1048 : }
1049 : }
1050 :
1051 : /*
1052 : * Determine total space needed
1053 : */
1054 33687114 : len = offsetof(HeapTupleHeaderData, t_bits);
1055 :
1056 33687114 : if (hasnull)
1057 10720910 : len += BITMAPLEN(numberOfAttributes);
1058 :
1059 33687114 : hoff = len = MAXALIGN(len); /* align user data safely */
1060 :
1061 33687114 : data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1062 :
1063 33687114 : len += data_len;
1064 :
1065 : /*
1066 : * Allocate and zero the space needed. Note that the tuple body and
1067 : * HeapTupleData management structure are allocated in one chunk.
1068 : */
1069 33687114 : tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
1070 33687114 : tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
1071 :
1072 : /*
1073 : * And fill in the information. Note we fill the Datum fields even though
1074 : * this tuple may never become a Datum. This lets HeapTupleHeaderGetDatum
1075 : * identify the tuple type if needed.
1076 : */
1077 33687114 : tuple->t_len = len;
1078 33687114 : ItemPointerSetInvalid(&(tuple->t_self));
1079 33687114 : tuple->t_tableOid = InvalidOid;
1080 :
1081 33687114 : HeapTupleHeaderSetDatumLength(td, len);
1082 33687114 : HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
1083 33687114 : HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
1084 : /* We also make sure that t_ctid is invalid unless explicitly set */
1085 33687114 : ItemPointerSetInvalid(&(td->t_ctid));
1086 :
1087 33687114 : HeapTupleHeaderSetNatts(td, numberOfAttributes);
1088 33687114 : td->t_hoff = hoff;
1089 :
1090 33687114 : heap_fill_tuple(tupleDescriptor,
1091 : values,
1092 : isnull,
1093 : (char *) td + hoff,
1094 : data_len,
1095 : &td->t_infomask,
1096 : (hasnull ? td->t_bits : NULL));
1097 :
1098 33687114 : return tuple;
1099 : }
1100 :
1101 : /*
1102 : * heap_modify_tuple
1103 : * form a new tuple from an old tuple and a set of replacement values.
1104 : *
1105 : * The replValues, replIsnull, and doReplace arrays must be of the length
1106 : * indicated by tupleDesc->natts. The new tuple is constructed using the data
1107 : * from replValues/replIsnull at columns where doReplace is true, and using
1108 : * the data from the old tuple at columns where doReplace is false.
1109 : *
1110 : * The result is allocated in the current memory context.
1111 : */
1112 : HeapTuple
1113 197864 : heap_modify_tuple(HeapTuple tuple,
1114 : TupleDesc tupleDesc,
1115 : Datum *replValues,
1116 : bool *replIsnull,
1117 : bool *doReplace)
1118 : {
1119 197864 : int numberOfAttributes = tupleDesc->natts;
1120 : int attoff;
1121 : Datum *values;
1122 : bool *isnull;
1123 : HeapTuple newTuple;
1124 :
1125 : /*
1126 : * allocate and fill values and isnull arrays from either the tuple or the
1127 : * repl information, as appropriate.
1128 : *
1129 : * NOTE: it's debatable whether to use heap_deform_tuple() here or just
1130 : * heap_getattr() only the non-replaced columns. The latter could win if
1131 : * there are many replaced columns and few non-replaced ones. However,
1132 : * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
1133 : * O(N^2) if there are many non-replaced columns, so it seems better to
1134 : * err on the side of linear cost.
1135 : */
1136 197864 : values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1137 197864 : isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
1138 :
1139 197864 : heap_deform_tuple(tuple, tupleDesc, values, isnull);
1140 :
1141 6075418 : for (attoff = 0; attoff < numberOfAttributes; attoff++)
1142 : {
1143 5877554 : if (doReplace[attoff])
1144 : {
1145 2106720 : values[attoff] = replValues[attoff];
1146 2106720 : isnull[attoff] = replIsnull[attoff];
1147 : }
1148 : }
1149 :
1150 : /*
1151 : * create a new tuple from the values and isnull arrays
1152 : */
1153 197864 : newTuple = heap_form_tuple(tupleDesc, values, isnull);
1154 :
1155 197864 : pfree(values);
1156 197864 : pfree(isnull);
1157 :
1158 : /*
1159 : * copy the identification info of the old tuple: t_ctid, t_self
1160 : */
1161 197864 : newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1162 197864 : newTuple->t_self = tuple->t_self;
1163 197864 : newTuple->t_tableOid = tuple->t_tableOid;
1164 :
1165 197864 : return newTuple;
1166 : }
1167 :
1168 : /*
1169 : * heap_modify_tuple_by_cols
1170 : * form a new tuple from an old tuple and a set of replacement values.
1171 : *
1172 : * This is like heap_modify_tuple, except that instead of specifying which
1173 : * column(s) to replace by a boolean map, an array of target column numbers
1174 : * is used. This is often more convenient when a fixed number of columns
1175 : * are to be replaced. The replCols, replValues, and replIsnull arrays must
1176 : * be of length nCols. Target column numbers are indexed from 1.
1177 : *
1178 : * The result is allocated in the current memory context.
1179 : */
1180 : HeapTuple
1181 36 : heap_modify_tuple_by_cols(HeapTuple tuple,
1182 : TupleDesc tupleDesc,
1183 : int nCols,
1184 : int *replCols,
1185 : Datum *replValues,
1186 : bool *replIsnull)
1187 : {
1188 36 : int numberOfAttributes = tupleDesc->natts;
1189 : Datum *values;
1190 : bool *isnull;
1191 : HeapTuple newTuple;
1192 : int i;
1193 :
1194 : /*
1195 : * allocate and fill values and isnull arrays from the tuple, then replace
1196 : * selected columns from the input arrays.
1197 : */
1198 36 : values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1199 36 : isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
1200 :
1201 36 : heap_deform_tuple(tuple, tupleDesc, values, isnull);
1202 :
1203 72 : for (i = 0; i < nCols; i++)
1204 : {
1205 36 : int attnum = replCols[i];
1206 :
1207 36 : if (attnum <= 0 || attnum > numberOfAttributes)
1208 0 : elog(ERROR, "invalid column number %d", attnum);
1209 36 : values[attnum - 1] = replValues[i];
1210 36 : isnull[attnum - 1] = replIsnull[i];
1211 : }
1212 :
1213 : /*
1214 : * create a new tuple from the values and isnull arrays
1215 : */
1216 36 : newTuple = heap_form_tuple(tupleDesc, values, isnull);
1217 :
1218 36 : pfree(values);
1219 36 : pfree(isnull);
1220 :
1221 : /*
1222 : * copy the identification info of the old tuple: t_ctid, t_self
1223 : */
1224 36 : newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1225 36 : newTuple->t_self = tuple->t_self;
1226 36 : newTuple->t_tableOid = tuple->t_tableOid;
1227 :
1228 36 : return newTuple;
1229 : }
1230 :
1231 : /*
1232 : * heap_deform_tuple
1233 : * Given a tuple, extract data into values/isnull arrays; this is
1234 : * the inverse of heap_form_tuple.
1235 : *
1236 : * Storage for the values/isnull arrays is provided by the caller;
1237 : * it should be sized according to tupleDesc->natts not
1238 : * HeapTupleHeaderGetNatts(tuple->t_data).
1239 : *
1240 : * Note that for pass-by-reference datatypes, the pointer placed
1241 : * in the Datum will point into the given tuple.
1242 : *
1243 : * When all or most of a tuple's fields need to be extracted,
1244 : * this routine will be significantly quicker than a loop around
1245 : * heap_getattr; the loop will become O(N^2) as soon as any
1246 : * noncacheable attribute offsets are involved.
1247 : */
1248 : void
1249 5862884 : heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
1250 : Datum *values, bool *isnull)
1251 : {
1252 5862884 : HeapTupleHeader tup = tuple->t_data;
1253 5862884 : bool hasnulls = HeapTupleHasNulls(tuple);
1254 5862884 : int tdesc_natts = tupleDesc->natts;
1255 : int natts; /* number of atts to extract */
1256 : int attnum;
1257 : char *tp; /* ptr to tuple data */
1258 : uint32 off; /* offset in tuple data */
1259 5862884 : bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
1260 5862884 : bool slow = false; /* can we use/set attcacheoff? */
1261 :
1262 5862884 : natts = HeapTupleHeaderGetNatts(tup);
1263 :
1264 : /*
1265 : * In inheritance situations, it is possible that the given tuple actually
1266 : * has more fields than the caller is expecting. Don't run off the end of
1267 : * the caller's arrays.
1268 : */
1269 5862884 : natts = Min(natts, tdesc_natts);
1270 :
1271 5862884 : tp = (char *) tup + tup->t_hoff;
1272 :
1273 5862884 : off = 0;
1274 :
1275 25830498 : for (attnum = 0; attnum < natts; attnum++)
1276 : {
1277 19967614 : Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum);
1278 :
1279 19967614 : if (hasnulls && att_isnull(attnum, bp))
1280 : {
1281 1765984 : values[attnum] = (Datum) 0;
1282 1765984 : isnull[attnum] = true;
1283 1765984 : slow = true; /* can't use attcacheoff anymore */
1284 1765984 : continue;
1285 : }
1286 :
1287 18201630 : isnull[attnum] = false;
1288 :
1289 18201630 : if (!slow && thisatt->attcacheoff >= 0)
1290 16913188 : off = thisatt->attcacheoff;
1291 1288442 : else if (thisatt->attlen == -1)
1292 : {
1293 : /*
1294 : * We can only cache the offset for a varlena attribute if the
1295 : * offset is already suitably aligned, so that there would be no
1296 : * pad bytes in any case: then the offset will be valid for either
1297 : * an aligned or unaligned value.
1298 : */
1299 853384 : if (!slow &&
1300 145602 : off == att_align_nominal(off, thisatt->attalign))
1301 46908 : thisatt->attcacheoff = off;
1302 : else
1303 : {
1304 660874 : off = att_align_pointer(off, thisatt->attalign, -1,
1305 : tp + off);
1306 660874 : slow = true;
1307 : }
1308 : }
1309 : else
1310 : {
1311 : /* not varlena, so safe to use att_align_nominal */
1312 580660 : off = att_align_nominal(off, thisatt->attalign);
1313 :
1314 580660 : if (!slow)
1315 101010 : thisatt->attcacheoff = off;
1316 : }
1317 :
1318 18201630 : values[attnum] = fetchatt(thisatt, tp + off);
1319 :
1320 18201630 : off = att_addlength_pointer(off, thisatt->attlen, tp + off);
1321 :
1322 18201630 : if (thisatt->attlen <= 0)
1323 3033666 : slow = true; /* can't use attcacheoff anymore */
1324 : }
1325 :
1326 : /*
1327 : * If tuple doesn't have all the atts indicated by tupleDesc, read the
1328 : * rest as nulls or missing values as appropriate.
1329 : */
1330 5862910 : for (; attnum < tdesc_natts; attnum++)
1331 26 : values[attnum] = getmissingattr(tupleDesc, attnum + 1, &isnull[attnum]);
1332 5862884 : }
1333 :
1334 : /*
1335 : * heap_freetuple
1336 : */
1337 : void
1338 31201212 : heap_freetuple(HeapTuple htup)
1339 : {
1340 31201212 : pfree(htup);
1341 31201212 : }
1342 :
1343 :
1344 : /*
1345 : * heap_form_minimal_tuple
1346 : * construct a MinimalTuple from the given values[] and isnull[] arrays,
1347 : * which are of the length indicated by tupleDescriptor->natts
1348 : *
1349 : * This is exactly like heap_form_tuple() except that the result is a
1350 : * "minimal" tuple lacking a HeapTupleData header as well as room for system
1351 : * columns.
1352 : *
1353 : * The result is allocated in the current memory context.
1354 : */
1355 : MinimalTuple
1356 43092282 : heap_form_minimal_tuple(TupleDesc tupleDescriptor,
1357 : Datum *values,
1358 : bool *isnull)
1359 : {
1360 : MinimalTuple tuple; /* return tuple */
1361 : Size len,
1362 : data_len;
1363 : int hoff;
1364 43092282 : bool hasnull = false;
1365 43092282 : int numberOfAttributes = tupleDescriptor->natts;
1366 : int i;
1367 :
1368 43092282 : if (numberOfAttributes > MaxTupleAttributeNumber)
1369 0 : ereport(ERROR,
1370 : (errcode(ERRCODE_TOO_MANY_COLUMNS),
1371 : errmsg("number of columns (%d) exceeds limit (%d)",
1372 : numberOfAttributes, MaxTupleAttributeNumber)));
1373 :
1374 : /*
1375 : * Check for nulls
1376 : */
1377 118530956 : for (i = 0; i < numberOfAttributes; i++)
1378 : {
1379 75938576 : if (isnull[i])
1380 : {
1381 499902 : hasnull = true;
1382 499902 : break;
1383 : }
1384 : }
1385 :
1386 : /*
1387 : * Determine total space needed
1388 : */
1389 43092282 : len = SizeofMinimalTupleHeader;
1390 :
1391 43092282 : if (hasnull)
1392 499902 : len += BITMAPLEN(numberOfAttributes);
1393 :
1394 43092282 : hoff = len = MAXALIGN(len); /* align user data safely */
1395 :
1396 43092282 : data_len = heap_compute_data_size(tupleDescriptor, values, isnull);
1397 :
1398 43092282 : len += data_len;
1399 :
1400 : /*
1401 : * Allocate and zero the space needed.
1402 : */
1403 43092282 : tuple = (MinimalTuple) palloc0(len);
1404 :
1405 : /*
1406 : * And fill in the information.
1407 : */
1408 43092282 : tuple->t_len = len;
1409 43092282 : HeapTupleHeaderSetNatts(tuple, numberOfAttributes);
1410 43092282 : tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
1411 :
1412 43092282 : heap_fill_tuple(tupleDescriptor,
1413 : values,
1414 : isnull,
1415 : (char *) tuple + hoff,
1416 : data_len,
1417 : &tuple->t_infomask,
1418 : (hasnull ? tuple->t_bits : NULL));
1419 :
1420 43092282 : return tuple;
1421 : }
1422 :
1423 : /*
1424 : * heap_free_minimal_tuple
1425 : */
1426 : void
1427 37180880 : heap_free_minimal_tuple(MinimalTuple mtup)
1428 : {
1429 37180880 : pfree(mtup);
1430 37180880 : }
1431 :
1432 : /*
1433 : * heap_copy_minimal_tuple
1434 : * copy a MinimalTuple
1435 : *
1436 : * The result is allocated in the current memory context.
1437 : */
1438 : MinimalTuple
1439 4435834 : heap_copy_minimal_tuple(MinimalTuple mtup)
1440 : {
1441 : MinimalTuple result;
1442 :
1443 4435834 : result = (MinimalTuple) palloc(mtup->t_len);
1444 4435834 : memcpy(result, mtup, mtup->t_len);
1445 4435834 : return result;
1446 : }
1447 :
1448 : /*
1449 : * heap_tuple_from_minimal_tuple
1450 : * create a HeapTuple by copying from a MinimalTuple;
1451 : * system columns are filled with zeroes
1452 : *
1453 : * The result is allocated in the current memory context.
1454 : * The HeapTuple struct, tuple header, and tuple data are all allocated
1455 : * as a single palloc() block.
1456 : */
1457 : HeapTuple
1458 990526 : heap_tuple_from_minimal_tuple(MinimalTuple mtup)
1459 : {
1460 : HeapTuple result;
1461 990526 : uint32 len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
1462 :
1463 990526 : result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
1464 990526 : result->t_len = len;
1465 990526 : ItemPointerSetInvalid(&(result->t_self));
1466 990526 : result->t_tableOid = InvalidOid;
1467 990526 : result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
1468 990526 : memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
1469 990526 : memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_infomask2));
1470 990526 : return result;
1471 : }
1472 :
1473 : /*
1474 : * minimal_tuple_from_heap_tuple
1475 : * create a MinimalTuple by copying from a HeapTuple
1476 : *
1477 : * The result is allocated in the current memory context.
1478 : */
1479 : MinimalTuple
1480 3479040 : minimal_tuple_from_heap_tuple(HeapTuple htup)
1481 : {
1482 : MinimalTuple result;
1483 : uint32 len;
1484 :
1485 : Assert(htup->t_len > MINIMAL_TUPLE_OFFSET);
1486 3479040 : len = htup->t_len - MINIMAL_TUPLE_OFFSET;
1487 3479040 : result = (MinimalTuple) palloc(len);
1488 3479040 : memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
1489 3479040 : result->t_len = len;
1490 3479040 : return result;
1491 : }
1492 :
1493 : /*
1494 : * This mainly exists so JIT can inline the definition, but it's also
1495 : * sometimes useful in debugging sessions.
1496 : */
1497 : size_t
1498 324012 : varsize_any(void *p)
1499 : {
1500 324012 : return VARSIZE_ANY(p);
1501 : }
|