From 70d827c851facc1a9cf79642444e7b770cb5296e Mon Sep 17 00:00:00 2001
From: Ranier Vilela <ranier.vf@gmail.com>
Date: Thu, 31 Aug 2023 10:48:00 -0300
Subject: [PATCH 1/2] Replace cstring_to_text with empty_text

Use the new function empty_text where cstring_to_text and
cstring_to_text_with_len are used with "".

Author: Ranier Vilela (ranier.vf@gmail.com)
---
 contrib/btree_gin/btree_gin.c         |  2 +-
 contrib/fuzzystrmatch/fuzzystrmatch.c |  2 +-
 src/backend/utils/adt/formatting.c    |  2 +-
 src/backend/utils/adt/misc.c          |  2 +-
 src/backend/utils/adt/varlena.c       | 37 +++++++++++++++++++--------
 src/include/utils/builtins.h          |  1 +
 src/pl/plpgsql/src/pl_exec.c          |  2 +-
 7 files changed, 33 insertions(+), 15 deletions(-)

diff --git a/contrib/btree_gin/btree_gin.c b/contrib/btree_gin/btree_gin.c
index c50d68ce18..f8b596a8c3 100644
--- a/contrib/btree_gin/btree_gin.c
+++ b/contrib/btree_gin/btree_gin.c
@@ -347,7 +347,7 @@ GIN_SUPPORT(cidr, true, leftmostvalue_inet, network_cmp)
 static Datum
 leftmostvalue_text(void)
 {
-	return PointerGetDatum(cstring_to_text_with_len("", 0));
+	return PointerGetDatum(empty_text());
 }
 
 GIN_SUPPORT(text, true, leftmostvalue_text, bttextcmp)
diff --git a/contrib/fuzzystrmatch/fuzzystrmatch.c b/contrib/fuzzystrmatch/fuzzystrmatch.c
index 5686497983..1d385b352e 100644
--- a/contrib/fuzzystrmatch/fuzzystrmatch.c
+++ b/contrib/fuzzystrmatch/fuzzystrmatch.c
@@ -264,7 +264,7 @@ metaphone(PG_FUNCTION_ARGS)
 
 	/* return an empty string if we receive one */
 	if (!(str_i_len > 0))
-		PG_RETURN_TEXT_P(cstring_to_text(""));
+		PG_RETURN_TEXT_P(empty_text());
 
 	if (str_i_len > MAX_METAPHONE_STRLEN)
 		ereport(ERROR,
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index e27ea8ef97..4d1d1fba3b 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -6059,7 +6059,7 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout,
 do { \
 	int len = VARSIZE_ANY_EXHDR(fmt); \
 	if (len <= 0 || len >= (INT_MAX-VARHDRSZ)/NUM_MAX_ITEM_SIZ)		\
-		PG_RETURN_TEXT_P(cstring_to_text("")); \
+		PG_RETURN_TEXT_P(empty_text()); \
 	result	= (text *) palloc0((len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ);	\
 	format	= NUM_cache(len, &Num, fmt, &shouldFree);		\
 } while (0)
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 5d78d6dc06..7cc2bc4e39 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -319,7 +319,7 @@ pg_tablespace_location(PG_FUNCTION_ARGS)
 	 */
 	if (tablespaceOid == DEFAULTTABLESPACE_OID ||
 		tablespaceOid == GLOBALTABLESPACE_OID)
-		PG_RETURN_TEXT_P(cstring_to_text(""));
+		PG_RETURN_TEXT_P(empty_text());
 
 	/*
 	 * Find the location of the tablespace by reading the symbolic link that
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index 72e1e24fe0..644b777d77 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -171,6 +171,23 @@ static void text_format_append_string(StringInfo buf, const char *str,
  *	 CONVERSION ROUTINES EXPORTED FOR USE BY C CODE							 *
  *****************************************************************************/
 
+/*
+ * empty_text
+ *
+ * Create a empty text value
+ *
+ * The new text value is freshly palloc'd with a full-size VARHDR.
+ */
+text *
+empty_text(void)
+{
+	text	   *result = (text *) palloc(VARHDRSZ);
+
+	SET_VARSIZE(result, VARHDRSZ);
+
+	return result;
+}
+
 /*
  * cstring_to_text
  *
@@ -924,7 +941,7 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
 			 * string.
 			 */
 			if (E < 1)
-				return cstring_to_text("");
+				return empty_text();
 
 			L1 = E - S1;
 		}
@@ -987,7 +1004,7 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
 			 * string.
 			 */
 			if (E < 1)
-				return cstring_to_text("");
+				return empty_text();
 
 			/*
 			 * if E is past the end of the string, the tuple toaster will
@@ -1019,7 +1036,7 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
 		{
 			if (slice != (text *) DatumGetPointer(str))
 				pfree(slice);
-			return cstring_to_text("");
+			return empty_text();
 		}
 
 		/* Now we can get the actual length of the slice in MB characters */
@@ -1034,7 +1051,7 @@ text_substring(Datum str, int32 start, int32 length, bool length_not_specified)
 		{
 			if (slice != (text *) DatumGetPointer(str))
 				pfree(slice);
-			return cstring_to_text("");
+			return empty_text();
 		}
 
 		/*
@@ -4386,7 +4403,7 @@ split_part(PG_FUNCTION_ARGS)
 
 	/* return empty string for empty input string */
 	if (inputstring_len < 1)
-		PG_RETURN_TEXT_P(cstring_to_text(""));
+		PG_RETURN_TEXT_P(empty_text());
 
 	/* handle empty field separator */
 	if (fldsep_len < 1)
@@ -4395,7 +4412,7 @@ split_part(PG_FUNCTION_ARGS)
 		if (fldnum == 1 || fldnum == -1)
 			PG_RETURN_TEXT_P(inputstring);
 		else
-			PG_RETURN_TEXT_P(cstring_to_text(""));
+			PG_RETURN_TEXT_P(empty_text());
 	}
 
 	/* find the first field separator */
