From 0d9742f99aa0ba6b96d0729dd2cb2634a29d0be9 Mon Sep 17 00:00:00 2001
From: Neil Conway <neilc@samurai.com>
Date: Wed, 1 Mar 2006 06:51:01 +0000
Subject: [PATCH] Attached is a patch that replaces a bunch of places where
 StringInfos are unnecessarily allocated on the heap rather than the stack. If
 the StringInfo doesn't outlive the stack frame in which it is created, there
 is no need to allocate it on the heap via makeStringInfo() -- stack
 allocation is faster.  While it's not a big deal unless the code is in a
 critical path, I don't see a reason not to save a few cycles -- using stack
 allocation is not less readable.

I also cleaned up a bit of code along the way: moved variable
declarations into a more tightly-enclosing scope where possible,
fixed some pointless copying of strings in dblink, etc.
---
 contrib/dblink/dblink.c         | 125 +++++++++++++++-----------------
 contrib/tablefunc/tablefunc.c   |  51 ++++++-------
 contrib/xml2/xpath.c            |  11 ++-
 src/backend/commands/explain.c  |  24 +++---
 src/backend/utils/adt/varlena.c |  55 +++++++-------
 5 files changed, 126 insertions(+), 140 deletions(-)

diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 4fd17c32271..b1b863ea1e4 100644
--- a/contrib/dblink/dblink.c
+++ b/contrib/dblink/dblink.c
@@ -301,11 +301,12 @@ dblink_open(PG_FUNCTION_ARGS)
 	char	   *curname = NULL;
 	char	   *sql = NULL;
 	char	   *conname = NULL;
-	StringInfo	str = makeStringInfo();
+	StringInfoData buf;
 	remoteConn *rconn = NULL;
 	bool		fail = true;	/* default to backward compatible behavior */
 
 	DBLINK_INIT;
+	initStringInfo(&buf);
 
 	if (PG_NARGS() == 2)
 	{
@@ -361,8 +362,8 @@ dblink_open(PG_FUNCTION_ARGS)
 	if (rconn->newXactForCursor)
 		(rconn->openCursorCount)++;
 
-	appendStringInfo(str, "DECLARE %s CURSOR FOR %s", curname, sql);
-	res = PQexec(conn, str->data);
+	appendStringInfo(&buf, "DECLARE %s CURSOR FOR %s", curname, sql);
+	res = PQexec(conn, buf.data);
 	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
 		if (fail)
@@ -389,12 +390,13 @@ dblink_close(PG_FUNCTION_ARGS)
 	PGresult   *res = NULL;
 	char	   *curname = NULL;
 	char	   *conname = NULL;
-	StringInfo	str = makeStringInfo();
+	StringInfoData buf;
 	char	   *msg;
 	remoteConn *rconn = NULL;
 	bool		fail = true;	/* default to backward compatible behavior */
 
 	DBLINK_INIT;
+	initStringInfo(&buf);
 
 	if (PG_NARGS() == 1)
 	{
@@ -432,10 +434,10 @@ dblink_close(PG_FUNCTION_ARGS)
 	else
 		conn = rconn->conn;
 
-	appendStringInfo(str, "CLOSE %s", curname);
+	appendStringInfo(&buf, "CLOSE %s", curname);
 
 	/* close the cursor */
-	res = PQexec(conn, str->data);
+	res = PQexec(conn, buf.data);
 	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
 		if (fail)
@@ -493,7 +495,7 @@ dblink_fetch(PG_FUNCTION_ARGS)
 	if (SRF_IS_FIRSTCALL())
 	{
 		PGconn	   *conn = NULL;
-		StringInfo	str = makeStringInfo();
+		StringInfoData buf;
 		char	   *curname = NULL;
 		int			howmany = 0;
 		bool		fail = true;	/* default to backward compatible */
@@ -542,6 +544,9 @@ dblink_fetch(PG_FUNCTION_ARGS)
 		if (!conn)
 			DBLINK_CONN_NOT_AVAIL;
 
+		initStringInfo(&buf);
+		appendStringInfo(&buf, "FETCH %d FROM %s", howmany, curname);
+
 		/* create a function context for cross-call persistence */
 		funcctx = SRF_FIRSTCALL_INIT();
 
@@ -550,9 +555,7 @@ dblink_fetch(PG_FUNCTION_ARGS)
 		 */
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-		appendStringInfo(str, "FETCH %d FROM %s", howmany, curname);
-
-		res = PQexec(conn, str->data);
+		res = PQexec(conn, buf.data);
 		if (!res ||
 			(PQresultStatus(res) != PGRES_COMMAND_OK &&
 			 PQresultStatus(res) != PGRES_TUPLES_OK))
@@ -1547,13 +1550,14 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 	HeapTuple	tuple;
 	TupleDesc	tupdesc;
 	int			natts;
-	StringInfo	str = makeStringInfo();
-	char	   *sql;
+	StringInfoData buf;
 	char	   *val;
 	int16		key;
 	int			i;
 	bool		needComma;
 
+	initStringInfo(&buf);
+
 	/* get relation name including any needed schema prefix and quoting */
 	relname = generate_relation_name(relid);
 
@@ -1570,7 +1574,7 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 				(errcode(ERRCODE_CARDINALITY_VIOLATION),
 				 errmsg("source row not found")));
 
-	appendStringInfo(str, "INSERT INTO %s(", relname);
+	appendStringInfo(&buf, "INSERT INTO %s(", relname);
 
 	needComma = false;
 	for (i = 0; i < natts; i++)
@@ -1579,14 +1583,14 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 			continue;
 
 		if (needComma)
-			appendStringInfo(str, ",");
+			appendStringInfo(&buf, ",");
 
-		appendStringInfo(str, "%s",
+		appendStringInfoString(&buf,
 					  quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname)));
 		needComma = true;
 	}
 
