]> granicus.if.org Git - postgresql/blob - src/backend/access/common/heaptuple.c
Ensure that the Datum generated from a whole-row Var contains valid
[postgresql] / src / backend / access / common / heaptuple.c
1 /*-------------------------------------------------------------------------
2  *
3  * heaptuple.c
4  *        This file contains heap tuple accessor and mutator routines, as well
5  *        as various tuple utilities.
6  *
7  * NOTE: there is massive duplication of code in this module to
8  * support both the convention that a null is marked by a bool TRUE,
9  * and the convention that a null is marked by a char 'n'.      The latter
10  * convention is deprecated but it'll probably be a long time before
11  * we can get rid of it entirely.
12  *
13  *
14  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
15  * Portions Copyright (c) 1994, Regents of the University of California
16  *
17  *
18  * IDENTIFICATION
19  *        $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.101 2005/10/19 18:18:32 tgl Exp $
20  *
21  *-------------------------------------------------------------------------
22  */
23
24 #include "postgres.h"
25
26 #include "access/heapam.h"
27 #include "access/tuptoaster.h"
28 #include "catalog/pg_type.h"
29 #include "executor/tuptable.h"
30 #include "utils/typcache.h"
31
32
33 /* ----------------------------------------------------------------
34  *                                              misc support routines
35  * ----------------------------------------------------------------
36  */
37
38 /*
39  * heap_compute_data_size
40  *              Determine size of the data area of a tuple to be constructed
41  */
42 Size
43 heap_compute_data_size(TupleDesc tupleDesc,
44                                            Datum *values,
45                                            bool *isnull)
46 {
47         Size            data_length = 0;
48         int                     i;
49         int                     numberOfAttributes = tupleDesc->natts;
50         Form_pg_attribute *att = tupleDesc->attrs;
51
52         for (i = 0; i < numberOfAttributes; i++)
53         {
54                 if (isnull[i])
55                         continue;
56
57                 data_length = att_align(data_length, att[i]->attalign);
58                 data_length = att_addlength(data_length, att[i]->attlen, values[i]);
59         }
60
61         return data_length;
62 }
63
64 /* ----------------
65  *              ComputeDataSize
66  *
67  * Determine size of the data area of a tuple to be constructed
68  *
69  * OLD API with char 'n'/' ' convention for indicating nulls
70  * ----------------
71  */
72 static Size
73 ComputeDataSize(TupleDesc tupleDesc,
74                                 Datum *values,
75                                 char *nulls)
76 {
77         Size            data_length = 0;
78         int                     i;
79         int                     numberOfAttributes = tupleDesc->natts;
80         Form_pg_attribute *att = tupleDesc->attrs;
81
82         for (i = 0; i < numberOfAttributes; i++)
83         {
84                 if (nulls[i] != ' ')
85                         continue;
86
87                 data_length = att_align(data_length, att[i]->attalign);
88                 data_length = att_addlength(data_length, att[i]->attlen, values[i]);
89         }
90
91         return data_length;
92 }
93
94 /*
95  * heap_fill_tuple
96  *              Load data portion of a tuple from values/isnull arrays
97  *
98  * We also fill the null bitmap (if any) and set the infomask bits
99  * that reflect the tuple's data contents.
100  */
101 void
102 heap_fill_tuple(TupleDesc tupleDesc,
103                                 Datum *values, bool *isnull,
104                                 char *data, uint16 *infomask, bits8 *bit)
105 {
106         bits8      *bitP;
107         int                     bitmask;
108         int                     i;
109         int                     numberOfAttributes = tupleDesc->natts;
110         Form_pg_attribute *att = tupleDesc->attrs;
111
112         if (bit != NULL)
113         {
114                 bitP = &bit[-1];
115                 bitmask = CSIGNBIT;
116         }
117         else
118         {
119                 /* just to keep compiler quiet */
120                 bitP = NULL;
121                 bitmask = 0;
122         }
123
124         *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTENDED);
125
126         for (i = 0; i < numberOfAttributes; i++)
127         {
128                 Size            data_length;
129
130                 if (bit != NULL)
131                 {
132                         if (bitmask != CSIGNBIT)
133                                 bitmask <<= 1;
134                         else
135                         {
136                                 bitP += 1;
137                                 *bitP = 0x0;
138                                 bitmask = 1;
139                         }
140
141                         if (isnull[i])
142                         {
143                                 *infomask |= HEAP_HASNULL;
144                                 continue;
145                         }
146
147                         *bitP |= bitmask;
148                 }
149
150                 /* XXX we are aligning the pointer itself, not the offset */
151                 data = (char *) att_align((long) data, att[i]->attalign);
152
153                 if (att[i]->attbyval)
154                 {
155                         /* pass-by-value */
156                         store_att_byval(data, values[i], att[i]->attlen);
157                         data_length = att[i]->attlen;
158                 }
159                 else if (att[i]->attlen == -1)
160                 {
161                         /* varlena */
162                         *infomask |= HEAP_HASVARWIDTH;
163                         if (VARATT_IS_EXTERNAL(values[i]))
164                                 *infomask |= HEAP_HASEXTERNAL;
165                         if (VARATT_IS_COMPRESSED(values[i]))
166                                 *infomask |= HEAP_HASCOMPRESSED;
167                         data_length = VARATT_SIZE(DatumGetPointer(values[i]));
168                         memcpy(data, DatumGetPointer(values[i]), data_length);
169                 }
170                 else if (att[i]->attlen == -2)
171                 {
172                         /* cstring */
173                         *infomask |= HEAP_HASVARWIDTH;
174                         data_length = strlen(DatumGetCString(values[i])) + 1;
175                         memcpy(data, DatumGetPointer(values[i]), data_length);
176                 }
177                 else
178                 {
179                         /* fixed-length pass-by-reference */
180                         Assert(att[i]->attlen > 0);
181                         data_length = att[i]->attlen;
182                         memcpy(data, DatumGetPointer(values[i]), data_length);
183                 }
184
185                 data += data_length;
186         }
187 }
188
189 /* ----------------
190  *              DataFill
191  *
192  * Load data portion of a tuple from values/nulls arrays
193  *
194  * OLD API with char 'n'/' ' convention for indicating nulls
195  * ----------------
196  */
197 static void
198 DataFill(char *data,
199                  TupleDesc tupleDesc,
200                  Datum *values,
201                  char *nulls,
202                  uint16 *infomask,
203                  bits8 *bit)
204 {
205         bits8      *bitP;
206         int                     bitmask;
207         int                     i;
208         int                     numberOfAttributes = tupleDesc->natts;
209         Form_pg_attribute *att = tupleDesc->attrs;
210
211         if (bit != NULL)
212         {
213                 bitP = &bit[-1];
214                 bitmask = CSIGNBIT;
215         }
216         else
217         {
218                 /* just to keep compiler quiet */
219                 bitP = NULL;
220                 bitmask = 0;
221         }
222
223         *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTENDED);
224
225         for (i = 0; i < numberOfAttributes; i++)
226         {
227                 Size            data_length;
228
229                 if (bit != NULL)
230                 {
231                         if (bitmask != CSIGNBIT)
232                                 bitmask <<= 1;
233                         else
234                         {
235                                 bitP += 1;
236                                 *bitP = 0x0;
237                                 bitmask = 1;
238                         }
239
240                         if (nulls[i] == 'n')
241                         {
242                                 *infomask |= HEAP_HASNULL;
243                                 continue;
244                         }
245
246                         *bitP |= bitmask;
247                 }
248
249                 /* XXX we are aligning the pointer itself, not the offset */
250                 data = (char *) att_align((long) data, att[i]->attalign);
251
252                 if (att[i]->attbyval)
253                 {
254                         /* pass-by-value */
255                         store_att_byval(data, values[i], att[i]->attlen);
256                         data_length = att[i]->attlen;
257                 }
258                 else if (att[i]->attlen == -1)
259                 {
260                         /* varlena */
261                         *infomask |= HEAP_HASVARWIDTH;
262                         if (VARATT_IS_EXTERNAL(values[i]))
263                                 *infomask |= HEAP_HASEXTERNAL;
264                         if (VARATT_IS_COMPRESSED(values[i]))
265                                 *infomask |= HEAP_HASCOMPRESSED;
266                         data_length = VARATT_SIZE(DatumGetPointer(values[i]));
267                         memcpy(data, DatumGetPointer(values[i]), data_length);
268                 }
269                 else if (att[i]->attlen == -2)
270                 {
271                         /* cstring */
272                         *infomask |= HEAP_HASVARWIDTH;
273                         data_length = strlen(DatumGetCString(values[i])) + 1;
274                         memcpy(data, DatumGetPointer(values[i]), data_length);
275                 }
276                 else
277                 {
278                         /* fixed-length pass-by-reference */
279                         Assert(att[i]->attlen > 0);
280                         data_length = att[i]->attlen;
281                         memcpy(data, DatumGetPointer(values[i]), data_length);
282                 }
283
284                 data += data_length;
285         }
286 }
287
288 /* ----------------------------------------------------------------
289  *                                              heap tuple interface
290  * ----------------------------------------------------------------
291  */
292
293 /* ----------------
294  *              heap_attisnull  - returns TRUE iff tuple attribute is not present
295  * ----------------
296  */
297 bool
298 heap_attisnull(HeapTuple tup, int attnum)
299 {
300         if (attnum > (int) tup->t_data->t_natts)
301                 return true;
302
303         if (attnum > 0)
304         {
305                 if (HeapTupleNoNulls(tup))
306                         return false;
307                 return att_isnull(attnum - 1, tup->t_data->t_bits);
308         }
309
310         switch (attnum)
311         {
312                 case TableOidAttributeNumber:
313                 case SelfItemPointerAttributeNumber:
314                 case ObjectIdAttributeNumber:
315                 case MinTransactionIdAttributeNumber:
316                 case MinCommandIdAttributeNumber:
317                 case MaxTransactionIdAttributeNumber:
318                 case MaxCommandIdAttributeNumber:
319                         /* these are never null */
320                         break;
321
322                 default:
323                         elog(ERROR, "invalid attnum: %d", attnum);
324         }
325
326         return false;
327 }
328
329 /* ----------------
330  *              nocachegetattr
331  *
332  *              This only gets called from fastgetattr() macro, in cases where
333  *              we can't use a cacheoffset and the value is not null.
334  *
335  *              This caches attribute offsets in the attribute descriptor.
336  *
337  *              An alternate way to speed things up would be to cache offsets
338  *              with the tuple, but that seems more difficult unless you take
339  *              the storage hit of actually putting those offsets into the
340  *              tuple you send to disk.  Yuck.
341  *
342  *              This scheme will be slightly slower than that, but should
343  *              perform well for queries which hit large #'s of tuples.  After
344  *              you cache the offsets once, examining all the other tuples using
345  *              the same attribute descriptor will go much quicker. -cim 5/4/91
346  *
347  *              NOTE: if you need to change this code, see also heap_deform_tuple.
348  * ----------------
349  */
350 Datum
351 nocachegetattr(HeapTuple tuple,
352                            int attnum,
353                            TupleDesc tupleDesc,
354                            bool *isnull)
355 {
356         HeapTupleHeader tup = tuple->t_data;
357         Form_pg_attribute *att = tupleDesc->attrs;
358         char       *tp;                         /* ptr to att in tuple */
359         bits8      *bp = tup->t_bits;           /* ptr to null bitmap in tuple */
360         bool            slow = false;   /* do we have to walk nulls? */
361
362         (void) isnull;                          /* not used */
363 #ifdef IN_MACRO
364 /* This is handled in the macro */
365         Assert(attnum > 0);
366
367         if (isnull)
368                 *isnull = false;
369 #endif
370
371         attnum--;
372
373         /* ----------------
374          *       Three cases:
375          *
376          *       1: No nulls and no variable-width attributes.
377          *       2: Has a null or a var-width AFTER att.
378          *       3: Has nulls or var-widths BEFORE att.
379          * ----------------
380          */
381
382         if (HeapTupleNoNulls(tuple))
383         {
384 #ifdef IN_MACRO
385 /* This is handled in the macro */
386                 if (att[attnum]->attcacheoff != -1)
387                 {
388                         return fetchatt(att[attnum],
389                                                         (char *) tup + tup->t_hoff +
390                                                         att[attnum]->attcacheoff);
391                 }
392 #endif
393         }
394         else
395         {
396                 /*
397                  * there's a null somewhere in the tuple
398                  *
399                  * check to see if desired att is null
400                  */
401
402 #ifdef IN_MACRO
403 /* This is handled in the macro */
404                 if (att_isnull(attnum, bp))
405                 {
406                         if (isnull)
407                                 *isnull = true;
408                         return (Datum) NULL;
409                 }
410 #endif
411
412                 /*
413                  * Now check to see if any preceding bits are null...
414                  */
415                 {
416                         int                     byte = attnum >> 3;
417                         int                     finalbit = attnum & 0x07;
418
419                         /* check for nulls "before" final bit of last byte */
420                         if ((~bp[byte]) & ((1 << finalbit) - 1))
421                                 slow = true;
422                         else
423                         {
424                                 /* check for nulls in any "earlier" bytes */
425                                 int                     i;
426
427                                 for (i = 0; i < byte; i++)
428                                 {
429                                         if (bp[i] != 0xFF)
430                                         {
431                                                 slow = true;
432                                                 break;
433                                         }
434                                 }
435                         }
436                 }
437         }
438
439         tp = (char *) tup + tup->t_hoff;
440
441         /*
442          * now check for any non-fixed length attrs before our attribute
443          */
444         if (!slow)
445         {
446                 if (att[attnum]->attcacheoff != -1)
447                 {
448                         return fetchatt(att[attnum],
449                                                         tp + att[attnum]->attcacheoff);
450                 }
451                 else if (HeapTupleHasVarWidth(tuple))
452                 {
453                         int                     j;
454
455                         /*
456                          * In for(), we test <= and not < because we want to see if we can
457                          * go past it in initializing offsets.
458                          */
459                         for (j = 0; j <= attnum; j++)
460                         {
461                                 if (att[j]->attlen <= 0)
462                                 {
463                                         slow = true;
464                                         break;
465                                 }
466                         }
467                 }
468         }
469
470         /*
471          * If slow is false, and we got here, we know that we have a tuple with no
472          * nulls or var-widths before the target attribute. If possible, we also
473          * want to initialize the remainder of the attribute cached offset values.
474          */
475         if (!slow)
476         {
477                 int                     j = 1;
478                 long            off;
479
480                 /*
481                  * need to set cache for some atts
482                  */
483
484                 att[0]->attcacheoff = 0;
485
486                 while (j < attnum && att[j]->attcacheoff > 0)
487                         j++;
488
489                 off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
490
491                 for (; j <= attnum ||
492                 /* Can we compute more?  We will probably need them */
493                          (j < tup->t_natts &&
494                           att[j]->attcacheoff == -1 &&
495                           (HeapTupleNoNulls(tuple) || !att_isnull(j, bp)) &&
496                           (HeapTupleAllFixed(tuple) || att[j]->attlen > 0)); j++)
497                 {
498                         off = att_align(off, att[j]->attalign);
499
500                         att[j]->attcacheoff = off;
501
502                         off = att_addlength(off, att[j]->attlen, tp + off);
503                 }
504
505                 return fetchatt(att[attnum], tp + att[attnum]->attcacheoff);
506         }
507         else
508         {
509                 bool            usecache = true;
510                 int                     off = 0;
511                 int                     i;
512
513                 /*
514                  * Now we know that we have to walk the tuple CAREFULLY.
515                  *
516                  * Note - This loop is a little tricky.  For each non-null attribute, we
517                  * have to first account for alignment padding before the attr, then
518                  * advance over the attr based on its length.  Nulls have no storage
519                  * and no alignment padding either.  We can use/set attcacheoff until
520                  * we pass either a null or a var-width attribute.
521                  */
522
523                 for (i = 0; i < attnum; i++)
524                 {
525                         if (HeapTupleHasNulls(tuple) && att_isnull(i, bp))
526                         {
527                                 usecache = false;
528                                 continue;
529                         }
530
531                         /* If we know the next offset, we can skip the alignment calc */
532                         if (usecache && att[i]->attcacheoff != -1)
533                                 off = att[i]->attcacheoff;
534                         else
535                         {
536                                 off = att_align(off, att[i]->attalign);
537
538                                 if (usecache)
539                                         att[i]->attcacheoff = off;
540                         }
541
542                         off = att_addlength(off, att[i]->attlen, tp + off);
543
544                         if (usecache && att[i]->attlen <= 0)
545                                 usecache = false;
546                 }
547
548                 off = att_align(off, att[attnum]->attalign);
549
550                 return fetchatt(att[attnum], tp + off);
551         }
552 }
553
554 /* ----------------
555  *              heap_getsysattr
556  *
557  *              Fetch the value of a system attribute for a tuple.
558  *
559  * This is a support routine for the heap_getattr macro.  The macro
560  * has already determined that the attnum refers to a system attribute.
561  * ----------------
562  */
563 Datum
564 heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
565 {
566         Datum           result;
567
568         Assert(tup);
569
570         /* Currently, no sys attribute ever reads as NULL. */
571         if (isnull)
572                 *isnull = false;
573
574         switch (attnum)
575         {
576                 case SelfItemPointerAttributeNumber:
577                         /* pass-by-reference datatype */
578                         result = PointerGetDatum(&(tup->t_self));
579                         break;
580                 case ObjectIdAttributeNumber:
581                         result = ObjectIdGetDatum(HeapTupleGetOid(tup));
582                         break;
583                 case MinTransactionIdAttributeNumber:
584                         result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));
585                         break;
586                 case MinCommandIdAttributeNumber:
587                         result = CommandIdGetDatum(HeapTupleHeaderGetCmin(tup->t_data));
588                         break;
589                 case MaxTransactionIdAttributeNumber:
590                         result = TransactionIdGetDatum(HeapTupleHeaderGetXmax(tup->t_data));
591                         break;
592                 case MaxCommandIdAttributeNumber:
593                         result = CommandIdGetDatum(HeapTupleHeaderGetCmax(tup->t_data));
594                         break;
595                 case TableOidAttributeNumber:
596                         result = ObjectIdGetDatum(tup->t_tableOid);
597                         break;
598
599                         /*
600                          * If the attribute number is 0, then we are supposed to return
601                          * the entire tuple as a row-type Datum.  (Using zero for this
602                          * purpose is unclean since it risks confusion with "invalid attr"
603                          * result codes, but it's not worth changing now.)
604                          *
605                          * We have to make a copy of the tuple so we can safely insert the
606                          * Datum overhead fields, which are not set in on-disk tuples.
607                          *
608                          * It's possible that the passed tupleDesc is a record type that
609                          * hasn't been "blessed" yet, so cover that case.
610                          */
611                 case InvalidAttrNumber:
612                         {
613                                 HeapTupleHeader dtup;
614
615                                 if (tupleDesc->tdtypeid == RECORDOID &&
616                                         tupleDesc->tdtypmod < 0)
617                                         assign_record_type_typmod(tupleDesc);
618
619                                 dtup = (HeapTupleHeader) palloc(tup->t_len);
620                                 memcpy((char *) dtup, (char *) tup->t_data, tup->t_len);
621
622                                 HeapTupleHeaderSetDatumLength(dtup, tup->t_len);
623                                 HeapTupleHeaderSetTypeId(dtup, tupleDesc->tdtypeid);
624                                 HeapTupleHeaderSetTypMod(dtup, tupleDesc->tdtypmod);
625
626                                 result = PointerGetDatum(dtup);
627                         }
628                         break;
629
630                 default:
631                         elog(ERROR, "invalid attnum: %d", attnum);
632                         result = 0;                     /* keep compiler quiet */
633                         break;
634         }
635         return result;
636 }
637
638 /* ----------------
639  *              heap_copytuple
640  *
641  *              returns a copy of an entire tuple
642  *
643  * The HeapTuple struct, tuple header, and tuple data are all allocated
644  * as a single palloc() block.
645  * ----------------
646  */
647 HeapTuple
648 heap_copytuple(HeapTuple tuple)
649 {
650         HeapTuple       newTuple;
651
652         if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
653                 return NULL;
654
655         newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
656         newTuple->t_len = tuple->t_len;
657         newTuple->t_self = tuple->t_self;
658         newTuple->t_tableOid = tuple->t_tableOid;
659         newTuple->t_datamcxt = CurrentMemoryContext;
660         newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
661         memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
662         return newTuple;
663 }
664
665 /* ----------------
666  *              heap_copytuple_with_tuple
667  *
668  *              copy a tuple into a caller-supplied HeapTuple management struct
669  * ----------------
670  */
671 void
672 heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
673 {
674         if (!HeapTupleIsValid(src) || src->t_data == NULL)
675         {
676                 dest->t_data = NULL;
677                 return;
678         }
679
680         dest->t_len = src->t_len;
681         dest->t_self = src->t_self;
682         dest->t_tableOid = src->t_tableOid;
683         dest->t_datamcxt = CurrentMemoryContext;
684         dest->t_data = (HeapTupleHeader) palloc(src->t_len);
685         memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
686 }
687
688 /*
689  * heap_form_tuple
690  *              construct a tuple from the given values[] and isnull[] arrays,
691  *              which are of the length indicated by tupleDescriptor->natts
692  *
693  * The result is allocated in the current memory context.
694  */
695 HeapTuple
696 heap_form_tuple(TupleDesc tupleDescriptor,
697                                 Datum *values,
698                                 bool *isnull)
699 {
700         HeapTuple       tuple;                  /* return tuple */
701         HeapTupleHeader td;                     /* tuple data */
702         unsigned long len;
703         int                     hoff;
704         bool            hasnull = false;
705         Form_pg_attribute *att = tupleDescriptor->attrs;
706         int                     numberOfAttributes = tupleDescriptor->natts;
707         int                     i;
708
709         if (numberOfAttributes > MaxTupleAttributeNumber)
710                 ereport(ERROR,
711                                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
712                                  errmsg("number of columns (%d) exceeds limit (%d)",
713                                                 numberOfAttributes, MaxTupleAttributeNumber)));
714
715         /*
716          * Check for nulls and embedded tuples; expand any toasted attributes in
717          * embedded tuples.  This preserves the invariant that toasting can only
718          * go one level deep.
719          *
720          * We can skip calling toast_flatten_tuple_attribute() if the attribute
721          * couldn't possibly be of composite type.  All composite datums are
722          * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
723          * if an attribute is already toasted, it must have been sent to disk
724          * already and so cannot contain toasted attributes.
725          */
726         for (i = 0; i < numberOfAttributes; i++)
727         {
728                 if (isnull[i])
729                         hasnull = true;
730                 else if (att[i]->attlen == -1 &&
731                                  att[i]->attalign == 'd' &&
732                                  att[i]->attndims == 0 &&
733                                  !VARATT_IS_EXTENDED(values[i]))
734                 {
735                         values[i] = toast_flatten_tuple_attribute(values[i],
736                                                                                                           att[i]->atttypid,
737                                                                                                           att[i]->atttypmod);
738                 }
739         }
740
741         /*
742          * Determine total space needed
743          */
744         len = offsetof(HeapTupleHeaderData, t_bits);
745
746         if (hasnull)
747                 len += BITMAPLEN(numberOfAttributes);
748
749         if (tupleDescriptor->tdhasoid)
750                 len += sizeof(Oid);
751
752         hoff = len = MAXALIGN(len); /* align user data safely */
753
754         len += heap_compute_data_size(tupleDescriptor, values, isnull);
755
756         /*
757          * Allocate and zero the space needed.  Note that the tuple body and
758          * HeapTupleData management structure are allocated in one chunk.
759          */
760         tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
761         tuple->t_datamcxt = CurrentMemoryContext;
762         tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
763
764         /*
765          * And fill in the information.  Note we fill the Datum fields even though
766          * this tuple may never become a Datum.
767          */
768         tuple->t_len = len;
769         ItemPointerSetInvalid(&(tuple->t_self));
770         tuple->t_tableOid = InvalidOid;
771
772         HeapTupleHeaderSetDatumLength(td, len);
773         HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
774         HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
775
776         td->t_natts = numberOfAttributes;
777         td->t_hoff = hoff;
778
779         if (tupleDescriptor->tdhasoid)          /* else leave infomask = 0 */
780                 td->t_infomask = HEAP_HASOID;
781
782         heap_fill_tuple(tupleDescriptor,
783                                         values,
784                                         isnull,
785                                         (char *) td + hoff,
786                                         &td->t_infomask,
787                                         (hasnull ? td->t_bits : NULL));
788
789         return tuple;
790 }
791
792 /* ----------------
793  *              heap_formtuple
794  *
795  *              construct a tuple from the given values[] and nulls[] arrays
796  *
797  *              Null attributes are indicated by a 'n' in the appropriate byte
798  *              of nulls[]. Non-null attributes are indicated by a ' ' (space).
799  *
800  * OLD API with char 'n'/' ' convention for indicating nulls
801  * ----------------
802  */
803 HeapTuple
804 heap_formtuple(TupleDesc tupleDescriptor,
805                            Datum *values,
806                            char *nulls)
807 {
808         HeapTuple       tuple;                  /* return tuple */
809         HeapTupleHeader td;                     /* tuple data */
810         unsigned long len;
811         int                     hoff;
812         bool            hasnull = false;
813         Form_pg_attribute *att = tupleDescriptor->attrs;
814         int                     numberOfAttributes = tupleDescriptor->natts;
815         int                     i;
816
817         if (numberOfAttributes > MaxTupleAttributeNumber)
818                 ereport(ERROR,
819                                 (errcode(ERRCODE_TOO_MANY_COLUMNS),
820                                  errmsg("number of columns (%d) exceeds limit (%d)",
821                                                 numberOfAttributes, MaxTupleAttributeNumber)));
822
823         /*
824          * Check for nulls and embedded tuples; expand any toasted attributes in
825          * embedded tuples.  This preserves the invariant that toasting can only
826          * go one level deep.
827          *
828          * We can skip calling toast_flatten_tuple_attribute() if the attribute
829          * couldn't possibly be of composite type.  All composite datums are
830          * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
831          * if an attribute is already toasted, it must have been sent to disk
832          * already and so cannot contain toasted attributes.
833          */
834         for (i = 0; i < numberOfAttributes; i++)
835         {
836                 if (nulls[i] != ' ')
837                         hasnull = true;
838                 else if (att[i]->attlen == -1 &&
839                                  att[i]->attalign == 'd' &&
840                                  att[i]->attndims == 0 &&
841                                  !VARATT_IS_EXTENDED(values[i]))
842                 {
843                         values[i] = toast_flatten_tuple_attribute(values[i],
844                                                                                                           att[i]->atttypid,
845                                                                                                           att[i]->atttypmod);
846                 }
847         }
848
849         /*
850          * Determine total space needed
851          */
852         len = offsetof(HeapTupleHeaderData, t_bits);
853
854         if (hasnull)
855                 len += BITMAPLEN(numberOfAttributes);
856
857         if (tupleDescriptor->tdhasoid)
858                 len += sizeof(Oid);
859
860         hoff = len = MAXALIGN(len); /* align user data safely */
861
862         len += ComputeDataSize(tupleDescriptor, values, nulls);
863
864         /*
865          * Allocate and zero the space needed.  Note that the tuple body and
866          * HeapTupleData management structure are allocated in one chunk.
867          */
868         tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
869         tuple->t_datamcxt = CurrentMemoryContext;
870         tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
871
872         /*
873          * And fill in the information.  Note we fill the Datum fields even though
874          * this tuple may never become a Datum.
875          */
876         tuple->t_len = len;
877         ItemPointerSetInvalid(&(tuple->t_self));
878         tuple->t_tableOid = InvalidOid;
879
880         HeapTupleHeaderSetDatumLength(td, len);
881         HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
882         HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
883
884         td->t_natts = numberOfAttributes;
885         td->t_hoff = hoff;
886
887         if (tupleDescriptor->tdhasoid)          /* else leave infomask = 0 */
888                 td->t_infomask = HEAP_HASOID;
889
890         DataFill((char *) td + hoff,
891                          tupleDescriptor,
892                          values,
893                          nulls,
894                          &td->t_infomask,
895                          (hasnull ? td->t_bits : NULL));
896
897         return tuple;
898 }
899
900 /*
901  * heap_modify_tuple
902  *              form a new tuple from an old tuple and a set of replacement values.
903  *
904  * The replValues, replIsnull, and doReplace arrays must be of the length
905  * indicated by tupleDesc->natts.  The new tuple is constructed using the data
906  * from replValues/replIsnull at columns where doReplace is true, and using
907  * the data from the old tuple at columns where doReplace is false.
908  *
909  * The result is allocated in the current memory context.
910  */
911 HeapTuple
912 heap_modify_tuple(HeapTuple tuple,
913                                   TupleDesc tupleDesc,
914                                   Datum *replValues,
915                                   bool *replIsnull,
916                                   bool *doReplace)
917 {
918         int                     numberOfAttributes = tupleDesc->natts;
919         int                     attoff;
920         Datum      *values;
921         bool       *isnull;
922         HeapTuple       newTuple;
923
924         /*
925          * allocate and fill values and isnull arrays from either the tuple or the
926          * repl information, as appropriate.
927          *
928          * NOTE: it's debatable whether to use heap_deform_tuple() here or just
929          * heap_getattr() only the non-replaced colums.  The latter could win if
930          * there are many replaced columns and few non-replaced ones. However,
931          * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
932          * O(N^2) if there are many non-replaced columns, so it seems better to
933          * err on the side of linear cost.
934          */
935         values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
936         isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
937
938         heap_deform_tuple(tuple, tupleDesc, values, isnull);
939
940         for (attoff = 0; attoff < numberOfAttributes; attoff++)
941         {
942                 if (doReplace[attoff])
943                 {
944                         values[attoff] = replValues[attoff];
945                         isnull[attoff] = replIsnull[attoff];
946                 }
947         }
948
949         /*
950          * create a new tuple from the values and isnull arrays
951          */
952         newTuple = heap_form_tuple(tupleDesc, values, isnull);
953
954         pfree(values);
955         pfree(isnull);
956
957         /*
958          * copy the identification info of the old tuple: t_ctid, t_self, and OID
959          * (if any)
960          */
961         newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
962         newTuple->t_self = tuple->t_self;
963         newTuple->t_tableOid = tuple->t_tableOid;
964         if (tupleDesc->tdhasoid)
965                 HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
966
967         return newTuple;
968 }
969
970 /* ----------------
971  *              heap_modifytuple
972  *
973  *              forms a new tuple from an old tuple and a set of replacement values.
974  *              returns a new palloc'ed tuple.
975  *
976  * OLD API with char 'n'/' ' convention for indicating nulls, and
977  * char 'r'/' ' convention for indicating whether to replace columns.
978  * ----------------
979  */
980 HeapTuple
981 heap_modifytuple(HeapTuple tuple,
982                                  TupleDesc tupleDesc,
983                                  Datum *replValues,
984                                  char *replNulls,
985                                  char *replActions)
986 {
987         int                     numberOfAttributes = tupleDesc->natts;
988         int                     attoff;
989         Datum      *values;
990         char       *nulls;
991         HeapTuple       newTuple;
992
993         /*
994          * allocate and fill values and nulls arrays from either the tuple or the
995          * repl information, as appropriate.
996          *
997          * NOTE: it's debatable whether to use heap_deformtuple() here or just
998          * heap_getattr() only the non-replaced colums.  The latter could win if
999          * there are many replaced columns and few non-replaced ones. However,
1000          * heap_deformtuple costs only O(N) while the heap_getattr way would cost
1001          * O(N^2) if there are many non-replaced columns, so it seems better to
1002          * err on the side of linear cost.
1003          */
1004         values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1005         nulls = (char *) palloc(numberOfAttributes * sizeof(char));
1006
1007         heap_deformtuple(tuple, tupleDesc, values, nulls);
1008
1009         for (attoff = 0; attoff < numberOfAttributes; attoff++)
1010         {
1011                 if (replActions[attoff] == 'r')
1012                 {
1013                         values[attoff] = replValues[attoff];
1014                         nulls[attoff] = replNulls[attoff];
1015                 }
1016                 else if (replActions[attoff] != ' ')
1017                         elog(ERROR, "unrecognized replace flag: %d",
1018                                  (int) replActions[attoff]);
1019         }
1020
1021         /*
1022          * create a new tuple from the values and nulls arrays
1023          */
1024         newTuple = heap_formtuple(tupleDesc, values, nulls);
1025
1026         pfree(values);
1027         pfree(nulls);
1028
1029         /*
1030          * copy the identification info of the old tuple: t_ctid, t_self, and OID
1031          * (if any)
1032          */
1033         newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
1034         newTuple->t_self = tuple->t_self;
1035         newTuple->t_tableOid = tuple->t_tableOid;
1036         if (tupleDesc->tdhasoid)
1037                 HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
1038
1039         return newTuple;
1040 }
1041
1042 /*
1043  * heap_deform_tuple
1044  *              Given a tuple, extract data into values/isnull arrays; this is
1045  *              the inverse of heap_form_tuple.
1046  *
1047  *              Storage for the values/isnull arrays is provided by the caller;
1048  *              it should be sized according to tupleDesc->natts not tuple->t_natts.
1049  *
1050  *              Note that for pass-by-reference datatypes, the pointer placed
1051  *              in the Datum will point into the given tuple.
1052  *
1053  *              When all or most of a tuple's fields need to be extracted,
1054  *              this routine will be significantly quicker than a loop around
1055  *              heap_getattr; the loop will become O(N^2) as soon as any
1056  *              noncacheable attribute offsets are involved.
1057  */
1058 void
1059 heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
1060                                   Datum *values, bool *isnull)
1061 {
1062         HeapTupleHeader tup = tuple->t_data;
1063         bool            hasnulls = HeapTupleHasNulls(tuple);
1064         Form_pg_attribute *att = tupleDesc->attrs;
1065         int                     tdesc_natts = tupleDesc->natts;
1066         int                     natts;                  /* number of atts to extract */
1067         int                     attnum;
1068         char       *tp;                         /* ptr to tuple data */
1069         long            off;                    /* offset in tuple data */
1070         bits8      *bp = tup->t_bits;           /* ptr to null bitmap in tuple */
1071         bool            slow = false;   /* can we use/set attcacheoff? */
1072
1073         natts = tup->t_natts;
1074
1075         /*
1076          * In inheritance situations, it is possible that the given tuple actually
1077          * has more fields than the caller is expecting.  Don't run off the end of
1078          * the caller's arrays.
1079          */
1080         natts = Min(natts, tdesc_natts);
1081
1082         tp = (char *) tup + tup->t_hoff;
1083
1084         off = 0;
1085
1086         for (attnum = 0; attnum < natts; attnum++)
1087         {
1088                 Form_pg_attribute thisatt = att[attnum];
1089
1090                 if (hasnulls && att_isnull(attnum, bp))
1091                 {
1092                         values[attnum] = (Datum) 0;
1093                         isnull[attnum] = true;
1094                         slow = true;            /* can't use attcacheoff anymore */
1095                         continue;
1096                 }
1097
1098                 isnull[attnum] = false;
1099
1100                 if (!slow && thisatt->attcacheoff >= 0)
1101                         off = thisatt->attcacheoff;
1102                 else
1103                 {
1104                         off = att_align(off, thisatt->attalign);
1105
1106                         if (!slow)
1107                                 thisatt->attcacheoff = off;
1108                 }
1109
1110                 values[attnum] = fetchatt(thisatt, tp + off);
1111
1112                 off = att_addlength(off, thisatt->attlen, tp + off);
1113
1114                 if (thisatt->attlen <= 0)
1115                         slow = true;            /* can't use attcacheoff anymore */
1116         }
1117
1118         /*
1119          * If tuple doesn't have all the atts indicated by tupleDesc, read the
1120          * rest as null
1121          */
1122         for (; attnum < tdesc_natts; attnum++)
1123         {
1124                 values[attnum] = (Datum) 0;
1125                 isnull[attnum] = true;
1126         }
1127 }
1128
1129 /* ----------------
1130  *              heap_deformtuple
1131  *
1132  *              Given a tuple, extract data into values/nulls arrays; this is
1133  *              the inverse of heap_formtuple.
1134  *
1135  *              Storage for the values/nulls arrays is provided by the caller;
1136  *              it should be sized according to tupleDesc->natts not tuple->t_natts.
1137  *
1138  *              Note that for pass-by-reference datatypes, the pointer placed
1139  *              in the Datum will point into the given tuple.
1140  *
1141  *              When all or most of a tuple's fields need to be extracted,
1142  *              this routine will be significantly quicker than a loop around
1143  *              heap_getattr; the loop will become O(N^2) as soon as any
1144  *              noncacheable attribute offsets are involved.
1145  *
1146  * OLD API with char 'n'/' ' convention for indicating nulls
1147  * ----------------
1148  */
1149 void
1150 heap_deformtuple(HeapTuple tuple,
1151                                  TupleDesc tupleDesc,
1152                                  Datum *values,
1153                                  char *nulls)
1154 {
1155         HeapTupleHeader tup = tuple->t_data;
1156         bool            hasnulls = HeapTupleHasNulls(tuple);
1157         Form_pg_attribute *att = tupleDesc->attrs;
1158         int                     tdesc_natts = tupleDesc->natts;
1159         int                     natts;                  /* number of atts to extract */
1160         int                     attnum;
1161         char       *tp;                         /* ptr to tuple data */
1162         long            off;                    /* offset in tuple data */
1163         bits8      *bp = tup->t_bits;           /* ptr to null bitmap in tuple */
1164         bool            slow = false;   /* can we use/set attcacheoff? */
1165
1166         natts = tup->t_natts;
1167
1168         /*
1169          * In inheritance situations, it is possible that the given tuple actually
1170          * has more fields than the caller is expecting.  Don't run off the end of
1171          * the caller's arrays.
1172          */
1173         natts = Min(natts, tdesc_natts);
1174
1175         tp = (char *) tup + tup->t_hoff;
1176
1177         off = 0;
1178
1179         for (attnum = 0; attnum < natts; attnum++)
1180         {
1181                 Form_pg_attribute thisatt = att[attnum];
1182
1183                 if (hasnulls && att_isnull(attnum, bp))
1184                 {
1185                         values[attnum] = (Datum) 0;
1186                         nulls[attnum] = 'n';
1187                         slow = true;            /* can't use attcacheoff anymore */
1188                         continue;
1189                 }
1190
1191                 nulls[attnum] = ' ';
1192
1193                 if (!slow && thisatt->attcacheoff >= 0)
1194                         off = thisatt->attcacheoff;
1195                 else
1196                 {
1197                         off = att_align(off, thisatt->attalign);
1198
1199                         if (!slow)
1200                                 thisatt->attcacheoff = off;
1201                 }
1202
1203                 values[attnum] = fetchatt(thisatt, tp + off);
1204
1205                 off = att_addlength(off, thisatt->attlen, tp + off);
1206
1207                 if (thisatt->attlen <= 0)
1208                         slow = true;            /* can't use attcacheoff anymore */
1209         }
1210
1211         /*
1212          * If tuple doesn't have all the atts indicated by tupleDesc, read the
1213          * rest as null
1214          */
1215         for (; attnum < tdesc_natts; attnum++)
1216         {
1217                 values[attnum] = (Datum) 0;
1218                 nulls[attnum] = 'n';
1219         }
1220 }
1221
1222 /*
1223  * slot_deform_tuple
1224  *              Given a TupleTableSlot, extract data from the slot's physical tuple
1225  *              into its Datum/isnull arrays.  Data is extracted up through the
1226  *              natts'th column (caller must ensure this is a legal column number).
1227  *
1228  *              This is essentially an incremental version of heap_deform_tuple:
1229  *              on each call we extract attributes up to the one needed, without
1230  *              re-computing information about previously extracted attributes.
1231  *              slot->tts_nvalid is the number of attributes already extracted.
1232  */
1233 static void
1234 slot_deform_tuple(TupleTableSlot *slot, int natts)
1235 {
1236         HeapTuple       tuple = slot->tts_tuple;
1237         TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
1238         Datum      *values = slot->tts_values;
1239         bool       *isnull = slot->tts_isnull;
1240         HeapTupleHeader tup = tuple->t_data;
1241         bool            hasnulls = HeapTupleHasNulls(tuple);
1242         Form_pg_attribute *att = tupleDesc->attrs;
1243         int                     attnum;
1244         char       *tp;                         /* ptr to tuple data */
1245         long            off;                    /* offset in tuple data */
1246         bits8      *bp = tup->t_bits;           /* ptr to null bitmap in tuple */
1247         bool            slow;                   /* can we use/set attcacheoff? */
1248
1249         /*
1250          * Check whether the first call for this tuple, and initialize or restore
1251          * loop state.
1252          */
1253         attnum = slot->tts_nvalid;
1254         if (attnum == 0)
1255         {
1256                 /* Start from the first attribute */
1257                 off = 0;
1258                 slow = false;
1259         }
1260         else
1261         {
1262                 /* Restore state from previous execution */
1263                 off = slot->tts_off;
1264                 slow = slot->tts_slow;
1265         }
1266
1267         tp = (char *) tup + tup->t_hoff;
1268
1269         for (; attnum < natts; attnum++)
1270         {
1271                 Form_pg_attribute thisatt = att[attnum];
1272
1273                 if (hasnulls && att_isnull(attnum, bp))
1274                 {
1275                         values[attnum] = (Datum) 0;
1276                         isnull[attnum] = true;
1277                         slow = true;            /* can't use attcacheoff anymore */
1278                         continue;
1279                 }
1280
1281                 isnull[attnum] = false;
1282
1283                 if (!slow && thisatt->attcacheoff >= 0)
1284                         off = thisatt->attcacheoff;
1285                 else
1286                 {
1287                         off = att_align(off, thisatt->attalign);
1288
1289                         if (!slow)
1290                                 thisatt->attcacheoff = off;
1291                 }
1292
1293                 values[attnum] = fetchatt(thisatt, tp + off);
1294
1295                 off = att_addlength(off, thisatt->attlen, tp + off);
1296
1297                 if (thisatt->attlen <= 0)
1298                         slow = true;            /* can't use attcacheoff anymore */
1299         }
1300
1301         /*
1302          * Save state for next execution
1303          */
1304         slot->tts_nvalid = attnum;
1305         slot->tts_off = off;
1306         slot->tts_slow = slow;
1307 }
1308
1309 /*
1310  * slot_getattr
1311  *              This function fetches an attribute of the slot's current tuple.
1312  *              It is functionally equivalent to heap_getattr, but fetches of
1313  *              multiple attributes of the same tuple will be optimized better,
1314  *              because we avoid O(N^2) behavior from multiple calls of
1315  *              nocachegetattr(), even when attcacheoff isn't usable.
1316  *
1317  *              A difference from raw heap_getattr is that attnums beyond the
1318  *              slot's tupdesc's last attribute will be considered NULL even
1319  *              when the physical tuple is longer than the tupdesc.
1320  */
1321 Datum
1322 slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
1323 {
1324         HeapTuple       tuple = slot->tts_tuple;
1325         TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
1326         HeapTupleHeader tup;
1327
1328         /*
1329          * system attributes are handled by heap_getsysattr
1330          */
1331         if (attnum <= 0)
1332         {
1333                 if (tuple == NULL)              /* internal error */
1334                         elog(ERROR, "cannot extract system attribute from virtual tuple");
1335                 return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
1336         }
1337
1338         /*
1339          * fast path if desired attribute already cached
1340          */
1341         if (attnum <= slot->tts_nvalid)
1342         {
1343                 *isnull = slot->tts_isnull[attnum - 1];
1344                 return slot->tts_values[attnum - 1];
1345         }
1346
1347         /*
1348          * return NULL if attnum is out of range according to the tupdesc
1349          */
1350         if (attnum > tupleDesc->natts)
1351         {
1352                 *isnull = true;
1353                 return (Datum) 0;
1354         }
1355
1356         /*
1357          * otherwise we had better have a physical tuple (tts_nvalid should equal
1358          * natts in all virtual-tuple cases)
1359          */
1360         if (tuple == NULL)                      /* internal error */
1361                 elog(ERROR, "cannot extract attribute from empty tuple slot");
1362
1363         /*
1364          * return NULL if attnum is out of range according to the tuple
1365          *
1366          * (We have to check this separately because of various inheritance and
1367          * table-alteration scenarios: the tuple could be either longer or shorter
1368          * than the tupdesc.)
1369          */
1370         tup = tuple->t_data;
1371         if (attnum > tup->t_natts)
1372         {
1373                 *isnull = true;
1374                 return (Datum) 0;
1375         }
1376
1377         /*
1378          * check if target attribute is null: no point in groveling through tuple
1379          */
1380         if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
1381         {
1382                 *isnull = true;
1383                 return (Datum) 0;
1384         }
1385
1386         /*
1387          * If the attribute's column has been dropped, we force a NULL result.
1388          * This case should not happen in normal use, but it could happen if we
1389          * are executing a plan cached before the column was dropped.
1390          */
1391         if (tupleDesc->attrs[attnum - 1]->attisdropped)
1392         {
1393                 *isnull = true;
1394                 return (Datum) 0;
1395         }
1396
1397         /*
1398          * Extract the attribute, along with any preceding attributes.
1399          */
1400         slot_deform_tuple(slot, attnum);
1401
1402         /*
1403          * The result is acquired from tts_values array.
1404          */
1405         *isnull = slot->tts_isnull[attnum - 1];
1406         return slot->tts_values[attnum - 1];
1407 }
1408
1409 /*
1410  * slot_getallattrs
1411  *              This function forces all the entries of the slot's Datum/isnull
1412  *              arrays to be valid.  The caller may then extract data directly
1413  *              from those arrays instead of using slot_getattr.
1414  */
1415 void
1416 slot_getallattrs(TupleTableSlot *slot)
1417 {
1418         int                     tdesc_natts = slot->tts_tupleDescriptor->natts;
1419         int                     attnum;
1420         HeapTuple       tuple;
1421
1422         /* Quick out if we have 'em all already */
1423         if (slot->tts_nvalid == tdesc_natts)
1424                 return;
1425
1426         /*
1427          * otherwise we had better have a physical tuple (tts_nvalid should equal
1428          * natts in all virtual-tuple cases)
1429          */
1430         tuple = slot->tts_tuple;
1431         if (tuple == NULL)                      /* internal error */
1432                 elog(ERROR, "cannot extract attribute from empty tuple slot");
1433
1434         /*
1435          * load up any slots available from physical tuple
1436          */
1437         attnum = tuple->t_data->t_natts;
1438         attnum = Min(attnum, tdesc_natts);
1439
1440         slot_deform_tuple(slot, attnum);
1441
1442         /*
1443          * If tuple doesn't have all the atts indicated by tupleDesc, read the
1444          * rest as null
1445          */
1446         for (; attnum < tdesc_natts; attnum++)
1447         {
1448                 slot->tts_values[attnum] = (Datum) 0;
1449                 slot->tts_isnull[attnum] = true;
1450         }
1451         slot->tts_nvalid = tdesc_natts;
1452 }
1453
1454 /*
1455  * slot_getsomeattrs
1456  *              This function forces the entries of the slot's Datum/isnull
1457  *              arrays to be valid at least up through the attnum'th entry.
1458  */
1459 void
1460 slot_getsomeattrs(TupleTableSlot *slot, int attnum)
1461 {
1462         HeapTuple       tuple;
1463         int                     attno;
1464
1465         /* Quick out if we have 'em all already */
1466         if (slot->tts_nvalid >= attnum)
1467                 return;
1468
1469         /* Check for caller error */
1470         if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
1471                 elog(ERROR, "invalid attribute number %d", attnum);
1472
1473         /*
1474          * otherwise we had better have a physical tuple (tts_nvalid should equal
1475          * natts in all virtual-tuple cases)
1476          */
1477         tuple = slot->tts_tuple;
1478         if (tuple == NULL)                      /* internal error */
1479                 elog(ERROR, "cannot extract attribute from empty tuple slot");
1480
1481         /*
1482          * load up any slots available from physical tuple
1483          */
1484         attno = tuple->t_data->t_natts;
1485         attno = Min(attno, attnum);
1486
1487         slot_deform_tuple(slot, attno);
1488
1489         /*
1490          * If tuple doesn't have all the atts indicated by tupleDesc, read the
1491          * rest as null
1492          */
1493         for (; attno < attnum; attno++)
1494         {
1495                 slot->tts_values[attno] = (Datum) 0;
1496                 slot->tts_isnull[attno] = true;
1497         }
1498         slot->tts_nvalid = attnum;
1499 }
1500
1501 /*
1502  * slot_attisnull
1503  *              Detect whether an attribute of the slot is null, without
1504  *              actually fetching it.
1505  */
1506 bool
1507 slot_attisnull(TupleTableSlot *slot, int attnum)
1508 {
1509         HeapTuple       tuple = slot->tts_tuple;
1510         TupleDesc       tupleDesc = slot->tts_tupleDescriptor;
1511
1512         /*
1513          * system attributes are handled by heap_attisnull
1514          */
1515         if (attnum <= 0)
1516         {
1517                 if (tuple == NULL)              /* internal error */
1518                         elog(ERROR, "cannot extract system attribute from virtual tuple");
1519                 return heap_attisnull(tuple, attnum);
1520         }
1521
1522         /*
1523          * fast path if desired attribute already cached
1524          */
1525         if (attnum <= slot->tts_nvalid)
1526                 return slot->tts_isnull[attnum - 1];
1527
1528         /*
1529          * return NULL if attnum is out of range according to the tupdesc
1530          */
1531         if (attnum > tupleDesc->natts)
1532                 return true;
1533
1534         /*
1535          * otherwise we had better have a physical tuple (tts_nvalid should equal
1536          * natts in all virtual-tuple cases)
1537          */
1538         if (tuple == NULL)                      /* internal error */
1539                 elog(ERROR, "cannot extract attribute from empty tuple slot");
1540
1541         /* and let the tuple tell it */
1542         return heap_attisnull(tuple, attnum);
1543 }
1544
1545 /* ----------------
1546  *              heap_freetuple
1547  * ----------------
1548  */
1549 void
1550 heap_freetuple(HeapTuple htup)
1551 {
1552         if (htup->t_data != NULL)
1553                 if (htup->t_datamcxt != NULL && (char *) (htup->t_data) !=
1554                         ((char *) htup + HEAPTUPLESIZE))
1555                         pfree(htup->t_data);
1556
1557         pfree(htup);
1558 }
1559
1560
1561 /* ----------------
1562  *              heap_addheader
1563  *
1564  * This routine forms a HeapTuple by copying the given structure (tuple
1565  * data) and adding a generic header.  Note that the tuple data is
1566  * presumed to contain no null fields and no varlena fields.
1567  *
1568  * This routine is really only useful for certain system tables that are
1569  * known to be fixed-width and null-free.  It is used in some places for
1570  * pg_class, but that is a gross hack (it only works because relacl can
1571  * be omitted from the tuple entirely in those places).
1572  * ----------------
1573  */
1574 HeapTuple
1575 heap_addheader(int natts,               /* max domain index */
1576                            bool withoid,        /* reserve space for oid */
1577                            Size structlen,      /* its length */
1578                            void *structure) /* pointer to the struct */
1579 {
1580         HeapTuple       tuple;
1581         HeapTupleHeader td;
1582         Size            len;
1583         int                     hoff;
1584
1585         AssertArg(natts > 0);
1586
1587         /* header needs no null bitmap */
1588         hoff = offsetof(HeapTupleHeaderData, t_bits);
1589         if (withoid)
1590                 hoff += sizeof(Oid);
1591         hoff = MAXALIGN(hoff);
1592         len = hoff + structlen;
1593
1594         tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
1595         tuple->t_datamcxt = CurrentMemoryContext;
1596         tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
1597
1598         tuple->t_len = len;
1599         ItemPointerSetInvalid(&(tuple->t_self));
1600         tuple->t_tableOid = InvalidOid;
1601
1602         /* we don't bother to fill the Datum fields */
1603
1604         td->t_natts = natts;
1605         td->t_hoff = hoff;
1606
1607         if (withoid)                            /* else leave infomask = 0 */
1608                 td->t_infomask = HEAP_HASOID;
1609
1610         memcpy((char *) td + hoff, structure, structlen);
1611
1612         return tuple;
1613 }