Role has superuser privileges
+ |
+ rolinherit
+ bool
+
+ Role automatically inherits privileges of roles it is a
+ member of
+
+
|
rolcreaterole
bool
that blanks out the password field.
+ This view explicitly exposes the OID column of the underlying table,
+ since that is needed to do joins to other catalogs.
+
+
pg_roles> Columns
Role has superuser privileges
+ |
+ rolinherit
+ bool
+
+ Role automatically inherits privileges of roles it is a
+ member of
+
+
|
rolcreaterole
bool
Session defaults for run-time configuration variables
+
+ |
+ oid
+ oid
+ pg_authid .oid
+ ID of role
+
can access a role in a particular way. The possibilities for its
arguments are analogous to has_table_privilege .
The desired access privilege type must evaluate to
- MEMBER .
+ MEMBER or
+ USAGE .
+ MEMBER denotes direct or indirect membership in
+ the role (that is, the right to do SET ROLE>), while
+ USAGE denotes whether the privileges of the role
+ are immediately available without doing SET ROLE>.
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.115 2005/07/07 20:39:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.116 2005/07/26 16:38:26 tgl Exp $
*
* NOTES
* See acl.h.
ReleaseSysCache(tuple);
- return is_member _of_role(roleid, ownerId);
+ return has_privs _of_role(roleid, ownerId);
}
/*
ReleaseSysCache(tuple);
- return is_member _of_role(roleid, ownerId);
+ return has_privs _of_role(roleid, ownerId);
}
/*
ReleaseSysCache(tuple);
- return is_member _of_role(roleid, ownerId);
+ return has_privs _of_role(roleid, ownerId);
}
/*
ReleaseSysCache(tuple);
- return is_member _of_role(roleid, ownerId);
+ return has_privs _of_role(roleid, ownerId);
}
/*
ReleaseSysCache(tuple);
- return is_member _of_role(roleid, ownerId);
+ return has_privs _of_role(roleid, ownerId);
}
/*
heap_endscan(scan);
heap_close(pg_tablespace, AccessShareLock);
- return is_member _of_role(roleid, spcowner);
+ return has_privs _of_role(roleid, spcowner);
}
/*
ReleaseSysCache(tuple);
- return is_member _of_role(roleid, ownerId);
+ return has_privs _of_role(roleid, ownerId);
}
/*
heap_endscan(scan);
heap_close(pg_database, AccessShareLock);
- return is_member _of_role(roleid, dba);
+ return has_privs _of_role(roleid, dba);
}
/*
ReleaseSysCache(tuple);
- return is_member _of_role(roleid, ownerId);
+ return has_privs _of_role(roleid, ownerId);
}
*
* Copyright (c) 1996-2005, PostgreSQL Global Development Group
*
- * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.16 2005/06/28 05:08:52 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.17 2005/07/26 16:38:26 tgl Exp $
*/
CREATE VIEW pg_roles AS
SELECT
rolname,
rolsuper,
+ rolinherit,
rolcreaterole,
rolcreatedb,
rolcatupdate,
rolcanlogin,
'********'::text as rolpassword,
rolvaliduntil,
- rolconfig
+ rolconfig,
+ oid
FROM pg_authid;
CREATE VIEW pg_shadow AS
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.157 2005/07/25 22:12:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.158 2005/07/26 16:38:26 tgl Exp $
*
*-------------------------------------------------------------------------
*/
bool encrypt_password = Password_encryption; /* encrypt password? */
char encrypted_password[MD5_PASSWD_LEN + 1];
bool issuper = false; /* Make the user a superuser? */
+ bool inherit = true; /* Auto inherit privileges? */
bool createrole = false; /* Can this user create roles? */
bool createdb = false; /* Can the user create databases? */
bool canlogin = false; /* Can this user login? */
char *validUntil = NULL; /* time the login is valid until */
DefElem *dpassword = NULL;
DefElem *dissuper = NULL;
+ DefElem *dinherit = NULL;
DefElem *dcreaterole = NULL;
DefElem *dcreatedb = NULL;
DefElem *dcanlogin = NULL;
DefElem *dadminmembers = NULL;
DefElem *dvalidUntil = NULL;
+ /* The defaults can vary depending on the original statement type */
+ switch (stmt->stmt_type)
+ {
+ case ROLESTMT_ROLE:
+ break;
+ case ROLESTMT_USER:
+ canlogin = true;
+ /* may eventually want inherit to default to false here */
+ break;
+ case ROLESTMT_GROUP:
+ break;
+ }
+
/* Extract options from the statement node tree */
foreach(option, stmt->options)
{
}
else if (strcmp(defel->defname, "sysid") == 0)
{
- ereport(WARNING ,
+ ereport(NOTICE ,
(errmsg("SYSID can no longer be specified")));
}
else if (strcmp(defel->defname, "superuser") == 0)
errmsg("conflicting or redundant options")));
dissuper = defel;
}
+ else if (strcmp(defel->defname, "inherit") == 0)
+ {
+ if (dinherit)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ dinherit = defel;
+ }
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
password = strVal(dpassword->arg);
if (dissuper)
issuper = intVal(dissuper->arg) != 0;
+ if (dinherit)
+ inherit = intVal(dinherit->arg) != 0;
if (dcreaterole)
createrole = intVal(dcreaterole->arg) != 0;
if (dcreatedb)
DirectFunctionCall1(namein, CStringGetDatum(stmt->role));
new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
+ new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit);
new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole);
new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb);
/* superuser gets catupdate right by default */
bool encrypt_password = Password_encryption; /* encrypt password? */
char encrypted_password[MD5_PASSWD_LEN + 1];
int issuper = -1; /* Make the user a superuser? */
+ int inherit = -1; /* Auto inherit privileges? */
int createrole = -1; /* Can this user create roles? */
int createdb = -1; /* Can the user create databases? */
int canlogin = -1; /* Can this user login? */
char *validUntil = NULL; /* time the login is valid until */
DefElem *dpassword = NULL;
DefElem *dissuper = NULL;
+ DefElem *dinherit = NULL;
DefElem *dcreaterole = NULL;
DefElem *dcreatedb = NULL;
DefElem *dcanlogin = NULL;
errmsg("conflicting or redundant options")));
dissuper = defel;
}
+ else if (strcmp(defel->defname, "inherit") == 0)
+ {
+ if (dinherit)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ dinherit = defel;
+ }
else if (strcmp(defel->defname, "createrole") == 0)
{
if (dcreaterole)
password = strVal(dpassword->arg);
if (dissuper)
issuper = intVal(dissuper->arg);
+ if (dinherit)
+ inherit = intVal(dinherit->arg);
if (dcreaterole)
createrole = intVal(dcreaterole->arg);
if (dcreatedb)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to alter superusers")));
}
- else
+ else if (!have_createrole_privilege())
{
- if (!have_createrole_privilege() &&
- !( createrole < 0 &&
+ if (!(inherit < 0 &&
+ createrole < 0 &&
createdb < 0 &&
canlogin < 0 &&
!rolemembers &&
new_record_repl[Anum_pg_authid_rolcatupdate - 1] = 'r';
}
+ if (inherit >= 0)
+ {
+ new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit > 0);
+ new_record_repl[Anum_pg_authid_rolinherit - 1] = 'r';
+ }
+
if (createrole >= 0)
{
new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole > 0);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.311 2005/07/02 23:00:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.312 2005/07/26 16:38:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
CreateRoleStmt *newnode = makeNode(CreateRoleStmt);
+ COPY_SCALAR_FIELD(stmt_type);
COPY_STRING_FIELD(role);
COPY_NODE_FIELD(options);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.248 2005/07/02 23:00:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.249 2005/07/26 16:38:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static bool
_equalCreateRoleStmt(CreateRoleStmt *a, CreateRoleStmt *b)
{
+ COMPARE_SCALAR_FIELD(stmt_type);
COMPARE_STRING_FIELD(role);
COMPARE_NODE_FIELD(options);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.502 2005/07/25 22:12:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.503 2005/07/26 16:38:27 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
HANDLER HAVING HEADER HOLD HOUR_P
ILIKE IMMEDIATE IMMUTABLE IMPLICIT_P IN_P INCLUDING INCREMENT
- INDEX INHERITS INITIALLY INNER_P INOUT INPUT_P
+ INDEX INHERIT INHERIT S INITIALLY INNER_P INOUT INPUT_P
INSENSITIVE INSERT INSTEAD INT_P INTEGER INTERSECT
INTERVAL INTO INVOKER IS ISNULL ISOLATION
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
- NOCREATEROLE NOCREATEUSER NOLOGIN_P NONE NOSUPERUSER NOT NOTHING NOTIFY
- NOTNULL NOWAIT NULL_P NULLIF NUMERIC
+ NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
+ NOT NOTHING NOTIFY NOT NULL NOWAIT NULL_P NULLIF NUMERIC
OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR
ORDER OUT_P OUTER_P OVERLAPS OVERLAY OWNER
CREATE ROLE RoleId opt_with OptRoleList
{
CreateRoleStmt *n = makeNode(CreateRoleStmt);
+ n->stmt_type = ROLESTMT_ROLE;
n->role = $3;
n->options = $5;
$$ = (Node *)n;
{
$$ = makeDefElem("superuser", (Node *)makeInteger(FALSE));
}
+ | INHERIT
+ {
+ $$ = makeDefElem("inherit", (Node *)makeInteger(TRUE));
+ }
+ | NOINHERIT
+ {
+ $$ = makeDefElem("inherit", (Node *)makeInteger(FALSE));
+ }
| CREATEDB
{
$$ = makeDefElem("createdb", (Node *)makeInteger(TRUE));
CREATE USER RoleId opt_with OptRoleList
{
CreateRoleStmt *n = makeNode(CreateRoleStmt);
+ n->stmt_type = ROLESTMT_USER;
n->role = $3;
- n->options = lappend($5,
- makeDefElem("canlogin",
- (Node *)makeInteger(TRUE)));
+ n->options = $5;
$$ = (Node *)n;
}
;
CREATE GROUP_P RoleId opt_with OptRoleList
{
CreateRoleStmt *n = makeNode(CreateRoleStmt);
+ n->stmt_type = ROLESTMT_GROUP;
n->role = $3;
n->options = $5;
$$ = (Node *)n;
| INCLUDING
| INCREMENT
| INDEX
+ | INHERIT
| INHERITS
| INPUT_P
| INSENSITIVE
| NOCREATEDB
| NOCREATEROLE
| NOCREATEUSER
+ | NOINHERIT
| NOLOGIN_P
| NOSUPERUSER
| NOTHING
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.162 2005/06/29 20:34:14 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.163 2005/07/26 16:38:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{"including", INCLUDING},
{"increment", INCREMENT},
{"index", INDEX},
+ {"inherit", INHERIT},
{"inherits", INHERITS},
{"initially", INITIALLY},
{"inner", INNER_P},
{"nocreatedb", NOCREATEDB},
{"nocreaterole", NOCREATEROLE},
{"nocreateuser", NOCREATEUSER},
+ {"noinherit", NOINHERIT},
{"nologin", NOLOGIN_P},
{"none", NONE},
{"nosuperuser", NOSUPERUSER},
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.121 2005/07/26 00:04:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.122 2005/07/26 16:38:27 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* all the roles the "given role" is a member of, directly or indirectly.
* The cache is flushed whenever we detect a change in pg_auth_members.
*
+ * There are actually two caches, one computed under "has_privs" rules
+ * (do not recurse where rolinherit isn't true) and one computed under
+ * "is_member" rules (recurse regardless of rolinherit).
+ *
* Possibly this mechanism should be generalized to allow caching membership
- * info for more than one role?
+ * info for multiple roles?
+ *
+ * The has_privs cache is:
+ * cached_privs_role is the role OID the cache is for.
+ * cached_privs_roles is an OID list of roles that cached_privs_role
+ * has the privileges of (always including itself).
+ * The cache is valid if cached_privs_role is not InvalidOid.
*
- * cached_role is the role OID the cache is for.
- * cached_memberships is an OID list of roles that cached_role is a member of.
- * The cache is valid if cached_role is not InvalidOid.
+ * The is_member cache is similarly:
+ * cached_member_role is the role OID the cache is for.
+ * cached_membership_roles is an OID list of roles that cached_member_role
+ * is a member of (always including itself).
+ * The cache is valid if cached_member_role is not InvalidOid.
*/
-static Oid cached_role = InvalidOid;
-static List *cached_memberships = NIL;
+static Oid cached_privs_role = InvalidOid;
+static List *cached_privs_roles = NIL;
+static Oid cached_member_role = InvalidOid;
+static List *cached_membership_roles = NIL;
static const char *getid(const char *s, char *n);
result = 0;
/* Owner always implicitly has all grant options */
- if (is_member _of_role(roleid, ownerId))
+ if (has_privs _of_role(roleid, ownerId))
{
result = mask & ACLITEM_ALL_GOPTION_BITS;
if (result == mask)
continue; /* already checked it */
if ((aidata->ai_privs & remaining) &&
- is_member _of_role(roleid, aidata->ai_grantee))
+ has_privs _of_role(roleid, aidata->ai_grantee))
{
result |= aidata->ai_privs & mask;
if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
* convert_role_priv_string
* Convert text string to AclMode value.
*
- * There is only one interesting option, MEMBER, which we represent by
- * ACL_USAGE since no formal ACL bit is defined for it. This convention
+ * We use USAGE to denote whether the privileges of the role are accessible
+ * (has_privs), MEMBER to denote is_member, and MEMBER WITH GRANT OPTION
+ * (or ADMIN OPTION) to denote is_admin. There is no ACL bit corresponding
+ * to MEMBER so we cheat and use ACL_CREATE for that. This convention
* is shared only with pg_role_aclcheck, below.
*/
static AclMode
/*
* Return mode from priv_type string
*/
- if (pg_strcasecmp(priv_type, "MEMBER ") == 0)
+ if (pg_strcasecmp(priv_type, "USAGE ") == 0)
return ACL_USAGE;
- if (pg_strcasecmp(priv_type, "MEMBER WITH GRANT OPTION") == 0)
- return ACL_GRANT_OPTION_FOR(ACL_USAGE);
- if (pg_strcasecmp(priv_type, "MEMBER WITH ADMIN OPTION") == 0)
- return ACL_GRANT_OPTION_FOR(ACL_USAGE);
+ if (pg_strcasecmp(priv_type, "MEMBER") == 0)
+ return ACL_CREATE;
+ if (pg_strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0 ||
+ pg_strcasecmp(priv_type, "USAGE WITH ADMIN OPTION") == 0 ||
+ pg_strcasecmp(priv_type, "MEMBER WITH GRANT OPTION") == 0 ||
+ pg_strcasecmp(priv_type, "MEMBER WITH ADMIN OPTION") == 0)
+ return ACL_GRANT_OPTION_FOR(ACL_CREATE);
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
static AclResult
pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
{
- if (mode & ACL_GRANT_OPTION_FOR(ACL_USAG E))
+ if (mode & ACL_GRANT_OPTION_FOR(ACL_CREAT E))
{
if (is_admin_of_role(roleid, role_oid))
return ACLCHECK_OK;
- else
- return ACLCHECK_NO_PRIV;
}
- else
+ if (mode & ACL_CREATE)
{
if (is_member_of_role(roleid, role_oid))
return ACLCHECK_OK;
- else
- return ACLCHECK_NO_PRIV;
}
+ if (mode & ACL_USAGE)
+ {
+ if (has_privs_of_role(roleid, role_oid))
+ return ACLCHECK_OK;
+ }
+ return ACLCHECK_NO_PRIV;
}
static void
RoleMembershipCacheCallback(Datum arg, Oid relid)
{
- /* Force membership cache to be recomputed on next use */
- cached_role = InvalidOid;
+ /* Force membership caches to be recomputed on next use */
+ cached_privs_role = InvalidOid;
+ cached_member_role = InvalidOid;
+}
+
+
+/* Check if specified role has rolinherit set */
+static bool
+has_rolinherit(Oid roleid)
+{
+ bool result = false;
+ HeapTuple utup;
+
+ utup = SearchSysCache(AUTHOID,
+ ObjectIdGetDatum(roleid),
+ 0, 0, 0);
+ if (HeapTupleIsValid(utup))
+ {
+ result = ((Form_pg_authid) GETSTRUCT(utup))->rolinherit;
+ ReleaseSysCache(utup);
+ }
+ return result;
+}
+
+
+/*
+ * Does member have the privileges of role (directly or indirectly)?
+ *
+ * This is defined not to recurse through roles that don't have rolinherit
+ * set; for such roles, membership implies the ability to do SET ROLE, but
+ * the privileges are not available until you've done so.
+ *
+ * Since indirect membership testing is relatively expensive, we cache
+ * a list of memberships.
+ */
+bool
+has_privs_of_role(Oid member, Oid role)
+{
+ List *roles_list;
+ ListCell *l;
+ List *new_cached_privs_roles;
+ MemoryContext oldctx;
+
+ /* Fast path for simple case */
+ if (member == role)
+ return true;
+
+ /* Superusers have every privilege, so are part of every role */
+ if (superuser_arg(member))
+ return true;
+
+ /* If cache is already valid, just use the list */
+ if (OidIsValid(cached_privs_role) && cached_privs_role == member)
+ return list_member_oid(cached_privs_roles, role);
+
+ /*
+ * Find all the roles that member is a member of,
+ * including multi-level recursion. The role itself will always
+ * be the first element of the resulting list.
+ *
+ * Each element of the list is scanned to see if it adds any indirect
+ * memberships. We can use a single list as both the record of
+ * already-found memberships and the agenda of roles yet to be scanned.
+ * This is a bit tricky but works because the foreach() macro doesn't
+ * fetch the next list element until the bottom of the loop.
+ */
+ roles_list = list_make1_oid(member);
+
+ foreach(l, roles_list)
+ {
+ Oid memberid = lfirst_oid(l);
+ CatCList *memlist;
+ int i;
+
+ /* Ignore non-inheriting roles */
+ if (!has_rolinherit(memberid))
+ continue;
+
+ /* Find roles that memberid is directly a member of */
+ memlist = SearchSysCacheList(AUTHMEMMEMROLE, 1,
+ ObjectIdGetDatum(memberid),
+ 0, 0, 0);
+ for (i = 0; i < memlist->n_members; i++)
+ {
+ HeapTuple tup = &memlist->members[i]->tuple;
+ Oid otherid = ((Form_pg_auth_members) GETSTRUCT(tup))->roleid;
+
+ /*
+ * Even though there shouldn't be any loops in the membership
+ * graph, we must test for having already seen this role.
+ * It is legal for instance to have both A->B and A->C->B.
+ */
+ if (!list_member_oid(roles_list, otherid))
+ roles_list = lappend_oid(roles_list, otherid);
+ }
+ ReleaseSysCacheList(memlist);
+ }
+
+ /*
+ * Copy the completed list into TopMemoryContext so it will persist.
+ */
+ oldctx = MemoryContextSwitchTo(TopMemoryContext);
+ new_cached_privs_roles = list_copy(roles_list);
+ MemoryContextSwitchTo(oldctx);
+ list_free(roles_list);
+
+ /*
+ * Now safe to assign to state variable
+ */
+ cached_privs_role = InvalidOid; /* just paranoia */
+ list_free(cached_privs_roles);
+ cached_privs_roles = new_cached_privs_roles;
+ cached_privs_role = member;
+
+ /* And now we can return the answer */
+ return list_member_oid(cached_privs_roles, role);
}
/*
* Is member a member of role (directly or indirectly)?
*
+ * This is defined to recurse through roles regardless of rolinherit.
+ *
* Since indirect membership testing is relatively expensive, we cache
* a list of memberships.
*/
{
List *roles_list;
ListCell *l;
- List *new_cached_memberships;
+ List *new_cached_membership_role s;
MemoryContext oldctx;
/* Fast path for simple case */
return true;
/* If cache is already valid, just use the list */
- if (OidIsValid(cached_role) && cached _role == member)
- return list_member_oid(cached_memberships, role);
+ if (OidIsValid(cached_member_role) && cached_member _role == member)
+ return list_member_oid(cached_membership_role s, role);
/*
* Find all the roles that member is a member of,
* Copy the completed list into TopMemoryContext so it will persist.
*/
oldctx = MemoryContextSwitchTo(TopMemoryContext);
- new_cached_memberships = list_copy(roles_list);
+ new_cached_membership_role s = list_copy(roles_list);
MemoryContextSwitchTo(oldctx);
list_free(roles_list);
/*
* Now safe to assign to state variable
*/
- cached_role = InvalidOid; /* just paranoia */
- list_free(cached_memberships);
- cached_memberships = new_cached_membership s;
- cached_role = member;
+ cached_member_role = InvalidOid; /* just paranoia */
+ list_free(cached_membership_role s);
+ cached_membership_roles = new_cached_membership_role s;
+ cached_member_ role = member;
/* And now we can return the answer */
- return list_member_oid(cached_memberships, role);
+ return list_member_oid(cached_membership_role s, role);
}
/*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.291 2005/07/26 00:04:1 8 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.292 2005/07/26 16:38:2 8 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 20050725 1
+#define CATALOG_VERSION_NO 20050726 1
#endif
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/catalog/pg_authid.h,v 1.1 2005/06/28 05:09:05 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_authid.h,v 1.2 2005/07/26 16:38:28 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
{
NameData rolname; /* name of role */
bool rolsuper; /* read this field via superuser() only! */
+ bool rolinherit; /* inherit privileges from other roles? */
bool rolcreaterole; /* allowed to create more roles? */
bool rolcreatedb; /* allowed to create databases? */
bool rolcatupdate; /* allowed to alter catalogs manually? */
* compiler constants for pg_authid
* ----------------
*/
-#define Natts_pg_authid 9
+#define Natts_pg_authid 10
#define Anum_pg_authid_rolname 1
#define Anum_pg_authid_rolsuper 2
-#define Anum_pg_authid_rolcreaterole 3
-#define Anum_pg_authid_rolcreatedb 4
-#define Anum_pg_authid_rolcatupdate 5
-#define Anum_pg_authid_rolcanlogin 6
-#define Anum_pg_authid_rolpassword 7
-#define Anum_pg_authid_rolvaliduntil 8
-#define Anum_pg_authid_rolconfig 9
+#define Anum_pg_authid_rolinherit 3
+#define Anum_pg_authid_rolcreaterole 4
+#define Anum_pg_authid_rolcreatedb 5
+#define Anum_pg_authid_rolcatupdate 6
+#define Anum_pg_authid_rolcanlogin 7
+#define Anum_pg_authid_rolpassword 8
+#define Anum_pg_authid_rolvaliduntil 9
+#define Anum_pg_authid_rolconfig 10
/* ----------------
* initial contents of pg_authid
* user choices.
* ----------------
*/
-DATA(insert OID = 10 ( "POSTGRES" t t t t t _null_ _null_ _null_ ));
+DATA(insert OID = 10 ( "POSTGRES" t t t t t t _null_ _null_ _null_ ));
#define BOOTSTRAP_SUPERUSERID 10
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.285 2005/06/28 19:51:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.286 2005/07/26 16:38:28 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* ----------------------
* Create/Alter/Drop Role Statements
+ *
+ * Note: these node types are also used for the backwards-compatible
+ * Create/Alter/Drop User/Group statements. In the ALTER and DROP cases
+ * there's really no need to distinguish what the original spelling was,
+ * but for CREATE we mark the type because the defaults vary.
* ----------------------
*/
+typedef enum RoleStmtType
+{
+ ROLESTMT_ROLE,
+ ROLESTMT_USER,
+ ROLESTMT_GROUP
+} RoleStmtType;
+
typedef struct CreateRoleStmt
{
NodeTag type;
+ RoleStmtType stmt_type; /* ROLE/USER/GROUP */
char *role; /* role name */
List *options; /* List of DefElem nodes */
} CreateRoleStmt;
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.82 2005/07/14 21:46:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.83 2005/07/26 16:38:29 tgl Exp $
*
* NOTES
* An ACL array is simply an array of AclItems, representing the union
AclMode mask, AclMaskHow how);
extern int aclmembers(const Acl *acl, Oid **roleids);
+extern bool has_privs_of_role(Oid member, Oid role);
extern bool is_member_of_role(Oid member, Oid role);
extern bool is_admin_of_role(Oid member, Oid role);
extern void check_is_member_of_role(Oid member, Oid role);
pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char"));
pg_locks | SELECT l.locktype, l."database", l.relation, l.page, l.tuple, l.transactionid, l.classid, l.objid, l.objsubid, l."transaction", l.pid, l."mode", l."granted" FROM pg_lock_status() l(locktype text, "database" oid, relation oid, page integer, tuple smallint, transactionid xid, classid oid, objid oid, objsubid smallint, "transaction" xid, pid integer, "mode" text, "granted" boolean);
pg_prepared_xacts | SELECT p."transaction", p.gid, p."prepared", u.rolname AS "owner", d.datname AS "database" FROM ((pg_prepared_xact() p("transaction" xid, gid text, "prepared" timestamp with time zone, ownerid oid, dbid oid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid)));
- pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig FROM pg_authid;
+ pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig, pg_authid.oid FROM pg_authid;
pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name);
pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text);
pg_shadow | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, pg_authid.rolconfig AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin;