summaryrefslogtreecommitdiff
path: root/src/backend/access/heap
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-03-26 19:14:47 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2017-03-26 19:14:57 -0400
commit2f0903ea196503fc8af373a9de46b1e01a23508c (patch)
tree9eceb4a64d9f6585508fcb2a2c003110cf040cc2 /src/backend/access/heap
parent895f93701fd78b6faab6b437685357298a91dfe3 (diff)
downloadpostgresql-2f0903ea196503fc8af373a9de46b1e01a23508c.tar.gz
Improve performance of ExecEvalWholeRowVar.
In commit b8d7f053c, we needed to fix ExecEvalWholeRowVar to not change the state of the slot it's copying. The initial quick hack at that required two rounds of tuple construction, which is not very nice. To fix, add another primitive to tuptoaster.c that does precisely what we need. (I initially tried to do this by refactoring one of the existing functions into two pieces; but it looked like that might hurt performance for the existing case, and the amount of code that could be shared is not very large, so I gave up on that.) Discussion: https://postgr.es/m/26088.1490315792@sss.pgh.pa.us
Diffstat (limited to 'src/backend/access/heap')
-rw-r--r--src/backend/access/heap/tuptoaster.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 19e7048002..aa5a45ded4 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -1289,6 +1289,74 @@ toast_flatten_tuple_to_datum(HeapTupleHeader tup,
/* ----------
+ * toast_build_flattened_tuple -
+ *
+ * Build a tuple containing no out-of-line toasted fields.
+ * (This does not eliminate compressed or short-header datums.)
+ *
+ * This is essentially just like heap_form_tuple, except that it will
+ * expand any external-data pointers beforehand.
+ *
+ * It's not very clear whether it would be preferable to decompress
+ * in-line compressed datums while at it. For now, we don't.
+ * ----------
+ */
+HeapTuple
+toast_build_flattened_tuple(TupleDesc tupleDesc,
+ Datum *values,
+ bool *isnull)
+{
+ HeapTuple new_tuple;
+ Form_pg_attribute *att = tupleDesc->attrs;
+ int numAttrs = tupleDesc->natts;
+ int num_to_free;
+ int i;
+ Datum new_values[MaxTupleAttributeNumber];
+ Pointer freeable_values[MaxTupleAttributeNumber];
+
+ /*
+ * We can pass the caller's isnull array directly to heap_form_tuple, but
+ * we potentially need to modify the values array.
+ */
+ Assert(numAttrs <= MaxTupleAttributeNumber);
+ memcpy(new_values, values, numAttrs * sizeof(Datum));
+
+ num_to_free = 0;
+ for (i = 0; i < numAttrs; i++)
+ {
+ /*
+ * Look at non-null varlena attributes
+ */
+ if (!isnull[i] && att[i]->attlen == -1)
+ {
+ struct varlena *new_value;
+
+ new_value = (struct varlena *) DatumGetPointer(new_values[i]);
+ if (VARATT_IS_EXTERNAL(new_value))
+ {
+ new_value = heap_tuple_fetch_attr(new_value);
+ new_values[i] = PointerGetDatum(new_value);
+ freeable_values[num_to_free++] = (Pointer) new_value;
+ }
+ }
+ }
+
+ /*
+ * Form the reconfigured tuple.
+ */
+ new_tuple = heap_form_tuple(tupleDesc, new_values, isnull);
+
+ /*
+ * Free allocated temp values
+ */
+ for (i = 0; i < num_to_free; i++)
+ pfree(freeable_values[i]);
+
+ return new_tuple;
+}
+
+
+/* ----------
* toast_compress_datum -
*
* Create a compressed version of a varlena datum