1 /*-------------------------------------------------------------------------
4 * This file contains heap tuple accessor and mutator routines, as well
5 * as various tuple utilities.
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.
14 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
15 * Portions Copyright (c) 1994, Regents of the University of California
19 * $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.108 2006/07/02 02:23:18 momjian Exp $
21 *-------------------------------------------------------------------------
26 #include "access/heapam.h"
27 #include "access/tuptoaster.h"
28 #include "catalog/pg_type.h"
29 #include "executor/tuptable.h"
32 /* ----------------------------------------------------------------
33 * misc support routines
34 * ----------------------------------------------------------------
38 * heap_compute_data_size
39 * Determine size of the data area of a tuple to be constructed
42 heap_compute_data_size(TupleDesc tupleDesc,
48 int numberOfAttributes = tupleDesc->natts;
49 Form_pg_attribute *att = tupleDesc->attrs;
51 for (i = 0; i < numberOfAttributes; i++)
56 data_length = att_align(data_length, att[i]->attalign);
57 data_length = att_addlength(data_length, att[i]->attlen, values[i]);
66 * Determine size of the data area of a tuple to be constructed
68 * OLD API with char 'n'/' ' convention for indicating nulls
72 ComputeDataSize(TupleDesc tupleDesc,
78 int numberOfAttributes = tupleDesc->natts;
79 Form_pg_attribute *att = tupleDesc->attrs;
81 for (i = 0; i < numberOfAttributes; i++)
86 data_length = att_align(data_length, att[i]->attalign);
87 data_length = att_addlength(data_length, att[i]->attlen, values[i]);
95 * Load data portion of a tuple from values/isnull arrays
97 * We also fill the null bitmap (if any) and set the infomask bits
98 * that reflect the tuple's data contents.
101 heap_fill_tuple(TupleDesc tupleDesc,
102 Datum *values, bool *isnull,
103 char *data, uint16 *infomask, bits8 *bit)
108 int numberOfAttributes = tupleDesc->natts;
109 Form_pg_attribute *att = tupleDesc->attrs;
118 /* just to keep compiler quiet */
123 *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTENDED);
125 for (i = 0; i < numberOfAttributes; i++)
131 if (bitmask != HIGHBIT)
142 *infomask |= HEAP_HASNULL;
149 /* XXX we are aligning the pointer itself, not the offset */
150 data = (char *) att_align((long) data, att[i]->attalign);
152 if (att[i]->attbyval)
155 store_att_byval(data, values[i], att[i]->attlen);
156 data_length = att[i]->attlen;
158 else if (att[i]->attlen == -1)
161 *infomask |= HEAP_HASVARWIDTH;
162 if (VARATT_IS_EXTERNAL(values[i]))
163 *infomask |= HEAP_HASEXTERNAL;
164 if (VARATT_IS_COMPRESSED(values[i]))
165 *infomask |= HEAP_HASCOMPRESSED;
166 data_length = VARATT_SIZE(DatumGetPointer(values[i]));
167 memcpy(data, DatumGetPointer(values[i]), data_length);
169 else if (att[i]->attlen == -2)
172 *infomask |= HEAP_HASVARWIDTH;
173 data_length = strlen(DatumGetCString(values[i])) + 1;
174 memcpy(data, DatumGetPointer(values[i]), data_length);
178 /* fixed-length pass-by-reference */
179 Assert(att[i]->attlen > 0);
180 data_length = att[i]->attlen;
181 memcpy(data, DatumGetPointer(values[i]), data_length);
191 * Load data portion of a tuple from values/nulls arrays
193 * OLD API with char 'n'/' ' convention for indicating nulls
207 int numberOfAttributes = tupleDesc->natts;
208 Form_pg_attribute *att = tupleDesc->attrs;
217 /* just to keep compiler quiet */
222 *infomask &= ~(HEAP_HASNULL | HEAP_HASVARWIDTH | HEAP_HASEXTENDED);
224 for (i = 0; i < numberOfAttributes; i++)
230 if (bitmask != HIGHBIT)
241 *infomask |= HEAP_HASNULL;
248 /* XXX we are aligning the pointer itself, not the offset */
249 data = (char *) att_align((long) data, att[i]->attalign);
251 if (att[i]->attbyval)
254 store_att_byval(data, values[i], att[i]->attlen);
255 data_length = att[i]->attlen;
257 else if (att[i]->attlen == -1)
260 *infomask |= HEAP_HASVARWIDTH;
261 if (VARATT_IS_EXTERNAL(values[i]))
262 *infomask |= HEAP_HASEXTERNAL;
263 if (VARATT_IS_COMPRESSED(values[i]))
264 *infomask |= HEAP_HASCOMPRESSED;
265 data_length = VARATT_SIZE(DatumGetPointer(values[i]));
266 memcpy(data, DatumGetPointer(values[i]), data_length);
268 else if (att[i]->attlen == -2)
271 *infomask |= HEAP_HASVARWIDTH;
272 data_length = strlen(DatumGetCString(values[i])) + 1;
273 memcpy(data, DatumGetPointer(values[i]), data_length);
277 /* fixed-length pass-by-reference */
278 Assert(att[i]->attlen > 0);
279 data_length = att[i]->attlen;
280 memcpy(data, DatumGetPointer(values[i]), data_length);
287 /* ----------------------------------------------------------------
288 * heap tuple interface
289 * ----------------------------------------------------------------
293 * heap_attisnull - returns TRUE iff tuple attribute is not present
297 heap_attisnull(HeapTuple tup, int attnum)
299 if (attnum > (int) tup->t_data->t_natts)
304 if (HeapTupleNoNulls(tup))
306 return att_isnull(attnum - 1, tup->t_data->t_bits);
311 case TableOidAttributeNumber:
312 case SelfItemPointerAttributeNumber:
313 case ObjectIdAttributeNumber:
314 case MinTransactionIdAttributeNumber:
315 case MinCommandIdAttributeNumber:
316 case MaxTransactionIdAttributeNumber:
317 case MaxCommandIdAttributeNumber:
318 /* these are never null */
322 elog(ERROR, "invalid attnum: %d", attnum);
331 * This only gets called from fastgetattr() macro, in cases where
332 * we can't use a cacheoffset and the value is not null.
334 * This caches attribute offsets in the attribute descriptor.
336 * An alternate way to speed things up would be to cache offsets
337 * with the tuple, but that seems more difficult unless you take
338 * the storage hit of actually putting those offsets into the
339 * tuple you send to disk. Yuck.
341 * This scheme will be slightly slower than that, but should
342 * perform well for queries which hit large #'s of tuples. After
343 * you cache the offsets once, examining all the other tuples using
344 * the same attribute descriptor will go much quicker. -cim 5/4/91
346 * NOTE: if you need to change this code, see also heap_deform_tuple.
350 nocachegetattr(HeapTuple tuple,
355 HeapTupleHeader tup = tuple->t_data;
356 Form_pg_attribute *att = tupleDesc->attrs;
357 char *tp; /* ptr to att in tuple */
358 bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
359 bool slow = false; /* do we have to walk nulls? */
361 (void) isnull; /* not used */
363 /* This is handled in the macro */
375 * 1: No nulls and no variable-width attributes.
376 * 2: Has a null or a var-width AFTER att.
377 * 3: Has nulls or var-widths BEFORE att.
381 if (HeapTupleNoNulls(tuple))
384 /* This is handled in the macro */
385 if (att[attnum]->attcacheoff != -1)
387 return fetchatt(att[attnum],
388 (char *) tup + tup->t_hoff +
389 att[attnum]->attcacheoff);
396 * there's a null somewhere in the tuple
398 * check to see if desired att is null
402 /* This is handled in the macro */
403 if (att_isnull(attnum, bp))
412 * Now check to see if any preceding bits are null...
415 int byte = attnum >> 3;
416 int finalbit = attnum & 0x07;
418 /* check for nulls "before" final bit of last byte */
419 if ((~bp[byte]) & ((1 << finalbit) - 1))
423 /* check for nulls in any "earlier" bytes */
426 for (i = 0; i < byte; i++)
438 tp = (char *) tup + tup->t_hoff;
441 * now check for any non-fixed length attrs before our attribute
445 if (att[attnum]->attcacheoff != -1)
447 return fetchatt(att[attnum],
448 tp + att[attnum]->attcacheoff);
450 else if (HeapTupleHasVarWidth(tuple))
455 * In for(), we test <= and not < because we want to see if we can
456 * go past it in initializing offsets.
458 for (j = 0; j <= attnum; j++)
460 if (att[j]->attlen <= 0)
470 * If slow is false, and we got here, we know that we have a tuple with no
471 * nulls or var-widths before the target attribute. If possible, we also
472 * want to initialize the remainder of the attribute cached offset values.
480 * need to set cache for some atts
483 att[0]->attcacheoff = 0;
485 while (j < attnum && att[j]->attcacheoff > 0)
488 off = att[j - 1]->attcacheoff + att[j - 1]->attlen;
490 for (; j <= attnum ||
491 /* Can we compute more? We will probably need them */
493 att[j]->attcacheoff == -1 &&
494 (HeapTupleNoNulls(tuple) || !att_isnull(j, bp)) &&
495 (HeapTupleAllFixed(tuple) || att[j]->attlen > 0)); j++)
497 off = att_align(off, att[j]->attalign);
499 att[j]->attcacheoff = off;
501 off = att_addlength(off, att[j]->attlen, tp + off);
504 return fetchatt(att[attnum], tp + att[attnum]->attcacheoff);
508 bool usecache = true;
513 * Now we know that we have to walk the tuple CAREFULLY.
515 * Note - This loop is a little tricky. For each non-null attribute,
516 * we have to first account for alignment padding before the attr,
517 * then advance over the attr based on its length. Nulls have no
518 * storage and no alignment padding either. We can use/set
519 * attcacheoff until we pass either a null or a var-width attribute.
522 for (i = 0; i < attnum; i++)
524 if (HeapTupleHasNulls(tuple) && att_isnull(i, bp))
530 /* If we know the next offset, we can skip the alignment calc */
531 if (usecache && att[i]->attcacheoff != -1)
532 off = att[i]->attcacheoff;
535 off = att_align(off, att[i]->attalign);
538 att[i]->attcacheoff = off;
541 off = att_addlength(off, att[i]->attlen, tp + off);
543 if (usecache && att[i]->attlen <= 0)
547 off = att_align(off, att[attnum]->attalign);
549 return fetchatt(att[attnum], tp + off);
556 * Fetch the value of a system attribute for a tuple.
558 * This is a support routine for the heap_getattr macro. The macro
559 * has already determined that the attnum refers to a system attribute.
563 heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
569 /* Currently, no sys attribute ever reads as NULL. */
575 case SelfItemPointerAttributeNumber:
576 /* pass-by-reference datatype */
577 result = PointerGetDatum(&(tup->t_self));
579 case ObjectIdAttributeNumber:
580 result = ObjectIdGetDatum(HeapTupleGetOid(tup));
582 case MinTransactionIdAttributeNumber:
583 result = TransactionIdGetDatum(HeapTupleHeaderGetXmin(tup->t_data));
585 case MinCommandIdAttributeNumber:
586 result = CommandIdGetDatum(HeapTupleHeaderGetCmin(tup->t_data));
588 case MaxTransactionIdAttributeNumber:
589 result = TransactionIdGetDatum(HeapTupleHeaderGetXmax(tup->t_data));
591 case MaxCommandIdAttributeNumber:
592 result = CommandIdGetDatum(HeapTupleHeaderGetCmax(tup->t_data));
594 case TableOidAttributeNumber:
595 result = ObjectIdGetDatum(tup->t_tableOid);
598 elog(ERROR, "invalid attnum: %d", attnum);
599 result = 0; /* keep compiler quiet */
608 * returns a copy of an entire tuple
610 * The HeapTuple struct, tuple header, and tuple data are all allocated
611 * as a single palloc() block.
615 heap_copytuple(HeapTuple tuple)
619 if (!HeapTupleIsValid(tuple) || tuple->t_data == NULL)
622 newTuple = (HeapTuple) palloc(HEAPTUPLESIZE + tuple->t_len);
623 newTuple->t_len = tuple->t_len;
624 newTuple->t_self = tuple->t_self;
625 newTuple->t_tableOid = tuple->t_tableOid;
626 newTuple->t_data = (HeapTupleHeader) ((char *) newTuple + HEAPTUPLESIZE);
627 memcpy((char *) newTuple->t_data, (char *) tuple->t_data, tuple->t_len);
632 * heap_copytuple_with_tuple
634 * copy a tuple into a caller-supplied HeapTuple management struct
638 heap_copytuple_with_tuple(HeapTuple src, HeapTuple dest)
640 if (!HeapTupleIsValid(src) || src->t_data == NULL)
646 dest->t_len = src->t_len;
647 dest->t_self = src->t_self;
648 dest->t_tableOid = src->t_tableOid;
649 dest->t_data = (HeapTupleHeader) palloc(src->t_len);
650 memcpy((char *) dest->t_data, (char *) src->t_data, src->t_len);
655 * construct a tuple from the given values[] and isnull[] arrays,
656 * which are of the length indicated by tupleDescriptor->natts
658 * The result is allocated in the current memory context.
661 heap_form_tuple(TupleDesc tupleDescriptor,
665 HeapTuple tuple; /* return tuple */
666 HeapTupleHeader td; /* tuple data */
669 bool hasnull = false;
670 Form_pg_attribute *att = tupleDescriptor->attrs;
671 int numberOfAttributes = tupleDescriptor->natts;
674 if (numberOfAttributes > MaxTupleAttributeNumber)
676 (errcode(ERRCODE_TOO_MANY_COLUMNS),
677 errmsg("number of columns (%d) exceeds limit (%d)",
678 numberOfAttributes, MaxTupleAttributeNumber)));
681 * Check for nulls and embedded tuples; expand any toasted attributes in
682 * embedded tuples. This preserves the invariant that toasting can only
685 * We can skip calling toast_flatten_tuple_attribute() if the attribute
686 * couldn't possibly be of composite type. All composite datums are
687 * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
688 * if an attribute is already toasted, it must have been sent to disk
689 * already and so cannot contain toasted attributes.
691 for (i = 0; i < numberOfAttributes; i++)
695 else if (att[i]->attlen == -1 &&
696 att[i]->attalign == 'd' &&
697 att[i]->attndims == 0 &&
698 !VARATT_IS_EXTENDED(values[i]))
700 values[i] = toast_flatten_tuple_attribute(values[i],
707 * Determine total space needed
709 len = offsetof(HeapTupleHeaderData, t_bits);
712 len += BITMAPLEN(numberOfAttributes);
714 if (tupleDescriptor->tdhasoid)
717 hoff = len = MAXALIGN(len); /* align user data safely */
719 len += heap_compute_data_size(tupleDescriptor, values, isnull);
722 * Allocate and zero the space needed. Note that the tuple body and
723 * HeapTupleData management structure are allocated in one chunk.
725 tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
726 tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
729 * And fill in the information. Note we fill the Datum fields even though
730 * this tuple may never become a Datum.
733 ItemPointerSetInvalid(&(tuple->t_self));
734 tuple->t_tableOid = InvalidOid;
736 HeapTupleHeaderSetDatumLength(td, len);
737 HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
738 HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
740 td->t_natts = numberOfAttributes;
743 if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */
744 td->t_infomask = HEAP_HASOID;
746 heap_fill_tuple(tupleDescriptor,
751 (hasnull ? td->t_bits : NULL));
759 * construct a tuple from the given values[] and nulls[] arrays
761 * Null attributes are indicated by a 'n' in the appropriate byte
762 * of nulls[]. Non-null attributes are indicated by a ' ' (space).
764 * OLD API with char 'n'/' ' convention for indicating nulls
768 heap_formtuple(TupleDesc tupleDescriptor,
772 HeapTuple tuple; /* return tuple */
773 HeapTupleHeader td; /* tuple data */
776 bool hasnull = false;
777 Form_pg_attribute *att = tupleDescriptor->attrs;
778 int numberOfAttributes = tupleDescriptor->natts;
781 if (numberOfAttributes > MaxTupleAttributeNumber)
783 (errcode(ERRCODE_TOO_MANY_COLUMNS),
784 errmsg("number of columns (%d) exceeds limit (%d)",
785 numberOfAttributes, MaxTupleAttributeNumber)));
788 * Check for nulls and embedded tuples; expand any toasted attributes in
789 * embedded tuples. This preserves the invariant that toasting can only
792 * We can skip calling toast_flatten_tuple_attribute() if the attribute
793 * couldn't possibly be of composite type. All composite datums are
794 * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
795 * if an attribute is already toasted, it must have been sent to disk
796 * already and so cannot contain toasted attributes.
798 for (i = 0; i < numberOfAttributes; i++)
802 else if (att[i]->attlen == -1 &&
803 att[i]->attalign == 'd' &&
804 att[i]->attndims == 0 &&
805 !VARATT_IS_EXTENDED(values[i]))
807 values[i] = toast_flatten_tuple_attribute(values[i],
814 * Determine total space needed
816 len = offsetof(HeapTupleHeaderData, t_bits);
819 len += BITMAPLEN(numberOfAttributes);
821 if (tupleDescriptor->tdhasoid)
824 hoff = len = MAXALIGN(len); /* align user data safely */
826 len += ComputeDataSize(tupleDescriptor, values, nulls);
829 * Allocate and zero the space needed. Note that the tuple body and
830 * HeapTupleData management structure are allocated in one chunk.
832 tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
833 tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
836 * And fill in the information. Note we fill the Datum fields even though
837 * this tuple may never become a Datum.
840 ItemPointerSetInvalid(&(tuple->t_self));
841 tuple->t_tableOid = InvalidOid;
843 HeapTupleHeaderSetDatumLength(td, len);
844 HeapTupleHeaderSetTypeId(td, tupleDescriptor->tdtypeid);
845 HeapTupleHeaderSetTypMod(td, tupleDescriptor->tdtypmod);
847 td->t_natts = numberOfAttributes;
850 if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */
851 td->t_infomask = HEAP_HASOID;
853 DataFill((char *) td + hoff,
858 (hasnull ? td->t_bits : NULL));
865 * form a new tuple from an old tuple and a set of replacement values.
867 * The replValues, replIsnull, and doReplace arrays must be of the length
868 * indicated by tupleDesc->natts. The new tuple is constructed using the data
869 * from replValues/replIsnull at columns where doReplace is true, and using
870 * the data from the old tuple at columns where doReplace is false.
872 * The result is allocated in the current memory context.
875 heap_modify_tuple(HeapTuple tuple,
881 int numberOfAttributes = tupleDesc->natts;
888 * allocate and fill values and isnull arrays from either the tuple or the
889 * repl information, as appropriate.
891 * NOTE: it's debatable whether to use heap_deform_tuple() here or just
892 * heap_getattr() only the non-replaced colums. The latter could win if
893 * there are many replaced columns and few non-replaced ones. However,
894 * heap_deform_tuple costs only O(N) while the heap_getattr way would cost
895 * O(N^2) if there are many non-replaced columns, so it seems better to
896 * err on the side of linear cost.
898 values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
899 isnull = (bool *) palloc(numberOfAttributes * sizeof(bool));
901 heap_deform_tuple(tuple, tupleDesc, values, isnull);
903 for (attoff = 0; attoff < numberOfAttributes; attoff++)
905 if (doReplace[attoff])
907 values[attoff] = replValues[attoff];
908 isnull[attoff] = replIsnull[attoff];
913 * create a new tuple from the values and isnull arrays
915 newTuple = heap_form_tuple(tupleDesc, values, isnull);
921 * copy the identification info of the old tuple: t_ctid, t_self, and OID
924 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
925 newTuple->t_self = tuple->t_self;
926 newTuple->t_tableOid = tuple->t_tableOid;
927 if (tupleDesc->tdhasoid)
928 HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
936 * forms a new tuple from an old tuple and a set of replacement values.
937 * returns a new palloc'ed tuple.
939 * OLD API with char 'n'/' ' convention for indicating nulls, and
940 * char 'r'/' ' convention for indicating whether to replace columns.
944 heap_modifytuple(HeapTuple tuple,
950 int numberOfAttributes = tupleDesc->natts;
957 * allocate and fill values and nulls arrays from either the tuple or the
958 * repl information, as appropriate.
960 * NOTE: it's debatable whether to use heap_deformtuple() here or just
961 * heap_getattr() only the non-replaced colums. The latter could win if
962 * there are many replaced columns and few non-replaced ones. However,
963 * heap_deformtuple costs only O(N) while the heap_getattr way would cost
964 * O(N^2) if there are many non-replaced columns, so it seems better to
965 * err on the side of linear cost.
967 values = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
968 nulls = (char *) palloc(numberOfAttributes * sizeof(char));
970 heap_deformtuple(tuple, tupleDesc, values, nulls);
972 for (attoff = 0; attoff < numberOfAttributes; attoff++)
974 if (replActions[attoff] == 'r')
976 values[attoff] = replValues[attoff];
977 nulls[attoff] = replNulls[attoff];
979 else if (replActions[attoff] != ' ')
980 elog(ERROR, "unrecognized replace flag: %d",
981 (int) replActions[attoff]);
985 * create a new tuple from the values and nulls arrays
987 newTuple = heap_formtuple(tupleDesc, values, nulls);
993 * copy the identification info of the old tuple: t_ctid, t_self, and OID
996 newTuple->t_data->t_ctid = tuple->t_data->t_ctid;
997 newTuple->t_self = tuple->t_self;
998 newTuple->t_tableOid = tuple->t_tableOid;
999 if (tupleDesc->tdhasoid)
1000 HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple));
1007 * Given a tuple, extract data into values/isnull arrays; this is
1008 * the inverse of heap_form_tuple.
1010 * Storage for the values/isnull arrays is provided by the caller;
1011 * it should be sized according to tupleDesc->natts not tuple->t_natts.
1013 * Note that for pass-by-reference datatypes, the pointer placed
1014 * in the Datum will point into the given tuple.
1016 * When all or most of a tuple's fields need to be extracted,
1017 * this routine will be significantly quicker than a loop around
1018 * heap_getattr; the loop will become O(N^2) as soon as any
1019 * noncacheable attribute offsets are involved.
1022 heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
1023 Datum *values, bool *isnull)
1025 HeapTupleHeader tup = tuple->t_data;
1026 bool hasnulls = HeapTupleHasNulls(tuple);
1027 Form_pg_attribute *att = tupleDesc->attrs;
1028 int tdesc_natts = tupleDesc->natts;
1029 int natts; /* number of atts to extract */
1031 char *tp; /* ptr to tuple data */
1032 long off; /* offset in tuple data */
1033 bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
1034 bool slow = false; /* can we use/set attcacheoff? */
1036 natts = tup->t_natts;
1039 * In inheritance situations, it is possible that the given tuple actually
1040 * has more fields than the caller is expecting. Don't run off the end of
1041 * the caller's arrays.
1043 natts = Min(natts, tdesc_natts);
1045 tp = (char *) tup + tup->t_hoff;
1049 for (attnum = 0; attnum < natts; attnum++)
1051 Form_pg_attribute thisatt = att[attnum];
1053 if (hasnulls && att_isnull(attnum, bp))
1055 values[attnum] = (Datum) 0;
1056 isnull[attnum] = true;
1057 slow = true; /* can't use attcacheoff anymore */
1061 isnull[attnum] = false;
1063 if (!slow && thisatt->attcacheoff >= 0)
1064 off = thisatt->attcacheoff;
1067 off = att_align(off, thisatt->attalign);
1070 thisatt->attcacheoff = off;
1073 values[attnum] = fetchatt(thisatt, tp + off);
1075 off = att_addlength(off, thisatt->attlen, tp + off);
1077 if (thisatt->attlen <= 0)
1078 slow = true; /* can't use attcacheoff anymore */
1082 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1085 for (; attnum < tdesc_natts; attnum++)
1087 values[attnum] = (Datum) 0;
1088 isnull[attnum] = true;
1095 * Given a tuple, extract data into values/nulls arrays; this is
1096 * the inverse of heap_formtuple.
1098 * Storage for the values/nulls arrays is provided by the caller;
1099 * it should be sized according to tupleDesc->natts not tuple->t_natts.
1101 * Note that for pass-by-reference datatypes, the pointer placed
1102 * in the Datum will point into the given tuple.
1104 * When all or most of a tuple's fields need to be extracted,
1105 * this routine will be significantly quicker than a loop around
1106 * heap_getattr; the loop will become O(N^2) as soon as any
1107 * noncacheable attribute offsets are involved.
1109 * OLD API with char 'n'/' ' convention for indicating nulls
1113 heap_deformtuple(HeapTuple tuple,
1114 TupleDesc tupleDesc,
1118 HeapTupleHeader tup = tuple->t_data;
1119 bool hasnulls = HeapTupleHasNulls(tuple);
1120 Form_pg_attribute *att = tupleDesc->attrs;
1121 int tdesc_natts = tupleDesc->natts;
1122 int natts; /* number of atts to extract */
1124 char *tp; /* ptr to tuple data */
1125 long off; /* offset in tuple data */
1126 bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
1127 bool slow = false; /* can we use/set attcacheoff? */
1129 natts = tup->t_natts;
1132 * In inheritance situations, it is possible that the given tuple actually
1133 * has more fields than the caller is expecting. Don't run off the end of
1134 * the caller's arrays.
1136 natts = Min(natts, tdesc_natts);
1138 tp = (char *) tup + tup->t_hoff;
1142 for (attnum = 0; attnum < natts; attnum++)
1144 Form_pg_attribute thisatt = att[attnum];
1146 if (hasnulls && att_isnull(attnum, bp))
1148 values[attnum] = (Datum) 0;
1149 nulls[attnum] = 'n';
1150 slow = true; /* can't use attcacheoff anymore */
1154 nulls[attnum] = ' ';
1156 if (!slow && thisatt->attcacheoff >= 0)
1157 off = thisatt->attcacheoff;
1160 off = att_align(off, thisatt->attalign);
1163 thisatt->attcacheoff = off;
1166 values[attnum] = fetchatt(thisatt, tp + off);
1168 off = att_addlength(off, thisatt->attlen, tp + off);
1170 if (thisatt->attlen <= 0)
1171 slow = true; /* can't use attcacheoff anymore */
1175 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1178 for (; attnum < tdesc_natts; attnum++)
1180 values[attnum] = (Datum) 0;
1181 nulls[attnum] = 'n';
1187 * Given a TupleTableSlot, extract data from the slot's physical tuple
1188 * into its Datum/isnull arrays. Data is extracted up through the
1189 * natts'th column (caller must ensure this is a legal column number).
1191 * This is essentially an incremental version of heap_deform_tuple:
1192 * on each call we extract attributes up to the one needed, without
1193 * re-computing information about previously extracted attributes.
1194 * slot->tts_nvalid is the number of attributes already extracted.
1197 slot_deform_tuple(TupleTableSlot *slot, int natts)
1199 HeapTuple tuple = slot->tts_tuple;
1200 TupleDesc tupleDesc = slot->tts_tupleDescriptor;
1201 Datum *values = slot->tts_values;
1202 bool *isnull = slot->tts_isnull;
1203 HeapTupleHeader tup = tuple->t_data;
1204 bool hasnulls = HeapTupleHasNulls(tuple);
1205 Form_pg_attribute *att = tupleDesc->attrs;
1207 char *tp; /* ptr to tuple data */
1208 long off; /* offset in tuple data */
1209 bits8 *bp = tup->t_bits; /* ptr to null bitmap in tuple */
1210 bool slow; /* can we use/set attcacheoff? */
1213 * Check whether the first call for this tuple, and initialize or restore
1216 attnum = slot->tts_nvalid;
1219 /* Start from the first attribute */
1225 /* Restore state from previous execution */
1226 off = slot->tts_off;
1227 slow = slot->tts_slow;
1230 tp = (char *) tup + tup->t_hoff;
1232 for (; attnum < natts; attnum++)
1234 Form_pg_attribute thisatt = att[attnum];
1236 if (hasnulls && att_isnull(attnum, bp))
1238 values[attnum] = (Datum) 0;
1239 isnull[attnum] = true;
1240 slow = true; /* can't use attcacheoff anymore */
1244 isnull[attnum] = false;
1246 if (!slow && thisatt->attcacheoff >= 0)
1247 off = thisatt->attcacheoff;
1250 off = att_align(off, thisatt->attalign);
1253 thisatt->attcacheoff = off;
1256 values[attnum] = fetchatt(thisatt, tp + off);
1258 off = att_addlength(off, thisatt->attlen, tp + off);
1260 if (thisatt->attlen <= 0)
1261 slow = true; /* can't use attcacheoff anymore */
1265 * Save state for next execution
1267 slot->tts_nvalid = attnum;
1268 slot->tts_off = off;
1269 slot->tts_slow = slow;
1274 * This function fetches an attribute of the slot's current tuple.
1275 * It is functionally equivalent to heap_getattr, but fetches of
1276 * multiple attributes of the same tuple will be optimized better,
1277 * because we avoid O(N^2) behavior from multiple calls of
1278 * nocachegetattr(), even when attcacheoff isn't usable.
1280 * A difference from raw heap_getattr is that attnums beyond the
1281 * slot's tupdesc's last attribute will be considered NULL even
1282 * when the physical tuple is longer than the tupdesc.
1285 slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
1287 HeapTuple tuple = slot->tts_tuple;
1288 TupleDesc tupleDesc = slot->tts_tupleDescriptor;
1289 HeapTupleHeader tup;
1292 * system attributes are handled by heap_getsysattr
1296 if (tuple == NULL) /* internal error */
1297 elog(ERROR, "cannot extract system attribute from virtual tuple");
1298 if (slot->tts_mintuple) /* internal error */
1299 elog(ERROR, "cannot extract system attribute from minimal tuple");
1300 return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
1304 * fast path if desired attribute already cached
1306 if (attnum <= slot->tts_nvalid)
1308 *isnull = slot->tts_isnull[attnum - 1];
1309 return slot->tts_values[attnum - 1];
1313 * return NULL if attnum is out of range according to the tupdesc
1315 if (attnum > tupleDesc->natts)
1322 * otherwise we had better have a physical tuple (tts_nvalid should equal
1323 * natts in all virtual-tuple cases)
1325 if (tuple == NULL) /* internal error */
1326 elog(ERROR, "cannot extract attribute from empty tuple slot");
1329 * return NULL if attnum is out of range according to the tuple
1331 * (We have to check this separately because of various inheritance and
1332 * table-alteration scenarios: the tuple could be either longer or shorter
1333 * than the tupdesc.)
1335 tup = tuple->t_data;
1336 if (attnum > tup->t_natts)
1343 * check if target attribute is null: no point in groveling through tuple
1345 if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
1352 * If the attribute's column has been dropped, we force a NULL result.
1353 * This case should not happen in normal use, but it could happen if we
1354 * are executing a plan cached before the column was dropped.
1356 if (tupleDesc->attrs[attnum - 1]->attisdropped)
1363 * Extract the attribute, along with any preceding attributes.
1365 slot_deform_tuple(slot, attnum);
1368 * The result is acquired from tts_values array.
1370 *isnull = slot->tts_isnull[attnum - 1];
1371 return slot->tts_values[attnum - 1];
1376 * This function forces all the entries of the slot's Datum/isnull
1377 * arrays to be valid. The caller may then extract data directly
1378 * from those arrays instead of using slot_getattr.
1381 slot_getallattrs(TupleTableSlot *slot)
1383 int tdesc_natts = slot->tts_tupleDescriptor->natts;
1387 /* Quick out if we have 'em all already */
1388 if (slot->tts_nvalid == tdesc_natts)
1392 * otherwise we had better have a physical tuple (tts_nvalid should equal
1393 * natts in all virtual-tuple cases)
1395 tuple = slot->tts_tuple;
1396 if (tuple == NULL) /* internal error */
1397 elog(ERROR, "cannot extract attribute from empty tuple slot");
1400 * load up any slots available from physical tuple
1402 attnum = tuple->t_data->t_natts;
1403 attnum = Min(attnum, tdesc_natts);
1405 slot_deform_tuple(slot, attnum);
1408 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1411 for (; attnum < tdesc_natts; attnum++)
1413 slot->tts_values[attnum] = (Datum) 0;
1414 slot->tts_isnull[attnum] = true;
1416 slot->tts_nvalid = tdesc_natts;
1421 * This function forces the entries of the slot's Datum/isnull
1422 * arrays to be valid at least up through the attnum'th entry.
1425 slot_getsomeattrs(TupleTableSlot *slot, int attnum)
1430 /* Quick out if we have 'em all already */
1431 if (slot->tts_nvalid >= attnum)
1434 /* Check for caller error */
1435 if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
1436 elog(ERROR, "invalid attribute number %d", attnum);
1439 * otherwise we had better have a physical tuple (tts_nvalid should equal
1440 * natts in all virtual-tuple cases)
1442 tuple = slot->tts_tuple;
1443 if (tuple == NULL) /* internal error */
1444 elog(ERROR, "cannot extract attribute from empty tuple slot");
1447 * load up any slots available from physical tuple
1449 attno = tuple->t_data->t_natts;
1450 attno = Min(attno, attnum);
1452 slot_deform_tuple(slot, attno);
1455 * If tuple doesn't have all the atts indicated by tupleDesc, read the
1458 for (; attno < attnum; attno++)
1460 slot->tts_values[attno] = (Datum) 0;
1461 slot->tts_isnull[attno] = true;
1463 slot->tts_nvalid = attnum;
1468 * Detect whether an attribute of the slot is null, without
1469 * actually fetching it.
1472 slot_attisnull(TupleTableSlot *slot, int attnum)
1474 HeapTuple tuple = slot->tts_tuple;
1475 TupleDesc tupleDesc = slot->tts_tupleDescriptor;
1478 * system attributes are handled by heap_attisnull
1482 if (tuple == NULL) /* internal error */
1483 elog(ERROR, "cannot extract system attribute from virtual tuple");
1484 if (slot->tts_mintuple) /* internal error */
1485 elog(ERROR, "cannot extract system attribute from minimal tuple");
1486 return heap_attisnull(tuple, attnum);
1490 * fast path if desired attribute already cached
1492 if (attnum <= slot->tts_nvalid)
1493 return slot->tts_isnull[attnum - 1];
1496 * return NULL if attnum is out of range according to the tupdesc
1498 if (attnum > tupleDesc->natts)
1502 * otherwise we had better have a physical tuple (tts_nvalid should equal
1503 * natts in all virtual-tuple cases)
1505 if (tuple == NULL) /* internal error */
1506 elog(ERROR, "cannot extract attribute from empty tuple slot");
1508 /* and let the tuple tell it */
1509 return heap_attisnull(tuple, attnum);
1516 heap_freetuple(HeapTuple htup)
1523 * heap_form_minimal_tuple
1524 * construct a MinimalTuple from the given values[] and isnull[] arrays,
1525 * which are of the length indicated by tupleDescriptor->natts
1527 * This is exactly like heap_form_tuple() except that the result is a
1528 * "minimal" tuple lacking a HeapTupleData header as well as room for system
1531 * The result is allocated in the current memory context.
1534 heap_form_minimal_tuple(TupleDesc tupleDescriptor,
1538 MinimalTuple tuple; /* return tuple */
1541 bool hasnull = false;
1542 Form_pg_attribute *att = tupleDescriptor->attrs;
1543 int numberOfAttributes = tupleDescriptor->natts;
1546 if (numberOfAttributes > MaxTupleAttributeNumber)
1548 (errcode(ERRCODE_TOO_MANY_COLUMNS),
1549 errmsg("number of columns (%d) exceeds limit (%d)",
1550 numberOfAttributes, MaxTupleAttributeNumber)));
1553 * Check for nulls and embedded tuples; expand any toasted attributes in
1554 * embedded tuples. This preserves the invariant that toasting can only
1555 * go one level deep.
1557 * We can skip calling toast_flatten_tuple_attribute() if the attribute
1558 * couldn't possibly be of composite type. All composite datums are
1559 * varlena and have alignment 'd'; furthermore they aren't arrays. Also,
1560 * if an attribute is already toasted, it must have been sent to disk
1561 * already and so cannot contain toasted attributes.
1563 for (i = 0; i < numberOfAttributes; i++)
1567 else if (att[i]->attlen == -1 &&
1568 att[i]->attalign == 'd' &&
1569 att[i]->attndims == 0 &&
1570 !VARATT_IS_EXTENDED(values[i]))
1572 values[i] = toast_flatten_tuple_attribute(values[i],
1579 * Determine total space needed
1581 len = offsetof(MinimalTupleData, t_bits);
1584 len += BITMAPLEN(numberOfAttributes);
1586 if (tupleDescriptor->tdhasoid)
1589 hoff = len = MAXALIGN(len); /* align user data safely */
1591 len += heap_compute_data_size(tupleDescriptor, values, isnull);
1594 * Allocate and zero the space needed.
1596 tuple = (MinimalTuple) palloc0(len);
1599 * And fill in the information.
1602 tuple->t_natts = numberOfAttributes;
1603 tuple->t_hoff = hoff + MINIMAL_TUPLE_OFFSET;
1605 if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */
1606 tuple->t_infomask = HEAP_HASOID;
1608 heap_fill_tuple(tupleDescriptor,
1611 (char *) tuple + hoff,
1613 (hasnull ? tuple->t_bits : NULL));
1619 * heap_free_minimal_tuple
1622 heap_free_minimal_tuple(MinimalTuple mtup)
1628 * heap_copy_minimal_tuple
1629 * copy a MinimalTuple
1631 * The result is allocated in the current memory context.
1634 heap_copy_minimal_tuple(MinimalTuple mtup)
1636 MinimalTuple result;
1638 result = (MinimalTuple) palloc(mtup->t_len);
1639 memcpy(result, mtup, mtup->t_len);
1644 * heap_tuple_from_minimal_tuple
1645 * create a HeapTuple by copying from a MinimalTuple;
1646 * system columns are filled with zeroes
1648 * The result is allocated in the current memory context.
1649 * The HeapTuple struct, tuple header, and tuple data are all allocated
1650 * as a single palloc() block.
1653 heap_tuple_from_minimal_tuple(MinimalTuple mtup)
1656 uint32 len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
1658 result = (HeapTuple) palloc(HEAPTUPLESIZE + len);
1659 result->t_len = len;
1660 ItemPointerSetInvalid(&(result->t_self));
1661 result->t_tableOid = InvalidOid;
1662 result->t_data = (HeapTupleHeader) ((char *) result + HEAPTUPLESIZE);
1663 memcpy((char *) result->t_data + MINIMAL_TUPLE_OFFSET, mtup, mtup->t_len);
1664 memset(result->t_data, 0, offsetof(HeapTupleHeaderData, t_natts));
1669 * minimal_tuple_from_heap_tuple
1670 * create a MinimalTuple by copying from a HeapTuple
1672 * The result is allocated in the current memory context.
1675 minimal_tuple_from_heap_tuple(HeapTuple htup)
1677 MinimalTuple result;
1680 Assert(htup->t_len > MINIMAL_TUPLE_OFFSET);
1681 len = htup->t_len - MINIMAL_TUPLE_OFFSET;
1682 result = (MinimalTuple) palloc(len);
1683 memcpy(result, (char *) htup->t_data + MINIMAL_TUPLE_OFFSET, len);
1684 result->t_len = len;
1692 * This routine forms a HeapTuple by copying the given structure (tuple
1693 * data) and adding a generic header. Note that the tuple data is
1694 * presumed to contain no null fields and no varlena fields.
1696 * This routine is really only useful for certain system tables that are
1697 * known to be fixed-width and null-free. It is used in some places for
1698 * pg_class, but that is a gross hack (it only works because relacl can
1699 * be omitted from the tuple entirely in those places).
1703 heap_addheader(int natts, /* max domain index */
1704 bool withoid, /* reserve space for oid */
1705 Size structlen, /* its length */
1706 void *structure) /* pointer to the struct */
1713 AssertArg(natts > 0);
1715 /* header needs no null bitmap */
1716 hoff = offsetof(HeapTupleHeaderData, t_bits);
1718 hoff += sizeof(Oid);
1719 hoff = MAXALIGN(hoff);
1720 len = hoff + structlen;
1722 tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
1723 tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
1726 ItemPointerSetInvalid(&(tuple->t_self));
1727 tuple->t_tableOid = InvalidOid;
1729 /* we don't bother to fill the Datum fields */
1731 td->t_natts = natts;
1734 if (withoid) /* else leave infomask = 0 */
1735 td->t_infomask = HEAP_HASOID;
1737 memcpy((char *) td + hoff, structure, structlen);
1745 * XXX Natts_pg_class_fixed is a hack - see pg_class.h
1748 build_class_tuple(Form_pg_class pgclass, ArrayType *options)
1752 Form_pg_class data; /* contents of tuple */
1757 /* size of pg_class tuple with options */
1759 size = offsetof(FormData_pg_class, reloptions) + VARATT_SIZE(options);
1761 size = CLASS_TUPLE_SIZE;
1763 /* header needs no null bitmap */
1764 hoff = offsetof(HeapTupleHeaderData, t_bits);
1765 hoff += sizeof(Oid);
1766 hoff = MAXALIGN(hoff);
1769 tuple = (HeapTuple) palloc0(HEAPTUPLESIZE + len);
1770 tuple->t_data = td = (HeapTupleHeader) ((char *) tuple + HEAPTUPLESIZE);
1773 ItemPointerSetInvalid(&(tuple->t_self));
1774 tuple->t_tableOid = InvalidOid;
1776 /* we don't bother to fill the Datum fields */
1778 td->t_natts = Natts_pg_class_fixed;
1780 td->t_infomask = HEAP_HASOID;
1782 data = (Form_pg_class) ((char *) td + hoff);
1783 memcpy(data, pgclass, CLASS_TUPLE_SIZE);
1787 memcpy(data->reloptions, options, VARATT_SIZE(options));