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.91 2003/06/27 00:33:25 tgl 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 aclitem_match(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 to match iff they have the same
420 * grantee and grantor; the privileges are ignored.
423 aclitem_match(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 * aclitem equality operator
434 aclitem_eq(PG_FUNCTION_ARGS)
436 AclItem *a1 = PG_GETARG_ACLITEM_P(0);
437 AclItem *a2 = PG_GETARG_ACLITEM_P(1);
440 result = a1->ai_privs == a2->ai_privs &&
441 a1->ai_grantee == a2->ai_grantee &&
442 a1->ai_grantor == a2->ai_grantor;
443 PG_RETURN_BOOL(result);
447 * acldefault() --- create an ACL describing default access permissions
449 * Change this routine if you want to alter the default access policy for
450 * newly-created objects (or any object with a NULL acl entry).
453 acldefault(GrantObjectType objtype, AclId ownerid)
455 AclMode world_default;
456 AclMode owner_default;
462 case ACL_OBJECT_RELATION:
463 world_default = ACL_NO_RIGHTS;
464 owner_default = ACL_ALL_RIGHTS_RELATION;
466 case ACL_OBJECT_DATABASE:
467 world_default = ACL_CREATE_TEMP; /* not NO_RIGHTS! */
468 owner_default = ACL_ALL_RIGHTS_DATABASE;
470 case ACL_OBJECT_FUNCTION:
471 /* Grant EXECUTE by default, for now */
472 world_default = ACL_EXECUTE;
473 owner_default = ACL_ALL_RIGHTS_FUNCTION;
475 case ACL_OBJECT_LANGUAGE:
476 /* Grant USAGE by default, for now */
477 world_default = ACL_USAGE;
478 owner_default = ACL_ALL_RIGHTS_LANGUAGE;
480 case ACL_OBJECT_NAMESPACE:
481 world_default = ACL_NO_RIGHTS;
482 owner_default = ACL_ALL_RIGHTS_NAMESPACE;
485 elog(ERROR, "acldefault: bogus objtype %d", (int) objtype);
486 world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
487 owner_default = ACL_NO_RIGHTS;
491 acl = allocacl((world_default != ACL_NO_RIGHTS ? 1 : 0)
492 + (ownerid ? 1 : 0));
495 if (world_default != ACL_NO_RIGHTS)
497 aip[0].ai_grantee = ACL_ID_WORLD;
498 aip[0].ai_grantor = ownerid;
499 ACLITEM_SET_PRIVS_IDTYPE(aip[0], world_default, ACL_NO_RIGHTS, ACL_IDTYPE_WORLD);
504 int index = (world_default != ACL_NO_RIGHTS ? 1: 0);
506 aip[index].ai_grantee = ownerid;
507 aip[index].ai_grantor = ownerid;
508 /* owner gets default privileges with grant option */
509 ACLITEM_SET_PRIVS_IDTYPE(aip[index], owner_default, owner_default, ACL_IDTYPE_UID);
517 * Add or replace an item in an ACL array. The result is a modified copy;
518 * the input object is not changed.
520 * NB: caller is responsible for having detoasted the input ACL, if needed.
523 aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBehavior behavior)
531 /* These checks for null input are probably dead code, but... */
532 if (!old_acl || ACL_NUM(old_acl) < 1)
533 old_acl = allocacl(1);
536 new_acl = allocacl(ACL_NUM(old_acl));
537 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
541 num = ACL_NUM(old_acl);
542 old_aip = ACL_DAT(old_acl);
545 * Search the ACL for an existing entry for this grantee and
546 * grantor. If one exists, just modify the entry in-place (well,
547 * in the same position, since we actually return a copy);
548 * otherwise, insert the new entry at the end.
551 for (dst = 0; dst < num; ++dst)
553 if (aclitem_match(mod_aip, old_aip + dst))
555 /* found a match, so modify existing item */
556 new_acl = allocacl(num);
557 new_aip = ACL_DAT(new_acl);
558 memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
565 /* need to append a new item */
566 new_acl = allocacl(num + 1);
567 new_aip = ACL_DAT(new_acl);
568 memcpy(new_aip, old_aip, num * sizeof(AclItem));
570 /* initialize the new entry with no permissions */
571 new_aip[dst].ai_grantee = mod_aip->ai_grantee;
572 new_aip[dst].ai_grantor = mod_aip->ai_grantor;
573 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst], ACL_NO_RIGHTS, ACL_NO_RIGHTS,
574 ACLITEM_GET_IDTYPE(*mod_aip));
575 num++; /* set num to the size of new_acl */
578 /* apply the permissions mod */
581 case ACL_MODECHG_ADD:
582 ACLITEM_SET_PRIVS(new_aip[dst], ACLITEM_GET_PRIVS(new_aip[dst]) | ACLITEM_GET_PRIVS(*mod_aip));
583 ACLITEM_SET_GOPTIONS(new_aip[dst], ACLITEM_GET_GOPTIONS(new_aip[dst]) | ACLITEM_GET_GOPTIONS(*mod_aip));
585 case ACL_MODECHG_DEL:
586 ACLITEM_SET_PRIVS(new_aip[dst], ACLITEM_GET_PRIVS(new_aip[dst]) & ~ACLITEM_GET_PRIVS(*mod_aip));
587 ACLITEM_SET_GOPTIONS(new_aip[dst], ACLITEM_GET_GOPTIONS(new_aip[dst]) & ~ACLITEM_GET_GOPTIONS(*mod_aip));
589 case ACL_MODECHG_EQL:
590 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst],
591 ACLITEM_GET_PRIVS(*mod_aip),
592 ACLITEM_GET_GOPTIONS(*mod_aip),
593 ACLITEM_GET_IDTYPE(new_aip[dst]));
598 * If the adjusted entry has no permissions, delete it from the list.
600 if (ACLITEM_GET_PRIVS(new_aip[dst]) == ACL_NO_RIGHTS)
602 memmove(new_aip + dst,
604 (num - dst - 1) * sizeof(AclItem));
605 ARR_DIMS(new_acl)[0] = num - 1;
606 ARR_SIZE(new_acl) -= sizeof(AclItem);
610 * Remove abandoned privileges (cascading revoke)
612 if (modechg != ACL_MODECHG_ADD
613 && ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID
614 && ACLITEM_GET_GOPTIONS(*mod_aip))
615 new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee, ACLITEM_GET_GOPTIONS(*mod_aip), behavior);
622 * Ensure that no privilege is "abandoned". A privilege is abandoned
623 * if the user that granted the privilege loses the grant option. (So
624 * the chain through which it was granted is broken.) Either the
625 * abandoned privileges are revoked as well, or an error message is
626 * printed, depending on the drop behavior option.
629 recursive_revoke(Acl *acl,
631 AclMode revoke_privs,
632 DropBehavior behavior)
637 for (i = 0; i < ACL_NUM(acl); i++)
639 AclItem *aip = ACL_DAT(acl);
641 if (aip[i].ai_grantor == grantee
642 && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
646 if (behavior == DROP_RESTRICT)
647 elog(ERROR, "dependent privileges exist (use CASCADE to revoke them too)");
649 mod_acl.ai_grantor = grantee;
650 mod_acl.ai_grantee = aip[i].ai_grantee;
651 ACLITEM_SET_PRIVS_IDTYPE(mod_acl,
654 ACLITEM_GET_IDTYPE(aip[i]));
656 acl = aclinsert3(acl, &mod_acl, ACL_MODECHG_DEL, behavior);
666 * aclinsert (exported function)
669 aclinsert(PG_FUNCTION_ARGS)
671 Acl *old_acl = PG_GETARG_ACL_P(0);
672 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
674 PG_RETURN_ACL_P(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL, DROP_CASCADE));
678 aclremove(PG_FUNCTION_ARGS)
680 Acl *old_acl = PG_GETARG_ACL_P(0);
681 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
689 /* These checks for null input should be dead code, but... */
690 if (!old_acl || ACL_NUM(old_acl) < 1)
691 old_acl = allocacl(1);
694 new_acl = allocacl(ACL_NUM(old_acl));
695 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
696 PG_RETURN_ACL_P(new_acl);
699 old_num = ACL_NUM(old_acl);
700 old_aip = ACL_DAT(old_acl);
702 /* Search for the matching entry */
704 dst < old_num && !aclitem_match(mod_aip, old_aip + dst);
710 /* Not found, so return copy of source ACL */
711 new_acl = allocacl(old_num);
712 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
716 new_num = old_num - 1;
717 new_acl = allocacl(new_num);
718 new_aip = ACL_DAT(new_acl);
721 elog(ERROR, "aclremove: removal of the world ACL??");
723 else if (dst == old_num - 1)
725 memcpy((char *) new_aip,
727 new_num * sizeof(AclItem));
731 memcpy((char *) new_aip,
733 dst * sizeof(AclItem));
734 memcpy((char *) (new_aip + dst),
735 (char *) (old_aip + dst + 1),
736 (new_num - dst) * sizeof(AclItem));
740 PG_RETURN_ACL_P(new_acl);
744 aclcontains(PG_FUNCTION_ARGS)
746 Acl *acl = PG_GETARG_ACL_P(0);
747 AclItem *aip = PG_GETARG_ACLITEM_P(1);
753 aidat = ACL_DAT(acl);
754 for (i = 0; i < num; ++i)
756 if (aip->ai_grantee == aidat[i].ai_grantee
757 && ACLITEM_GET_IDTYPE(*aip) == ACLITEM_GET_IDTYPE(aidat[i])
758 && aip->ai_grantor == aidat[i].ai_grantor
759 && (ACLITEM_GET_PRIVS(*aip) & ACLITEM_GET_PRIVS(aidat[i])) == ACLITEM_GET_PRIVS(*aip)
760 && (ACLITEM_GET_GOPTIONS(*aip) & ACLITEM_GET_GOPTIONS(aidat[i])) == ACLITEM_GET_GOPTIONS(*aip))
761 PG_RETURN_BOOL(true);
763 PG_RETURN_BOOL(false);
767 makeaclitem(PG_FUNCTION_ARGS)
769 int32 u_grantee = PG_GETARG_INT32(0);
770 int32 g_grantee = PG_GETARG_INT32(1);
771 int32 grantor = PG_GETARG_INT32(2);
772 text *privtext = PG_GETARG_TEXT_P(3);
773 bool goption = PG_GETARG_BOOL(4);
777 priv = convert_priv_string(privtext);
779 aclitem = (AclItem *) palloc(sizeof(*aclitem));
780 if (u_grantee == 0 && g_grantee == 0)
782 aclitem->ai_grantee = 0;
783 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_WORLD);
785 else if (u_grantee != 0 && g_grantee != 0)
787 elog(ERROR, "cannot specify both user and group");
789 else if (u_grantee != 0)
791 aclitem->ai_grantee = u_grantee;
792 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_UID);
794 else if (g_grantee != 0)
796 aclitem->ai_grantee = g_grantee;
797 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_GID);
800 aclitem->ai_grantor = grantor;
801 ACLITEM_SET_PRIVS(*aclitem, priv);
803 ACLITEM_SET_GOPTIONS(*aclitem, priv);
805 ACLITEM_SET_GOPTIONS(*aclitem, ACL_NO_RIGHTS);
807 PG_RETURN_ACLITEM_P(aclitem);
811 convert_priv_string(text *priv_type_text)
815 priv_type = DatumGetCString(DirectFunctionCall1(textout,
816 PointerGetDatum(priv_type_text)));
818 if (strcasecmp(priv_type, "SELECT") == 0)
820 if (strcasecmp(priv_type, "INSERT") == 0)
822 if (strcasecmp(priv_type, "UPDATE") == 0)
824 if (strcasecmp(priv_type, "DELETE") == 0)
826 if (strcasecmp(priv_type, "RULE") == 0)
828 if (strcasecmp(priv_type, "REFERENCES") == 0)
829 return ACL_REFERENCES;
830 if (strcasecmp(priv_type, "TRIGGER") == 0)
832 if (strcasecmp(priv_type, "EXECUTE") == 0)
834 if (strcasecmp(priv_type, "USAGE") == 0)
836 if (strcasecmp(priv_type, "CREATE") == 0)
838 if (strcasecmp(priv_type, "TEMP") == 0)
839 return ACL_CREATE_TEMP;
840 if (strcasecmp(priv_type, "TEMPORARY") == 0)
841 return ACL_CREATE_TEMP;
843 elog(ERROR, "invalid privilege type %s", priv_type);
844 return ACL_NO_RIGHTS; /* keep compiler quiet */
849 * has_table_privilege variants
850 * These are all named "has_table_privilege" at the SQL level.
851 * They take various combinations of relation name, relation OID,
852 * user name, user sysid, or implicit user = current_user.
854 * The result is a boolean value: true if user has the indicated
855 * privilege, false if not.
859 * has_table_privilege_name_name
860 * Check user privileges on a table given
861 * name username, text tablename, and text priv name.
864 has_table_privilege_name_name(PG_FUNCTION_ARGS)
866 Name username = PG_GETARG_NAME(0);
867 text *tablename = PG_GETARG_TEXT_P(1);
868 text *priv_type_text = PG_GETARG_TEXT_P(2);
874 usesysid = get_usesysid(NameStr(*username));
875 tableoid = convert_table_name(tablename);
876 mode = convert_table_priv_string(priv_type_text);
878 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
880 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
884 * has_table_privilege_name
885 * Check user privileges on a table given
886 * text tablename and text priv name.
887 * current_user is assumed
890 has_table_privilege_name(PG_FUNCTION_ARGS)
892 text *tablename = PG_GETARG_TEXT_P(0);
893 text *priv_type_text = PG_GETARG_TEXT_P(1);
899 usesysid = GetUserId();
900 tableoid = convert_table_name(tablename);
901 mode = convert_table_priv_string(priv_type_text);
903 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
905 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
909 * has_table_privilege_name_id
910 * Check user privileges on a table given
911 * name usename, table oid, and text priv name.
914 has_table_privilege_name_id(PG_FUNCTION_ARGS)
916 Name username = PG_GETARG_NAME(0);
917 Oid tableoid = PG_GETARG_OID(1);
918 text *priv_type_text = PG_GETARG_TEXT_P(2);
923 usesysid = get_usesysid(NameStr(*username));
924 mode = convert_table_priv_string(priv_type_text);
926 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
928 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
932 * has_table_privilege_id
933 * Check user privileges on a table given
934 * table oid, and text priv name.
935 * current_user is assumed
938 has_table_privilege_id(PG_FUNCTION_ARGS)
940 Oid tableoid = PG_GETARG_OID(0);
941 text *priv_type_text = PG_GETARG_TEXT_P(1);
946 usesysid = GetUserId();
947 mode = convert_table_priv_string(priv_type_text);
949 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
951 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
955 * has_table_privilege_id_name
956 * Check user privileges on a table given
957 * usesysid, text tablename, and text priv name.
960 has_table_privilege_id_name(PG_FUNCTION_ARGS)
962 int32 usesysid = PG_GETARG_INT32(0);
963 text *tablename = PG_GETARG_TEXT_P(1);
964 text *priv_type_text = PG_GETARG_TEXT_P(2);
969 tableoid = convert_table_name(tablename);
970 mode = convert_table_priv_string(priv_type_text);
972 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
974 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
978 * has_table_privilege_id_id
979 * Check user privileges on a table given
980 * usesysid, table oid, and text priv name.
983 has_table_privilege_id_id(PG_FUNCTION_ARGS)
985 int32 usesysid = PG_GETARG_INT32(0);
986 Oid tableoid = PG_GETARG_OID(1);
987 text *priv_type_text = PG_GETARG_TEXT_P(2);
991 mode = convert_table_priv_string(priv_type_text);
993 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
995 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
999 * Support routines for has_table_privilege family.
1003 * Given a table name expressed as a string, look it up and return Oid
1006 convert_table_name(text *tablename)
1010 relrv = makeRangeVarFromNameList(textToQualifiedNameList(tablename,
1011 "has_table_privilege"));
1013 return RangeVarGetRelid(relrv, false);
1017 * convert_table_priv_string
1018 * Convert text string to AclMode value.
1021 convert_table_priv_string(text *priv_type_text)
1025 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1026 PointerGetDatum(priv_type_text)));
1029 * Return mode from priv_type string
1031 if (strcasecmp(priv_type, "SELECT") == 0)
1033 if (strcasecmp(priv_type, "SELECT WITH GRANT OPTION") == 0)
1034 return ACL_GRANT_OPTION_FOR(ACL_SELECT);
1036 if (strcasecmp(priv_type, "INSERT") == 0)
1038 if (strcasecmp(priv_type, "INSERT WITH GRANT OPTION") == 0)
1039 return ACL_GRANT_OPTION_FOR(ACL_INSERT);
1041 if (strcasecmp(priv_type, "UPDATE") == 0)
1043 if (strcasecmp(priv_type, "UPDATE WITH GRANT OPTION") == 0)
1044 return ACL_GRANT_OPTION_FOR(ACL_UPDATE);
1046 if (strcasecmp(priv_type, "DELETE") == 0)
1048 if (strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0)
1049 return ACL_GRANT_OPTION_FOR(ACL_DELETE);
1051 if (strcasecmp(priv_type, "RULE") == 0)
1053 if (strcasecmp(priv_type, "RULE WITH GRANT OPTION") == 0)
1054 return ACL_GRANT_OPTION_FOR(ACL_RULE);
1056 if (strcasecmp(priv_type, "REFERENCES") == 0)
1057 return ACL_REFERENCES;
1058 if (strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0)
1059 return ACL_GRANT_OPTION_FOR(ACL_REFERENCES);
1061 if (strcasecmp(priv_type, "TRIGGER") == 0)
1063 if (strcasecmp(priv_type, "TRIGGER WITH GRANT OPTION") == 0)
1064 return ACL_GRANT_OPTION_FOR(ACL_TRIGGER);
1066 elog(ERROR, "has_table_privilege: invalid privilege type %s",
1068 return ACL_NO_RIGHTS; /* keep compiler quiet */
1073 * has_database_privilege variants
1074 * These are all named "has_database_privilege" at the SQL level.
1075 * They take various combinations of database name, database OID,
1076 * user name, user sysid, or implicit user = current_user.
1078 * The result is a boolean value: true if user has the indicated
1079 * privilege, false if not.
1083 * has_database_privilege_name_name
1084 * Check user privileges on a database given
1085 * name username, text databasename, and text priv name.
1088 has_database_privilege_name_name(PG_FUNCTION_ARGS)
1090 Name username = PG_GETARG_NAME(0);
1091 text *databasename = PG_GETARG_TEXT_P(1);
1092 text *priv_type_text = PG_GETARG_TEXT_P(2);
1096 AclResult aclresult;
1098 usesysid = get_usesysid(NameStr(*username));
1099 databaseoid = convert_database_name(databasename);
1100 mode = convert_database_priv_string(priv_type_text);
1102 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1104 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1108 * has_database_privilege_name
1109 * Check user privileges on a database given
1110 * text databasename and text priv name.
1111 * current_user is assumed
1114 has_database_privilege_name(PG_FUNCTION_ARGS)
1116 text *databasename = PG_GETARG_TEXT_P(0);
1117 text *priv_type_text = PG_GETARG_TEXT_P(1);
1121 AclResult aclresult;
1123 usesysid = GetUserId();
1124 databaseoid = convert_database_name(databasename);
1125 mode = convert_database_priv_string(priv_type_text);
1127 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1129 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1133 * has_database_privilege_name_id
1134 * Check user privileges on a database given
1135 * name usename, database oid, and text priv name.
1138 has_database_privilege_name_id(PG_FUNCTION_ARGS)
1140 Name username = PG_GETARG_NAME(0);
1141 Oid databaseoid = PG_GETARG_OID(1);
1142 text *priv_type_text = PG_GETARG_TEXT_P(2);
1145 AclResult aclresult;
1147 usesysid = get_usesysid(NameStr(*username));
1148 mode = convert_database_priv_string(priv_type_text);
1150 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1152 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1156 * has_database_privilege_id
1157 * Check user privileges on a database given
1158 * database oid, and text priv name.
1159 * current_user is assumed
1162 has_database_privilege_id(PG_FUNCTION_ARGS)
1164 Oid databaseoid = PG_GETARG_OID(0);
1165 text *priv_type_text = PG_GETARG_TEXT_P(1);
1168 AclResult aclresult;
1170 usesysid = GetUserId();
1171 mode = convert_database_priv_string(priv_type_text);
1173 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1175 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1179 * has_database_privilege_id_name
1180 * Check user privileges on a database given
1181 * usesysid, text databasename, and text priv name.
1184 has_database_privilege_id_name(PG_FUNCTION_ARGS)
1186 int32 usesysid = PG_GETARG_INT32(0);
1187 text *databasename = PG_GETARG_TEXT_P(1);
1188 text *priv_type_text = PG_GETARG_TEXT_P(2);
1191 AclResult aclresult;
1193 databaseoid = convert_database_name(databasename);
1194 mode = convert_database_priv_string(priv_type_text);
1196 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1198 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1202 * has_database_privilege_id_id
1203 * Check user privileges on a database given
1204 * usesysid, database oid, and text priv name.
1207 has_database_privilege_id_id(PG_FUNCTION_ARGS)
1209 int32 usesysid = PG_GETARG_INT32(0);
1210 Oid databaseoid = PG_GETARG_OID(1);
1211 text *priv_type_text = PG_GETARG_TEXT_P(2);
1213 AclResult aclresult;
1215 mode = convert_database_priv_string(priv_type_text);
1217 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1219 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1223 * Support routines for has_database_privilege family.
1227 * Given a database name expressed as a string, look it up and return Oid
1230 convert_database_name(text *databasename)
1235 dbname = DatumGetCString(DirectFunctionCall1(textout,
1236 PointerGetDatum(databasename)));
1238 oid = get_database_oid(dbname);
1239 if (!OidIsValid(oid))
1240 elog(ERROR, "database \"%s\" does not exist", dbname);
1246 * convert_database_priv_string
1247 * Convert text string to AclMode value.
1250 convert_database_priv_string(text *priv_type_text)
1254 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1255 PointerGetDatum(priv_type_text)));
1258 * Return mode from priv_type string
1260 if (strcasecmp(priv_type, "CREATE") == 0)
1262 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1263 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1265 if (strcasecmp(priv_type, "TEMPORARY") == 0)
1266 return ACL_CREATE_TEMP;
1267 if (strcasecmp(priv_type, "TEMPORARY WITH GRANT OPTION") == 0)
1268 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1270 if (strcasecmp(priv_type, "TEMP") == 0)
1271 return ACL_CREATE_TEMP;
1272 if (strcasecmp(priv_type, "TEMP WITH GRANT OPTION") == 0)
1273 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1275 elog(ERROR, "has_database_privilege: invalid privilege type %s",
1277 return ACL_NO_RIGHTS; /* keep compiler quiet */
1282 * has_function_privilege variants
1283 * These are all named "has_function_privilege" at the SQL level.
1284 * They take various combinations of function name, function OID,
1285 * user name, user sysid, or implicit user = current_user.
1287 * The result is a boolean value: true if user has the indicated
1288 * privilege, false if not.
1292 * has_function_privilege_name_name
1293 * Check user privileges on a function given
1294 * name username, text functionname, and text priv name.
1297 has_function_privilege_name_name(PG_FUNCTION_ARGS)
1299 Name username = PG_GETARG_NAME(0);
1300 text *functionname = PG_GETARG_TEXT_P(1);
1301 text *priv_type_text = PG_GETARG_TEXT_P(2);
1305 AclResult aclresult;
1307 usesysid = get_usesysid(NameStr(*username));
1308 functionoid = convert_function_name(functionname);
1309 mode = convert_function_priv_string(priv_type_text);
1311 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1313 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1317 * has_function_privilege_name
1318 * Check user privileges on a function given
1319 * text functionname and text priv name.
1320 * current_user is assumed
1323 has_function_privilege_name(PG_FUNCTION_ARGS)
1325 text *functionname = PG_GETARG_TEXT_P(0);
1326 text *priv_type_text = PG_GETARG_TEXT_P(1);
1330 AclResult aclresult;
1332 usesysid = GetUserId();
1333 functionoid = convert_function_name(functionname);
1334 mode = convert_function_priv_string(priv_type_text);
1336 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1338 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1342 * has_function_privilege_name_id
1343 * Check user privileges on a function given
1344 * name usename, function oid, and text priv name.
1347 has_function_privilege_name_id(PG_FUNCTION_ARGS)
1349 Name username = PG_GETARG_NAME(0);
1350 Oid functionoid = PG_GETARG_OID(1);
1351 text *priv_type_text = PG_GETARG_TEXT_P(2);
1354 AclResult aclresult;
1356 usesysid = get_usesysid(NameStr(*username));
1357 mode = convert_function_priv_string(priv_type_text);
1359 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1361 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1365 * has_function_privilege_id
1366 * Check user privileges on a function given
1367 * function oid, and text priv name.
1368 * current_user is assumed
1371 has_function_privilege_id(PG_FUNCTION_ARGS)
1373 Oid functionoid = PG_GETARG_OID(0);
1374 text *priv_type_text = PG_GETARG_TEXT_P(1);
1377 AclResult aclresult;
1379 usesysid = GetUserId();
1380 mode = convert_function_priv_string(priv_type_text);
1382 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1384 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1388 * has_function_privilege_id_name
1389 * Check user privileges on a function given
1390 * usesysid, text functionname, and text priv name.
1393 has_function_privilege_id_name(PG_FUNCTION_ARGS)
1395 int32 usesysid = PG_GETARG_INT32(0);
1396 text *functionname = PG_GETARG_TEXT_P(1);
1397 text *priv_type_text = PG_GETARG_TEXT_P(2);
1400 AclResult aclresult;
1402 functionoid = convert_function_name(functionname);
1403 mode = convert_function_priv_string(priv_type_text);
1405 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1407 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1411 * has_function_privilege_id_id
1412 * Check user privileges on a function given
1413 * usesysid, function oid, and text priv name.
1416 has_function_privilege_id_id(PG_FUNCTION_ARGS)
1418 int32 usesysid = PG_GETARG_INT32(0);
1419 Oid functionoid = PG_GETARG_OID(1);
1420 text *priv_type_text = PG_GETARG_TEXT_P(2);
1422 AclResult aclresult;
1424 mode = convert_function_priv_string(priv_type_text);
1426 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1428 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1432 * Support routines for has_function_privilege family.
1436 * Given a function name expressed as a string, look it up and return Oid
1439 convert_function_name(text *functionname)
1444 funcname = DatumGetCString(DirectFunctionCall1(textout,
1445 PointerGetDatum(functionname)));
1447 oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
1448 CStringGetDatum(funcname)));
1450 if (!OidIsValid(oid))
1451 elog(ERROR, "function \"%s\" does not exist", funcname);
1457 * convert_function_priv_string
1458 * Convert text string to AclMode value.
1461 convert_function_priv_string(text *priv_type_text)
1465 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1466 PointerGetDatum(priv_type_text)));
1469 * Return mode from priv_type string
1471 if (strcasecmp(priv_type, "EXECUTE") == 0)
1473 if (strcasecmp(priv_type, "EXECUTE WITH GRANT OPTION") == 0)
1474 return ACL_GRANT_OPTION_FOR(ACL_EXECUTE);
1476 elog(ERROR, "has_function_privilege: invalid privilege type %s",
1478 return ACL_NO_RIGHTS; /* keep compiler quiet */
1483 * has_language_privilege variants
1484 * These are all named "has_language_privilege" at the SQL level.
1485 * They take various combinations of language name, language OID,
1486 * user name, user sysid, or implicit user = current_user.
1488 * The result is a boolean value: true if user has the indicated
1489 * privilege, false if not.
1493 * has_language_privilege_name_name
1494 * Check user privileges on a language given
1495 * name username, text languagename, and text priv name.
1498 has_language_privilege_name_name(PG_FUNCTION_ARGS)
1500 Name username = PG_GETARG_NAME(0);
1501 text *languagename = PG_GETARG_TEXT_P(1);
1502 text *priv_type_text = PG_GETARG_TEXT_P(2);
1506 AclResult aclresult;
1508 usesysid = get_usesysid(NameStr(*username));
1509 languageoid = convert_language_name(languagename);
1510 mode = convert_language_priv_string(priv_type_text);
1512 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1514 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1518 * has_language_privilege_name
1519 * Check user privileges on a language given
1520 * text languagename and text priv name.
1521 * current_user is assumed
1524 has_language_privilege_name(PG_FUNCTION_ARGS)
1526 text *languagename = PG_GETARG_TEXT_P(0);
1527 text *priv_type_text = PG_GETARG_TEXT_P(1);
1531 AclResult aclresult;
1533 usesysid = GetUserId();
1534 languageoid = convert_language_name(languagename);
1535 mode = convert_language_priv_string(priv_type_text);
1537 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1539 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1543 * has_language_privilege_name_id
1544 * Check user privileges on a language given
1545 * name usename, language oid, and text priv name.
1548 has_language_privilege_name_id(PG_FUNCTION_ARGS)
1550 Name username = PG_GETARG_NAME(0);
1551 Oid languageoid = PG_GETARG_OID(1);
1552 text *priv_type_text = PG_GETARG_TEXT_P(2);
1555 AclResult aclresult;
1557 usesysid = get_usesysid(NameStr(*username));
1558 mode = convert_language_priv_string(priv_type_text);
1560 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1562 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1566 * has_language_privilege_id
1567 * Check user privileges on a language given
1568 * language oid, and text priv name.
1569 * current_user is assumed
1572 has_language_privilege_id(PG_FUNCTION_ARGS)
1574 Oid languageoid = PG_GETARG_OID(0);
1575 text *priv_type_text = PG_GETARG_TEXT_P(1);
1578 AclResult aclresult;
1580 usesysid = GetUserId();
1581 mode = convert_language_priv_string(priv_type_text);
1583 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1585 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1589 * has_language_privilege_id_name
1590 * Check user privileges on a language given
1591 * usesysid, text languagename, and text priv name.
1594 has_language_privilege_id_name(PG_FUNCTION_ARGS)
1596 int32 usesysid = PG_GETARG_INT32(0);
1597 text *languagename = PG_GETARG_TEXT_P(1);
1598 text *priv_type_text = PG_GETARG_TEXT_P(2);
1601 AclResult aclresult;
1603 languageoid = convert_language_name(languagename);
1604 mode = convert_language_priv_string(priv_type_text);
1606 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1608 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1612 * has_language_privilege_id_id
1613 * Check user privileges on a language given
1614 * usesysid, language oid, and text priv name.
1617 has_language_privilege_id_id(PG_FUNCTION_ARGS)
1619 int32 usesysid = PG_GETARG_INT32(0);
1620 Oid languageoid = PG_GETARG_OID(1);
1621 text *priv_type_text = PG_GETARG_TEXT_P(2);
1623 AclResult aclresult;
1625 mode = convert_language_priv_string(priv_type_text);
1627 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1629 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1633 * Support routines for has_language_privilege family.
1637 * Given a language name expressed as a string, look it up and return Oid
1640 convert_language_name(text *languagename)
1645 langname = DatumGetCString(DirectFunctionCall1(textout,
1646 PointerGetDatum(languagename)));
1648 oid = GetSysCacheOid(LANGNAME,
1649 CStringGetDatum(langname),
1651 if (!OidIsValid(oid))
1652 elog(ERROR, "language \"%s\" does not exist", langname);
1658 * convert_language_priv_string
1659 * Convert text string to AclMode value.
1662 convert_language_priv_string(text *priv_type_text)
1666 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1667 PointerGetDatum(priv_type_text)));
1670 * Return mode from priv_type string
1672 if (strcasecmp(priv_type, "USAGE") == 0)
1674 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1675 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1677 elog(ERROR, "has_language_privilege: invalid privilege type %s",
1679 return ACL_NO_RIGHTS; /* keep compiler quiet */
1684 * has_schema_privilege variants
1685 * These are all named "has_schema_privilege" at the SQL level.
1686 * They take various combinations of schema name, schema OID,
1687 * user name, user sysid, or implicit user = current_user.
1689 * The result is a boolean value: true if user has the indicated
1690 * privilege, false if not.
1694 * has_schema_privilege_name_name
1695 * Check user privileges on a schema given
1696 * name username, text schemaname, and text priv name.
1699 has_schema_privilege_name_name(PG_FUNCTION_ARGS)
1701 Name username = PG_GETARG_NAME(0);
1702 text *schemaname = PG_GETARG_TEXT_P(1);
1703 text *priv_type_text = PG_GETARG_TEXT_P(2);
1707 AclResult aclresult;
1709 usesysid = get_usesysid(NameStr(*username));
1710 schemaoid = convert_schema_name(schemaname);
1711 mode = convert_schema_priv_string(priv_type_text);
1713 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1715 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1719 * has_schema_privilege_name
1720 * Check user privileges on a schema given
1721 * text schemaname and text priv name.
1722 * current_user is assumed
1725 has_schema_privilege_name(PG_FUNCTION_ARGS)
1727 text *schemaname = PG_GETARG_TEXT_P(0);
1728 text *priv_type_text = PG_GETARG_TEXT_P(1);
1732 AclResult aclresult;
1734 usesysid = GetUserId();
1735 schemaoid = convert_schema_name(schemaname);
1736 mode = convert_schema_priv_string(priv_type_text);
1738 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1740 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1744 * has_schema_privilege_name_id
1745 * Check user privileges on a schema given
1746 * name usename, schema oid, and text priv name.
1749 has_schema_privilege_name_id(PG_FUNCTION_ARGS)
1751 Name username = PG_GETARG_NAME(0);
1752 Oid schemaoid = PG_GETARG_OID(1);
1753 text *priv_type_text = PG_GETARG_TEXT_P(2);
1756 AclResult aclresult;
1758 usesysid = get_usesysid(NameStr(*username));
1759 mode = convert_schema_priv_string(priv_type_text);
1761 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1763 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1767 * has_schema_privilege_id
1768 * Check user privileges on a schema given
1769 * schema oid, and text priv name.
1770 * current_user is assumed
1773 has_schema_privilege_id(PG_FUNCTION_ARGS)
1775 Oid schemaoid = PG_GETARG_OID(0);
1776 text *priv_type_text = PG_GETARG_TEXT_P(1);
1779 AclResult aclresult;
1781 usesysid = GetUserId();
1782 mode = convert_schema_priv_string(priv_type_text);
1784 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1786 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1790 * has_schema_privilege_id_name
1791 * Check user privileges on a schema given
1792 * usesysid, text schemaname, and text priv name.
1795 has_schema_privilege_id_name(PG_FUNCTION_ARGS)
1797 int32 usesysid = PG_GETARG_INT32(0);
1798 text *schemaname = PG_GETARG_TEXT_P(1);
1799 text *priv_type_text = PG_GETARG_TEXT_P(2);
1802 AclResult aclresult;
1804 schemaoid = convert_schema_name(schemaname);
1805 mode = convert_schema_priv_string(priv_type_text);
1807 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1809 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1813 * has_schema_privilege_id_id
1814 * Check user privileges on a schema given
1815 * usesysid, schema oid, and text priv name.
1818 has_schema_privilege_id_id(PG_FUNCTION_ARGS)
1820 int32 usesysid = PG_GETARG_INT32(0);
1821 Oid schemaoid = PG_GETARG_OID(1);
1822 text *priv_type_text = PG_GETARG_TEXT_P(2);
1824 AclResult aclresult;
1826 mode = convert_schema_priv_string(priv_type_text);
1828 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1830 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1834 * Support routines for has_schema_privilege family.
1838 * Given a schema name expressed as a string, look it up and return Oid
1841 convert_schema_name(text *schemaname)
1846 nspname = DatumGetCString(DirectFunctionCall1(textout,
1847 PointerGetDatum(schemaname)));
1849 oid = GetSysCacheOid(NAMESPACENAME,
1850 CStringGetDatum(nspname),
1852 if (!OidIsValid(oid))
1853 elog(ERROR, "schema \"%s\" does not exist", nspname);
1859 * convert_schema_priv_string
1860 * Convert text string to AclMode value.
1863 convert_schema_priv_string(text *priv_type_text)
1867 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1868 PointerGetDatum(priv_type_text)));
1871 * Return mode from priv_type string
1873 if (strcasecmp(priv_type, "CREATE") == 0)
1875 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1876 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1878 if (strcasecmp(priv_type, "USAGE") == 0)
1880 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1881 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1883 elog(ERROR, "has_schema_privilege: invalid privilege type %s",
1885 return ACL_NO_RIGHTS; /* keep compiler quiet */