From 93e27b84bef5232346d01cfffe60851434451c2b Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 14 Jan 2020 12:50:06 -0800
Subject: [PATCH v1 3/6] pqformat: Move functions for type sending inline, add
 pq_begintypsend_ex().

Combined with the previous commit inlining more functions in
stringinfo this allows many type send functions to be optimized
considerably better, optimizing away the StringInfoData entirely.

The new pq_begintypsend_ex() is useful to avoid over-allocating for
send functions that only output a small amount of data, e.g. int4send
now allocates 9 bytes, instead of 1024.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/include/libpq/pqformat.h | 52 ++++++++++++++++++++++++++++++++++++
 src/backend/libpq/pqformat.c | 38 --------------------------
 2 files changed, 52 insertions(+), 38 deletions(-)

diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h
index af31e9caba3..e0dbb783c6a 100644
--- a/src/include/libpq/pqformat.h
+++ b/src/include/libpq/pqformat.h
@@ -31,6 +31,58 @@ extern void pq_send_ascii_string(StringInfo buf, const char *str);
 extern void pq_sendfloat4(StringInfo buf, float4 f);
 extern void pq_sendfloat8(StringInfo buf, float8 f);
 
+
+/* --------------------------------
+ *		pq_begintypsend		- initialize for constructing a bytea result
+ * --------------------------------
+ */
+static inline void
+pq_begintypsend(StringInfo buf)
+{
+	initStringInfo(buf);
+	/* Reserve four bytes for the bytea length word */
+	appendStringInfoSpaces(buf, 4);
+}
+
+/* --------------------------------
+ *		pq_begintypsend_ex	- like pq_begintypesend, but with length hint
+ *
+ * This can be used over pq_begintypesend if the caller can cheaply determine
+ * how much data will be sent, reducing the initial size of the
+ * StringInfo. The passed in size need not include the overhead of the length
+ * word.
+ * --------------------------------
+ */
+static inline void
+pq_begintypsend_ex(StringInfo buf, int size)
+{
+	initStringInfoEx(buf, size + 4);
+	/* Reserve four bytes for the bytea length word */
+	appendStringInfoSpaces(buf, 4);
+}
+
+
+/* --------------------------------
+ *		pq_endtypsend	- finish constructing a bytea result
+ *
+ * The data buffer is returned as the palloc'd bytea value.  (We expect
+ * that it will be suitably aligned for this because it has been palloc'd.)
+ * We assume the StringInfoData is just a local variable in the caller and
+ * need not be pfree'd.
+ * --------------------------------
+ */
+static inline bytea *
+pq_endtypsend(StringInfo buf)
+{
+	bytea	   *result = (bytea *) buf->data;
+
+	/* Insert correct length into bytea length word */
+	Assert(buf->len >= VARHDRSZ);
+	SET_VARSIZE(result, buf->len);
+
+	return result;
+}
+
 /*
  * Append a [u]int8 to a StringInfo buffer, which already has enough space
  * preallocated.
diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c
index 999252681c2..347a0aa697a 100644
--- a/src/backend/libpq/pqformat.c
+++ b/src/backend/libpq/pqformat.c
@@ -319,44 +319,6 @@ pq_endmessage_reuse(StringInfo buf)
 	(void) pq_putmessage(buf->cursor, buf->data, buf->len);
 }
 
-
-/* --------------------------------
- *		pq_begintypsend		- initialize for constructing a bytea result
- * --------------------------------
- */
-void
-pq_begintypsend(StringInfo buf)
-{
-	initStringInfo(buf);
-	/* Reserve four bytes for the bytea length word */
-	appendStringInfoCharMacro(buf, '\0');
-	appendStringInfoCharMacro(buf, '\0');
-	appendStringInfoCharMacro(buf, '\0');
-	appendStringInfoCharMacro(buf, '\0');
-}
-
-/* --------------------------------
- *		pq_endtypsend	- finish constructing a bytea result
- *
- * The data buffer is returned as the palloc'd bytea value.  (We expect
- * that it will be suitably aligned for this because it has been palloc'd.)
- * We assume the StringInfoData is just a local variable in the caller and
- * need not be pfree'd.
- * --------------------------------
- */
-bytea *
-pq_endtypsend(StringInfo buf)
-{
-	bytea	   *result = (bytea *) buf->data;
-
-	/* Insert correct length into bytea length word */
-	Assert(buf->len >= VARHDRSZ);
-	SET_VARSIZE(result, buf->len);
-
-	return result;
-}
-
-
 /* --------------------------------
  *		pq_puttextmessage - generate a character set-converted message in one step
  *
-- 
2.25.0.rc1