@@ -4411,7 +4428,7 @@ split_part(PG_FUNCTION_ARGS)
 		if (fldnum == 1 || fldnum == -1)
 			PG_RETURN_TEXT_P(inputstring);
 		else
-			PG_RETURN_TEXT_P(cstring_to_text(""));
+			PG_RETURN_TEXT_P(empty_text());
 	}
 
 	/*
@@ -4443,7 +4460,7 @@ split_part(PG_FUNCTION_ARGS)
 		if (fldnum <= 0)
 		{
 			text_position_cleanup(&state);
-			PG_RETURN_TEXT_P(cstring_to_text(""));
+			PG_RETURN_TEXT_P(empty_text());
 		}
 
 		/* reset to pointing at first match, but now with positive fldnum */
@@ -4479,7 +4496,7 @@ split_part(PG_FUNCTION_ARGS)
 												   inputstring_len - last_len);
 		}
 		else
-			result_text = cstring_to_text("");
+			result_text = empty_text();
 	}
 	else
 	{
@@ -4827,7 +4844,7 @@ array_to_text_internal(FunctionCallInfo fcinfo, ArrayType *v,
 
 	/* if there are no elements, return an empty string */
 	if (nitems == 0)
-		return cstring_to_text_with_len("", 0);
+		return empty_text();
 
 	element_type = ARR_ELEMTYPE(v);
 	initStringInfo(&buf);
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 2f8b46d6da..bb1c4e2055 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -86,6 +86,7 @@ extern void generate_operator_clause(fmStringInfo buf,
 extern int	bpchartruelen(char *s, int len);
 
 /* popular functions from varlena.c */
+extern text *empty_text(void);
 extern text *cstring_to_text(const char *s);
 extern text *cstring_to_text_with_len(const char *s, int len);
 extern char *text_to_cstring(const text *t);
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 4b76f7699a..0d744e1f92 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -5058,7 +5058,7 @@ exec_assign_c_string(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
 	if (str != NULL)
 		value = cstring_to_text(str);
 	else
-		value = cstring_to_text("");
+		value = empty_text();
 	MemoryContextSwitchTo(oldcontext);
 
 	exec_assign_value(estate, target, PointerGetDatum(value), false,
-- 
2.32.0.windows.1