-	appendStringInfo(str, ") VALUES(");
+	appendStringInfo(&buf, ") VALUES(");
 
 	/*
 	 * remember attvals are 1 based
@@ -1598,7 +1602,7 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 			continue;
 
 		if (needComma)
-			appendStringInfo(str, ",");
+			appendStringInfo(&buf, ",");
 
 		if (tgt_pkattvals != NULL)
 			key = get_attnum_pk_pos(pkattnums, pknumatts, i + 1);
@@ -1612,21 +1616,17 @@ get_sql_insert(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 
 		if (val != NULL)
 		{
-			appendStringInfo(str, "%s", quote_literal_cstr(val));
+			appendStringInfoString(&buf, quote_literal_cstr(val));
 			pfree(val);
 		}
 		else
-			appendStringInfo(str, "NULL");
+			appendStringInfo(&buf, "NULL");
 		needComma = true;
 	}
-	appendStringInfo(str, ")");
+	appendStringInfo(&buf, ")");
 
-	sql = pstrdup(str->data);
-	pfree(str->data);
-	pfree(str);
 	relation_close(rel, AccessShareLock);
-
-	return (sql);
+	return (buf.data);
 }
 
 static char *
@@ -1636,10 +1636,11 @@ get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pka
 	char	   *relname;
 	TupleDesc	tupdesc;
 	int			natts;
-	StringInfo	str = makeStringInfo();
-	char	   *sql;
+	StringInfoData	buf;
 	int			i;
 
+	initStringInfo(&buf);
+
 	/* get relation name including any needed schema prefix and quoting */
 	relname = generate_relation_name(relid);
 
@@ -1650,15 +1651,15 @@ get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pka
 	tupdesc = rel->rd_att;
 	natts = tupdesc->natts;
 
