Commit 5ddbe904 authored by Tom Lane's avatar Tom Lane

Refactor low-level aclcheck code to provide useful interfaces for multi-bit

permissions tests in about the same amount of code as before.  Exactly what
the GRANT/REVOKE code ought to be doing is still up for debate, but this
should be helpful in any case, and it already solves an efficiency problem
in executor startup.
parent f739deb5
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.97 2004/01/14 03:44:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.98 2004/05/11 17:36:12 tgl Exp $
* *
* NOTES * NOTES
* See acl.h. * See acl.h.
...@@ -48,7 +48,8 @@ static void ExecuteGrantStmt_Namespace(GrantStmt *stmt); ...@@ -48,7 +48,8 @@ static void ExecuteGrantStmt_Namespace(GrantStmt *stmt);
static const char *privilege_to_string(AclMode privilege); static const char *privilege_to_string(AclMode privilege);
static AclResult aclcheck(Acl *acl, AclId userid, AclMode mode); static AclMode aclmask(Acl *acl, AclId userid,
AclMode mask, AclMaskHow how);
#ifdef ACLDEBUG #ifdef ACLDEBUG
...@@ -869,15 +870,33 @@ in_group(AclId uid, AclId gid) ...@@ -869,15 +870,33 @@ in_group(AclId uid, AclId gid)
/* /*
* aclcheck * aclmask --- compute bitmask of all privileges held by userid.
* *
* Returns ACLCHECK_OK if the 'userid' has ACL entries in 'acl' to * When 'how' = ACLMASK_ALL, this simply returns the privilege bits
* satisfy any one of the requirements of 'mode'. Returns an * held by the given userid according to the given ACL list, ANDed
* appropriate ACLCHECK_* error code otherwise. * with 'mask'. (The point of passing 'mask' is to let the routine
* exit early if all privileges of interest have been found.)
*
* When 'how' = ACLMASK_ANY, returns as soon as any bit in the mask
* is known true. (This lets us exit soonest in cases where the
* caller is only going to test for zero or nonzero result.)
*
* Usage patterns:
*
* To see if any of a set of privileges are held:
* if (aclmask(acl, userid, privs, ACLMASK_ANY) != 0)
*
* To see if all of a set of privileges are held:
* if (aclmask(acl, userid, privs, ACLMASK_ALL) == privs)
*
* To determine exactly which of a set of privileges are held:
* heldprivs = aclmask(acl, userid, privs, ACLMASK_ALL);
*/ */
static AclResult static AclMode
aclcheck(Acl *acl, AclId userid, AclMode mode) aclmask(Acl *acl, AclId userid, AclMode mask, AclMaskHow how)
{ {
AclMode result;
AclMode remaining;
AclItem *aidat; AclItem *aidat;
int i, int i,
num; num;
...@@ -887,38 +906,55 @@ aclcheck(Acl *acl, AclId userid, AclMode mode) ...@@ -887,38 +906,55 @@ aclcheck(Acl *acl, AclId userid, AclMode mode)
* appropriate default * appropriate default
*/ */
if (acl == NULL) if (acl == NULL)
{
elog(ERROR, "null ACL"); elog(ERROR, "null ACL");
return ACLCHECK_NO_PRIV;
} /* Quick exit for mask == 0 */
if (mask == 0)
return 0;
num = ACL_NUM(acl); num = ACL_NUM(acl);
aidat = ACL_DAT(acl); aidat = ACL_DAT(acl);
result = 0;
/* /*
* See if privilege is granted directly to user or to public * Check privileges granted directly to user or to public
*/ */
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
if (ACLITEM_GET_IDTYPE(aidat[i]) == ACL_IDTYPE_WORLD {
|| (ACLITEM_GET_IDTYPE(aidat[i]) == ACL_IDTYPE_UID AclItem *aidata = &aidat[i];
&& aidat[i].ai_grantee == userid))
if (ACLITEM_GET_IDTYPE(*aidata) == ACL_IDTYPE_WORLD
|| (ACLITEM_GET_IDTYPE(*aidata) == ACL_IDTYPE_UID
&& aidata->ai_grantee == userid))
{ {
if (aidat[i].ai_privs & mode) result |= (aidata->ai_privs & mask);
return ACLCHECK_OK; if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
return result;
} }
}
/* /*
* See if he has the permission via any group (do this in a separate * Check privileges granted via groups. We do this in a separate
* pass to avoid expensive(?) lookups in pg_group) * pass to minimize expensive lookups in pg_group.
*/ */
remaining = (mask & ~result);
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
if (ACLITEM_GET_IDTYPE(aidat[i]) == ACL_IDTYPE_GID {
&& aidat[i].ai_privs & mode AclItem *aidata = &aidat[i];
&& in_group(userid, aidat[i].ai_grantee))
return ACLCHECK_OK; if (ACLITEM_GET_IDTYPE(*aidata) == ACL_IDTYPE_GID
&& (aidata->ai_privs & remaining)
&& in_group(userid, aidata->ai_grantee))
{
result |= (aidata->ai_privs & mask);
if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
return result;
remaining = (mask & ~result);
}
}
/* If here, doesn't have the privilege. */ return result;
return ACLCHECK_NO_PRIV;
} }
...@@ -1001,17 +1037,20 @@ aclcheck_error(AclResult aclerr, AclObjectKind objectkind, ...@@ -1001,17 +1037,20 @@ aclcheck_error(AclResult aclerr, AclObjectKind objectkind,
/* /*
* Exported routine for checking a user's access privileges to a table * Exported routine for examining a user's privileges for a table
*
* See aclmask() for a description of the API.
* *
* Note: we give lookup failure the full ereport treatment because the * Note: we give lookup failure the full ereport treatment because the
* has_table_privilege() family of functions allow users to pass * has_table_privilege() family of functions allow users to pass
* any random OID to this function. Likewise for the sibling functions * any random OID to this function. Likewise for the sibling functions
* below. * below.
*/ */
AclResult AclMode
pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode) pg_class_aclmask(Oid table_oid, AclId userid,
AclMode mask, AclMaskHow how)
{ {
AclResult result; AclMode result;
bool usesuper, bool usesuper,
usecatupd; usecatupd;
HeapTuple tuple; HeapTuple tuple;
...@@ -1046,7 +1085,8 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode) ...@@ -1046,7 +1085,8 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode)
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE), (errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation with OID %u does not exist", table_oid))); errmsg("relation with OID %u does not exist",
table_oid)));
classForm = (Form_pg_class) GETSTRUCT(tuple); classForm = (Form_pg_class) GETSTRUCT(tuple);
/* /*
...@@ -1058,7 +1098,7 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode) ...@@ -1058,7 +1098,7 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode)
* be protected in this way. Assume the view rules can take care * be protected in this way. Assume the view rules can take care
* of themselves. * of themselves.
*/ */
if ((mode & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) && if ((mask & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
IsSystemClass(classForm) && IsSystemClass(classForm) &&
classForm->relkind != RELKIND_VIEW && classForm->relkind != RELKIND_VIEW &&
!usecatupd && !usecatupd &&
...@@ -1067,8 +1107,7 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode) ...@@ -1067,8 +1107,7 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode)
#ifdef ACLDEBUG #ifdef ACLDEBUG
elog(DEBUG2, "permission denied for system catalog update"); elog(DEBUG2, "permission denied for system catalog update");
#endif #endif
ReleaseSysCache(tuple); mask &= ~(ACL_INSERT | ACL_UPDATE | ACL_DELETE);
return ACLCHECK_NO_PRIV;
} }
/* /*
...@@ -1080,7 +1119,7 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode) ...@@ -1080,7 +1119,7 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode)
elog(DEBUG2, "%u is superuser, home free", userid); elog(DEBUG2, "%u is superuser, home free", userid);
#endif #endif
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
return ACLCHECK_OK; return mask;
} }
/* /*
...@@ -1102,7 +1141,7 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode) ...@@ -1102,7 +1141,7 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode)
acl = DatumGetAclP(aclDatum); acl = DatumGetAclP(aclDatum);
} }
result = aclcheck(acl, userid, mode); result = aclmask(acl, userid, mask, how);
/* if we have a detoasted copy, free it */ /* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum)) if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
...@@ -1114,12 +1153,13 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode) ...@@ -1114,12 +1153,13 @@ pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode)
} }
/* /*
* Exported routine for checking a user's access privileges to a database * Exported routine for examining a user's privileges for a database
*/ */
AclResult AclMode
pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode) pg_database_aclmask(Oid db_oid, AclId userid,
AclMode mask, AclMaskHow how)
{ {
AclResult result; AclMode result;
Relation pg_database; Relation pg_database;
ScanKeyData entry[1]; ScanKeyData entry[1];
HeapScanDesc scan; HeapScanDesc scan;
...@@ -1130,7 +1170,7 @@ pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode) ...@@ -1130,7 +1170,7 @@ pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode)
/* Superusers bypass all permission checking. */ /* Superusers bypass all permission checking. */
if (superuser_arg(userid)) if (superuser_arg(userid))
return ACLCHECK_OK; return mask;
/* /*
* Get the database's ACL from pg_database * Get the database's ACL from pg_database
...@@ -1167,7 +1207,7 @@ pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode) ...@@ -1167,7 +1207,7 @@ pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode)
acl = DatumGetAclP(aclDatum); acl = DatumGetAclP(aclDatum);
} }
result = aclcheck(acl, userid, mode); result = aclmask(acl, userid, mask, how);
/* if we have a detoasted copy, free it */ /* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum)) if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
...@@ -1180,12 +1220,13 @@ pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode) ...@@ -1180,12 +1220,13 @@ pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode)
} }
/* /*
* Exported routine for checking a user's access privileges to a function * Exported routine for examining a user's privileges for a function
*/ */
AclResult AclMode
pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode) pg_proc_aclmask(Oid proc_oid, AclId userid,
AclMode mask, AclMaskHow how)
{ {
AclResult result; AclMode result;
HeapTuple tuple; HeapTuple tuple;
Datum aclDatum; Datum aclDatum;
bool isNull; bool isNull;
...@@ -1193,7 +1234,7 @@ pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode) ...@@ -1193,7 +1234,7 @@ pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode)
/* Superusers bypass all permission checking. */ /* Superusers bypass all permission checking. */
if (superuser_arg(userid)) if (superuser_arg(userid))
return ACLCHECK_OK; return mask;
/* /*
* Get the function's ACL from pg_proc * Get the function's ACL from pg_proc
...@@ -1223,7 +1264,7 @@ pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode) ...@@ -1223,7 +1264,7 @@ pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode)
acl = DatumGetAclP(aclDatum); acl = DatumGetAclP(aclDatum);
} }
result = aclcheck(acl, userid, mode); result = aclmask(acl, userid, mask, how);
/* if we have a detoasted copy, free it */ /* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum)) if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
...@@ -1235,12 +1276,13 @@ pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode) ...@@ -1235,12 +1276,13 @@ pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode)
} }
/* /*
* Exported routine for checking a user's access privileges to a language * Exported routine for examining a user's privileges for a language
*/ */
AclResult AclMode
pg_language_aclcheck(Oid lang_oid, AclId userid, AclMode mode) pg_language_aclmask(Oid lang_oid, AclId userid,
AclMode mask, AclMaskHow how)
{ {
AclResult result; AclMode result;
HeapTuple tuple; HeapTuple tuple;
Datum aclDatum; Datum aclDatum;
bool isNull; bool isNull;
...@@ -1248,7 +1290,7 @@ pg_language_aclcheck(Oid lang_oid, AclId userid, AclMode mode) ...@@ -1248,7 +1290,7 @@ pg_language_aclcheck(Oid lang_oid, AclId userid, AclMode mode)
/* Superusers bypass all permission checking. */ /* Superusers bypass all permission checking. */
if (superuser_arg(userid)) if (superuser_arg(userid))
return ACLCHECK_OK; return mask;
/* /*
* Get the language's ACL from pg_language * Get the language's ACL from pg_language
...@@ -1276,7 +1318,7 @@ pg_language_aclcheck(Oid lang_oid, AclId userid, AclMode mode) ...@@ -1276,7 +1318,7 @@ pg_language_aclcheck(Oid lang_oid, AclId userid, AclMode mode)
acl = DatumGetAclP(aclDatum); acl = DatumGetAclP(aclDatum);
} }
result = aclcheck(acl, userid, mode); result = aclmask(acl, userid, mask, how);
/* if we have a detoasted copy, free it */ /* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum)) if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
...@@ -1288,12 +1330,13 @@ pg_language_aclcheck(Oid lang_oid, AclId userid, AclMode mode) ...@@ -1288,12 +1330,13 @@ pg_language_aclcheck(Oid lang_oid, AclId userid, AclMode mode)
} }
/* /*
* Exported routine for checking a user's access privileges to a namespace * Exported routine for examining a user's privileges for a namespace
*/ */
AclResult AclMode
pg_namespace_aclcheck(Oid nsp_oid, AclId userid, AclMode mode) pg_namespace_aclmask(Oid nsp_oid, AclId userid,
AclMode mask, AclMaskHow how)
{ {
AclResult result; AclMode result;
HeapTuple tuple; HeapTuple tuple;
Datum aclDatum; Datum aclDatum;
bool isNull; bool isNull;
...@@ -1304,11 +1347,11 @@ pg_namespace_aclcheck(Oid nsp_oid, AclId userid, AclMode mode) ...@@ -1304,11 +1347,11 @@ pg_namespace_aclcheck(Oid nsp_oid, AclId userid, AclMode mode)
* we have all grantable privileges on it. * we have all grantable privileges on it.
*/ */
if (isTempNamespace(nsp_oid)) if (isTempNamespace(nsp_oid))
return ACLCHECK_OK; return mask;
/* Superusers bypass all permission checking. */ /* Superusers bypass all permission checking. */
if (superuser_arg(userid)) if (superuser_arg(userid))
return ACLCHECK_OK; return mask;
/* /*
* Get the schema's ACL from pg_namespace * Get the schema's ACL from pg_namespace
...@@ -1338,7 +1381,7 @@ pg_namespace_aclcheck(Oid nsp_oid, AclId userid, AclMode mode) ...@@ -1338,7 +1381,7 @@ pg_namespace_aclcheck(Oid nsp_oid, AclId userid, AclMode mode)
acl = DatumGetAclP(aclDatum); acl = DatumGetAclP(aclDatum);
} }
result = aclcheck(acl, userid, mode); result = aclmask(acl, userid, mask, how);
/* if we have a detoasted copy, free it */ /* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum)) if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
...@@ -1350,6 +1393,71 @@ pg_namespace_aclcheck(Oid nsp_oid, AclId userid, AclMode mode) ...@@ -1350,6 +1393,71 @@ pg_namespace_aclcheck(Oid nsp_oid, AclId userid, AclMode mode)
} }
/*
* Exported routine for checking a user's access privileges to a table
*
* Returns ACLCHECK_OK if the user has any of the privileges identified by
* 'mode'; otherwise returns a suitable error code (in practice, always
* ACLCHECK_NO_PRIV).
*/
AclResult
pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode)
{
if (pg_class_aclmask(table_oid, userid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
/*
* Exported routine for checking a user's access privileges to a database
*/
AclResult
pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode)
{
if (pg_database_aclmask(db_oid, userid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
/*
* Exported routine for checking a user's access privileges to a function
*/
AclResult
pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode)
{
if (pg_proc_aclmask(proc_oid, userid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
/*
* Exported routine for checking a user's access privileges to a language
*/
AclResult
pg_language_aclcheck(Oid lang_oid, AclId userid, AclMode mode)
{
if (pg_language_aclmask(lang_oid, userid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
/*
* Exported routine for checking a user's access privileges to a namespace
*/
AclResult
pg_namespace_aclcheck(Oid nsp_oid, AclId userid, AclMode mode)
{
if (pg_namespace_aclmask(nsp_oid, userid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
/* /*
* Ownership check for a relation (specified by OID). * Ownership check for a relation (specified by OID).
*/ */
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.230 2004/03/23 19:35:16 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.231 2004/05/11 17:36:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -412,28 +412,13 @@ ExecCheckRTEPerms(RangeTblEntry *rte) ...@@ -412,28 +412,13 @@ ExecCheckRTEPerms(RangeTblEntry *rte)
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId(); userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
/* /*
* For each bit in requiredPerms, apply the required check. (We can't * We must have *all* the requiredPerms bits, so use aclmask not
* do this in one aclcheck call because aclcheck treats multiple bits * aclcheck.
* as OR semantics, when we want AND.)
*
* We use a well-known cute trick for isolating the rightmost one-bit
* in a nonzero word. See nodes/bitmapset.c for commentary.
*/ */
#define RIGHTMOST_ONE(x) ((int32) (x) & -((int32) (x))) if (pg_class_aclmask(relOid, userid, requiredPerms, ACLMASK_ALL)
!= requiredPerms)
while (requiredPerms != 0) aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_CLASS,
{ get_rel_name(relOid));
AclMode thisPerm;
AclResult aclcheck_result;
thisPerm = RIGHTMOST_ONE(requiredPerms);
requiredPerms &= ~thisPerm;
aclcheck_result = pg_class_aclcheck(relOid, userid, thisPerm);
if (aclcheck_result != ACLCHECK_OK)
aclcheck_error(aclcheck_result, ACL_KIND_CLASS,
get_rel_name(relOid));
}
} }
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.68 2004/05/02 13:38:28 momjian Exp $ * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.69 2004/05/11 17:36:13 tgl Exp $
* *
* NOTES * NOTES
* An ACL array is simply an array of AclItems, representing the union * An ACL array is simply an array of AclItems, representing the union
...@@ -177,6 +177,12 @@ typedef ArrayType IdList; ...@@ -177,6 +177,12 @@ typedef ArrayType IdList;
#define ACL_ALL_RIGHTS_LANGUAGE (ACL_USAGE) #define ACL_ALL_RIGHTS_LANGUAGE (ACL_USAGE)
#define ACL_ALL_RIGHTS_NAMESPACE (ACL_USAGE|ACL_CREATE) #define ACL_ALL_RIGHTS_NAMESPACE (ACL_USAGE|ACL_CREATE)
/* operation codes for pg_*_aclmask */
typedef enum
{
ACLMASK_ALL, /* normal case: compute all bits */
ACLMASK_ANY /* return when result is known nonzero */
} AclMaskHow;
/* result codes for pg_*_aclcheck */ /* result codes for pg_*_aclcheck */
typedef enum typedef enum
...@@ -228,6 +234,17 @@ extern void ExecuteGrantStmt(GrantStmt *stmt); ...@@ -228,6 +234,17 @@ extern void ExecuteGrantStmt(GrantStmt *stmt);
extern AclId get_grosysid(char *groname); extern AclId get_grosysid(char *groname);
extern char *get_groname(AclId grosysid); extern char *get_groname(AclId grosysid);
extern AclMode pg_class_aclmask(Oid table_oid, AclId userid,
AclMode mask, AclMaskHow how);
extern AclMode pg_database_aclmask(Oid db_oid, AclId userid,
AclMode mask, AclMaskHow how);
extern AclMode pg_proc_aclmask(Oid proc_oid, AclId userid,
AclMode mask, AclMaskHow how);
extern AclMode pg_language_aclmask(Oid lang_oid, AclId userid,
AclMode mask, AclMaskHow how);
extern AclMode pg_namespace_aclmask(Oid nsp_oid, AclId userid,
AclMode mask, AclMaskHow how);
extern AclResult pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode); extern AclResult pg_class_aclcheck(Oid table_oid, AclId userid, AclMode mode);
extern AclResult pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode); extern AclResult pg_database_aclcheck(Oid db_oid, AclId userid, AclMode mode);
extern AclResult pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode); extern AclResult pg_proc_aclcheck(Oid proc_oid, AclId userid, AclMode mode);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment