From 895985d7d7178c25c0b9e24550c6a7e7fc7cd129 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Wed, 20 Oct 2010 16:02:07 -0300
Subject: [PATCH 1/2] Separate SQL function processing from postgres.c

Instead, simply inline the code from pg_parse_and_rewrite into the two
callers.  There's not enough gain for the modularity break.  Since this
makes pg_parse_and_rewrite() dead code, remove it.

Per comment from Tom.

Author: Marko Tiikkaja
---
 src/backend/catalog/pg_proc.c    |   24 +++++++++++++++++++--
 src/backend/executor/functions.c |   18 ++++++++++++++-
 src/backend/tcop/postgres.c      |   42 --------------------------------------
 src/include/tcop/tcopprot.h      |    2 -
 4 files changed, 37 insertions(+), 49 deletions(-)

diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 34cd862..a63fb9f 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -755,7 +755,9 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
 	Oid			funcoid = PG_GETARG_OID(0);
 	HeapTuple	tuple;
 	Form_pg_proc proc;
+	List	   *raw_parsetree_list;
 	List	   *querytree_list;
+	ListCell   *list_item;
 	bool		isnull;
 	Datum		tmp;
 	char	   *prosrc;
@@ -828,9 +830,25 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
 		 */
 		if (!haspolyarg)
 		{
-			querytree_list = pg_parse_and_rewrite(prosrc,
-												  proc->proargtypes.values,
-												  proc->pronargs);
+			/*
+			 * Parse and rewrite the queries in the function text.
+			 *
+			 * Even though check_sql_fn_retval is only interested in the last
+			 * query, we analyze all of them here to check for any errors.
+			 */
+			raw_parsetree_list = pg_parse_query(prosrc);
+			
+			querytree_list = NIL;
+			foreach(list_item, raw_parsetree_list)
+			{
+				Node *parsetree = (Node *) lfirst(list_item);
+
+				querytree_list = pg_analyze_and_rewrite(parsetree, prosrc,
+														proc->proargtypes.values, proc->pronargs);
+			}
+
+			Assert(querytree_list != NIL);
+
 			(void) check_sql_fn_retval(funcoid, proc->prorettype,
 									   querytree_list,
 									   NULL, NULL);
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 498bcba..46433d0 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -224,7 +224,9 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
 	SQLFunctionCachePtr fcache;
 	Oid		   *argOidVect;
 	int			nargs;
+	List	   *raw_parsetree_list;
 	List	   *queryTree_list;
+	ListCell   *list_item;
 	Datum		tmp;
 	bool		isNull;
 
@@ -319,7 +321,19 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
 	/*
 	 * Parse and rewrite the queries in the function text.
 	 */
-	queryTree_list = pg_parse_and_rewrite(fcache->src, argOidVect, nargs);
+	raw_parsetree_list = pg_parse_query(fcache->src);
+
+	queryTree_list = NIL;
+	foreach(list_item, raw_parsetree_list)
+	{
+		Node *parsetree = (Node *) lfirst(list_item);
+
+		queryTree_list = lappend(queryTree_list,
+								 pg_analyze_and_rewrite(parsetree,
+									 					fcache->src,
+														argOidVect,
+														nargs));
+	}
 
 	/*
 	 * Check that the function returns the type it claims to.  Although in
@@ -342,7 +356,7 @@ init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK)
 	 */
 	fcache->returnsTuple = check_sql_fn_retval(foid,
 											   rettype,
-											   queryTree_list,
+											   llast(queryTree_list),
 											   NULL,
 											   &fcache->junkFilter);
 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index cba90a9..c6ce8de 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -505,48 +505,6 @@ client_read_ended(void)
 	}
 }
 
-
-/*
- * Parse a query string and pass it through the rewriter.
- *
- * A list of Query nodes is returned, since the string might contain
- * multiple queries and/or the rewriter might expand one query to several.
- *
- * NOTE: this routine is no longer used for processing interactive queries,
- * but it is still needed for parsing of SQL function bodies.
- */
-List *
-pg_parse_and_rewrite(const char *query_string,	/* string to execute */
-					 Oid *paramTypes,	/* parameter types */
-					 int numParams)		/* number of parameters */
-{
-	List	   *raw_parsetree_list;
-	List	   *querytree_list;
-	ListCell   *list_item;
-
-	/*
-	 * (1) parse the request string into a list of raw parse trees.
-	 */
-	raw_parsetree_list = pg_parse_query(query_string);
-
-	/*
-	 * (2) Do parse analysis and rule rewrite.
-	 */
-	querytree_list = NIL;
-	foreach(list_item, raw_parsetree_list)
-	{
-		Node	   *parsetree = (Node *) lfirst(list_item);
-
-		querytree_list = list_concat(querytree_list,
-									 pg_analyze_and_rewrite(parsetree,
-															query_string,
-															paramTypes,
-															numParams));
-	}
-
-	return querytree_list;
-}
-
 /*
  * Do raw parsing (only).
  *
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index f4026ec..0a9714d 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -45,8 +45,6 @@ typedef enum
 
 extern int	log_statement;
 
-extern List *pg_parse_and_rewrite(const char *query_string,
-					 Oid *paramTypes, int numParams);
 extern List *pg_parse_query(const char *query_string);
 extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
 					   Oid *paramTypes, int numParams);
-- 
1.7.1

