Hi,
heap_deform_tuple and slot_deform_tuple contain duplicated code. This
patch refactors them so that the guts are in a single place.
I have checked the resulting assembly code for heap_deform_tuple, and
with the "inline" declaration, the gcc version I have (4.7.2) generates
almost identical output both after the patch than before, thus there
shouldn't be any slowdown.
--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services
diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index e39b977..4afd998 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -865,6 +865,109 @@ heap_modifytuple(HeapTuple tuple,
return result;
}
+
+/*
+ * heap_deconstruct_tuple
+ * Guts of attribute extraction from a heap tuple. See heap_deform_tuple
+ * and slot_deform_tuple for the user-friendly versions.
+ *
+ * Its arguments are:
+ * tupdata pointer to the tuple data area
+ * t_bits pointer to the tuple null bitmask
+ * hasnulls "has nulls" bit in tuple infomask
+ * start_attnum attnum at which to start decoding
+ * end_attnum attnum at which to stop decoding
+ * att the tuple's TupleDesc Form_pg_attribute pointer
+ * offset offset (into tp) at which start_attnum starts.
+ * slowly whether the cache can be used; updated same as offset.
+ * values output values
+ * isnull output nulls
+ *
+ * offset and slowly are updated to be the values corresponding to the next
+ * attribute to be decoded; thus this function can be used to deconstruct a
+ * tuple incrementally. For the first call, start_attnum and offset should
+ * both be zero; a subsequent call would pass a start_attnum equal to the
+ * previous end_attnum.
+ *
+ * If hasnulls is false, NULL can be passed for t_bits.
+ */
+static inline void
+heap_deconstruct_tuple(char *tupdata,
+ bits8 *t_bits,
+ bool hasnulls,
+ int start_attnum,
+ int end_attnum,
+ Form_pg_attribute *att,
+ Datum *values,
+ bool *isnull,
+ long *offset,
+ bool *slowly)
+{
+ int attnum;
+ bool slow;
+ long off;
+
+ off = *offset;
+ slow = *slowly;
+
+ for (attnum = start_attnum; attnum < end_attnum; attnum++)
+ {
+ Form_pg_attribute thisatt = att[attnum];
+
+ if (hasnulls && att_isnull(attnum, t_bits))
+ {
+ values[attnum] = (Datum) 0;
+ isnull[attnum] = true;
+ slow = true; /* can't use attcacheoff anymore */
+ continue;
+ }
+
+ isnull[attnum] = false;
+
+ if (!slow && thisatt->attcacheoff >= 0)
+ off = thisatt->attcacheoff;
+ else if (thisatt->attlen == -1)
+ {
+ /*
+ * We can only cache the offset for a varlena attribute if the
+ * offset is already suitably aligned, so that there would be no
+ * pad bytes in any case: then the offset will be valid for either
+ * an aligned or unaligned value.
+ */
+ if (!slow &&
+ off == att_align_nominal(off, thisatt->attalign))
+ thisatt->attcacheoff = off;
+ else
+ {
+ off = att_align_pointer(off, thisatt->attalign, -1,
+ tp + off);
+ slow = true;
+ }
+ }
+ else
+ {
+ /* not varlena, so safe to use att_align_nominal */
+ off = att_align_nominal(off, thisatt->attalign);
+
+ if (!slow)
+ thisatt->attcacheoff = off;
+ }
+
+ values[attnum] = fetchatt(thisatt, tp + off);
+
+ off = att_addlength_pointer(off, thisatt->attlen, tp + off);
+
+ if (thisatt->attlen <= 0)
+ slow = true; /* can't use attcacheoff anymore */
+ }
+
+ *slowly = slow;
+ *offset = off;
+
+ return attnum;
+}
+
+
/*
* heap_deform_tuple
* Given a tuple, extract data into values/isnull arrays; this is
@@ -910,56 +1013,8 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
off = 0;
- for (attnum = 0; attnum < natts; attnum++)
- {
- Form_pg_attribute thisatt = att[attnum];
-
- if (hasnulls && att_isnull(attnum, bp))
- {
- values[attnum] = (Datum) 0;
- isnull[attnum] = true;
- slow = true; /* can't use attcacheoff anymore */
- continue;
- }
-
- isnull[attnum] = false;
-
- if (!slow && thisatt->attcacheoff >= 0)
- off = thisatt->attcacheoff;
- else if (thisatt->attlen == -1)
- {
- /*
- * We can only cache the offset for a varlena attribute if the
- * offset is already suitably aligned, so that there would be no
- * pad bytes in any case: then the offset will be valid for either
- * an aligned or unaligned value.
- */
- if (!slow &&
- off == att_align_nominal(off, thisatt->attalign))
- thisatt->attcacheoff = off;
- else
- {
- off = att_align_pointer(off, thisatt->attalign, -1,
- tp + off);
- slow = true;
- }
- }
- else
- {
- /* not varlena, so safe to use att_align_nominal */
- off = att_align_nominal(off, thisatt->attalign);
-
- if (!slow)
- thisatt->attcacheoff = off;
- }
-
- values[attnum] = fetchatt(thisatt, tp + off);
-
- off = att_addlength_pointer(off, thisatt->attlen, tp + off);
-
- if (thisatt->attlen <= 0)
- slow = true; /* can't use attcacheoff anymore */
- }
+ attnum = heap_deconstruct_tuple(tp, bp, hasnulls, 0, natts, att,
+ values, isnull, &off, &slow);
/*
* If tuple doesn't have all the atts indicated by tupleDesc, read the
@@ -1059,56 +1114,8 @@ slot_deform_tuple(TupleTableSlot *slot, int natts)
tp = (char *) tup + tup->t_hoff;
- for (; attnum < natts; attnum++)
- {
- Form_pg_attribute thisatt = att[attnum];
-
- if (hasnulls && att_isnull(attnum, bp))
- {
- values[attnum] = (Datum) 0;
- isnull[attnum] = true;
- slow = true; /* can't use attcacheoff anymore */
- continue;
- }
-
- isnull[attnum] = false;
-
- if (!slow && thisatt->attcacheoff >= 0)
- off = thisatt->attcacheoff;
- else if (thisatt->attlen == -1)
- {
- /*
- * We can only cache the offset for a varlena attribute if the
- * offset is already suitably aligned, so that there would be no
- * pad bytes in any case: then the offset will be valid for either
- * an aligned or unaligned value.
- */
- if (!slow &&
- off == att_align_nominal(off, thisatt->attalign))
- thisatt->attcacheoff = off;
- else
- {
- off = att_align_pointer(off, thisatt->attalign, -1,
- tp + off);
- slow = true;
- }
- }
- else
- {
- /* not varlena, so safe to use att_align_nominal */
- off = att_align_nominal(off, thisatt->attalign);
-
- if (!slow)
- thisatt->attcacheoff = off;
- }
-
- values[attnum] = fetchatt(thisatt, tp + off);
-
- off = att_addlength_pointer(off, thisatt->attlen, tp + off);
-
- if (thisatt->attlen <= 0)
- slow = true; /* can't use attcacheoff anymore */
- }
+ attnum = heap_deconstruct_tuple(tp, bp, hasnulls, attnum, natts, att,
+ values, isnull, &off, &slow);
/*
* Save state for next execution
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers