1 /*-------------------------------------------------------------------------
4 * Basic access control list data structures manipulation routines.
6 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.89 2003/06/24 23:14:45 momjian Exp $
13 *-------------------------------------------------------------------------
19 #include "catalog/namespace.h"
20 #include "catalog/pg_shadow.h"
21 #include "catalog/pg_type.h"
22 #include "commands/dbcommands.h"
23 #include "miscadmin.h"
24 #include "utils/acl.h"
25 #include "utils/builtins.h"
26 #include "utils/lsyscache.h"
27 #include "utils/syscache.h"
30 #define ACL_IDTYPE_GID_KEYWORD "group"
31 #define ACL_IDTYPE_UID_KEYWORD "user"
33 static const char *getid(const char *s, char *n);
34 static void putid(char *p, const char *s);
35 static Acl *allocacl(int n);
36 static const char *aclparse(const char *s, AclItem *aip);
37 static bool aclitemeq(const AclItem *a1, const AclItem *a2);
38 static Acl *recursive_revoke(Acl *acl, AclId grantee,
39 AclMode revoke_privs, DropBehavior behavior);
41 static AclMode convert_priv_string(text *priv_type_text);
43 static Oid convert_table_name(text *tablename);
44 static AclMode convert_table_priv_string(text *priv_type_text);
45 static Oid convert_database_name(text *databasename);
46 static AclMode convert_database_priv_string(text *priv_type_text);
47 static Oid convert_function_name(text *functionname);
48 static AclMode convert_function_priv_string(text *priv_type_text);
49 static Oid convert_language_name(text *languagename);
50 static AclMode convert_language_priv_string(text *priv_type_text);
51 static Oid convert_schema_name(text *schemaname);
52 static AclMode convert_schema_priv_string(text *priv_type_text);
57 * Consumes the first alphanumeric string (identifier) found in string
58 * 's', ignoring any leading white space. If it finds a double quote
59 * it returns the word inside the quotes.
62 * the string position in 's' that points to the next non-space character
63 * in 's', after any quotes. Also:
64 * - loads the identifier into 'name'. (If no identifier is found, 'name'
65 * contains an empty string.) name must be NAMEDATALEN bytes.
68 getid(const char *s, char *n)
71 bool in_quotes = false;
75 while (isspace((unsigned char) *s))
77 /* This test had better match what putid() does, below */
80 (isalnum((unsigned char) *s) ||
88 in_quotes = !in_quotes;
92 if (len >= NAMEDATALEN-1)
93 elog(ERROR, "identifier must be less than %d characters",
99 while (isspace((unsigned char) *s))
105 * Write a user or group Name at *p, surrounding it with double quotes if
106 * needed. There must be at least NAMEDATALEN+2 bytes available at *p.
109 putid(char *p, const char *s)
114 for (src = s; *src; src++)
116 /* This test had better match what getid() does, above */
117 if (!isalnum((unsigned char) *src) && *src != '_')
125 for (src = s; *src; src++)
134 * Consumes and parses an ACL specification of the form:
135 * [group|user] [A-Za-z0-9]*=[rwaR]*
136 * from string 's', ignoring any leading white space or white space
137 * between the optional id type keyword (group|user) and the actual
140 * This routine is called by the parser as well as aclitemin(), hence
141 * the added generality.
144 * the string position in 's' immediately following the ACL
145 * specification. Also:
146 * - loads the structure pointed to by 'aip' with the appropriate
147 * UID/GID, id type identifier and mode type values.
150 aclparse(const char *s, AclItem *aip)
152 AclMode privs, goption, read;
154 char name[NAMEDATALEN];
155 char name2[NAMEDATALEN];
160 elog(LOG, "aclparse: input = '%s'", s);
162 idtype = ACL_IDTYPE_UID;
166 /* we just read a keyword, not a name */
167 if (strncmp(name, ACL_IDTYPE_GID_KEYWORD, sizeof(name)) == 0)
168 idtype = ACL_IDTYPE_GID;
169 else if (strncmp(name, ACL_IDTYPE_UID_KEYWORD, sizeof(name)) != 0)
170 elog(ERROR, "aclparse: bad keyword, must be [group|user]");
171 s = getid(s, name); /* move s to the name beyond the keyword */
173 elog(ERROR, "aclparse: a name must follow the [group|user] keyword");
176 idtype = ACL_IDTYPE_WORLD;
179 elog(ERROR, "aclparse: expecting \"=\" sign");
181 privs = goption = ACL_NO_RIGHTS;
183 for (++s, read=0; isalpha((unsigned char) *s) || *s == '*'; s++)
205 case ACL_REFERENCES_CHR:
206 read = ACL_REFERENCES;
208 case ACL_TRIGGER_CHR:
211 case ACL_EXECUTE_CHR:
220 case ACL_CREATE_TEMP_CHR:
221 read = ACL_CREATE_TEMP;
224 elog(ERROR, "aclparse: mode flags must use \"%s\"",
234 aip->ai_grantee = get_usesysid(name);
237 aip->ai_grantee = get_grosysid(name);
239 case ACL_IDTYPE_WORLD:
240 aip->ai_grantee = ACL_ID_WORLD;
244 /* XXX Allow a degree of backward compatibility by defaulting the
245 * grantor to the superuser. */
248 s = getid(s + 1, name2);
249 if (name2[0] == '\0')
250 elog(ERROR, "aclparse: a name must follow the \"/\" sign");
252 aip->ai_grantor = get_usesysid(name2);
256 aip->ai_grantor = BOOTSTRAP_USESYSID;
257 elog(WARNING, "defaulting grantor to %u", BOOTSTRAP_USESYSID);
260 ACLITEM_SET_PRIVS_IDTYPE(*aip, privs, goption, idtype);
263 elog(LOG, "aclparse: correctly read [%x %d %x]",
264 idtype, aip->ai_grantee, privs);
271 * Allocates storage for a new Acl with 'n' entries.
283 elog(ERROR, "allocacl: invalid size: %d", n);
284 size = ACL_N_SIZE(n);
285 new_acl = (Acl *) palloc0(size);
286 new_acl->size = size;
289 new_acl->elemtype = ACLITEMOID;
290 ARR_LBOUND(new_acl)[0] = 0;
291 ARR_DIMS(new_acl)[0] = n;
297 * Allocates storage for, and fills in, a new AclItem given a string
298 * 's' that contains an ACL specification. See aclparse for details.
304 aclitemin(PG_FUNCTION_ARGS)
306 const char *s = PG_GETARG_CSTRING(0);
309 aip = (AclItem *) palloc(sizeof(AclItem));
310 s = aclparse(s, aip);
311 while (isspace((unsigned char) *s))
314 elog(ERROR, "aclitemin: extra garbage at end of specification");
315 PG_RETURN_ACLITEM_P(aip);
320 * Allocates storage for, and fills in, a new null-delimited string
321 * containing a formatted ACL specification. See aclparse for details.
327 aclitemout(PG_FUNCTION_ARGS)
329 AclItem *aip = PG_GETARG_ACLITEM_P(0);
336 out = palloc(strlen("group =/") +
338 2 * (NAMEDATALEN+2) +
344 switch (ACLITEM_GET_IDTYPE(*aip))
347 htup = SearchSysCache(SHADOWSYSID,
348 ObjectIdGetDatum(aip->ai_grantee),
350 if (HeapTupleIsValid(htup))
352 putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
353 ReleaseSysCache(htup);
357 /* Generate numeric UID if we don't find an entry */
358 sprintf(p, "%d", aip->ai_grantee);
364 tmpname = get_groname(aip->ai_grantee);
369 /* Generate numeric GID if we don't find an entry */
370 sprintf(p, "%d", aip->ai_grantee);
373 case ACL_IDTYPE_WORLD:
376 elog(ERROR, "aclitemout: bad idtype: %d",
377 ACLITEM_GET_IDTYPE(*aip));
385 for (i = 0; i < N_ACL_RIGHTS; ++i)
387 if (ACLITEM_GET_PRIVS(*aip) & (1 << i))
388 *p++ = ACL_ALL_RIGHTS_STR[i];
389 if (ACLITEM_GET_GOPTIONS(*aip) & (1 << i))
396 htup = SearchSysCache(SHADOWSYSID,
397 ObjectIdGetDatum(aip->ai_grantor),
399 if (HeapTupleIsValid(htup))
401 putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
402 ReleaseSysCache(htup);
406 /* Generate numeric UID if we don't find an entry */
407 sprintf(p, "%d", aip->ai_grantor);
414 PG_RETURN_CSTRING(out);
419 * Two AclItems are considered equal iff they have the same
420 * grantee and grantor; the privileges are ignored.
423 aclitemeq(const AclItem *a1, const AclItem *a2)
425 return ACLITEM_GET_IDTYPE(*a1) == ACLITEM_GET_IDTYPE(*a2) &&
426 a1->ai_grantee == a2->ai_grantee &&
427 a1->ai_grantor == a2->ai_grantor;
431 * user-facing version of aclitemeq() for use as the
432 * aclitem equality operator
435 aclitem_eq(PG_FUNCTION_ARGS)
437 PG_RETURN_BOOL(aclitemeq(PG_GETARG_ACLITEM_P(0), PG_GETARG_ACLITEM_P(1)));
441 * acldefault() --- create an ACL describing default access permissions
443 * Change this routine if you want to alter the default access policy for
444 * newly-created objects (or any object with a NULL acl entry).
447 acldefault(GrantObjectType objtype, AclId ownerid)
449 AclMode world_default;
450 AclMode owner_default;
456 case ACL_OBJECT_RELATION:
457 world_default = ACL_NO_RIGHTS;
458 owner_default = ACL_ALL_RIGHTS_RELATION;
460 case ACL_OBJECT_DATABASE:
461 world_default = ACL_CREATE_TEMP; /* not NO_RIGHTS! */
462 owner_default = ACL_ALL_RIGHTS_DATABASE;
464 case ACL_OBJECT_FUNCTION:
465 /* Grant EXECUTE by default, for now */
466 world_default = ACL_EXECUTE;
467 owner_default = ACL_ALL_RIGHTS_FUNCTION;
469 case ACL_OBJECT_LANGUAGE:
470 /* Grant USAGE by default, for now */
471 world_default = ACL_USAGE;
472 owner_default = ACL_ALL_RIGHTS_LANGUAGE;
474 case ACL_OBJECT_NAMESPACE:
475 world_default = ACL_NO_RIGHTS;
476 owner_default = ACL_ALL_RIGHTS_NAMESPACE;
479 elog(ERROR, "acldefault: bogus objtype %d", (int) objtype);
480 world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
481 owner_default = ACL_NO_RIGHTS;
485 acl = allocacl((world_default != ACL_NO_RIGHTS ? 1 : 0)
486 + (ownerid ? 1 : 0));
489 if (world_default != ACL_NO_RIGHTS)
491 aip[0].ai_grantee = ACL_ID_WORLD;
492 aip[0].ai_grantor = ownerid;
493 ACLITEM_SET_PRIVS_IDTYPE(aip[0], world_default, ACL_NO_RIGHTS, ACL_IDTYPE_WORLD);
498 int index = (world_default != ACL_NO_RIGHTS ? 1: 0);
500 aip[index].ai_grantee = ownerid;
501 aip[index].ai_grantor = ownerid;
502 /* owner gets default privileges with grant option */
503 ACLITEM_SET_PRIVS_IDTYPE(aip[index], owner_default, owner_default, ACL_IDTYPE_UID);
511 * Add or replace an item in an ACL array. The result is a modified copy;
512 * the input object is not changed.
514 * NB: caller is responsible for having detoasted the input ACL, if needed.
517 aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBehavior behavior)
525 /* These checks for null input are probably dead code, but... */
526 if (!old_acl || ACL_NUM(old_acl) < 1)
527 old_acl = allocacl(1);
530 new_acl = allocacl(ACL_NUM(old_acl));
531 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
535 num = ACL_NUM(old_acl);
536 old_aip = ACL_DAT(old_acl);
539 * Search the ACL for an existing entry for this grantee and
540 * grantor. If one exists, just modify the entry in-place (well,
541 * in the same position, since we actually return a copy);
542 * otherwise, insert the new entry at the end.
545 for (dst = 0; dst < num; ++dst)
547 if (aclitemeq(mod_aip, old_aip + dst))
549 /* found a match, so modify existing item */
550 new_acl = allocacl(num);
551 new_aip = ACL_DAT(new_acl);
552 memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
559 /* need to append a new item */
560 new_acl = allocacl(num + 1);
561 new_aip = ACL_DAT(new_acl);
562 memcpy(new_aip, old_aip, num * sizeof(AclItem));
564 /* initialize the new entry with no permissions */
565 new_aip[dst].ai_grantee = mod_aip->ai_grantee;
566 new_aip[dst].ai_grantor = mod_aip->ai_grantor;
567 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst], ACL_NO_RIGHTS, ACL_NO_RIGHTS,
568 ACLITEM_GET_IDTYPE(*mod_aip));
569 num++; /* set num to the size of new_acl */
572 /* apply the permissions mod */
575 case ACL_MODECHG_ADD:
576 ACLITEM_SET_PRIVS(new_aip[dst], ACLITEM_GET_PRIVS(new_aip[dst]) | ACLITEM_GET_PRIVS(*mod_aip));
577 ACLITEM_SET_GOPTIONS(new_aip[dst], ACLITEM_GET_GOPTIONS(new_aip[dst]) | ACLITEM_GET_GOPTIONS(*mod_aip));
579 case ACL_MODECHG_DEL:
580 ACLITEM_SET_PRIVS(new_aip[dst], ACLITEM_GET_PRIVS(new_aip[dst]) & ~ACLITEM_GET_PRIVS(*mod_aip));
581 ACLITEM_SET_GOPTIONS(new_aip[dst], ACLITEM_GET_GOPTIONS(new_aip[dst]) & ~ACLITEM_GET_GOPTIONS(*mod_aip));
583 case ACL_MODECHG_EQL:
584 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst],
585 ACLITEM_GET_PRIVS(*mod_aip),
586 ACLITEM_GET_GOPTIONS(*mod_aip),
587 ACLITEM_GET_IDTYPE(new_aip[dst]));
592 * If the adjusted entry has no permissions, delete it from the list.
594 if (ACLITEM_GET_PRIVS(new_aip[dst]) == ACL_NO_RIGHTS)
596 memmove(new_aip + dst,
598 (num - dst - 1) * sizeof(AclItem));
599 ARR_DIMS(new_acl)[0] = num - 1;
600 ARR_SIZE(new_acl) -= sizeof(AclItem);
604 * Remove abandoned privileges (cascading revoke)
606 if (modechg != ACL_MODECHG_ADD
607 && ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID
608 && ACLITEM_GET_GOPTIONS(*mod_aip))
609 new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee, ACLITEM_GET_GOPTIONS(*mod_aip), behavior);
616 * Ensure that no privilege is "abandoned". A privilege is abandoned
617 * if the user that granted the privilege loses the grant option. (So
618 * the chain through which it was granted is broken.) Either the
619 * abandoned privileges are revoked as well, or an error message is
620 * printed, depending on the drop behavior option.
623 recursive_revoke(Acl *acl,
625 AclMode revoke_privs,
626 DropBehavior behavior)
631 for (i = 0; i < ACL_NUM(acl); i++)
633 AclItem *aip = ACL_DAT(acl);
635 if (aip[i].ai_grantor == grantee
636 && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
640 if (behavior == DROP_RESTRICT)
641 elog(ERROR, "dependent privileges exist (use CASCADE to revoke them too)");
643 mod_acl.ai_grantor = grantee;
644 mod_acl.ai_grantee = aip[i].ai_grantee;
645 ACLITEM_SET_PRIVS_IDTYPE(mod_acl,
648 ACLITEM_GET_IDTYPE(aip[i]));
650 acl = aclinsert3(acl, &mod_acl, ACL_MODECHG_DEL, behavior);
660 * aclinsert (exported function)
663 aclinsert(PG_FUNCTION_ARGS)
665 Acl *old_acl = PG_GETARG_ACL_P(0);
666 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
668 PG_RETURN_ACL_P(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL, DROP_CASCADE));
672 aclremove(PG_FUNCTION_ARGS)
674 Acl *old_acl = PG_GETARG_ACL_P(0);
675 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
683 /* These checks for null input should be dead code, but... */
684 if (!old_acl || ACL_NUM(old_acl) < 1)
685 old_acl = allocacl(1);
688 new_acl = allocacl(ACL_NUM(old_acl));
689 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
690 PG_RETURN_ACL_P(new_acl);
693 old_num = ACL_NUM(old_acl);
694 old_aip = ACL_DAT(old_acl);
696 /* Search for the matching entry */
697 for (dst = 0; dst < old_num && !aclitemeq(mod_aip, old_aip + dst); ++dst)
702 /* Not found, so return copy of source ACL */
703 new_acl = allocacl(old_num);
704 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
708 new_num = old_num - 1;
709 new_acl = allocacl(new_num);
710 new_aip = ACL_DAT(new_acl);
713 elog(ERROR, "aclremove: removal of the world ACL??");
715 else if (dst == old_num - 1)
717 memcpy((char *) new_aip,
719 new_num * sizeof(AclItem));
723 memcpy((char *) new_aip,
725 dst * sizeof(AclItem));
726 memcpy((char *) (new_aip + dst),
727 (char *) (old_aip + dst + 1),
728 (new_num - dst) * sizeof(AclItem));
732 PG_RETURN_ACL_P(new_acl);
736 aclcontains(PG_FUNCTION_ARGS)
738 Acl *acl = PG_GETARG_ACL_P(0);
739 AclItem *aip = PG_GETARG_ACLITEM_P(1);
745 aidat = ACL_DAT(acl);
746 for (i = 0; i < num; ++i)
748 if (aip->ai_grantee == aidat[i].ai_grantee
749 && ACLITEM_GET_IDTYPE(*aip) == ACLITEM_GET_IDTYPE(aidat[i])
750 && aip->ai_grantor == aidat[i].ai_grantor
751 && (ACLITEM_GET_PRIVS(*aip) & ACLITEM_GET_PRIVS(aidat[i])) == ACLITEM_GET_PRIVS(*aip)
752 && (ACLITEM_GET_GOPTIONS(*aip) & ACLITEM_GET_GOPTIONS(aidat[i])) == ACLITEM_GET_GOPTIONS(*aip))
753 PG_RETURN_BOOL(true);
755 PG_RETURN_BOOL(false);
759 makeaclitem(PG_FUNCTION_ARGS)
761 int32 u_grantee = PG_GETARG_INT32(0);
762 int32 g_grantee = PG_GETARG_INT32(1);
763 int32 grantor = PG_GETARG_INT32(2);
764 text *privtext = PG_GETARG_TEXT_P(3);
765 bool goption = PG_GETARG_BOOL(4);
769 priv = convert_priv_string(privtext);
771 aclitem = (AclItem *) palloc(sizeof(*aclitem));
772 if (u_grantee == 0 && g_grantee == 0)
774 aclitem->ai_grantee = 0;
775 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_WORLD);
777 else if (u_grantee != 0 && g_grantee != 0)
779 elog(ERROR, "cannot specify both user and group");
781 else if (u_grantee != 0)
783 aclitem->ai_grantee = u_grantee;
784 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_UID);
786 else if (g_grantee != 0)
788 aclitem->ai_grantee = g_grantee;
789 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_GID);
792 aclitem->ai_grantor = grantor;
793 ACLITEM_SET_PRIVS(*aclitem, priv);
795 ACLITEM_SET_GOPTIONS(*aclitem, priv);
797 ACLITEM_SET_GOPTIONS(*aclitem, ACL_NO_RIGHTS);
799 PG_RETURN_ACLITEM_P(aclitem);
803 convert_priv_string(text *priv_type_text)
807 priv_type = DatumGetCString(DirectFunctionCall1(textout,
808 PointerGetDatum(priv_type_text)));
810 if (strcasecmp(priv_type, "SELECT") == 0)
812 if (strcasecmp(priv_type, "INSERT") == 0)
814 if (strcasecmp(priv_type, "UPDATE") == 0)
816 if (strcasecmp(priv_type, "DELETE") == 0)
818 if (strcasecmp(priv_type, "RULE") == 0)
820 if (strcasecmp(priv_type, "REFERENCES") == 0)
821 return ACL_REFERENCES;
822 if (strcasecmp(priv_type, "TRIGGER") == 0)
824 if (strcasecmp(priv_type, "EXECUTE") == 0)
826 if (strcasecmp(priv_type, "USAGE") == 0)
828 if (strcasecmp(priv_type, "CREATE") == 0)
830 if (strcasecmp(priv_type, "TEMP") == 0)
831 return ACL_CREATE_TEMP;
832 if (strcasecmp(priv_type, "TEMPORARY") == 0)
833 return ACL_CREATE_TEMP;
835 elog(ERROR, "invalid privilege type %s", priv_type);
836 return ACL_NO_RIGHTS; /* keep compiler quiet */
841 * has_table_privilege variants
842 * These are all named "has_table_privilege" at the SQL level.
843 * They take various combinations of relation name, relation OID,
844 * user name, user sysid, or implicit user = current_user.
846 * The result is a boolean value: true if user has the indicated
847 * privilege, false if not.
851 * has_table_privilege_name_name
852 * Check user privileges on a table given
853 * name username, text tablename, and text priv name.
856 has_table_privilege_name_name(PG_FUNCTION_ARGS)
858 Name username = PG_GETARG_NAME(0);
859 text *tablename = PG_GETARG_TEXT_P(1);
860 text *priv_type_text = PG_GETARG_TEXT_P(2);
866 usesysid = get_usesysid(NameStr(*username));
867 tableoid = convert_table_name(tablename);
868 mode = convert_table_priv_string(priv_type_text);
870 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
872 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
876 * has_table_privilege_name
877 * Check user privileges on a table given
878 * text tablename and text priv name.
879 * current_user is assumed
882 has_table_privilege_name(PG_FUNCTION_ARGS)
884 text *tablename = PG_GETARG_TEXT_P(0);
885 text *priv_type_text = PG_GETARG_TEXT_P(1);
891 usesysid = GetUserId();
892 tableoid = convert_table_name(tablename);
893 mode = convert_table_priv_string(priv_type_text);
895 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
897 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
901 * has_table_privilege_name_id
902 * Check user privileges on a table given
903 * name usename, table oid, and text priv name.
906 has_table_privilege_name_id(PG_FUNCTION_ARGS)
908 Name username = PG_GETARG_NAME(0);
909 Oid tableoid = PG_GETARG_OID(1);
910 text *priv_type_text = PG_GETARG_TEXT_P(2);
915 usesysid = get_usesysid(NameStr(*username));
916 mode = convert_table_priv_string(priv_type_text);
918 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
920 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
924 * has_table_privilege_id
925 * Check user privileges on a table given
926 * table oid, and text priv name.
927 * current_user is assumed
930 has_table_privilege_id(PG_FUNCTION_ARGS)
932 Oid tableoid = PG_GETARG_OID(0);
933 text *priv_type_text = PG_GETARG_TEXT_P(1);
938 usesysid = GetUserId();
939 mode = convert_table_priv_string(priv_type_text);
941 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
943 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
947 * has_table_privilege_id_name
948 * Check user privileges on a table given
949 * usesysid, text tablename, and text priv name.
952 has_table_privilege_id_name(PG_FUNCTION_ARGS)
954 int32 usesysid = PG_GETARG_INT32(0);
955 text *tablename = PG_GETARG_TEXT_P(1);
956 text *priv_type_text = PG_GETARG_TEXT_P(2);
961 tableoid = convert_table_name(tablename);
962 mode = convert_table_priv_string(priv_type_text);
964 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
966 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
970 * has_table_privilege_id_id
971 * Check user privileges on a table given
972 * usesysid, table oid, and text priv name.
975 has_table_privilege_id_id(PG_FUNCTION_ARGS)
977 int32 usesysid = PG_GETARG_INT32(0);
978 Oid tableoid = PG_GETARG_OID(1);
979 text *priv_type_text = PG_GETARG_TEXT_P(2);
983 mode = convert_table_priv_string(priv_type_text);
985 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
987 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
991 * Support routines for has_table_privilege family.
995 * Given a table name expressed as a string, look it up and return Oid
998 convert_table_name(text *tablename)
1002 relrv = makeRangeVarFromNameList(textToQualifiedNameList(tablename,
1003 "has_table_privilege"));
1005 return RangeVarGetRelid(relrv, false);
1009 * convert_table_priv_string
1010 * Convert text string to AclMode value.
1013 convert_table_priv_string(text *priv_type_text)
1017 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1018 PointerGetDatum(priv_type_text)));
1021 * Return mode from priv_type string
1023 if (strcasecmp(priv_type, "SELECT") == 0)
1025 if (strcasecmp(priv_type, "SELECT WITH GRANT OPTION") == 0)
1026 return ACL_GRANT_OPTION_FOR(ACL_SELECT);
1028 if (strcasecmp(priv_type, "INSERT") == 0)
1030 if (strcasecmp(priv_type, "INSERT WITH GRANT OPTION") == 0)
1031 return ACL_GRANT_OPTION_FOR(ACL_INSERT);
1033 if (strcasecmp(priv_type, "UPDATE") == 0)
1035 if (strcasecmp(priv_type, "UPDATE WITH GRANT OPTION") == 0)
1036 return ACL_GRANT_OPTION_FOR(ACL_UPDATE);
1038 if (strcasecmp(priv_type, "DELETE") == 0)
1040 if (strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0)
1041 return ACL_GRANT_OPTION_FOR(ACL_DELETE);
1043 if (strcasecmp(priv_type, "RULE") == 0)
1045 if (strcasecmp(priv_type, "RULE WITH GRANT OPTION") == 0)
1046 return ACL_GRANT_OPTION_FOR(ACL_RULE);
1048 if (strcasecmp(priv_type, "REFERENCES") == 0)
1049 return ACL_REFERENCES;
1050 if (strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0)
1051 return ACL_GRANT_OPTION_FOR(ACL_REFERENCES);
1053 if (strcasecmp(priv_type, "TRIGGER") == 0)
1055 if (strcasecmp(priv_type, "TRIGGER WITH GRANT OPTION") == 0)
1056 return ACL_GRANT_OPTION_FOR(ACL_TRIGGER);
1058 elog(ERROR, "has_table_privilege: invalid privilege type %s",
1060 return ACL_NO_RIGHTS; /* keep compiler quiet */
1065 * has_database_privilege variants
1066 * These are all named "has_database_privilege" at the SQL level.
1067 * They take various combinations of database name, database OID,
1068 * user name, user sysid, or implicit user = current_user.
1070 * The result is a boolean value: true if user has the indicated
1071 * privilege, false if not.
1075 * has_database_privilege_name_name
1076 * Check user privileges on a database given
1077 * name username, text databasename, and text priv name.
1080 has_database_privilege_name_name(PG_FUNCTION_ARGS)
1082 Name username = PG_GETARG_NAME(0);
1083 text *databasename = PG_GETARG_TEXT_P(1);
1084 text *priv_type_text = PG_GETARG_TEXT_P(2);
1088 AclResult aclresult;
1090 usesysid = get_usesysid(NameStr(*username));
1091 databaseoid = convert_database_name(databasename);
1092 mode = convert_database_priv_string(priv_type_text);
1094 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1096 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1100 * has_database_privilege_name
1101 * Check user privileges on a database given
1102 * text databasename and text priv name.
1103 * current_user is assumed
1106 has_database_privilege_name(PG_FUNCTION_ARGS)
1108 text *databasename = PG_GETARG_TEXT_P(0);
1109 text *priv_type_text = PG_GETARG_TEXT_P(1);
1113 AclResult aclresult;
1115 usesysid = GetUserId();
1116 databaseoid = convert_database_name(databasename);
1117 mode = convert_database_priv_string(priv_type_text);
1119 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1121 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1125 * has_database_privilege_name_id
1126 * Check user privileges on a database given
1127 * name usename, database oid, and text priv name.
1130 has_database_privilege_name_id(PG_FUNCTION_ARGS)
1132 Name username = PG_GETARG_NAME(0);
1133 Oid databaseoid = PG_GETARG_OID(1);
1134 text *priv_type_text = PG_GETARG_TEXT_P(2);
1137 AclResult aclresult;
1139 usesysid = get_usesysid(NameStr(*username));
1140 mode = convert_database_priv_string(priv_type_text);
1142 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1144 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1148 * has_database_privilege_id
1149 * Check user privileges on a database given
1150 * database oid, and text priv name.
1151 * current_user is assumed
1154 has_database_privilege_id(PG_FUNCTION_ARGS)
1156 Oid databaseoid = PG_GETARG_OID(0);
1157 text *priv_type_text = PG_GETARG_TEXT_P(1);
1160 AclResult aclresult;
1162 usesysid = GetUserId();
1163 mode = convert_database_priv_string(priv_type_text);
1165 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1167 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1171 * has_database_privilege_id_name
1172 * Check user privileges on a database given
1173 * usesysid, text databasename, and text priv name.
1176 has_database_privilege_id_name(PG_FUNCTION_ARGS)
1178 int32 usesysid = PG_GETARG_INT32(0);
1179 text *databasename = PG_GETARG_TEXT_P(1);
1180 text *priv_type_text = PG_GETARG_TEXT_P(2);
1183 AclResult aclresult;
1185 databaseoid = convert_database_name(databasename);
1186 mode = convert_database_priv_string(priv_type_text);
1188 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1190 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1194 * has_database_privilege_id_id
1195 * Check user privileges on a database given
1196 * usesysid, database oid, and text priv name.
1199 has_database_privilege_id_id(PG_FUNCTION_ARGS)
1201 int32 usesysid = PG_GETARG_INT32(0);
1202 Oid databaseoid = PG_GETARG_OID(1);
1203 text *priv_type_text = PG_GETARG_TEXT_P(2);
1205 AclResult aclresult;
1207 mode = convert_database_priv_string(priv_type_text);
1209 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1211 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1215 * Support routines for has_database_privilege family.
1219 * Given a database name expressed as a string, look it up and return Oid
1222 convert_database_name(text *databasename)
1227 dbname = DatumGetCString(DirectFunctionCall1(textout,
1228 PointerGetDatum(databasename)));
1230 oid = get_database_oid(dbname);
1231 if (!OidIsValid(oid))
1232 elog(ERROR, "database \"%s\" does not exist", dbname);
1238 * convert_database_priv_string
1239 * Convert text string to AclMode value.
1242 convert_database_priv_string(text *priv_type_text)
1246 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1247 PointerGetDatum(priv_type_text)));
1250 * Return mode from priv_type string
1252 if (strcasecmp(priv_type, "CREATE") == 0)
1254 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1255 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1257 if (strcasecmp(priv_type, "TEMPORARY") == 0)
1258 return ACL_CREATE_TEMP;
1259 if (strcasecmp(priv_type, "TEMPORARY WITH GRANT OPTION") == 0)
1260 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1262 if (strcasecmp(priv_type, "TEMP") == 0)
1263 return ACL_CREATE_TEMP;
1264 if (strcasecmp(priv_type, "TEMP WITH GRANT OPTION") == 0)
1265 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1267 elog(ERROR, "has_database_privilege: invalid privilege type %s",
1269 return ACL_NO_RIGHTS; /* keep compiler quiet */
1274 * has_function_privilege variants
1275 * These are all named "has_function_privilege" at the SQL level.
1276 * They take various combinations of function name, function OID,
1277 * user name, user sysid, or implicit user = current_user.
1279 * The result is a boolean value: true if user has the indicated
1280 * privilege, false if not.
1284 * has_function_privilege_name_name
1285 * Check user privileges on a function given
1286 * name username, text functionname, and text priv name.
1289 has_function_privilege_name_name(PG_FUNCTION_ARGS)
1291 Name username = PG_GETARG_NAME(0);
1292 text *functionname = PG_GETARG_TEXT_P(1);
1293 text *priv_type_text = PG_GETARG_TEXT_P(2);
1297 AclResult aclresult;
1299 usesysid = get_usesysid(NameStr(*username));
1300 functionoid = convert_function_name(functionname);
1301 mode = convert_function_priv_string(priv_type_text);
1303 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1305 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1309 * has_function_privilege_name
1310 * Check user privileges on a function given
1311 * text functionname and text priv name.
1312 * current_user is assumed
1315 has_function_privilege_name(PG_FUNCTION_ARGS)
1317 text *functionname = PG_GETARG_TEXT_P(0);
1318 text *priv_type_text = PG_GETARG_TEXT_P(1);
1322 AclResult aclresult;
1324 usesysid = GetUserId();
1325 functionoid = convert_function_name(functionname);
1326 mode = convert_function_priv_string(priv_type_text);
1328 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1330 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1334 * has_function_privilege_name_id
1335 * Check user privileges on a function given
1336 * name usename, function oid, and text priv name.
1339 has_function_privilege_name_id(PG_FUNCTION_ARGS)
1341 Name username = PG_GETARG_NAME(0);
1342 Oid functionoid = PG_GETARG_OID(1);
1343 text *priv_type_text = PG_GETARG_TEXT_P(2);
1346 AclResult aclresult;
1348 usesysid = get_usesysid(NameStr(*username));
1349 mode = convert_function_priv_string(priv_type_text);
1351 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1353 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1357 * has_function_privilege_id
1358 * Check user privileges on a function given
1359 * function oid, and text priv name.
1360 * current_user is assumed
1363 has_function_privilege_id(PG_FUNCTION_ARGS)
1365 Oid functionoid = PG_GETARG_OID(0);
1366 text *priv_type_text = PG_GETARG_TEXT_P(1);
1369 AclResult aclresult;
1371 usesysid = GetUserId();
1372 mode = convert_function_priv_string(priv_type_text);
1374 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1376 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1380 * has_function_privilege_id_name
1381 * Check user privileges on a function given
1382 * usesysid, text functionname, and text priv name.
1385 has_function_privilege_id_name(PG_FUNCTION_ARGS)
1387 int32 usesysid = PG_GETARG_INT32(0);
1388 text *functionname = PG_GETARG_TEXT_P(1);
1389 text *priv_type_text = PG_GETARG_TEXT_P(2);
1392 AclResult aclresult;
1394 functionoid = convert_function_name(functionname);
1395 mode = convert_function_priv_string(priv_type_text);
1397 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1399 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1403 * has_function_privilege_id_id
1404 * Check user privileges on a function given
1405 * usesysid, function oid, and text priv name.
1408 has_function_privilege_id_id(PG_FUNCTION_ARGS)
1410 int32 usesysid = PG_GETARG_INT32(0);
1411 Oid functionoid = PG_GETARG_OID(1);
1412 text *priv_type_text = PG_GETARG_TEXT_P(2);
1414 AclResult aclresult;
1416 mode = convert_function_priv_string(priv_type_text);
1418 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1420 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1424 * Support routines for has_function_privilege family.
1428 * Given a function name expressed as a string, look it up and return Oid
1431 convert_function_name(text *functionname)
1436 funcname = DatumGetCString(DirectFunctionCall1(textout,
1437 PointerGetDatum(functionname)));
1439 oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
1440 CStringGetDatum(funcname)));
1442 if (!OidIsValid(oid))
1443 elog(ERROR, "function \"%s\" does not exist", funcname);
1449 * convert_function_priv_string
1450 * Convert text string to AclMode value.
1453 convert_function_priv_string(text *priv_type_text)
1457 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1458 PointerGetDatum(priv_type_text)));
1461 * Return mode from priv_type string
1463 if (strcasecmp(priv_type, "EXECUTE") == 0)
1465 if (strcasecmp(priv_type, "EXECUTE WITH GRANT OPTION") == 0)
1466 return ACL_GRANT_OPTION_FOR(ACL_EXECUTE);
1468 elog(ERROR, "has_function_privilege: invalid privilege type %s",
1470 return ACL_NO_RIGHTS; /* keep compiler quiet */
1475 * has_language_privilege variants
1476 * These are all named "has_language_privilege" at the SQL level.
1477 * They take various combinations of language name, language OID,
1478 * user name, user sysid, or implicit user = current_user.
1480 * The result is a boolean value: true if user has the indicated
1481 * privilege, false if not.
1485 * has_language_privilege_name_name
1486 * Check user privileges on a language given
1487 * name username, text languagename, and text priv name.
1490 has_language_privilege_name_name(PG_FUNCTION_ARGS)
1492 Name username = PG_GETARG_NAME(0);
1493 text *languagename = PG_GETARG_TEXT_P(1);
1494 text *priv_type_text = PG_GETARG_TEXT_P(2);
1498 AclResult aclresult;
1500 usesysid = get_usesysid(NameStr(*username));
1501 languageoid = convert_language_name(languagename);
1502 mode = convert_language_priv_string(priv_type_text);
1504 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1506 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1510 * has_language_privilege_name
1511 * Check user privileges on a language given
1512 * text languagename and text priv name.
1513 * current_user is assumed
1516 has_language_privilege_name(PG_FUNCTION_ARGS)
1518 text *languagename = PG_GETARG_TEXT_P(0);
1519 text *priv_type_text = PG_GETARG_TEXT_P(1);
1523 AclResult aclresult;
1525 usesysid = GetUserId();
1526 languageoid = convert_language_name(languagename);
1527 mode = convert_language_priv_string(priv_type_text);
1529 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1531 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1535 * has_language_privilege_name_id
1536 * Check user privileges on a language given
1537 * name usename, language oid, and text priv name.
1540 has_language_privilege_name_id(PG_FUNCTION_ARGS)
1542 Name username = PG_GETARG_NAME(0);
1543 Oid languageoid = PG_GETARG_OID(1);
1544 text *priv_type_text = PG_GETARG_TEXT_P(2);
1547 AclResult aclresult;
1549 usesysid = get_usesysid(NameStr(*username));
1550 mode = convert_language_priv_string(priv_type_text);
1552 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1554 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1558 * has_language_privilege_id
1559 * Check user privileges on a language given
1560 * language oid, and text priv name.
1561 * current_user is assumed
1564 has_language_privilege_id(PG_FUNCTION_ARGS)
1566 Oid languageoid = PG_GETARG_OID(0);
1567 text *priv_type_text = PG_GETARG_TEXT_P(1);
1570 AclResult aclresult;
1572 usesysid = GetUserId();
1573 mode = convert_language_priv_string(priv_type_text);
1575 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1577 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1581 * has_language_privilege_id_name
1582 * Check user privileges on a language given
1583 * usesysid, text languagename, and text priv name.
1586 has_language_privilege_id_name(PG_FUNCTION_ARGS)
1588 int32 usesysid = PG_GETARG_INT32(0);
1589 text *languagename = PG_GETARG_TEXT_P(1);
1590 text *priv_type_text = PG_GETARG_TEXT_P(2);
1593 AclResult aclresult;
1595 languageoid = convert_language_name(languagename);
1596 mode = convert_language_priv_string(priv_type_text);
1598 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1600 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1604 * has_language_privilege_id_id
1605 * Check user privileges on a language given
1606 * usesysid, language oid, and text priv name.
1609 has_language_privilege_id_id(PG_FUNCTION_ARGS)
1611 int32 usesysid = PG_GETARG_INT32(0);
1612 Oid languageoid = PG_GETARG_OID(1);
1613 text *priv_type_text = PG_GETARG_TEXT_P(2);
1615 AclResult aclresult;
1617 mode = convert_language_priv_string(priv_type_text);
1619 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1621 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1625 * Support routines for has_language_privilege family.
1629 * Given a language name expressed as a string, look it up and return Oid
1632 convert_language_name(text *languagename)
1637 langname = DatumGetCString(DirectFunctionCall1(textout,
1638 PointerGetDatum(languagename)));
1640 oid = GetSysCacheOid(LANGNAME,
1641 CStringGetDatum(langname),
1643 if (!OidIsValid(oid))
1644 elog(ERROR, "language \"%s\" does not exist", langname);
1650 * convert_language_priv_string
1651 * Convert text string to AclMode value.
1654 convert_language_priv_string(text *priv_type_text)
1658 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1659 PointerGetDatum(priv_type_text)));
1662 * Return mode from priv_type string
1664 if (strcasecmp(priv_type, "USAGE") == 0)
1666 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1667 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1669 elog(ERROR, "has_language_privilege: invalid privilege type %s",
1671 return ACL_NO_RIGHTS; /* keep compiler quiet */
1676 * has_schema_privilege variants
1677 * These are all named "has_schema_privilege" at the SQL level.
1678 * They take various combinations of schema name, schema OID,
1679 * user name, user sysid, or implicit user = current_user.
1681 * The result is a boolean value: true if user has the indicated
1682 * privilege, false if not.
1686 * has_schema_privilege_name_name
1687 * Check user privileges on a schema given
1688 * name username, text schemaname, and text priv name.
1691 has_schema_privilege_name_name(PG_FUNCTION_ARGS)
1693 Name username = PG_GETARG_NAME(0);
1694 text *schemaname = PG_GETARG_TEXT_P(1);
1695 text *priv_type_text = PG_GETARG_TEXT_P(2);
1699 AclResult aclresult;
1701 usesysid = get_usesysid(NameStr(*username));
1702 schemaoid = convert_schema_name(schemaname);
1703 mode = convert_schema_priv_string(priv_type_text);
1705 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1707 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1711 * has_schema_privilege_name
1712 * Check user privileges on a schema given
1713 * text schemaname and text priv name.
1714 * current_user is assumed
1717 has_schema_privilege_name(PG_FUNCTION_ARGS)
1719 text *schemaname = PG_GETARG_TEXT_P(0);
1720 text *priv_type_text = PG_GETARG_TEXT_P(1);
1724 AclResult aclresult;
1726 usesysid = GetUserId();
1727 schemaoid = convert_schema_name(schemaname);
1728 mode = convert_schema_priv_string(priv_type_text);
1730 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1732 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1736 * has_schema_privilege_name_id
1737 * Check user privileges on a schema given
1738 * name usename, schema oid, and text priv name.
1741 has_schema_privilege_name_id(PG_FUNCTION_ARGS)
1743 Name username = PG_GETARG_NAME(0);
1744 Oid schemaoid = PG_GETARG_OID(1);
1745 text *priv_type_text = PG_GETARG_TEXT_P(2);
1748 AclResult aclresult;
1750 usesysid = get_usesysid(NameStr(*username));
1751 mode = convert_schema_priv_string(priv_type_text);
1753 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1755 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1759 * has_schema_privilege_id
1760 * Check user privileges on a schema given
1761 * schema oid, and text priv name.
1762 * current_user is assumed
1765 has_schema_privilege_id(PG_FUNCTION_ARGS)
1767 Oid schemaoid = PG_GETARG_OID(0);
1768 text *priv_type_text = PG_GETARG_TEXT_P(1);
1771 AclResult aclresult;
1773 usesysid = GetUserId();
1774 mode = convert_schema_priv_string(priv_type_text);
1776 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1778 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1782 * has_schema_privilege_id_name
1783 * Check user privileges on a schema given
1784 * usesysid, text schemaname, and text priv name.
1787 has_schema_privilege_id_name(PG_FUNCTION_ARGS)
1789 int32 usesysid = PG_GETARG_INT32(0);
1790 text *schemaname = PG_GETARG_TEXT_P(1);
1791 text *priv_type_text = PG_GETARG_TEXT_P(2);
1794 AclResult aclresult;
1796 schemaoid = convert_schema_name(schemaname);
1797 mode = convert_schema_priv_string(priv_type_text);
1799 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1801 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1805 * has_schema_privilege_id_id
1806 * Check user privileges on a schema given
1807 * usesysid, schema oid, and text priv name.
1810 has_schema_privilege_id_id(PG_FUNCTION_ARGS)
1812 int32 usesysid = PG_GETARG_INT32(0);
1813 Oid schemaoid = PG_GETARG_OID(1);
1814 text *priv_type_text = PG_GETARG_TEXT_P(2);
1816 AclResult aclresult;
1818 mode = convert_schema_priv_string(priv_type_text);
1820 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1822 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1826 * Support routines for has_schema_privilege family.
1830 * Given a schema name expressed as a string, look it up and return Oid
1833 convert_schema_name(text *schemaname)
1838 nspname = DatumGetCString(DirectFunctionCall1(textout,
1839 PointerGetDatum(schemaname)));
1841 oid = GetSysCacheOid(NAMESPACENAME,
1842 CStringGetDatum(nspname),
1844 if (!OidIsValid(oid))
1845 elog(ERROR, "schema \"%s\" does not exist", nspname);
1851 * convert_schema_priv_string
1852 * Convert text string to AclMode value.
1855 convert_schema_priv_string(text *priv_type_text)
1859 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1860 PointerGetDatum(priv_type_text)));
1863 * Return mode from priv_type string
1865 if (strcasecmp(priv_type, "CREATE") == 0)
1867 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1868 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1870 if (strcasecmp(priv_type, "USAGE") == 0)
1872 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1873 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1875 elog(ERROR, "has_schema_privilege: invalid privilege type %s",
1877 return ACL_NO_RIGHTS; /* keep compiler quiet */