off = att_nominal_alignby(off, cattr->attalignby);
- cattr->attcacheoff = off;
+ /*
+ * attcacheoff is an int16, so don't try to cache any offsets larger
+ * than will fit in that type. Any attributes which are offset more
+ * than 2^15 are likely due to variable-length attributes. Since we
+ * don't cache offsets for or beyond variable-length attributes, using
+ * an int16 rather than an int32 here is unlikely to cost us anything.
+ */
+ if (off > PG_INT16_MAX)
+ break;
+
+ cattr->attcacheoff = (int16) off;
off += cattr->attlen;
firstNonCachedOffsetAttr = i + 1;
slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
int reqnatts)
{
+ CompactAttribute *cattrs;
CompactAttribute *cattr;
TupleDesc tupleDesc = slot->tts_tupleDescriptor;
HeapTupleHeader tup = tuple->t_data;
values = slot->tts_values;
slot->tts_nvalid = reqnatts;
+ /*
+ * We store the tupleDesc's CompactAttribute array in 'cattrs' as gcc
+ * seems to be unwilling to optimize accessing the CompactAttribute
+ * element efficiently when accessing it via TupleDescCompactAttr().
+ */
+ cattrs = tupleDesc->compact_attrs;
+
/* Ensure we calculated tp correctly */
Assert(tp == (char *) tup + tup->t_hoff);
do
{
isnull[attnum] = false;
- cattr = TupleDescCompactAttr(tupleDesc, attnum);
+ cattr = &cattrs[attnum];
attlen = cattr->attlen;
/* We don't expect any non-byval types */
do
{
isnull[attnum] = false;
- cattr = TupleDescCompactAttr(tupleDesc, attnum);
+ cattr = &cattrs[attnum];
attlen = cattr->attlen;
-
off = cattr->attcacheoff;
values[attnum] = fetch_att_noerr(tp + off,
cattr->attbyval,
int attlen;
isnull[attnum] = false;
- cattr = TupleDescCompactAttr(tupleDesc, attnum);
+ cattr = &cattrs[attnum];
attlen = cattr->attlen;
/*
continue;
}
- cattr = TupleDescCompactAttr(tupleDesc, attnum);
+ cattr = &cattrs[attnum];
attlen = cattr->attlen;
/* As above, we don't expect cstrings */
* directly after the FormData_pg_attribute struct is populated or
* altered in any way.
*
- * Currently, this struct is 16 bytes. Any code changes which enlarge this
+ * Currently, this struct is 8 bytes. Any code changes which enlarge this
* struct should be considered very carefully.
*
* Code which must access a TupleDesc's attribute data should always make use
*/
typedef struct CompactAttribute
{
- int32 attcacheoff; /* fixed offset into tuple, if known, or -1 */
+ int16 attcacheoff; /* fixed offset into tuple, if known, or -1 */
int16 attlen; /* attr len in bytes or -1 = varlen, -2 =
* cstring */
bool attbyval; /* as FormData_pg_attribute.attbyval */
- bool attispackable; /* FormData_pg_attribute.attstorage !=
- * TYPSTORAGE_PLAIN */
- bool atthasmissing; /* as FormData_pg_attribute.atthasmissing */
- bool attisdropped; /* as FormData_pg_attribute.attisdropped */
- bool attgenerated; /* FormData_pg_attribute.attgenerated != '\0' */
- char attnullability; /* status of not-null constraint, see below */
uint8 attalignby; /* alignment requirement in bytes */
+ bool attispackable:1; /* FormData_pg_attribute.attstorage !=
+ * TYPSTORAGE_PLAIN */
+ bool atthasmissing:1; /* as FormData_pg_attribute.atthasmissing */
+ bool attisdropped:1; /* as FormData_pg_attribute.attisdropped */
+ bool attgenerated:1; /* FormData_pg_attribute.attgenerated != '\0' */
+ char attnullability; /* status of not-null constraint, see below */
} CompactAttribute;
/* Valid values for CompactAttribute->attnullability */