From 381e81e4a525296dc11c5e4cc3ffd6bbca91e8c0 Mon Sep 17 00:00:00 2001
From: Alexander Pyhalov <a.pyhalov@postgrespro.ru>
Date: Wed, 29 Jan 2025 16:23:30 +0300
Subject: [PATCH 1/2] Split out SQL functions checks from
 init_execution_state()

---
 src/backend/executor/functions.c | 62 ++++++++++++++++++--------------
 1 file changed, 36 insertions(+), 26 deletions(-)

diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 757f8068e21..12565d0a7e0 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -454,6 +454,40 @@ sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo,
 	return NULL;
 }
 
+/* Precheck command for validity in a function */
+static void
+check_planned_stmt(PlannedStmt *stmt, SQLFunctionCachePtr fcache)
+{
+
+	/*
+	 * Precheck all commands for validity in a function.  This should
+	 * generally match the restrictions spi.c applies.
+	 */
+	if (stmt->commandType == CMD_UTILITY)
+	{
+		if (IsA(stmt->utilityStmt, CopyStmt) &&
+			((CopyStmt *) stmt->utilityStmt)->filename == NULL)
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("cannot COPY to/from client in an SQL function")));
+
+		if (IsA(stmt->utilityStmt, TransactionStmt))
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			/* translator: %s is a SQL statement name */
+					 errmsg("%s is not allowed in an SQL function",
+							CreateCommandName(stmt->utilityStmt))));
+	}
+
+	if (fcache->readonly_func && !CommandIsReadOnly(stmt))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+		/* translator: %s is a SQL statement name */
+				 errmsg("%s is not allowed in a non-volatile function",
+						CreateCommandName((Node *) stmt))));
+
+}
+
 /*
  * Set up the per-query execution_state records for a SQL function.
  *
@@ -500,32 +534,8 @@ init_execution_state(List *queryTree_list,
 									 CURSOR_OPT_PARALLEL_OK,
 									 NULL);
 
-			/*
-			 * Precheck all commands for validity in a function.  This should
-			 * generally match the restrictions spi.c applies.
-			 */
-			if (stmt->commandType == CMD_UTILITY)
-			{
-				if (IsA(stmt->utilityStmt, CopyStmt) &&
-					((CopyStmt *) stmt->utilityStmt)->filename == NULL)
-					ereport(ERROR,
-							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-							 errmsg("cannot COPY to/from client in an SQL function")));
-
-				if (IsA(stmt->utilityStmt, TransactionStmt))
-					ereport(ERROR,
-							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-					/* translator: %s is a SQL statement name */
-							 errmsg("%s is not allowed in an SQL function",
-									CreateCommandName(stmt->utilityStmt))));
-			}
-
-			if (fcache->readonly_func && !CommandIsReadOnly(stmt))
-				ereport(ERROR,
-						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-				/* translator: %s is a SQL statement name */
-						 errmsg("%s is not allowed in a non-volatile function",
-								CreateCommandName((Node *) stmt))));
+			/* Check that stmt is valid for SQL function */
+			check_planned_stmt(stmt, fcache);
 
 			/* OK, build the execution_state for this query */
 			newes = (execution_state *) palloc(sizeof(execution_state));
-- 
2.43.0

