Reserve the "pg_" namespace for roles
This will prevent users from creating roles which begin with "pg_" and will check for those roles before allowing an upgrade using pg_upgrade. This will allow for default roles to be provided at initdb time. Reviews by José Luis Tallón and Robert Haas
This commit is contained in:
parent
fa6075e551
commit
293007898d
|
@ -1365,13 +1365,15 @@ testdb=>
|
|||
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>\dg[+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
|
||||
<term><literal>\dg[S+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Lists database roles.
|
||||
(Since the concepts of <quote>users</> and <quote>groups</> have been
|
||||
unified into <quote>roles</>, this command is now equivalent to
|
||||
<literal>\du</literal>.)
|
||||
By default, only user-created roles are shown; supply the
|
||||
<literal>S</literal> modifier to include system roles.
|
||||
If <replaceable class="parameter">pattern</replaceable> is specified,
|
||||
only those roles whose names match the pattern are listed.
|
||||
If the form <literal>\dg+</literal> is used, additional information
|
||||
|
@ -1525,13 +1527,15 @@ testdb=>
|
|||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>\du[+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
|
||||
<term><literal>\du[S+] [ <link linkend="APP-PSQL-patterns"><replaceable class="parameter">pattern</replaceable></link> ]</literal></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Lists database roles.
|
||||
(Since the concepts of <quote>users</> and <quote>groups</> have been
|
||||
unified into <quote>roles</>, this command is now equivalent to
|
||||
<literal>\dg</literal>.)
|
||||
By default, only user-created roles are shown; supply the
|
||||
<literal>S</literal> modifier to include system roles.
|
||||
If <replaceable class="parameter">pattern</replaceable> is specified,
|
||||
only those roles whose names match the pattern are listed.
|
||||
If the form <literal>\du+</literal> is used, additional information
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#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)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"));
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_';
|
||||
|
||||
|
|
Loading…
Reference in New Issue