v1-0001-Don-t-copy-bytea-text-in-convert_from-to-unless-conv.patch

application/octet-stream

Filename: v1-0001-Don-t-copy-bytea-text-in-convert_from-to-unless-conv.patch
Type: application/octet-stream
Part: 0
Message: [PATCH] pg_convert improvement

Patch

Format: format-patch
Series: patch v1-0001
Subject: Don't copy bytea/text in convert_from/to unless converted.
File+
src/backend/utils/mb/mbutils.c 12 8
From afca3ec646aa940e2bd2c244b463d4aeac2344c3 Mon Sep 17 00:00:00 2001
From: Yurii Rashkovskii <yrashk@gmail.com>
Date: Fri, 24 Nov 2023 05:56:57 -0800
Subject: [PATCH] Don't copy bytea/text in convert_from/to unless converted.

`pg_convert` allocates a new bytea whether actual conversion occurred or
not, followed by copying the result which (by definition) is the same as
the original value.

In the case where conversion has not occurred, it will now simply return
the original value, this avoiding unnecessary allocation and copying.
---
 src/backend/utils/mb/mbutils.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/src/backend/utils/mb/mbutils.c b/src/backend/utils/mb/mbutils.c
index 67a1ab2ab2..8f89400aec 100644
--- a/src/backend/utils/mb/mbutils.c
+++ b/src/backend/utils/mb/mbutils.c
@@ -585,19 +585,23 @@ pg_convert(PG_FUNCTION_ARGS)
 												  src_encoding,
 												  dest_encoding);
 
-	/* update len if conversion actually happened */
-	if (dest_str != src_str)
-		len = strlen(dest_str);
 
-	/*
-	 * build bytea data type structure.
-	 */
+	/* if no actual conversion happened, return the original string */
+	/* (we are checking pointers to strings instead of encodings because
+	   `pg_do_encoding_conversion` above covers more cases than just
+	   encoding equality) */
+	if (dest_str == src_str) {
+		PG_RETURN_BYTEA_P(string);
+	}
+
+	/* if conversion happened, build a new bytea of a correct length */
+	len = strlen(dest_str);
 	retval = (bytea *) palloc(len + VARHDRSZ);
 	SET_VARSIZE(retval, len + VARHDRSZ);
 	memcpy(VARDATA(retval), dest_str, len);
 
-	if (dest_str != src_str)
-		pfree(dest_str);
+	/* free the original result of conversion */
+	pfree(dest_str);
 
 	/* free memory if allocated by the toaster */
 	PG_FREE_IF_COPY(string, 0);
-- 
2.33.0