diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index d8b9a03ee0e..60f882231bc 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1365,13 +1365,15 @@ testdb=> - \dg[+] [ pattern ] + \dg[S+] [ pattern ] Lists database roles. (Since the concepts of users and groups have been unified into roles, this command is now equivalent to \du.) + By default, only user-created roles are shown; supply the + S modifier to include system roles. If pattern is specified, only those roles whose names match the pattern are listed. If the form \dg+ is used, additional information @@ -1525,13 +1527,15 @@ testdb=> - \du[+] [ pattern ] + \du[S+] [ pattern ] Lists database roles. (Since the concepts of users and groups have been unified into roles, this command is now equivalent to \dg.) + By default, only user-created roles are shown; supply the + S modifier to include system roles. If pattern is specified, only those roles whose names match the pattern are listed. If the form \du+ is used, additional information diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 975fe13fcf9..4b49bb67ba0 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -423,6 +423,9 @@ ExecuteGrantStmt(GrantStmt *stmt) grantee_uid = ACL_ID_PUBLIC; break; default: + if (!IsBootstrapProcessingMode()) + check_rolespec_name((Node *) grantee, + "Cannot GRANT or REVOKE privileges to or from a reserved role."); grantee_uid = get_rolespec_oid((Node *) grantee, false); break; } @@ -918,6 +921,8 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt) grantee_uid = ACL_ID_PUBLIC; break; default: + check_rolespec_name((Node *) grantee, + "Cannot GRANT or REVOKE default privileges to or from a reserved role."); grantee_uid = get_rolespec_oid((Node *) grantee, false); break; } @@ -1008,6 +1013,8 @@ ExecAlterDefaultPrivilegesStmt(AlterDefaultPrivilegesStmt *stmt) { RoleSpec *rolespec = lfirst(rolecell); + check_rolespec_name((Node *) rolespec, + "Cannot alter default privileges for reserved role."); iacls.roleid = get_rolespec_oid((Node *) rolespec, false); /* diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index bead2c1e222..d1cf45bef47 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -184,8 +184,9 @@ IsToastNamespace(Oid namespaceId) * True iff name starts with the pg_ prefix. * * For some classes of objects, the prefix pg_ is reserved for - * system objects only. As of 8.0, this is only true for - * schema and tablespace names. + * system objects only. As of 8.0, this was only true for + * schema and tablespace names. With 9.6, this is also true + * for roles. */ bool IsReservedName(const char *name) diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c index 7e39422ecd6..27b75795928 100644 --- a/src/backend/commands/alter.c +++ b/src/backend/commands/alter.c @@ -747,6 +747,9 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt) { Oid newowner = get_rolespec_oid(stmt->newowner, false); + check_rolespec_name(stmt->newowner, + "Cannot make reserved roles owners of objects."); + switch (stmt->objectType) { case OBJECT_DATABASE: diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 804bab2e1f5..88cefb7f958 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -1148,6 +1148,10 @@ CreateUserMapping(CreateUserMappingStmt *stmt) else useId = get_rolespec_oid(stmt->user, false); + /* Additional check to protect reserved role names */ + check_rolespec_name(stmt->user, + "Cannot specify reserved role as mapping user."); + /* Check that the server exists. */ srv = GetForeignServerByName(stmt->servername, false); @@ -1248,6 +1252,10 @@ AlterUserMapping(AlterUserMappingStmt *stmt) else useId = get_rolespec_oid(stmt->user, false); + /* Additional check to protect reserved role names */ + check_rolespec_name(stmt->user, + "Cannot alter reserved role mapping user."); + srv = GetForeignServerByName(stmt->servername, false); umId = GetSysCacheOid2(USERMAPPINGUSERSERVER, @@ -1337,6 +1345,11 @@ RemoveUserMapping(DropUserMappingStmt *stmt) else { useId = get_rolespec_oid(stmt->user, stmt->missing_ok); + + /* Additional check to protect reserved role names */ + check_rolespec_name(stmt->user, + "Cannot remove reserved role mapping user."); + if (!OidIsValid(useId)) { /* diff --git a/src/backend/commands/policy.c b/src/backend/commands/policy.c index 93d15e477af..146b36c2fa5 100644 --- a/src/backend/commands/policy.c +++ b/src/backend/commands/policy.c @@ -176,8 +176,13 @@ policy_role_list_to_array(List *roles, int *num_roles) return role_oids; } else + { + /* Additional check to protect reserved role names */ + check_rolespec_name((Node *) spec, + "Cannot specify reserved role as policy target"); role_oids[i++] = ObjectIdGetDatum(get_rolespec_oid((Node *) spec, false)); + } } return role_oids; diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index a60ceb8eba7..dea3299ced5 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -65,6 +65,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString) else owner_uid = saved_uid; + /* Additional check to protect reserved role names */ + check_rolespec_name(stmt->authrole, + "Cannot specify reserved role as owner."); + /* fill schema name with the user name if not specified */ if (!schemaName) { diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 96dc923bcdf..eaf76d2b902 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -3566,6 +3566,8 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, (List *) cmd->def, lockmode); break; case AT_ChangeOwner: /* ALTER OWNER */ + check_rolespec_name(cmd->newowner, + "Cannot specify reserved role as owner."); ATExecChangeOwner(RelationGetRelid(rel), get_rolespec_oid(cmd->newowner, false), false, lockmode); diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 7902d433d55..fe7f25337dc 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -256,6 +256,10 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) else ownerId = GetUserId(); + /* Additional check to protect reserved role names */ + check_rolespec_name(stmt->owner, + "Cannot specify reserved role as owner."); + /* Unix-ify the offered path, and strip any trailing slashes */ location = pstrdup(stmt->location); canonicalize_path(location); diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index 4baeaa2676e..cc3d5645343 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -17,6 +17,7 @@ #include "access/htup_details.h" #include "access/xact.h" #include "catalog/binary_upgrade.h" +#include "catalog/catalog.h" #include "catalog/dependency.h" #include "catalog/indexing.h" #include "catalog/objectaccess.h" @@ -311,6 +312,17 @@ CreateRole(CreateRoleStmt *stmt) errmsg("permission denied to create role"))); } + /* + * Check that the user is not trying to create a role in the reserved + * "pg_" namespace. + */ + if (IsReservedName(stmt->role)) + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("role name \"%s\" is reserved", + stmt->role), + errdetail("Role names starting with \"pg_\" are reserved."))); + /* * Check the pg_authid relation to be certain the role doesn't already * exist. @@ -507,6 +519,9 @@ AlterRole(AlterRoleStmt *stmt) DefElem *dbypassRLS = NULL; Oid roleid; + check_rolespec_name(stmt->role, + "Cannot alter reserved roles."); + /* Extract options from the statement node tree */ foreach(option, stmt->options) { @@ -857,6 +872,9 @@ AlterRoleSet(AlterRoleSetStmt *stmt) if (stmt->role) { + check_rolespec_name(stmt->role, + "Cannot alter reserved roles."); + roletuple = get_rolespec_tuple(stmt->role); roleid = HeapTupleGetOid(roletuple); @@ -1117,6 +1135,7 @@ RenameRole(const char *oldname, const char *newname) int i; Oid roleid; ObjectAddress address; + Form_pg_authid authform; rel = heap_open(AuthIdRelationId, RowExclusiveLock); dsc = RelationGetDescr(rel); @@ -1136,6 +1155,7 @@ RenameRole(const char *oldname, const char *newname) */ roleid = HeapTupleGetOid(oldtuple); + authform = (Form_pg_authid) GETSTRUCT(oldtuple); if (roleid == GetSessionUserId()) ereport(ERROR, @@ -1146,6 +1166,24 @@ RenameRole(const char *oldname, const char *newname) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("current user cannot be renamed"))); + /* + * Check that the user is not trying to rename a system role and + * not trying to rename a role into the reserved "pg_" namespace. + */ + if (IsReservedName(NameStr(authform->rolname))) + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("role name \"%s\" is reserved", + NameStr(authform->rolname)), + errdetail("Role names starting with \"pg_\" are reserved."))); + + if (IsReservedName(newname)) + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("role name \"%s\" is reserved", + newname), + errdetail("Role names starting with \"pg_\" are reserved."))); + /* make sure the new name doesn't exist */ if (SearchSysCacheExists1(AUTHNAME, CStringGetDatum(newname))) ereport(ERROR, @@ -1224,10 +1262,18 @@ GrantRole(GrantRoleStmt *stmt) ListCell *item; if (stmt->grantor) + { + check_rolespec_name(stmt->grantor, + "Cannot specify reserved role as grantor."); grantor = get_rolespec_oid(stmt->grantor, false); + } else grantor = GetUserId(); + foreach(item, stmt->grantee_roles) + check_rolespec_name(lfirst(item), + "Cannot GRANT roles to a reserved role."); + grantee_ids = roleSpecsToIds(stmt->grantee_roles); /* AccessShareLock is enough since we aren't modifying pg_authid */ @@ -1318,6 +1364,9 @@ ReassignOwnedObjects(ReassignOwnedStmt *stmt) errmsg("permission denied to reassign objects"))); } + check_rolespec_name(stmt->newrole, + "Cannot specify reserved role as owner."); + /* Must have privileges on the receiving side too */ newrole = get_rolespec_oid(stmt->newrole, false); diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index f801faacd29..57da0149d9f 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -854,6 +854,9 @@ check_role(char **newval, void **extra, GucSource source) roleid = InvalidOid; is_superuser = false; } + /* Do not allow setting role to a reserved role. */ + else if (strncmp(*newval, "pg_", 3) == 0) + return false; else { if (!IsTransactionState()) diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index 63fbce017c5..d2b23d05cbd 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -17,6 +17,7 @@ #include #include "access/htup_details.h" +#include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_auth_members.h" @@ -5247,3 +5248,41 @@ get_rolespec_name(const Node *node) return rolename; } + +/* + * Given a RoleSpec, throw an error if the name is reserved, using detail_msg, + * if provided. + * + * If node is NULL, no error is thrown. If detail_msg is NULL then no detail + * message is provided. + */ +void +check_rolespec_name(const Node *node, const char *detail_msg) +{ + RoleSpec *role; + + if (!node) + return; + + role = (RoleSpec *) node; + + Assert(IsA(node, RoleSpec)); + + if (role->roletype != ROLESPEC_CSTRING) + return; + + if (IsReservedName(role->rolename)) + { + if (detail_msg) + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("role \"%s\" is reserved", + role->rolename), + errdetail("%s", detail_msg))); + else + ereport(ERROR, + (errcode(ERRCODE_RESERVED_NAME), + errmsg("role \"%s\" is reserved", + role->rolename))); + } +} diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index a59493710b2..a7dc41c46d0 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -665,7 +665,7 @@ dumpRoles(PGconn *conn) int i; /* note: rolconfig is dumped later */ - if (server_version >= 90500) + if (server_version >= 90600) printfPQExpBuffer(buf, "SELECT oid, rolname, rolsuper, rolinherit, " "rolcreaterole, rolcreatedb, " @@ -674,6 +674,7 @@ dumpRoles(PGconn *conn) "pg_catalog.shobj_description(oid, 'pg_authid') as rolcomment, " "rolname = current_user AS is_current_user " "FROM pg_authid " + "WHERE rolname !~ '^pg_' " "ORDER BY 2"); else if (server_version >= 90100) printfPQExpBuffer(buf, @@ -771,6 +772,13 @@ dumpRoles(PGconn *conn) auth_oid = atooid(PQgetvalue(res, i, i_oid)); rolename = PQgetvalue(res, i, i_rolname); + if (strncmp(rolename,"pg_",3) == 0) + { + fprintf(stderr, _("%s: role name starting with 'pg_' skipped (%s)\n"), + progname, rolename); + continue; + } + resetPQExpBuffer(buf); if (binary_upgrade) @@ -896,6 +904,7 @@ dumpRoleMembership(PGconn *conn) "LEFT JOIN pg_authid ur on ur.oid = a.roleid " "LEFT JOIN pg_authid um on um.oid = a.member " "LEFT JOIN pg_authid ug on ug.oid = a.grantor " + "WHERE NOT (ur.rolname ~ '^pg_' AND um.rolname ~ '^pg_')" "ORDER BY 1,2,3"); if (PQntuples(res) > 0) diff --git a/src/bin/pg_upgrade/check.c b/src/bin/pg_upgrade/check.c index f932094bd0d..6b6f5ba7ea6 100644 --- a/src/bin/pg_upgrade/check.c +++ b/src/bin/pg_upgrade/check.c @@ -24,6 +24,7 @@ static void check_for_prepared_transactions(ClusterInfo *cluster); static void check_for_isn_and_int8_passing_mismatch(ClusterInfo *cluster); static void check_for_reg_data_type_usage(ClusterInfo *cluster); static void check_for_jsonb_9_4_usage(ClusterInfo *cluster); +static void check_for_pg_role_prefix(ClusterInfo *cluster); static void get_bin_version(ClusterInfo *cluster); static char *get_canonical_locale_name(int category, const char *locale); @@ -96,6 +97,11 @@ check_and_dump_old_cluster(bool live_check) check_for_prepared_transactions(&old_cluster); check_for_reg_data_type_usage(&old_cluster); check_for_isn_and_int8_passing_mismatch(&old_cluster); + + /* 9.5 and below should not have roles starting with pg_ */ + if (GET_MAJOR_VERSION(old_cluster.major_version) <= 905) + check_for_pg_role_prefix(&old_cluster); + if (GET_MAJOR_VERSION(old_cluster.major_version) == 904 && old_cluster.controldata.cat_ver < JSONB_FORMAT_CHANGE_CAT_VER) check_for_jsonb_9_4_usage(&old_cluster); @@ -629,7 +635,8 @@ check_is_install_user(ClusterInfo *cluster) res = executeQueryOrDie(conn, "SELECT rolsuper, oid " "FROM pg_catalog.pg_roles " - "WHERE rolname = current_user"); + "WHERE rolname = current_user " + "AND rolname !~ '^pg_'"); /* * We only allow the install user in the new cluster (see comment below) @@ -645,7 +652,8 @@ check_is_install_user(ClusterInfo *cluster) res = executeQueryOrDie(conn, "SELECT COUNT(*) " - "FROM pg_catalog.pg_roles "); + "FROM pg_catalog.pg_roles " + "WHERE rolname !~ '^pg_'"); if (PQntuples(res) != 1) pg_fatal("could not determine the number of users\n"); @@ -1033,6 +1041,34 @@ check_for_jsonb_9_4_usage(ClusterInfo *cluster) check_ok(); } +/* + * check_for_pg_role_prefix() + * + * Versions older than 9.6 should not have any pg_* roles + */ +static void +check_for_pg_role_prefix(ClusterInfo *cluster) +{ + PGresult *res; + PGconn *conn = connectToServer(cluster, "template1"); + + prep_status("Checking for roles starting with 'pg_'"); + + res = executeQueryOrDie(conn, + "SELECT * " + "FROM pg_catalog.pg_roles " + "WHERE rolname ~ '^pg_'"); + + if (PQntuples(res) != 0) + pg_fatal("The %s cluster contains roles starting with 'pg_'\n", + CLUSTER_NAME(cluster)); + + PQclear(res); + + PQfinish(conn); + + check_ok(); +} static void get_bin_version(ClusterInfo *cluster) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 1d326a81afe..9eae76f7ba8 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -429,7 +429,7 @@ exec_command(const char *cmd, break; case 'g': /* no longer distinct from \du */ - success = describeRoles(pattern, show_verbose); + success = describeRoles(pattern, show_verbose, show_system); break; case 'l': success = do_lo_list(); @@ -474,7 +474,7 @@ exec_command(const char *cmd, success = PSQL_CMD_UNKNOWN; break; case 'u': - success = describeRoles(pattern, show_verbose); + success = describeRoles(pattern, show_verbose, show_system); break; case 'F': /* text search subsystem */ switch (cmd[2]) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 7b2f4e64ef1..0a771bd2107 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2646,7 +2646,7 @@ add_tablespace_footer(printTableContent *const cont, char relkind, * Describes roles. Any schema portion of the pattern is ignored. */ bool -describeRoles(const char *pattern, bool verbose) +describeRoles(const char *pattern, bool verbose, bool showSystem) { PQExpBufferData buf; PGresult *res; @@ -2691,6 +2691,9 @@ describeRoles(const char *pattern, bool verbose) appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n"); + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, "WHERE r.rolname !~ '^pg_'\n"); + processSQLNamePattern(pset.db, &buf, pattern, false, false, NULL, "r.rolname", NULL, NULL); } diff --git a/src/bin/psql/describe.h b/src/bin/psql/describe.h index e4fc79edd14..96722756b46 100644 --- a/src/bin/psql/describe.h +++ b/src/bin/psql/describe.h @@ -25,7 +25,7 @@ extern bool describeTypes(const char *pattern, bool verbose, bool showSystem); extern bool describeOperators(const char *pattern, bool verbose, bool showSystem); /* \du, \dg */ -extern bool describeRoles(const char *pattern, bool verbose); +extern bool describeRoles(const char *pattern, bool verbose, bool showSystem); /* \drds */ extern bool listDbRoleSettings(const char *pattern1, const char *pattern2); diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index 7549451d216..eda31e2fb0f 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -229,7 +229,7 @@ slashUsage(unsigned short int pager) fprintf(output, _(" \\dFd[+] [PATTERN] list text search dictionaries\n")); fprintf(output, _(" \\dFp[+] [PATTERN] list text search parsers\n")); fprintf(output, _(" \\dFt[+] [PATTERN] list text search templates\n")); - fprintf(output, _(" \\dg[+] [PATTERN] list roles\n")); + fprintf(output, _(" \\dg[S+] [PATTERN] list roles\n")); fprintf(output, _(" \\di[S+] [PATTERN] list indexes\n")); fprintf(output, _(" \\dl list large objects, same as \\lo_list\n")); fprintf(output, _(" \\dL[S+] [PATTERN] list procedural languages\n")); @@ -242,7 +242,7 @@ slashUsage(unsigned short int pager) fprintf(output, _(" \\ds[S+] [PATTERN] list sequences\n")); fprintf(output, _(" \\dt[S+] [PATTERN] list tables\n")); fprintf(output, _(" \\dT[S+] [PATTERN] list data types\n")); - fprintf(output, _(" \\du[+] [PATTERN] list roles\n")); + fprintf(output, _(" \\du[S+] [PATTERN] list roles\n")); fprintf(output, _(" \\dv[S+] [PATTERN] list views\n")); fprintf(output, _(" \\dE[S+] [PATTERN] list foreign tables\n")); fprintf(output, _(" \\dx[+] [PATTERN] list extensions\n")); diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 4e15a14d65a..d91437b2346 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -231,6 +231,7 @@ extern void check_is_member_of_role(Oid member, Oid role); extern Oid get_role_oid(const char *rolename, bool missing_ok); extern Oid get_role_oid_or_public(const char *rolename); extern Oid get_rolespec_oid(const Node *node, bool missing_ok); +extern void check_rolespec_name(const Node *node, const char *detail_msg); extern HeapTuple get_rolespec_tuple(const Node *node); extern char *get_rolespec_name(const Node *node); diff --git a/src/test/regress/expected/rolenames.out b/src/test/regress/expected/rolenames.out index 8f88c025e8f..01b3b90ec14 100644 --- a/src/test/regress/expected/rolenames.out +++ b/src/test/regress/expected/rolenames.out @@ -78,6 +78,18 @@ CREATE ROLE "none"; -- error ERROR: role name "none" is reserved LINE 1: CREATE ROLE "none"; ^ +CREATE ROLE pg_abc; -- error +ERROR: role name "pg_abc" is reserved +DETAIL: Role names starting with "pg_" are reserved. +CREATE ROLE "pg_abc"; -- error +ERROR: role name "pg_abc" is reserved +DETAIL: Role names starting with "pg_" are reserved. +CREATE ROLE pg_abcdef; -- error +ERROR: role name "pg_abcdef" is reserved +DETAIL: Role names starting with "pg_" are reserved. +CREATE ROLE "pg_abcdef"; -- error +ERROR: role name "pg_abcdef" is reserved +DETAIL: Role names starting with "pg_" are reserved. CREATE ROLE testrol0 SUPERUSER LOGIN; CREATE ROLE testrolx SUPERUSER LOGIN; CREATE ROLE testrol2 SUPERUSER; @@ -804,6 +816,14 @@ LINE 1: DROP USER MAPPING IF EXISTS FOR CURRENT_ROLE SERVER sv9; DROP USER MAPPING IF EXISTS FOR nonexistent SERVER sv9; -- error NOTICE: role "nonexistent" does not exist, skipping -- GRANT/REVOKE +GRANT testrol0 TO pg_abc; -- error +ERROR: role "pg_abc" is reserved +DETAIL: Cannot GRANT roles to a reserved role. +GRANT pg_abc TO pg_abcdef; -- error +ERROR: role "pg_abcdef" is reserved +DETAIL: Cannot GRANT roles to a reserved role. +SET ROLE pg_testrole; -- error +ERROR: invalid value for parameter "role": "pg_testrole" UPDATE pg_proc SET proacl = null WHERE proname LIKE 'testagg_'; SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_'; proname | proacl diff --git a/src/test/regress/sql/rolenames.sql b/src/test/regress/sql/rolenames.sql index e8c6b335ec2..1e0e9af8da1 100644 --- a/src/test/regress/sql/rolenames.sql +++ b/src/test/regress/sql/rolenames.sql @@ -57,6 +57,11 @@ CREATE ROLE "public"; -- error CREATE ROLE none; -- error CREATE ROLE "none"; -- error +CREATE ROLE pg_abc; -- error +CREATE ROLE "pg_abc"; -- error +CREATE ROLE pg_abcdef; -- error +CREATE ROLE "pg_abcdef"; -- error + CREATE ROLE testrol0 SUPERUSER LOGIN; CREATE ROLE testrolx SUPERUSER LOGIN; CREATE ROLE testrol2 SUPERUSER; @@ -376,6 +381,11 @@ DROP USER MAPPING IF EXISTS FOR CURRENT_ROLE SERVER sv9; --error DROP USER MAPPING IF EXISTS FOR nonexistent SERVER sv9; -- error -- GRANT/REVOKE +GRANT testrol0 TO pg_abc; -- error +GRANT pg_abc TO pg_abcdef; -- error + +SET ROLE pg_testrole; -- error + UPDATE pg_proc SET proacl = null WHERE proname LIKE 'testagg_'; SELECT proname, proacl FROM pg_proc WHERE proname LIKE 'testagg_';