-	appendStringInfo(str, "DELETE FROM %s WHERE ", relname);
+	appendStringInfo(&buf, "DELETE FROM %s WHERE ", relname);
 	for (i = 0; i < pknumatts; i++)
 	{
 		int16		pkattnum = pkattnums->values[i];
 
 		if (i > 0)
-			appendStringInfo(str, " AND ");
+			appendStringInfo(&buf, " AND ");
 
-		appendStringInfo(str, "%s",
+		appendStringInfoString(&buf,
 		   quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));
 
 		if (tgt_pkattvals == NULL)
@@ -1666,18 +1667,14 @@ get_sql_delete(Oid relid, int2vector *pkattnums, int16 pknumatts, char **tgt_pka
 			elog(ERROR, "target key array must not be NULL");
 
 		if (tgt_pkattvals[i] != NULL)
-			appendStringInfo(str, " = %s",
+			appendStringInfo(&buf, " = %s",
 							 quote_literal_cstr(tgt_pkattvals[i]));
 		else
-			appendStringInfo(str, " IS NULL");
+			appendStringInfo(&buf, " IS NULL");
 	}
 
-	sql = pstrdup(str->data);
-	pfree(str->data);
-	pfree(str);
 	relation_close(rel, AccessShareLock);
-
-	return (sql);
+	return (buf.data);
 }
 
 static char *
@@ -1688,13 +1685,14 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 	HeapTuple	tuple;
 	TupleDesc	tupdesc;
 	int			natts;
-	StringInfo	str = makeStringInfo();
-	char	   *sql;
+	StringInfoData buf;
 	char	   *val;
 	int16		key;
 	int			i;
 	bool		needComma;
 
+	initStringInfo(&buf);
+
 	/* get relation name including any needed schema prefix and quoting */
 	relname = generate_relation_name(relid);
 
@@ -1711,7 +1709,7 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 				(errcode(ERRCODE_CARDINALITY_VIOLATION),
 				 errmsg("source row not found")));
 
-	appendStringInfo(str, "UPDATE %s SET ", relname);
+	appendStringInfo(&buf, "UPDATE %s SET ", relname);
 
 	needComma = false;
 	for (i = 0; i < natts; i++)
@@ -1720,9 +1718,9 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 			continue;
 
 		if (needComma)
-			appendStringInfo(str, ", ");
+			appendStringInfo(&buf, ", ");
 
-		appendStringInfo(str, "%s = ",
+		appendStringInfo(&buf, "%s = ",
 					  quote_ident_cstr(NameStr(tupdesc->attrs[i]->attname)));
 
 		if (tgt_pkattvals != NULL)
@@ -1737,24 +1735,24 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 
 		if (val != NULL)
 		{
-			appendStringInfo(str, "%s", quote_literal_cstr(val));
+			appendStringInfoString(&buf, quote_literal_cstr(val));
 			pfree(val);
 		}
 		else
-			appendStringInfo(str, "NULL");
+			appendStringInfoString(&buf, "NULL");
 		needComma = true;
 	}
 
-	appendStringInfo(str, " WHERE ");
+	appendStringInfo(&buf, " WHERE ");
 
 	for (i = 0; i < pknumatts; i++)
 	{
 		int16		pkattnum = pkattnums->values[i];
 
 		if (i > 0)
-			appendStringInfo(str, " AND ");
+			appendStringInfo(&buf, " AND ");
 
-		appendStringInfo(str, "%s",
+		appendStringInfo(&buf, "%s",
 		   quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));
 
 		if (tgt_pkattvals != NULL)
@@ -1764,19 +1762,15 @@ get_sql_update(Oid relid, int2vector *pkattnums, int16 pknumatts, char **src_pka
 
 		if (val != NULL)
 		{
-			appendStringInfo(str, " = %s", quote_literal_cstr(val));
+			appendStringInfo(&buf, " = %s", quote_literal_cstr(val));
 			pfree(val);
 		}
 		else
-			appendStringInfo(str, " IS NULL");
+			appendStringInfo(&buf, " IS NULL");
 	}
 
-	sql = pstrdup(str->data);
-	pfree(str->data);
-	pfree(str);
 	relation_close(rel, AccessShareLock);
-
-	return (sql);
+	return (buf.data);
 }
 
 /*
@@ -1836,12 +1830,13 @@ get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **
 	Relation	rel;
 	char	   *relname;
 	TupleDesc	tupdesc;
-	StringInfo	str = makeStringInfo();
-	char	   *sql = NULL;
+	StringInfoData buf;
 	int			ret;
 	HeapTuple	tuple;
 	int			i;
 
+	initStringInfo(&buf);
+
 	/* get relation name including any needed schema prefix and quoting */
 	relname = generate_relation_name(relid);
 
