From 6cf9f319082735ebb9ae013d1165586dc073c217 Mon Sep 17 00:00:00 2001
From: Joe Conway <mail@joeconway.com>
Date: Wed, 22 Jul 2009 02:31:38 +0000
Subject: [PATCH] Replace PLpgSQL_dstring by StringInfo.

Replace redundant PLpgSQL_dstring functionality with StringInfo.
Patch by Pavel Stehule. Review by Joe Conway.
---
 src/pl/plpgsql/src/gram.y     | 79 ++++++++++++++++----------------
 src/pl/plpgsql/src/pl_exec.c  | 17 +++----
 src/pl/plpgsql/src/pl_funcs.c | 86 +----------------------------------
 src/pl/plpgsql/src/plpgsql.h  | 20 +-------
 4 files changed, 49 insertions(+), 153 deletions(-)

diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index 03f55acadd5..cb9dcbc5a50 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.126 2009/07/11 21:15:32 petere Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.127 2009/07/22 02:31:38 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "plpgsql.h"
 
 #include "catalog/pg_type.h"
+#include "lib/stringinfo.h"
 #include "parser/parser.h"
 
 
@@ -1978,7 +1979,7 @@ read_sql_construct(int until,
 {
 	int					tok;
 	int					lno;
-	PLpgSQL_dstring		ds;
+	StringInfoData		ds;
 	int					parenlevel = 0;
 	int					nparams = 0;
 	int					params[MAX_EXPR_PARAMS];
@@ -1986,8 +1987,8 @@ read_sql_construct(int until,
 	PLpgSQL_expr		*expr;
 
 	lno = plpgsql_scanner_lineno();
-	plpgsql_dstring_init(&ds);
-	plpgsql_dstring_append(&ds, sqlstart);
+	initStringInfo(&ds);
+	appendStringInfoString(&ds, sqlstart);
 
 	for (;;)
 	{
@@ -2029,7 +2030,7 @@ read_sql_construct(int until,
 		}
 
 		if (plpgsql_SpaceScanned)
-			plpgsql_dstring_append(&ds, " ");
+			appendStringInfoChar(&ds, ' ');
 
 		switch (tok)
 		{
@@ -2037,25 +2038,25 @@ read_sql_construct(int until,
 				snprintf(buf, sizeof(buf), " $%d ",
 						 assign_expr_param(yylval.scalar->dno,
 										   params, &nparams));
-				plpgsql_dstring_append(&ds, buf);
+				appendStringInfoString(&ds, buf);
 				break;
 
 			case T_ROW:
 				snprintf(buf, sizeof(buf), " $%d ",
 						 assign_expr_param(yylval.row->dno,
 										   params, &nparams));
-				plpgsql_dstring_append(&ds, buf);
+				appendStringInfoString(&ds, buf);
 				break;
 
 			case T_RECORD:
 				snprintf(buf, sizeof(buf), " $%d ",
 						 assign_expr_param(yylval.rec->dno,
 										   params, &nparams));
-				plpgsql_dstring_append(&ds, buf);
+				appendStringInfoString(&ds, buf);
 				break;
 
 			default:
-				plpgsql_dstring_append(&ds, yytext);
+				appendStringInfoString(&ds, yytext);
 				break;
 		}
 	}
@@ -2065,12 +2066,12 @@ read_sql_construct(int until,
 
 	expr = palloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
 	expr->dtype			= PLPGSQL_DTYPE_EXPR;
-	expr->query			= pstrdup(plpgsql_dstring_get(&ds));
+	expr->query			= pstrdup(ds.data);
 	expr->plan			= NULL;
 	expr->nparams		= nparams;
 	while(nparams-- > 0)
 		expr->params[nparams] = params[nparams];
-	plpgsql_dstring_free(&ds);
+	pfree(ds.data);
 
 	if (valid_sql)
 		check_sql_expr(expr->query);
@@ -2082,7 +2083,7 @@ static PLpgSQL_type *
 read_datatype(int tok)
 {
 	int					lno;
-	PLpgSQL_dstring		ds;
+	StringInfoData		ds;
 	char			   *type_name;
 	PLpgSQL_type		*result;
 	bool				needspace = false;
@@ -2100,7 +2101,7 @@ read_datatype(int tok)
 		return yylval.dtype;
 	}
 
-	plpgsql_dstring_init(&ds);
+	initStringInfo(&ds);
 
 	while (tok != ';')
 	{
@@ -2122,16 +2123,16 @@ read_datatype(int tok)
 		else if (tok == ')')
 			parenlevel--;
 		if (needspace)
-			plpgsql_dstring_append(&ds, " ");
+			appendStringInfoChar(&ds, ' ');
 		needspace = true;
-		plpgsql_dstring_append(&ds, yytext);
+		appendStringInfoString(&ds, yytext);
 
 		tok = yylex();
 	}
 
 	plpgsql_push_back_token(tok);
 
-	type_name = plpgsql_dstring_get(&ds);
+	type_name = ds.data;
 
 	if (type_name[0] == '\0')
 		yyerror("missing data type declaration");
@@ -2140,7 +2141,7 @@ read_datatype(int tok)
 
 	result = plpgsql_parse_datatype(type_name);
 
-	plpgsql_dstring_free(&ds);
+	pfree(ds.data);
 
 	return result;
 }
@@ -2148,7 +2149,7 @@ read_datatype(int tok)
 static PLpgSQL_stmt *
 make_execsql_stmt(const char *sqlstart, int lineno)
 {
-	PLpgSQL_dstring		ds;
+	StringInfoData		ds;
 	int					nparams = 0;
 	int					params[MAX_EXPR_PARAMS];
 	char				buf[32];
@@ -2161,8 +2162,8 @@ make_execsql_stmt(const char *sqlstart, int lineno)
 	bool				have_into = false;
 	bool				have_strict = false;
 
-	plpgsql_dstring_init(&ds);
-	plpgsql_dstring_append(&ds, sqlstart);
+	initStringInfo(&ds);
+	appendStringInfoString(&ds, sqlstart);
 
 	/*
 	 * We have to special-case the sequence INSERT INTO, because we don't want
@@ -2196,7 +2197,7 @@ make_execsql_stmt(const char *sqlstart, int lineno)
 		}
 
 		if (plpgsql_SpaceScanned)
-			plpgsql_dstring_append(&ds, " ");
+			appendStringInfoChar(&ds, ' ');
 
 		switch (tok)
 		{
@@ -2204,37 +2205,37 @@ make_execsql_stmt(const char *sqlstart, int lineno)
 				snprintf(buf, sizeof(buf), " $%d ",
 						 assign_expr_param(yylval.scalar->dno,
 										   params, &nparams));
-				plpgsql_dstring_append(&ds, buf);
+				appendStringInfoString(&ds, buf);
 				break;
 
 			case T_ROW:
 				snprintf(buf, sizeof(buf), " $%d ",
 						 assign_expr_param(yylval.row->dno,
 										   params, &nparams));
-				plpgsql_dstring_append(&ds, buf);
+				appendStringInfoString(&ds, buf);
 				break;
 
 			case T_RECORD:
 				snprintf(buf, sizeof(buf), " $%d ",
 						 assign_expr_param(yylval.rec->dno,
 										   params, &nparams));
-				plpgsql_dstring_append(&ds, buf);
+				appendStringInfoString(&ds, buf);
 				break;
 
 			default:
-				plpgsql_dstring_append(&ds, yytext);
+				appendStringInfoString(&ds, yytext);
 				break;
 		}
 	}
 
 	expr = palloc(sizeof(PLpgSQL_expr) + sizeof(int) * nparams - sizeof(int));
 	expr->dtype			= PLPGSQL_DTYPE_EXPR;
-	expr->query			= pstrdup(plpgsql_dstring_get(&ds));
+	expr->query			= pstrdup(ds.data);
 	expr->plan			= NULL;
 	expr->nparams		= nparams;
 	while(nparams-- > 0)
 		expr->params[nparams] = params[nparams];
-	plpgsql_dstring_free(&ds);
+	pfree(ds.data);
 
 	check_sql_expr(expr->query);
 
@@ -3023,8 +3024,7 @@ make_case(int lineno, PLpgSQL_expr *t_expr,
 			PLpgSQL_expr *expr = cwt->expr;
 			int		nparams = expr->nparams;
 			PLpgSQL_expr *new_expr;
-			PLpgSQL_dstring ds;
-			char	buff[32];
+			StringInfoData	ds;
 
 			/* Must add the CASE variable as an extra param to expression */
 			if (nparams >= MAX_EXPR_PARAMS)
@@ -3041,22 +3041,19 @@ make_case(int lineno, PLpgSQL_expr *t_expr,
 			new_expr->nparams = nparams + 1;
 			new_expr->params[nparams] = t_varno;
 
+			/* copy expression query without SELECT keyword (expr->query + 7) */
+			Assert(strncmp(expr->query, "SELECT ", 7) == 0);
+			
 			/* And do the string hacking */
-			plpgsql_dstring_init(&ds);
-
-			plpgsql_dstring_append(&ds, "SELECT $");
-			snprintf(buff, sizeof(buff), "%d", nparams + 1);
-			plpgsql_dstring_append(&ds, buff);
-			plpgsql_dstring_append(&ds, " IN (");
+			initStringInfo(&ds);
 
-			/* copy expression query without SELECT keyword */
-			Assert(strncmp(expr->query, "SELECT ", 7) == 0);
-			plpgsql_dstring_append(&ds, expr->query + 7);
-			plpgsql_dstring_append_char(&ds, ')');
+			appendStringInfo(&ds, "SELECT $%d IN(%s)", 
+								nparams + 1,
+								expr->query + 7);
 
-			new_expr->query = pstrdup(plpgsql_dstring_get(&ds));
+			new_expr->query = pstrdup(ds.data);
 
-			plpgsql_dstring_free(&ds);
+			pfree(ds.data);
 			pfree(expr->query);
 			pfree(expr);
 
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index f9344a395d9..683ad82730b 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.245 2009/07/18 19:15:42 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.246 2009/07/22 02:31:38 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,6 +22,7 @@
 #include "catalog/pg_type.h"
 #include "executor/spi_priv.h"
 #include "funcapi.h"
+#include "lib/stringinfo.h"
 #include "nodes/nodeFuncs.h"
 #include "parser/scansup.h"
 #include "storage/proc.h"
@@ -2394,11 +2395,11 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 
 	if (stmt->message)
 	{
-		PLpgSQL_dstring ds;
+		StringInfoData	ds;
 		ListCell   *current_param;
 		char	   *cp;
 
-		plpgsql_dstring_init(&ds);
+		initStringInfo(&ds);
 		current_param = list_head(stmt->params);
 
 		for (cp = stmt->message; *cp; cp++)
@@ -2416,7 +2417,7 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 
 				if (cp[1] == '%')
 				{
-					plpgsql_dstring_append_char(&ds, cp[1]);
+					appendStringInfoChar(&ds, '%');
 					cp++;
 					continue;
 				}
@@ -2435,12 +2436,12 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 					extval = "<NULL>";
 				else
 					extval = convert_value_to_string(paramvalue, paramtypeid);
-				plpgsql_dstring_append(&ds, extval);
+				appendStringInfoString(&ds, extval);
 				current_param = lnext(current_param);
 				exec_eval_cleanup(estate);
 			}
 			else
-				plpgsql_dstring_append_char(&ds, cp[0]);
+				appendStringInfoChar(&ds, cp[0]);
 		}
 
 		/*
@@ -2452,8 +2453,8 @@ exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
 					(errcode(ERRCODE_SYNTAX_ERROR),
 					 errmsg("too many parameters specified for RAISE")));
 
-		err_message = plpgsql_dstring_get(&ds);
-		/* No dstring_free here, the pfree(err_message) does it */
+		err_message = ds.data;
+		/* No pfree(ds.data), the pfree(err_message) does it */
 	}
 
 	foreach(lc, stmt->options)
diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c
index 5a3b621a4ef..cb2cb963edb 100644
--- a/src/pl/plpgsql/src/pl_funcs.c
+++ b/src/pl/plpgsql/src/pl_funcs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.79 2009/06/11 14:49:14 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.80 2009/07/22 02:31:38 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,90 +28,6 @@ static PLpgSQL_ns *ns_current = NULL;
 static bool ns_localmode = false;
 
 
-/* ----------
- * plpgsql_dstring_init			Dynamic string initialization
- * ----------
- */
-void
-plpgsql_dstring_init(PLpgSQL_dstring *ds)
-{
-	ds->value = palloc(ds->alloc = 512);
-	ds->used = 1;
-	ds->value[0] = '\0';
-}
-
-
-/* ----------
- * plpgsql_dstring_free			Dynamic string destruction
- * ----------
- */
-void
-plpgsql_dstring_free(PLpgSQL_dstring *ds)
-{
-	pfree(ds->value);
-}
-
-static void
-plpgsql_dstring_expand(PLpgSQL_dstring *ds, int needed)
-{
-	/* Don't allow truncating the string */
-	Assert(needed > ds->alloc);
-	Assert(ds->used <= ds->alloc);
-
-	/* Might have to double more than once, if needed is large */
-	do
-	{
-		ds->alloc *= 2;
-	} while (needed > ds->alloc);
-	ds->value = repalloc(ds->value, ds->alloc);
-}
-
-/* ----------
- * plpgsql_dstring_append		Dynamic string extending
- * ----------
- */
-void
-plpgsql_dstring_append(PLpgSQL_dstring *ds, const char *str)
-{
-	int			len = strlen(str);
-	int			needed = ds->used + len;
-
-	if (needed > ds->alloc)
-		plpgsql_dstring_expand(ds, needed);
-
-	memcpy(&(ds->value[ds->used - 1]), str, len);
-	ds->used += len;
-	ds->value[ds->used - 1] = '\0';
-}
-
-/* ----------
- * plpgsql_dstring_append_char	Append a single character
- *								to a dynamic string
- * ----------
- */
-void
-plpgsql_dstring_append_char(PLpgSQL_dstring *ds, char c)
-{
-	if (ds->used == ds->alloc)
-		plpgsql_dstring_expand(ds, ds->used + 1);
-
-	ds->value[ds->used - 1] = c;
-	ds->value[ds->used] = '\0';
-	ds->used++;
-}
-
-
-/* ----------
- * plpgsql_dstring_get			Dynamic string get value
- * ----------
- */
-char *
-plpgsql_dstring_get(PLpgSQL_dstring *ds)
-{
-	return ds->value;
-}
-
-
 /* ----------
  * plpgsql_ns_init			Initialize the namestack
  * ----------
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 8f21f3beb94..497b0c608a5 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.113 2009/06/11 14:49:14 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.114 2009/07/22 02:31:38 joe Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -147,14 +147,6 @@ enum
  **********************************************************************/
 
 
-typedef struct
-{								/* Dynamic string control structure */
-	int			alloc;
-	int			used;			/* Including NUL terminator */
-	char	   *value;
-} PLpgSQL_dstring;
-
-
 typedef struct
 {								/* Postgres data type */
 	char	   *typname;		/* (simple) name of the type */
@@ -851,16 +843,6 @@ extern void plpgsql_xact_cb(XactEvent event, void *arg);
 extern void plpgsql_subxact_cb(SubXactEvent event, SubTransactionId mySubid,
 				   SubTransactionId parentSubid, void *arg);
 
-/* ----------
- * Functions for the dynamic string handling in pl_funcs.c
- * ----------
- */
-extern void plpgsql_dstring_init(PLpgSQL_dstring *ds);
-extern void plpgsql_dstring_free(PLpgSQL_dstring *ds);
-extern void plpgsql_dstring_append(PLpgSQL_dstring *ds, const char *str);
-extern void plpgsql_dstring_append_char(PLpgSQL_dstring *ds, char c);
-extern char *plpgsql_dstring_get(PLpgSQL_dstring *ds);
-
 /* ----------
  * Functions for namestack handling in pl_funcs.c
  * ----------
-- 
GitLab