summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/pg_proc.c5
-rw-r--r--src/backend/executor/functions.c21
-rw-r--r--src/backend/pgxc/plan/planner.c24
-rw-r--r--src/include/pgxc/planner.h1
-rw-r--r--src/test/regress/expected/xc_misc.out40
-rw-r--r--src/test/regress/sql/xc_misc.sql45
6 files changed, 127 insertions, 9 deletions
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 704f9d277d..a3c6bca2d3 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -866,6 +866,11 @@ fmgr_sql_validator(PG_FUNCTION_ARGS)
/* Check if the list of queries contains temporary objects */
if (IS_PGXC_COORDINATOR && !IsConnFromCoord())
{
+ if (pgxc_query_contains_utility(querytree_sublist))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("In XC, SQL functions cannot contain utility statements")));
+
if (pgxc_query_contains_temp_tables(querytree_sublist))
ExecSetTempObjectIncluded();
}
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 8ca9458012..9f4503dcc1 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -309,15 +309,18 @@ init_execution_state(List *queryTree_list,
#ifdef PGXC
if (IS_PGXC_COORDINATOR && !IsConnFromCoord())
{
- /*
- * The parameterised queries in RemoteQuery nodes will be prepared
- * on the datanode, and need parameter types for the same. Set the
- * parameter types and their number in all RemoteQuery nodes in the
- * plan
- */
- SetRemoteStatementName(((PlannedStmt *)stmt)->planTree, NULL,
- fcache->pinfo->nargs,
- fcache->pinfo->argtypes, 0);
+ if (queryTree->commandType != CMD_UTILITY)
+ {
+ /*
+ * The parameterised queries in RemoteQuery nodes will be prepared
+ * on the datanode, and need parameter types for the same. Set the
+ * parameter types and their number in all RemoteQuery nodes in the
+ * plan
+ */
+ SetRemoteStatementName(((PlannedStmt *)stmt)->planTree, NULL,
+ fcache->pinfo->nargs,
+ fcache->pinfo->argtypes, 0);
+ }
}
#endif /* PGXC */
diff --git a/src/backend/pgxc/plan/planner.c b/src/backend/pgxc/plan/planner.c
index c753e05f11..d3f57944c2 100644
--- a/src/backend/pgxc/plan/planner.c
+++ b/src/backend/pgxc/plan/planner.c
@@ -2157,3 +2157,27 @@ pgxc_query_contains_temp_tables(List *queries)
return false;
}
+
+/*
+ * pgxc_query_contains_utility
+ *
+ * Check if there is any utility statement in given list of queries.
+ */
+bool
+pgxc_query_contains_utility(List *queries)
+{
+ ListCell *elt;
+
+ foreach(elt, queries)
+ {
+ Query *query = (Query *) lfirst(elt);
+
+ if (!query)
+ continue;
+
+ if (query->commandType == CMD_UTILITY)
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/include/pgxc/planner.h b/src/include/pgxc/planner.h
index db2ee3046a..c9310b4b0e 100644
--- a/src/include/pgxc/planner.h
+++ b/src/include/pgxc/planner.h
@@ -172,6 +172,7 @@ extern ExecNodes *IsJoinReducible(RemoteQuery *innernode, RemoteQuery *outernode
extern List *AddRemoteQueryNode(List *stmts, const char *queryString,
RemoteQueryExecType remoteExecType, bool is_temp);
extern bool pgxc_query_contains_temp_tables(List *queries);
+extern bool pgxc_query_contains_utility(List *queries);
extern Expr *pgxc_find_distcol_expr(Index varno, PartAttrNumber partAttrNum,
Node *quals);
diff --git a/src/test/regress/expected/xc_misc.out b/src/test/regress/expected/xc_misc.out
index 3e56f3913b..e714e8d299 100644
--- a/src/test/regress/expected/xc_misc.out
+++ b/src/test/regress/expected/xc_misc.out
@@ -101,3 +101,43 @@ ERROR: column name "xc_node_id" conflicts with a system column name
create table t2(a int , b int) distribute by modulo(xc_node_id);
ERROR: Column xc_node_id is not modulo distributable data type
drop table t1;
+-- Test an SQL function with multiple statements in it including a utility statement.
+create table my_tab1 (a int);
+insert into my_tab1 values(1);
+create function f1 () returns setof my_tab1 as $$ create table my_tab2 (a int); select * from my_tab1; $$ language sql;
+ERROR: In XC, SQL functions cannot contain utility statements
+CONTEXT: SQL function "f1"
+SET check_function_bodies = false;
+create function f1 () returns setof my_tab1 as $$ create table my_tab2 (a int); select * from my_tab1; $$ language sql;
+select f1();
+ERROR: Unexpected response from the data nodes for 'T' message, current request type 1
+CONTEXT: SQL function "f1" statement 1
+SET check_function_bodies = true;
+drop function f1();
+-- Test pl-pgsql functions containing utility statements
+CREATE OR REPLACE FUNCTION test_fun_2() RETURNS SETOF my_tab1 AS '
+DECLARE
+ t1 my_tab1;
+ occ RECORD;
+BEGIN
+ CREATE TABLE tab4(a int);
+ CREATE TABLE tab5(a int);
+
+ FOR occ IN SELECT * FROM my_tab1
+ LOOP
+ t1.a := occ.a;
+ RETURN NEXT t1;
+ END LOOP;
+
+ RETURN;
+END;' LANGUAGE 'plpgsql';
+select test_fun_2();
+ test_fun_2
+------------
+ (1)
+(1 row)
+
+drop function test_fun_2();
+drop table tab4;
+drop table tab5;
+drop table my_tab1;
diff --git a/src/test/regress/sql/xc_misc.sql b/src/test/regress/sql/xc_misc.sql
index 84f97d569d..2dfcf599f2 100644
--- a/src/test/regress/sql/xc_misc.sql
+++ b/src/test/regress/sql/xc_misc.sql
@@ -72,3 +72,48 @@ create table t2(a int , b int) distribute by modulo(xc_node_id);
drop table t1;
+-- Test an SQL function with multiple statements in it including a utility statement.
+
+create table my_tab1 (a int);
+
+insert into my_tab1 values(1);
+
+create function f1 () returns setof my_tab1 as $$ create table my_tab2 (a int); select * from my_tab1; $$ language sql;
+
+SET check_function_bodies = false;
+
+create function f1 () returns setof my_tab1 as $$ create table my_tab2 (a int); select * from my_tab1; $$ language sql;
+
+select f1();
+
+SET check_function_bodies = true;
+
+drop function f1();
+
+-- Test pl-pgsql functions containing utility statements
+
+CREATE OR REPLACE FUNCTION test_fun_2() RETURNS SETOF my_tab1 AS '
+DECLARE
+ t1 my_tab1;
+ occ RECORD;
+BEGIN
+ CREATE TABLE tab4(a int);
+ CREATE TABLE tab5(a int);
+
+ FOR occ IN SELECT * FROM my_tab1
+ LOOP
+ t1.a := occ.a;
+ RETURN NEXT t1;
+ END LOOP;
+
+ RETURN;
+END;' LANGUAGE 'plpgsql';
+
+select test_fun_2();
+
+drop function test_fun_2();
+
+drop table tab4;
+drop table tab5;
+drop table my_tab1;
+