diff --git a/src/backend/distributed/commands/role.c b/src/backend/distributed/commands/role.c index cb4b9d9dd..bf0114620 100644 --- a/src/backend/distributed/commands/role.c +++ b/src/backend/distributed/commands/role.c @@ -38,11 +38,13 @@ #include "nodes/makefuncs.h" #include "nodes/parsenodes.h" #include "nodes/pg_list.h" +#include "parser/scansup.h" #include "utils/acl.h" #include "utils/builtins.h" #include "utils/guc_tables.h" #include "utils/guc.h" #include "utils/rel.h" +#include "utils/varlena.h" #include "utils/syscache.h" static const char * ExtractEncryptedPassword(Oid roleOid); @@ -410,7 +412,7 @@ MakeVariableSetStmt(const char *config) VariableSetStmt *variableSetStmt = makeNode(VariableSetStmt); variableSetStmt->kind = VAR_SET_VALUE; variableSetStmt->name = name; - variableSetStmt->args = list_make1(MakeSetStatementArgument(name, value)); + variableSetStmt->args = MakeSetStatementArguments(name, value); return variableSetStmt; } @@ -624,15 +626,15 @@ GetRoleNameFromDbRoleSetting(HeapTuple tuple, TupleDesc DbRoleSettingDescription /* - * MakeSetStatementArgs parses a configuraton value and creates an A_Const - * with an appropriate type. + * MakeSetStatementArgs parses a configuraton value and creates an List of A_Const + * Nodes with appropriate types. * * The allowed A_Const types are Integer, Float, and String. */ -Node * -MakeSetStatementArgument(char *configurationName, char *configurationValue) +List * +MakeSetStatementArguments(char *configurationName, char *configurationValue) { - Node *arg = NULL; + List *args = NIL; char **key = &configurationName; /* Perform a lookup on GUC variables to find the config type and units. @@ -668,13 +670,15 @@ MakeSetStatementArgument(char *configurationName, char *configurationValue) int intValue; parse_int(configurationValue, &intValue, (*matchingConfig)->flags, NULL); - arg = makeIntConst(intValue, -1); + Node *arg = makeIntConst(intValue, -1); + args = lappend(args, arg); break; } case PGC_REAL: { - arg = makeFloatConst(configurationValue, -1); + Node *arg = makeFloatConst(configurationValue, -1); + args = lappend(args, arg); break; } @@ -682,7 +686,25 @@ MakeSetStatementArgument(char *configurationName, char *configurationValue) case PGC_STRING: case PGC_ENUM: { - arg = makeStringConst(configurationValue, -1); + List *configurationList = NIL; + + if ((*matchingConfig)->flags & GUC_LIST_INPUT) + { + char *configurationValueCopy = pstrdup(configurationValue); + SplitIdentifierString(configurationValueCopy, ',', + &configurationList); + } + else + { + configurationList = list_make1(configurationValue); + } + + char *configuration = NULL; + foreach_ptr(configuration, configurationList) + { + Node *arg = makeStringConst(configuration, -1); + args = lappend(args, arg); + } break; } @@ -696,9 +718,10 @@ MakeSetStatementArgument(char *configurationName, char *configurationValue) } else { - arg = makeStringConst(configurationValue, -1); + Node *arg = makeStringConst(configurationValue, -1); + args = lappend(args, arg); } - return (Node *) arg; + return args; } diff --git a/src/backend/distributed/deparser/qualify_role_stmt.c b/src/backend/distributed/deparser/qualify_role_stmt.c index 7b50f4fba..93a958ea9 100644 --- a/src/backend/distributed/deparser/qualify_role_stmt.c +++ b/src/backend/distributed/deparser/qualify_role_stmt.c @@ -56,5 +56,5 @@ QualifyVarSetCurrent(VariableSetStmt *setStmt) char *configValue = GetConfigOptionByName(configurationName, NULL, false); setStmt->kind = VAR_SET_VALUE; - setStmt->args = list_make1(MakeSetStatementArgument(configurationName, configValue)); + setStmt->args = list_make1(MakeSetStatementArguments(configurationName, configValue)); } diff --git a/src/include/distributed/deparser.h b/src/include/distributed/deparser.h index 78fc37bb3..527d806bb 100644 --- a/src/include/distributed/deparser.h +++ b/src/include/distributed/deparser.h @@ -99,7 +99,8 @@ extern void QualifyAlterFunctionDependsStmt(Node *stmt); extern char * DeparseAlterRoleStmt(Node *stmt); extern char * DeparseAlterRoleSetStmt(Node *stmt); -extern Node * MakeSetStatementArgument(char *configurationName, char *configurationValue); +extern List * MakeSetStatementArguments(char *configurationName, + char *configurationValue); extern void QualifyAlterRoleSetStmt(Node *stmt); /* forward declarations for deparse_extension_stmts.c */ diff --git a/src/test/regress/expected/alter_role_propagation.out b/src/test/regress/expected/alter_role_propagation.out index 66fff3fb7..ecaea374e 100644 --- a/src/test/regress/expected/alter_role_propagation.out +++ b/src/test/regress/expected/alter_role_propagation.out @@ -1,4 +1,5 @@ CREATE SCHEMA alter_role; +CREATE SCHEMA ",CitUs,.TeeN!?"; -- test if the passowrd of the extension owner can be upgraded ALTER ROLE CURRENT_USER PASSWORD 'password123' VALID UNTIL 'infinity'; SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$); @@ -111,6 +112,12 @@ SELECT run_command_on_workers('SHOW enable_hashagg'); (localhost,57638,t,off) (1 row) +-- provide a list of values in a supported configuration +ALTER ROLE CURRENT_USER SET search_path TO ",CitUs,.TeeN!?", alter_role, public; +-- test user defined GUCs that appear to be a list, but instead a single string +ALTER ROLE ALL SET public.myguc TO "Hello, World"; +-- test for configuration values that should not be downcased even when unquoted +ALTER ROLE CURRENT_USER SET lc_messages TO 'C'; -- add worker and check all settings are copied SELECT 1 FROM master_add_node('localhost', :worker_1_port); ?column? @@ -139,6 +146,27 @@ SELECT run_command_on_workers('SHOW enable_hashagg'); (localhost,57638,t,off) (2 rows) +SELECT run_command_on_workers('SHOW search_path'); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,""",CitUs,.TeeN!?"", alter_role, public") + (localhost,57638,t,""",CitUs,.TeeN!?"", alter_role, public") +(2 rows) + +SELECT run_command_on_workers('SHOW lc_messages'); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,C) + (localhost,57638,t,C) +(2 rows) + +SELECT run_command_on_workers('SHOW public.myguc'); + run_command_on_workers +--------------------------------------------------------------------- + (localhost,57637,t,"Hello, World") + (localhost,57638,t,"Hello, World") +(2 rows) + -- reset to default values ALTER ROLE CURRENT_USER RESET enable_hashagg; SELECT run_command_on_workers('SHOW enable_hashagg'); @@ -226,4 +254,4 @@ SELECT run_command_on_workers('SHOW enable_hashjoin'); (localhost,57638,t,on) (2 rows) -DROP SCHEMA alter_role CASCADE; +DROP SCHEMA alter_role, ",CitUs,.TeeN!?" CASCADE; diff --git a/src/test/regress/sql/alter_role_propagation.sql b/src/test/regress/sql/alter_role_propagation.sql index c180c91fd..a73c0248a 100644 --- a/src/test/regress/sql/alter_role_propagation.sql +++ b/src/test/regress/sql/alter_role_propagation.sql @@ -1,4 +1,5 @@ CREATE SCHEMA alter_role; +CREATE SCHEMA ",CitUs,.TeeN!?"; -- test if the passowrd of the extension owner can be upgraded ALTER ROLE CURRENT_USER PASSWORD 'password123' VALID UNTIL 'infinity'; @@ -35,11 +36,22 @@ SELECT run_command_on_workers('SHOW enable_indexonlyscan'); ALTER ROLE CURRENT_USER SET enable_hashagg TO FALSE; SELECT run_command_on_workers('SHOW enable_hashagg'); +-- provide a list of values in a supported configuration +ALTER ROLE CURRENT_USER SET search_path TO ",CitUs,.TeeN!?", alter_role, public; +-- test user defined GUCs that appear to be a list, but instead a single string +ALTER ROLE ALL SET public.myguc TO "Hello, World"; + +-- test for configuration values that should not be downcased even when unquoted +ALTER ROLE CURRENT_USER SET lc_messages TO 'C'; + -- add worker and check all settings are copied SELECT 1 FROM master_add_node('localhost', :worker_1_port); SELECT run_command_on_workers('SHOW enable_hashjoin'); SELECT run_command_on_workers('SHOW enable_indexonlyscan'); SELECT run_command_on_workers('SHOW enable_hashagg'); +SELECT run_command_on_workers('SHOW search_path'); +SELECT run_command_on_workers('SHOW lc_messages'); +SELECT run_command_on_workers('SHOW public.myguc'); -- reset to default values ALTER ROLE CURRENT_USER RESET enable_hashagg; @@ -70,4 +82,4 @@ SELECT run_command_on_workers('SHOW enable_hashjoin'); ALTER ROLE ALL RESET enable_hashjoin; SELECT run_command_on_workers('SHOW enable_hashjoin'); -DROP SCHEMA alter_role CASCADE; +DROP SCHEMA alter_role, ",CitUs,.TeeN!?" CASCADE;