@@ -1863,34 +1858,30 @@ get_tuple_of_interest(Oid relid, int2vector *pkattnums, int16 pknumatts, char **
 	 * Build sql statement to look up tuple of interest Use src_pkattvals as
 	 * the criteria.
 	 */
-	appendStringInfo(str, "SELECT * FROM %s WHERE ", relname);
+	appendStringInfo(&buf, "SELECT * FROM %s WHERE ", relname);
 
 	for (i = 0; i < pknumatts; i++)
 	{
 		int16		pkattnum = pkattnums->values[i];
 
 		if (i > 0)
-			appendStringInfo(str, " AND ");
+			appendStringInfo(&buf, " AND ");
 
-		appendStringInfo(str, "%s",
+		appendStringInfoString(&buf,
 		   quote_ident_cstr(NameStr(tupdesc->attrs[pkattnum - 1]->attname)));
 
 		if (src_pkattvals[i] != NULL)
-			appendStringInfo(str, " = %s",
+			appendStringInfo(&buf, " = %s",
 							 quote_literal_cstr(src_pkattvals[i]));
 		else
-			appendStringInfo(str, " IS NULL");
+			appendStringInfo(&buf, " IS NULL");
 	}
 
-	sql = pstrdup(str->data);
-	pfree(str->data);
-	pfree(str);
-
 	/*
 	 * Retrieve the desired tuple
 	 */
-	ret = SPI_exec(sql, 0);
-	pfree(sql);
+	ret = SPI_exec(buf.data, 0);
+	pfree(buf.data);
 
 	/*
 	 * Only allow one qualifying tuple
diff --git a/contrib/tablefunc/tablefunc.c b/contrib/tablefunc/tablefunc.c
index 0beb44f5845..aacc949ff28 100644
--- a/contrib/tablefunc/tablefunc.c
+++ b/contrib/tablefunc/tablefunc.c
@@ -1260,13 +1260,10 @@ build_tuplestore_recursively(char *key_fld,
 {
 	TupleDesc	tupdesc = attinmeta->tupdesc;
 	MemoryContext oldcontext;
-	StringInfo	sql = makeStringInfo();
 	int			ret;
 	int			proc;
 	int			serial_column;
-	StringInfo	branchstr = NULL;
-	StringInfo	chk_branchstr = NULL;
-	StringInfo	chk_current_key = NULL;
+	StringInfoData	sql;
 	char	  **values;
 	char	   *current_key;
 	char	   *current_key_parent;
@@ -1278,17 +1275,12 @@ build_tuplestore_recursively(char *key_fld,
 	if (max_depth > 0 && level > max_depth)
 		return tupstore;
 
-	/* start a new branch */
-	branchstr = makeStringInfo();
-
-	/* need these to check for recursion */
-	chk_branchstr = makeStringInfo();
-	chk_current_key = makeStringInfo();
+	initStringInfo(&sql);
 
 	/* Build initial sql statement */
 	if (!show_serial)
 	{
-		appendStringInfo(sql, "SELECT %s, %s FROM %s WHERE %s = %s AND %s IS NOT NULL AND %s <> %s",
+		appendStringInfo(&sql, "SELECT %s, %s FROM %s WHERE %s = %s AND %s IS NOT NULL AND %s <> %s",
 						 key_fld,
 						 parent_key_fld,
 						 relname,
@@ -1299,7 +1291,7 @@ build_tuplestore_recursively(char *key_fld,
 	}
 	else
 	{
-		appendStringInfo(sql, "SELECT %s, %s FROM %s WHERE %s = %s AND %s IS NOT NULL AND %s <> %s ORDER BY %s",
+		appendStringInfo(&sql, "SELECT %s, %s FROM %s WHERE %s = %s AND %s IS NOT NULL AND %s <> %s ORDER BY %s",
 						 key_fld,
 						 parent_key_fld,
 						 relname,
@@ -1359,7 +1351,7 @@ build_tuplestore_recursively(char *key_fld,
 	}
 
 	/* Retrieve the desired rows */
-	ret = SPI_execute(sql->data, true, 0);
+	ret = SPI_execute(sql.data, true, 0);
 	proc = SPI_processed;
 
 	/* Check for qualifying tuples */
@@ -1369,6 +1361,9 @@ build_tuplestore_recursively(char *key_fld,
 		SPITupleTable *tuptable = SPI_tuptable;
 		TupleDesc	spi_tupdesc = tuptable->tupdesc;
 		int			i;
+		StringInfoData	branchstr;
+		StringInfoData	chk_branchstr;
+		StringInfoData	chk_current_key;
 
 		/* First time through, do a little more setup */
 		if (level == 0)
@@ -1389,28 +1384,35 @@ build_tuplestore_recursively(char *key_fld,
 
 		for (i = 0; i < proc; i++)
 		{
+			/* start a new branch */
+			initStringInfo(&branchstr);
+
+			/* need these to check for recursion */
+			initStringInfo(&chk_branchstr);
+			initStringInfo(&chk_current_key);
+
 			/* initialize branch for this pass */
-			appendStringInfo(branchstr, "%s", branch);
-			appendStringInfo(chk_branchstr, "%s%s%s", branch_delim, branch, branch_delim);
+			appendStringInfo(&branchstr, "%s", branch);
+			appendStringInfo(&chk_branchstr, "%s%s%s", branch_delim, branch, branch_delim);
 
 			/* get the next sql result tuple */
 			spi_tuple = tuptable->vals[i];
 
 			/* get the current key and parent */
 			current_key = SPI_getvalue(spi_tuple, spi_tupdesc, 1);
-			appendStringInfo(chk_current_key, "%s%s%s", branch_delim, current_key, branch_delim);
+			appendStringInfo(&chk_current_key, "%s%s%s", branch_delim, current_key, branch_delim);
 			current_key_parent = pstrdup(SPI_getvalue(spi_tuple, spi_tupdesc, 2));
 
 			/* get the current level */
 			sprintf(current_level, "%d", level);
 
 			/* check to see if this key is also an ancestor */
-			if (strstr(chk_branchstr->data, chk_current_key->data))
+			if (strstr(chk_branchstr.data, chk_current_key.data))
 				elog(ERROR, "infinite recursion detected");
 
 			/* OK, extend the branch */
-			appendStringInfo(branchstr, "%s%s", branch_delim, current_key);
-			current_branch = branchstr->data;
+			appendStringInfo(&branchstr, "%s%s", branch_delim, current_key);
+			current_branch = branchstr.data;
 
 			/* build a tuple */
 			values[0] = pstrdup(current_key);
@@ -1461,14 +1463,9 @@ build_tuplestore_recursively(char *key_fld,
 													tupstore);
 
 			/* reset branch for next pass */
-			xpfree(branchstr->data);
-			initStringInfo(branchstr);
-
-			xpfree(chk_branchstr->data);
-			initStringInfo(chk_branchstr);
-
-			xpfree(chk_current_key->data);
-			initStringInfo(chk_current_key);
+			xpfree(branchstr.data);
+			xpfree(chk_branchstr.data);
+			xpfree(chk_current_key.data);
 		}
 	}
 
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
index 662731b5c04..3dfcdadf96b 100644
--- a/contrib/xml2/xpath.c
+++ b/contrib/xml2/xpath.c
@@ -668,7 +668,7 @@ xpath_table(PG_FUNCTION_ARGS)
 								 * document */
 	int			had_values;		/* To determine end of nodeset results */
 
-	StringInfo	querysql;
+	StringInfoData	query_buf;
 
 	/* We only have a valid tuple description in table function mode */
 	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
@@ -746,11 +746,10 @@ xpath_table(PG_FUNCTION_ARGS)
 	} while ((pos != NULL) && (numpaths < (ret_tupdesc->natts - 1)));
 
 	/* Now build query */
-
-	querysql = makeStringInfo();
+	initStringInfo(&query_buf);
 
 	/* Build initial sql statement */
-	appendStringInfo(querysql, "SELECT %s, %s FROM %s WHERE %s",
+	appendStringInfo(&query_buf, "SELECT %s, %s FROM %s WHERE %s",
 					 pkeyfield,
 					 xmlfield,
 					 relname,
@@ -761,8 +760,8 @@ xpath_table(PG_FUNCTION_ARGS)
 	if ((ret = SPI_connect()) < 0)
 		elog(ERROR, "xpath_table: SPI_connect returned %d", ret);
 
-	if ((ret = SPI_exec(querysql->data, 0)) != SPI_OK_SELECT)
-		elog(ERROR, "xpath_table: SPI execution failed for query %s", querysql->data);
+	if ((ret = SPI_exec(query_buf.data, 0)) != SPI_OK_SELECT)
+		elog(ERROR, "xpath_table: SPI execution failed for query %s", query_buf.data);
 
 	proc = SPI_processed;
 	/* elog(DEBUG1,"xpath_table: SPI returned %d rows",proc); */
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 755a64a9446..767d4c9f806 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994-5, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.144 2006/02/28 04:10:27 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.145 2006/03/01 06:51:01 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -232,7 +232,7 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
 	instr_time	starttime;
 	double		totaltime = 0;
 	ExplainState *es;
-	StringInfo	str;
+	StringInfoData buf;
 	int			eflags;
 
 	INSTR_TIME_SET_CURRENT(starttime);
@@ -285,9 +285,8 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
 		}
 	}
 
-	str = makeStringInfo();
-
-	explain_outNode(str, queryDesc->plantree, queryDesc->planstate,
+	initStringInfo(&buf);
+	explain_outNode(&buf, queryDesc->plantree, queryDesc->planstate,
 					NULL, 0, es);
 
 	/*
@@ -335,18 +334,18 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
 				if (trig->tgisconstraint &&
 				(conname = GetConstraintNameForTrigger(trig->tgoid)) != NULL)
 				{
-					appendStringInfo(str, "Trigger for constraint %s",
+					appendStringInfo(&buf, "Trigger for constraint %s",
 									 conname);
 					pfree(conname);
 				}
 				else
-					appendStringInfo(str, "Trigger %s", trig->tgname);
+					appendStringInfo(&buf, "Trigger %s", trig->tgname);
 
 				if (numrels > 1)
-					appendStringInfo(str, " on %s",
+					appendStringInfo(&buf, " on %s",
 							RelationGetRelationName(rInfo->ri_RelationDesc));
 
-				appendStringInfo(str, ": time=%.3f calls=%.0f\n",
+				appendStringInfo(&buf, ": time=%.3f calls=%.0f\n",
 								 1000.0 * instr->total,
 								 instr->ntuples);
 			}
@@ -370,12 +369,11 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
 	totaltime += elapsed_time(&starttime);
 
 	if (stmt->analyze)
-		appendStringInfo(str, "Total runtime: %.3f ms\n",
+		appendStringInfo(&buf, "Total runtime: %.3f ms\n",
 						 1000.0 * totaltime);
-	do_text_output_multiline(tstate, str->data);
+	do_text_output_multiline(tstate, buf.data);
 
-	pfree(str->data);
-	pfree(str);
+	pfree(buf.data);
 	pfree(es);
 }
 
diff --git a/src/backend/utils/adt/varlena.c b/src/backend/utils/adt/varlena.c
index c2119edcecc..cbfcf52ffe3 100644
--- a/src/backend/utils/adt/varlena.c
+++ b/src/backend/utils/adt/varlena.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.143 2006/02/26 02:23:41 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.144 2006/03/01 06:51:01 neilc Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2038,7 +2038,7 @@ replace_text(PG_FUNCTION_ARGS)
 	text	   *buf_text;
 	text	   *ret_text;
 	int			curr_posn;
-	StringInfo	str;
+	StringInfoData str;
 
 	if (src_text_len == 0 || from_sub_text_len == 0)
 		PG_RETURN_TEXT_P(src_text);
@@ -2049,7 +2049,7 @@ replace_text(PG_FUNCTION_ARGS)
 	if (curr_posn == 0)
 		PG_RETURN_TEXT_P(src_text);
 
-	str = makeStringInfo();
+	initStringInfo(&str);
 	buf_text = src_text;
 
 	while (curr_posn > 0)
@@ -2059,8 +2059,8 @@ replace_text(PG_FUNCTION_ARGS)
 		right_text = text_substring(PointerGetDatum(buf_text),
 									curr_posn + from_sub_text_len, -1, true);
 
-		appendStringInfoText(str, left_text);
-		appendStringInfoText(str, to_sub_text);
+		appendStringInfoText(&str, left_text);
+		appendStringInfoText(&str, to_sub_text);
 
 		if (buf_text != src_text)
 			pfree(buf_text);
@@ -2069,13 +2069,12 @@ replace_text(PG_FUNCTION_ARGS)
 		curr_posn = TEXTPOS(buf_text, from_sub_text);
 	}
 
-	appendStringInfoText(str, buf_text);
+	appendStringInfoText(&str, buf_text);
 	if (buf_text != src_text)
 		pfree(buf_text);
 
-	ret_text = PG_STR_GET_TEXT(str->data);
-	pfree(str->data);
-	pfree(str);
+	ret_text = PG_STR_GET_TEXT(str.data);
+	pfree(str.data);
 
 	PG_RETURN_TEXT_P(ret_text);
 }
@@ -2227,8 +2226,7 @@ replace_text_regexp(text *src_text, void *regexp,
 	text	   *ret_text;
 	regex_t    *re = (regex_t *) regexp;
 	int			src_text_len = VARSIZE(src_text) - VARHDRSZ;
-	StringInfo	str = makeStringInfo();
-	int			regexec_result;
+	StringInfoData	buf;
 	regmatch_t	pmatch[REGEXP_REPLACE_BACKREF_CNT];
 	pg_wchar   *data;
 	size_t		data_len;
@@ -2236,6 +2234,8 @@ replace_text_regexp(text *src_text, void *regexp,
 	int			data_pos;
 	bool		have_escape;
 
+	initStringInfo(&buf);
+
 	/* Convert data string to wide characters. */
 	data = (pg_wchar *) palloc((src_text_len + 1) * sizeof(pg_wchar));
 	data_len = pg_mb2wchar_with_len(VARDATA(src_text), data, src_text_len);
@@ -2245,6 +2245,8 @@ replace_text_regexp(text *src_text, void *regexp,
 
 	for (search_start = data_pos = 0; search_start <= data_len;)
 	{
+		int regexec_result;
+
 		regexec_result = pg_regexec(re,
 									data,
 									data_len,
@@ -2254,20 +2256,19 @@ replace_text_regexp(text *src_text, void *regexp,
 									pmatch,
 									0);
 
-		if (regexec_result != REG_OKAY && regexec_result != REG_NOMATCH)
+		if (regexec_result == REG_NOMATCH)
+			break;
+
+		if (regexec_result != REG_OKAY)
 		{
 			char		errMsg[100];
 
-			/* re failed??? */
 			pg_regerror(regexec_result, re, errMsg, sizeof(errMsg));
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_REGULAR_EXPRESSION),
 					 errmsg("regular expression failed: %s", errMsg)));
 		}
 
-		if (regexec_result == REG_NOMATCH)
-			break;
-
 		/*
 		 * Copy the text to the left of the match position.  Because we are
 		 * working with character not byte indexes, it's easiest to use
@@ -2281,7 +2282,7 @@ replace_text_regexp(text *src_text, void *regexp,
 									   data_pos + 1,
 									   pmatch[0].rm_so - data_pos,
 									   false);
-			appendStringInfoText(str, left_text);
+			appendStringInfoText(&buf, left_text);
 			pfree(left_text);
 		}
 
@@ -2290,9 +2291,9 @@ replace_text_regexp(text *src_text, void *regexp,
 		 * replace_text has escape characters.
 		 */
 		if (have_escape)
-			appendStringInfoRegexpSubstr(str, replace_text, pmatch, src_text);
+			appendStringInfoRegexpSubstr(&buf, replace_text, pmatch, src_text);
 		else
-			appendStringInfoText(str, replace_text);
+			appendStringInfoText(&buf, replace_text);
 
 		search_start = data_pos = pmatch[0].rm_eo;
 
@@ -2318,13 +2319,12 @@ replace_text_regexp(text *src_text, void *regexp,
 
 		right_text = text_substring(PointerGetDatum(src_text),
 									data_pos + 1, -1, true);
-		appendStringInfoText(str, right_text);
+		appendStringInfoText(&buf, right_text);
 		pfree(right_text);
 	}
 
-	ret_text = PG_STR_GET_TEXT(str->data);
-	pfree(str->data);
-	pfree(str);
+	ret_text = PG_STR_GET_TEXT(buf.data);
+	pfree(buf.data);
 	pfree(data);
 
 	return ret_text;
@@ -2512,7 +2512,7 @@ array_to_text(PG_FUNCTION_ARGS)
 	int			typlen;
 	bool		typbyval;
 	char		typalign;
-	StringInfo	result_str = makeStringInfo();
+	StringInfoData	buf;
 	bool		printed = false;
 	char	   *p;
 	bits8	   *bitmap;
@@ -2529,6 +2529,7 @@ array_to_text(PG_FUNCTION_ARGS)
 		PG_RETURN_TEXT_P(PG_STR_GET_TEXT(""));
 
 	element_type = ARR_ELEMTYPE(v);
+	initStringInfo(&buf);
 
 	/*
 	 * We arrange to look up info about element type, including its output
@@ -2583,9 +2584,9 @@ array_to_text(PG_FUNCTION_ARGS)
 												  itemvalue));
 
 			if (printed)
-				appendStringInfo(result_str, "%s%s", fldsep, value);
+				appendStringInfo(&buf, "%s%s", fldsep, value);
 			else
-				appendStringInfoString(result_str, value);
+				appendStringInfoString(&buf, value);
 			printed = true;
 
 			p = att_addlength(p, typlen, PointerGetDatum(p));
@@ -2604,7 +2605,7 @@ array_to_text(PG_FUNCTION_ARGS)
 		}
 	}
 
-	PG_RETURN_TEXT_P(PG_STR_GET_TEXT(result_str->data));
+	PG_RETURN_TEXT_P(PG_STR_GET_TEXT(buf.data));
 }
 
 #define HEXBASE 16
-- 
GitLab