summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/misc/guc.c36
-rw-r--r--src/include/utils/guc.h1
-rw-r--r--src/test/regress/expected/select_parallel.out33
-rw-r--r--src/test/regress/sql/select_parallel.sql23
4 files changed, 78 insertions, 15 deletions
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0ac30a859e0..18669ffb4ad 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1130,7 +1130,7 @@ static struct config_bool ConfigureNamesBool[] =
{"is_superuser", PGC_INTERNAL, UNGROUPED,
gettext_noop("Shows whether the current user is a superuser."),
NULL,
- GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
+ GUC_REPORT | GUC_NO_SHOW_ALL | GUC_NO_RESET_ALL | GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE | GUC_ALLOW_IN_PARALLEL
},
&session_auth_is_superuser,
false,
@@ -6939,10 +6939,12 @@ parse_and_validate_value(struct config_generic *record,
*
* Return value:
* +1: the value is valid and was successfully applied.
- * 0: the name or value is invalid (but see below).
- * -1: the value was not applied because of context, priority, or changeVal.
+ * 0: the name or value is invalid, or it's invalid to try to set
+ * this GUC now; but elevel was less than ERROR (see below).
+ * -1: no error detected, but the value was not applied, either
+ * because changeVal is false or there is some overriding setting.
*
- * If there is an error (non-existing option, invalid value) then an
+ * If there is an error (non-existing option, invalid value, etc) then an
* ereport(ERROR) is thrown *unless* this is called for a source for which
* we don't want an ERROR (currently, those are defaults, the config file,
* and per-database or per-user settings, as well as callers who specify
@@ -6982,6 +6984,15 @@ set_config_option(const char *name, const char *value,
elevel = ERROR;
}
+ record = find_option(name, true, elevel);
+ if (record == NULL)
+ {
+ ereport(elevel,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("unrecognized configuration parameter \"%s\"", name)));
+ return 0;
+ }
+
/*
* GUC_ACTION_SAVE changes are acceptable during a parallel operation,
* because the current worker will also pop the change. We're probably
@@ -6989,22 +7000,17 @@ set_config_option(const char *name, const char *value,
* body should observe the change, and peer workers do not share in the
* execution of a function call started by this worker.
*
+ * Also allow normal setting if the GUC is marked GUC_ALLOW_IN_PARALLEL.
+ *
* Other changes might need to affect other workers, so forbid them.
*/
- if (IsInParallelMode() && changeVal && action != GUC_ACTION_SAVE)
+ if (IsInParallelMode() && changeVal && action != GUC_ACTION_SAVE &&
+ (record->flags & GUC_ALLOW_IN_PARALLEL) == 0)
{
ereport(elevel,
(errcode(ERRCODE_INVALID_TRANSACTION_STATE),
- errmsg("cannot set parameters during a parallel operation")));
- return -1;
- }
-
- record = find_option(name, true, elevel);
- if (record == NULL)
- {
- ereport(elevel,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("unrecognized configuration parameter \"%s\"", name)));
+ errmsg("parameter \"%s\" cannot be set during a parallel operation",
+ name)));
return 0;
}
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 28192821816..3142595733b 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -228,6 +228,7 @@ typedef enum
#define GUC_UNIT_TIME 0xF0000 /* mask for time-related units */
#define GUC_EXPLAIN 0x100000 /* include in explain */
+#define GUC_ALLOW_IN_PARALLEL 0x200000 /* allow setting in parallel mode */
#define GUC_UNIT (GUC_UNIT_MEMORY | GUC_UNIT_TIME)
diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out
index cdbaa4a7b61..7906a3a5c0c 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -1221,3 +1221,36 @@ SELECT 1 FROM tenk1_vw_sec
(9 rows)
rollback;
+-- test that function option SET ROLE works in parallel workers.
+create role regress_parallel_worker;
+create function set_and_report_role() returns text as
+ $$ select current_setting('role') $$ language sql parallel safe
+ set role = regress_parallel_worker;
+create function set_role_and_error(int) returns int as
+ $$ select 1 / $1 $$ language sql parallel safe
+ set role = regress_parallel_worker;
+set force_parallel_mode = 0;
+select set_and_report_role();
+ set_and_report_role
+-------------------------
+ regress_parallel_worker
+(1 row)
+
+select set_role_and_error(0);
+ERROR: division by zero
+CONTEXT: SQL function "set_role_and_error" statement 1
+set force_parallel_mode = 1;
+select set_and_report_role();
+ set_and_report_role
+-------------------------
+ regress_parallel_worker
+(1 row)
+
+select set_role_and_error(0);
+ERROR: division by zero
+CONTEXT: SQL function "set_role_and_error" statement 1
+parallel worker
+reset force_parallel_mode;
+drop function set_and_report_role();
+drop function set_role_and_error(int);
+drop role regress_parallel_worker;
diff --git a/src/test/regress/sql/select_parallel.sql b/src/test/regress/sql/select_parallel.sql
index 43adb05b7a3..39870f0141d 100644
--- a/src/test/regress/sql/select_parallel.sql
+++ b/src/test/regress/sql/select_parallel.sql
@@ -464,3 +464,26 @@ SELECT 1 FROM tenk1_vw_sec
WHERE (SELECT sum(f1) FROM int4_tbl WHERE f1 < unique1) < 100;
rollback;
+
+-- test that function option SET ROLE works in parallel workers.
+create role regress_parallel_worker;
+
+create function set_and_report_role() returns text as
+ $$ select current_setting('role') $$ language sql parallel safe
+ set role = regress_parallel_worker;
+
+create function set_role_and_error(int) returns int as
+ $$ select 1 / $1 $$ language sql parallel safe
+ set role = regress_parallel_worker;
+
+set force_parallel_mode = 0;
+select set_and_report_role();
+select set_role_and_error(0);
+set force_parallel_mode = 1;
+select set_and_report_role();
+select set_role_and_error(0);
+reset force_parallel_mode;
+
+drop function set_and_report_role();
+drop function set_role_and_error(int);
+drop role regress_parallel_worker;