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.88 2003/06/11 09:23:55 petere 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;
432 * acldefault() --- create an ACL describing default access permissions
434 * Change this routine if you want to alter the default access policy for
435 * newly-created objects (or any object with a NULL acl entry).
438 acldefault(GrantObjectType objtype, AclId ownerid)
440 AclMode world_default;
441 AclMode owner_default;
447 case ACL_OBJECT_RELATION:
448 world_default = ACL_NO_RIGHTS;
449 owner_default = ACL_ALL_RIGHTS_RELATION;
451 case ACL_OBJECT_DATABASE:
452 world_default = ACL_CREATE_TEMP; /* not NO_RIGHTS! */
453 owner_default = ACL_ALL_RIGHTS_DATABASE;
455 case ACL_OBJECT_FUNCTION:
456 /* Grant EXECUTE by default, for now */
457 world_default = ACL_EXECUTE;
458 owner_default = ACL_ALL_RIGHTS_FUNCTION;
460 case ACL_OBJECT_LANGUAGE:
461 /* Grant USAGE by default, for now */
462 world_default = ACL_USAGE;
463 owner_default = ACL_ALL_RIGHTS_LANGUAGE;
465 case ACL_OBJECT_NAMESPACE:
466 world_default = ACL_NO_RIGHTS;
467 owner_default = ACL_ALL_RIGHTS_NAMESPACE;
470 elog(ERROR, "acldefault: bogus objtype %d", (int) objtype);
471 world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
472 owner_default = ACL_NO_RIGHTS;
476 acl = allocacl((world_default != ACL_NO_RIGHTS ? 1 : 0)
477 + (ownerid ? 1 : 0));
480 if (world_default != ACL_NO_RIGHTS)
482 aip[0].ai_grantee = ACL_ID_WORLD;
483 aip[0].ai_grantor = ownerid;
484 ACLITEM_SET_PRIVS_IDTYPE(aip[0], world_default, ACL_NO_RIGHTS, ACL_IDTYPE_WORLD);
489 int index = (world_default != ACL_NO_RIGHTS ? 1: 0);
491 aip[index].ai_grantee = ownerid;
492 aip[index].ai_grantor = ownerid;
493 /* owner gets default privileges with grant option */
494 ACLITEM_SET_PRIVS_IDTYPE(aip[index], owner_default, owner_default, ACL_IDTYPE_UID);
502 * Add or replace an item in an ACL array. The result is a modified copy;
503 * the input object is not changed.
505 * NB: caller is responsible for having detoasted the input ACL, if needed.
508 aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBehavior behavior)
516 /* These checks for null input are probably dead code, but... */
517 if (!old_acl || ACL_NUM(old_acl) < 1)
518 old_acl = allocacl(1);
521 new_acl = allocacl(ACL_NUM(old_acl));
522 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
526 num = ACL_NUM(old_acl);
527 old_aip = ACL_DAT(old_acl);
530 * Search the ACL for an existing entry for this grantee and
531 * grantor. If one exists, just modify the entry in-place (well,
532 * in the same position, since we actually return a copy);
533 * otherwise, insert the new entry at the end.
536 for (dst = 0; dst < num; ++dst)
538 if (aclitemeq(mod_aip, old_aip + dst))
540 /* found a match, so modify existing item */
541 new_acl = allocacl(num);
542 new_aip = ACL_DAT(new_acl);
543 memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
550 /* need to append a new item */
551 new_acl = allocacl(num + 1);
552 new_aip = ACL_DAT(new_acl);
553 memcpy(new_aip, old_aip, num * sizeof(AclItem));
555 /* initialize the new entry with no permissions */
556 new_aip[dst].ai_grantee = mod_aip->ai_grantee;
557 new_aip[dst].ai_grantor = mod_aip->ai_grantor;
558 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst], ACL_NO_RIGHTS, ACL_NO_RIGHTS,
559 ACLITEM_GET_IDTYPE(*mod_aip));
560 num++; /* set num to the size of new_acl */
563 /* apply the permissions mod */
566 case ACL_MODECHG_ADD:
567 ACLITEM_SET_PRIVS(new_aip[dst], ACLITEM_GET_PRIVS(new_aip[dst]) | ACLITEM_GET_PRIVS(*mod_aip));
568 ACLITEM_SET_GOPTIONS(new_aip[dst], ACLITEM_GET_GOPTIONS(new_aip[dst]) | ACLITEM_GET_GOPTIONS(*mod_aip));
570 case ACL_MODECHG_DEL:
571 ACLITEM_SET_PRIVS(new_aip[dst], ACLITEM_GET_PRIVS(new_aip[dst]) & ~ACLITEM_GET_PRIVS(*mod_aip));
572 ACLITEM_SET_GOPTIONS(new_aip[dst], ACLITEM_GET_GOPTIONS(new_aip[dst]) & ~ACLITEM_GET_GOPTIONS(*mod_aip));
574 case ACL_MODECHG_EQL:
575 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst],
576 ACLITEM_GET_PRIVS(*mod_aip),
577 ACLITEM_GET_GOPTIONS(*mod_aip),
578 ACLITEM_GET_IDTYPE(new_aip[dst]));
583 * If the adjusted entry has no permissions, delete it from the list.
585 if (ACLITEM_GET_PRIVS(new_aip[dst]) == ACL_NO_RIGHTS)
587 memmove(new_aip + dst,
589 (num - dst - 1) * sizeof(AclItem));
590 ARR_DIMS(new_acl)[0] = num - 1;
591 ARR_SIZE(new_acl) -= sizeof(AclItem);
595 * Remove abandoned privileges (cascading revoke)
597 if (modechg != ACL_MODECHG_ADD
598 && ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID
599 && ACLITEM_GET_GOPTIONS(*mod_aip))
600 new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee, ACLITEM_GET_GOPTIONS(*mod_aip), behavior);
607 * Ensure that no privilege is "abandoned". A privilege is abandoned
608 * if the user that granted the privilege loses the grant option. (So
609 * the chain through which it was granted is broken.) Either the
610 * abandoned privileges are revoked as well, or an error message is
611 * printed, depending on the drop behavior option.
614 recursive_revoke(Acl *acl,
616 AclMode revoke_privs,
617 DropBehavior behavior)
622 for (i = 0; i < ACL_NUM(acl); i++)
624 AclItem *aip = ACL_DAT(acl);
626 if (aip[i].ai_grantor == grantee
627 && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
631 if (behavior == DROP_RESTRICT)
632 elog(ERROR, "dependent privileges exist (use CASCADE to revoke them too)");
634 mod_acl.ai_grantor = grantee;
635 mod_acl.ai_grantee = aip[i].ai_grantee;
636 ACLITEM_SET_PRIVS_IDTYPE(mod_acl,
639 ACLITEM_GET_IDTYPE(aip[i]));
641 acl = aclinsert3(acl, &mod_acl, ACL_MODECHG_DEL, behavior);
651 * aclinsert (exported function)
654 aclinsert(PG_FUNCTION_ARGS)
656 Acl *old_acl = PG_GETARG_ACL_P(0);
657 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
659 PG_RETURN_ACL_P(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL, DROP_CASCADE));
663 aclremove(PG_FUNCTION_ARGS)
665 Acl *old_acl = PG_GETARG_ACL_P(0);
666 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
674 /* These checks for null input should be dead code, but... */
675 if (!old_acl || ACL_NUM(old_acl) < 1)
676 old_acl = allocacl(1);
679 new_acl = allocacl(ACL_NUM(old_acl));
680 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
681 PG_RETURN_ACL_P(new_acl);
684 old_num = ACL_NUM(old_acl);
685 old_aip = ACL_DAT(old_acl);
687 /* Search for the matching entry */
688 for (dst = 0; dst < old_num && !aclitemeq(mod_aip, old_aip + dst); ++dst)
693 /* Not found, so return copy of source ACL */
694 new_acl = allocacl(old_num);
695 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
699 new_num = old_num - 1;
700 new_acl = allocacl(new_num);
701 new_aip = ACL_DAT(new_acl);
704 elog(ERROR, "aclremove: removal of the world ACL??");
706 else if (dst == old_num - 1)
708 memcpy((char *) new_aip,
710 new_num * sizeof(AclItem));
714 memcpy((char *) new_aip,
716 dst * sizeof(AclItem));
717 memcpy((char *) (new_aip + dst),
718 (char *) (old_aip + dst + 1),
719 (new_num - dst) * sizeof(AclItem));
723 PG_RETURN_ACL_P(new_acl);
727 aclcontains(PG_FUNCTION_ARGS)
729 Acl *acl = PG_GETARG_ACL_P(0);
730 AclItem *aip = PG_GETARG_ACLITEM_P(1);
736 aidat = ACL_DAT(acl);
737 for (i = 0; i < num; ++i)
739 if (aip->ai_grantee == aidat[i].ai_grantee
740 && ACLITEM_GET_IDTYPE(*aip) == ACLITEM_GET_IDTYPE(aidat[i])
741 && aip->ai_grantor == aidat[i].ai_grantor
742 && (ACLITEM_GET_PRIVS(*aip) & ACLITEM_GET_PRIVS(aidat[i])) == ACLITEM_GET_PRIVS(*aip)
743 && (ACLITEM_GET_GOPTIONS(*aip) & ACLITEM_GET_GOPTIONS(aidat[i])) == ACLITEM_GET_GOPTIONS(*aip))
744 PG_RETURN_BOOL(true);
746 PG_RETURN_BOOL(false);
750 makeaclitem(PG_FUNCTION_ARGS)
752 int32 u_grantee = PG_GETARG_INT32(0);
753 int32 g_grantee = PG_GETARG_INT32(1);
754 int32 grantor = PG_GETARG_INT32(2);
755 text *privtext = PG_GETARG_TEXT_P(3);
756 bool goption = PG_GETARG_BOOL(4);
760 priv = convert_priv_string(privtext);
762 aclitem = (AclItem *) palloc(sizeof(*aclitem));
763 if (u_grantee == 0 && g_grantee == 0)
765 aclitem->ai_grantee = 0;
766 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_WORLD);
768 else if (u_grantee != 0 && g_grantee != 0)
770 elog(ERROR, "cannot specify both user and group");
772 else if (u_grantee != 0)
774 aclitem->ai_grantee = u_grantee;
775 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_UID);
777 else if (g_grantee != 0)
779 aclitem->ai_grantee = g_grantee;
780 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_GID);
783 aclitem->ai_grantor = grantor;
784 ACLITEM_SET_PRIVS(*aclitem, priv);
786 ACLITEM_SET_GOPTIONS(*aclitem, priv);
788 ACLITEM_SET_GOPTIONS(*aclitem, ACL_NO_RIGHTS);
790 PG_RETURN_ACLITEM_P(aclitem);
794 convert_priv_string(text *priv_type_text)
798 priv_type = DatumGetCString(DirectFunctionCall1(textout,
799 PointerGetDatum(priv_type_text)));
801 if (strcasecmp(priv_type, "SELECT") == 0)
803 if (strcasecmp(priv_type, "INSERT") == 0)
805 if (strcasecmp(priv_type, "UPDATE") == 0)
807 if (strcasecmp(priv_type, "DELETE") == 0)
809 if (strcasecmp(priv_type, "RULE") == 0)
811 if (strcasecmp(priv_type, "REFERENCES") == 0)
812 return ACL_REFERENCES;
813 if (strcasecmp(priv_type, "TRIGGER") == 0)
815 if (strcasecmp(priv_type, "EXECUTE") == 0)
817 if (strcasecmp(priv_type, "USAGE") == 0)
819 if (strcasecmp(priv_type, "CREATE") == 0)
821 if (strcasecmp(priv_type, "TEMP") == 0)
822 return ACL_CREATE_TEMP;
823 if (strcasecmp(priv_type, "TEMPORARY") == 0)
824 return ACL_CREATE_TEMP;
826 elog(ERROR, "invalid privilege type %s", priv_type);
827 return ACL_NO_RIGHTS; /* keep compiler quiet */
832 * has_table_privilege variants
833 * These are all named "has_table_privilege" at the SQL level.
834 * They take various combinations of relation name, relation OID,
835 * user name, user sysid, or implicit user = current_user.
837 * The result is a boolean value: true if user has the indicated
838 * privilege, false if not.
842 * has_table_privilege_name_name
843 * Check user privileges on a table given
844 * name username, text tablename, and text priv name.
847 has_table_privilege_name_name(PG_FUNCTION_ARGS)
849 Name username = PG_GETARG_NAME(0);
850 text *tablename = PG_GETARG_TEXT_P(1);
851 text *priv_type_text = PG_GETARG_TEXT_P(2);
857 usesysid = get_usesysid(NameStr(*username));
858 tableoid = convert_table_name(tablename);
859 mode = convert_table_priv_string(priv_type_text);
861 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
863 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
867 * has_table_privilege_name
868 * Check user privileges on a table given
869 * text tablename and text priv name.
870 * current_user is assumed
873 has_table_privilege_name(PG_FUNCTION_ARGS)
875 text *tablename = PG_GETARG_TEXT_P(0);
876 text *priv_type_text = PG_GETARG_TEXT_P(1);
882 usesysid = GetUserId();
883 tableoid = convert_table_name(tablename);
884 mode = convert_table_priv_string(priv_type_text);
886 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
888 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
892 * has_table_privilege_name_id
893 * Check user privileges on a table given
894 * name usename, table oid, and text priv name.
897 has_table_privilege_name_id(PG_FUNCTION_ARGS)
899 Name username = PG_GETARG_NAME(0);
900 Oid tableoid = PG_GETARG_OID(1);
901 text *priv_type_text = PG_GETARG_TEXT_P(2);
906 usesysid = get_usesysid(NameStr(*username));
907 mode = convert_table_priv_string(priv_type_text);
909 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
911 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
915 * has_table_privilege_id
916 * Check user privileges on a table given
917 * table oid, and text priv name.
918 * current_user is assumed
921 has_table_privilege_id(PG_FUNCTION_ARGS)
923 Oid tableoid = PG_GETARG_OID(0);
924 text *priv_type_text = PG_GETARG_TEXT_P(1);
929 usesysid = GetUserId();
930 mode = convert_table_priv_string(priv_type_text);
932 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
934 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
938 * has_table_privilege_id_name
939 * Check user privileges on a table given
940 * usesysid, text tablename, and text priv name.
943 has_table_privilege_id_name(PG_FUNCTION_ARGS)
945 int32 usesysid = PG_GETARG_INT32(0);
946 text *tablename = PG_GETARG_TEXT_P(1);
947 text *priv_type_text = PG_GETARG_TEXT_P(2);
952 tableoid = convert_table_name(tablename);
953 mode = convert_table_priv_string(priv_type_text);
955 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
957 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
961 * has_table_privilege_id_id
962 * Check user privileges on a table given
963 * usesysid, table oid, and text priv name.
966 has_table_privilege_id_id(PG_FUNCTION_ARGS)
968 int32 usesysid = PG_GETARG_INT32(0);
969 Oid tableoid = PG_GETARG_OID(1);
970 text *priv_type_text = PG_GETARG_TEXT_P(2);
974 mode = convert_table_priv_string(priv_type_text);
976 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
978 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
982 * Support routines for has_table_privilege family.
986 * Given a table name expressed as a string, look it up and return Oid
989 convert_table_name(text *tablename)
993 relrv = makeRangeVarFromNameList(textToQualifiedNameList(tablename,
994 "has_table_privilege"));
996 return RangeVarGetRelid(relrv, false);
1000 * convert_table_priv_string
1001 * Convert text string to AclMode value.
1004 convert_table_priv_string(text *priv_type_text)
1008 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1009 PointerGetDatum(priv_type_text)));
1012 * Return mode from priv_type string
1014 if (strcasecmp(priv_type, "SELECT") == 0)
1016 if (strcasecmp(priv_type, "SELECT WITH GRANT OPTION") == 0)
1017 return ACL_GRANT_OPTION_FOR(ACL_SELECT);
1019 if (strcasecmp(priv_type, "INSERT") == 0)
1021 if (strcasecmp(priv_type, "INSERT WITH GRANT OPTION") == 0)
1022 return ACL_GRANT_OPTION_FOR(ACL_INSERT);
1024 if (strcasecmp(priv_type, "UPDATE") == 0)
1026 if (strcasecmp(priv_type, "UPDATE WITH GRANT OPTION") == 0)
1027 return ACL_GRANT_OPTION_FOR(ACL_UPDATE);
1029 if (strcasecmp(priv_type, "DELETE") == 0)
1031 if (strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0)
1032 return ACL_GRANT_OPTION_FOR(ACL_DELETE);
1034 if (strcasecmp(priv_type, "RULE") == 0)
1036 if (strcasecmp(priv_type, "RULE WITH GRANT OPTION") == 0)
1037 return ACL_GRANT_OPTION_FOR(ACL_RULE);
1039 if (strcasecmp(priv_type, "REFERENCES") == 0)
1040 return ACL_REFERENCES;
1041 if (strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0)
1042 return ACL_GRANT_OPTION_FOR(ACL_REFERENCES);
1044 if (strcasecmp(priv_type, "TRIGGER") == 0)
1046 if (strcasecmp(priv_type, "TRIGGER WITH GRANT OPTION") == 0)
1047 return ACL_GRANT_OPTION_FOR(ACL_TRIGGER);
1049 elog(ERROR, "has_table_privilege: invalid privilege type %s",
1051 return ACL_NO_RIGHTS; /* keep compiler quiet */
1056 * has_database_privilege variants
1057 * These are all named "has_database_privilege" at the SQL level.
1058 * They take various combinations of database name, database OID,
1059 * user name, user sysid, or implicit user = current_user.
1061 * The result is a boolean value: true if user has the indicated
1062 * privilege, false if not.
1066 * has_database_privilege_name_name
1067 * Check user privileges on a database given
1068 * name username, text databasename, and text priv name.
1071 has_database_privilege_name_name(PG_FUNCTION_ARGS)
1073 Name username = PG_GETARG_NAME(0);
1074 text *databasename = PG_GETARG_TEXT_P(1);
1075 text *priv_type_text = PG_GETARG_TEXT_P(2);
1079 AclResult aclresult;
1081 usesysid = get_usesysid(NameStr(*username));
1082 databaseoid = convert_database_name(databasename);
1083 mode = convert_database_priv_string(priv_type_text);
1085 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1087 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1091 * has_database_privilege_name
1092 * Check user privileges on a database given
1093 * text databasename and text priv name.
1094 * current_user is assumed
1097 has_database_privilege_name(PG_FUNCTION_ARGS)
1099 text *databasename = PG_GETARG_TEXT_P(0);
1100 text *priv_type_text = PG_GETARG_TEXT_P(1);
1104 AclResult aclresult;
1106 usesysid = GetUserId();
1107 databaseoid = convert_database_name(databasename);
1108 mode = convert_database_priv_string(priv_type_text);
1110 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1112 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1116 * has_database_privilege_name_id
1117 * Check user privileges on a database given
1118 * name usename, database oid, and text priv name.
1121 has_database_privilege_name_id(PG_FUNCTION_ARGS)
1123 Name username = PG_GETARG_NAME(0);
1124 Oid databaseoid = PG_GETARG_OID(1);
1125 text *priv_type_text = PG_GETARG_TEXT_P(2);
1128 AclResult aclresult;
1130 usesysid = get_usesysid(NameStr(*username));
1131 mode = convert_database_priv_string(priv_type_text);
1133 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1135 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1139 * has_database_privilege_id
1140 * Check user privileges on a database given
1141 * database oid, and text priv name.
1142 * current_user is assumed
1145 has_database_privilege_id(PG_FUNCTION_ARGS)
1147 Oid databaseoid = PG_GETARG_OID(0);
1148 text *priv_type_text = PG_GETARG_TEXT_P(1);
1151 AclResult aclresult;
1153 usesysid = GetUserId();
1154 mode = convert_database_priv_string(priv_type_text);
1156 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1158 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1162 * has_database_privilege_id_name
1163 * Check user privileges on a database given
1164 * usesysid, text databasename, and text priv name.
1167 has_database_privilege_id_name(PG_FUNCTION_ARGS)
1169 int32 usesysid = PG_GETARG_INT32(0);
1170 text *databasename = PG_GETARG_TEXT_P(1);
1171 text *priv_type_text = PG_GETARG_TEXT_P(2);
1174 AclResult aclresult;
1176 databaseoid = convert_database_name(databasename);
1177 mode = convert_database_priv_string(priv_type_text);
1179 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1181 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1185 * has_database_privilege_id_id
1186 * Check user privileges on a database given
1187 * usesysid, database oid, and text priv name.
1190 has_database_privilege_id_id(PG_FUNCTION_ARGS)
1192 int32 usesysid = PG_GETARG_INT32(0);
1193 Oid databaseoid = PG_GETARG_OID(1);
1194 text *priv_type_text = PG_GETARG_TEXT_P(2);
1196 AclResult aclresult;
1198 mode = convert_database_priv_string(priv_type_text);
1200 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1202 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1206 * Support routines for has_database_privilege family.
1210 * Given a database name expressed as a string, look it up and return Oid
1213 convert_database_name(text *databasename)
1218 dbname = DatumGetCString(DirectFunctionCall1(textout,
1219 PointerGetDatum(databasename)));
1221 oid = get_database_oid(dbname);
1222 if (!OidIsValid(oid))
1223 elog(ERROR, "database \"%s\" does not exist", dbname);
1229 * convert_database_priv_string
1230 * Convert text string to AclMode value.
1233 convert_database_priv_string(text *priv_type_text)
1237 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1238 PointerGetDatum(priv_type_text)));
1241 * Return mode from priv_type string
1243 if (strcasecmp(priv_type, "CREATE") == 0)
1245 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1246 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1248 if (strcasecmp(priv_type, "TEMPORARY") == 0)
1249 return ACL_CREATE_TEMP;
1250 if (strcasecmp(priv_type, "TEMPORARY WITH GRANT OPTION") == 0)
1251 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1253 if (strcasecmp(priv_type, "TEMP") == 0)
1254 return ACL_CREATE_TEMP;
1255 if (strcasecmp(priv_type, "TEMP WITH GRANT OPTION") == 0)
1256 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1258 elog(ERROR, "has_database_privilege: invalid privilege type %s",
1260 return ACL_NO_RIGHTS; /* keep compiler quiet */
1265 * has_function_privilege variants
1266 * These are all named "has_function_privilege" at the SQL level.
1267 * They take various combinations of function name, function OID,
1268 * user name, user sysid, or implicit user = current_user.
1270 * The result is a boolean value: true if user has the indicated
1271 * privilege, false if not.
1275 * has_function_privilege_name_name
1276 * Check user privileges on a function given
1277 * name username, text functionname, and text priv name.
1280 has_function_privilege_name_name(PG_FUNCTION_ARGS)
1282 Name username = PG_GETARG_NAME(0);
1283 text *functionname = PG_GETARG_TEXT_P(1);
1284 text *priv_type_text = PG_GETARG_TEXT_P(2);
1288 AclResult aclresult;
1290 usesysid = get_usesysid(NameStr(*username));
1291 functionoid = convert_function_name(functionname);
1292 mode = convert_function_priv_string(priv_type_text);
1294 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1296 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1300 * has_function_privilege_name
1301 * Check user privileges on a function given
1302 * text functionname and text priv name.
1303 * current_user is assumed
1306 has_function_privilege_name(PG_FUNCTION_ARGS)
1308 text *functionname = PG_GETARG_TEXT_P(0);
1309 text *priv_type_text = PG_GETARG_TEXT_P(1);
1313 AclResult aclresult;
1315 usesysid = GetUserId();
1316 functionoid = convert_function_name(functionname);
1317 mode = convert_function_priv_string(priv_type_text);
1319 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1321 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1325 * has_function_privilege_name_id
1326 * Check user privileges on a function given
1327 * name usename, function oid, and text priv name.
1330 has_function_privilege_name_id(PG_FUNCTION_ARGS)
1332 Name username = PG_GETARG_NAME(0);
1333 Oid functionoid = PG_GETARG_OID(1);
1334 text *priv_type_text = PG_GETARG_TEXT_P(2);
1337 AclResult aclresult;
1339 usesysid = get_usesysid(NameStr(*username));
1340 mode = convert_function_priv_string(priv_type_text);
1342 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1344 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1348 * has_function_privilege_id
1349 * Check user privileges on a function given
1350 * function oid, and text priv name.
1351 * current_user is assumed
1354 has_function_privilege_id(PG_FUNCTION_ARGS)
1356 Oid functionoid = PG_GETARG_OID(0);
1357 text *priv_type_text = PG_GETARG_TEXT_P(1);
1360 AclResult aclresult;
1362 usesysid = GetUserId();
1363 mode = convert_function_priv_string(priv_type_text);
1365 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1367 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1371 * has_function_privilege_id_name
1372 * Check user privileges on a function given
1373 * usesysid, text functionname, and text priv name.
1376 has_function_privilege_id_name(PG_FUNCTION_ARGS)
1378 int32 usesysid = PG_GETARG_INT32(0);
1379 text *functionname = PG_GETARG_TEXT_P(1);
1380 text *priv_type_text = PG_GETARG_TEXT_P(2);
1383 AclResult aclresult;
1385 functionoid = convert_function_name(functionname);
1386 mode = convert_function_priv_string(priv_type_text);
1388 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1390 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1394 * has_function_privilege_id_id
1395 * Check user privileges on a function given
1396 * usesysid, function oid, and text priv name.
1399 has_function_privilege_id_id(PG_FUNCTION_ARGS)
1401 int32 usesysid = PG_GETARG_INT32(0);
1402 Oid functionoid = PG_GETARG_OID(1);
1403 text *priv_type_text = PG_GETARG_TEXT_P(2);
1405 AclResult aclresult;
1407 mode = convert_function_priv_string(priv_type_text);
1409 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1411 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1415 * Support routines for has_function_privilege family.
1419 * Given a function name expressed as a string, look it up and return Oid
1422 convert_function_name(text *functionname)
1427 funcname = DatumGetCString(DirectFunctionCall1(textout,
1428 PointerGetDatum(functionname)));
1430 oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
1431 CStringGetDatum(funcname)));
1433 if (!OidIsValid(oid))
1434 elog(ERROR, "function \"%s\" does not exist", funcname);
1440 * convert_function_priv_string
1441 * Convert text string to AclMode value.
1444 convert_function_priv_string(text *priv_type_text)
1448 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1449 PointerGetDatum(priv_type_text)));
1452 * Return mode from priv_type string
1454 if (strcasecmp(priv_type, "EXECUTE") == 0)
1456 if (strcasecmp(priv_type, "EXECUTE WITH GRANT OPTION") == 0)
1457 return ACL_GRANT_OPTION_FOR(ACL_EXECUTE);
1459 elog(ERROR, "has_function_privilege: invalid privilege type %s",
1461 return ACL_NO_RIGHTS; /* keep compiler quiet */
1466 * has_language_privilege variants
1467 * These are all named "has_language_privilege" at the SQL level.
1468 * They take various combinations of language name, language OID,
1469 * user name, user sysid, or implicit user = current_user.
1471 * The result is a boolean value: true if user has the indicated
1472 * privilege, false if not.
1476 * has_language_privilege_name_name
1477 * Check user privileges on a language given
1478 * name username, text languagename, and text priv name.
1481 has_language_privilege_name_name(PG_FUNCTION_ARGS)
1483 Name username = PG_GETARG_NAME(0);
1484 text *languagename = PG_GETARG_TEXT_P(1);
1485 text *priv_type_text = PG_GETARG_TEXT_P(2);
1489 AclResult aclresult;
1491 usesysid = get_usesysid(NameStr(*username));
1492 languageoid = convert_language_name(languagename);
1493 mode = convert_language_priv_string(priv_type_text);
1495 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1497 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1501 * has_language_privilege_name
1502 * Check user privileges on a language given
1503 * text languagename and text priv name.
1504 * current_user is assumed
1507 has_language_privilege_name(PG_FUNCTION_ARGS)
1509 text *languagename = PG_GETARG_TEXT_P(0);
1510 text *priv_type_text = PG_GETARG_TEXT_P(1);
1514 AclResult aclresult;
1516 usesysid = GetUserId();
1517 languageoid = convert_language_name(languagename);
1518 mode = convert_language_priv_string(priv_type_text);
1520 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1522 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1526 * has_language_privilege_name_id
1527 * Check user privileges on a language given
1528 * name usename, language oid, and text priv name.
1531 has_language_privilege_name_id(PG_FUNCTION_ARGS)
1533 Name username = PG_GETARG_NAME(0);
1534 Oid languageoid = PG_GETARG_OID(1);
1535 text *priv_type_text = PG_GETARG_TEXT_P(2);
1538 AclResult aclresult;
1540 usesysid = get_usesysid(NameStr(*username));
1541 mode = convert_language_priv_string(priv_type_text);
1543 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1545 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1549 * has_language_privilege_id
1550 * Check user privileges on a language given
1551 * language oid, and text priv name.
1552 * current_user is assumed
1555 has_language_privilege_id(PG_FUNCTION_ARGS)
1557 Oid languageoid = PG_GETARG_OID(0);
1558 text *priv_type_text = PG_GETARG_TEXT_P(1);
1561 AclResult aclresult;
1563 usesysid = GetUserId();
1564 mode = convert_language_priv_string(priv_type_text);
1566 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1568 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1572 * has_language_privilege_id_name
1573 * Check user privileges on a language given
1574 * usesysid, text languagename, and text priv name.
1577 has_language_privilege_id_name(PG_FUNCTION_ARGS)
1579 int32 usesysid = PG_GETARG_INT32(0);
1580 text *languagename = PG_GETARG_TEXT_P(1);
1581 text *priv_type_text = PG_GETARG_TEXT_P(2);
1584 AclResult aclresult;
1586 languageoid = convert_language_name(languagename);
1587 mode = convert_language_priv_string(priv_type_text);
1589 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1591 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1595 * has_language_privilege_id_id
1596 * Check user privileges on a language given
1597 * usesysid, language oid, and text priv name.
1600 has_language_privilege_id_id(PG_FUNCTION_ARGS)
1602 int32 usesysid = PG_GETARG_INT32(0);
1603 Oid languageoid = PG_GETARG_OID(1);
1604 text *priv_type_text = PG_GETARG_TEXT_P(2);
1606 AclResult aclresult;
1608 mode = convert_language_priv_string(priv_type_text);
1610 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1612 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1616 * Support routines for has_language_privilege family.
1620 * Given a language name expressed as a string, look it up and return Oid
1623 convert_language_name(text *languagename)
1628 langname = DatumGetCString(DirectFunctionCall1(textout,
1629 PointerGetDatum(languagename)));
1631 oid = GetSysCacheOid(LANGNAME,
1632 CStringGetDatum(langname),
1634 if (!OidIsValid(oid))
1635 elog(ERROR, "language \"%s\" does not exist", langname);
1641 * convert_language_priv_string
1642 * Convert text string to AclMode value.
1645 convert_language_priv_string(text *priv_type_text)
1649 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1650 PointerGetDatum(priv_type_text)));
1653 * Return mode from priv_type string
1655 if (strcasecmp(priv_type, "USAGE") == 0)
1657 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1658 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1660 elog(ERROR, "has_language_privilege: invalid privilege type %s",
1662 return ACL_NO_RIGHTS; /* keep compiler quiet */
1667 * has_schema_privilege variants
1668 * These are all named "has_schema_privilege" at the SQL level.
1669 * They take various combinations of schema name, schema OID,
1670 * user name, user sysid, or implicit user = current_user.
1672 * The result is a boolean value: true if user has the indicated
1673 * privilege, false if not.
1677 * has_schema_privilege_name_name
1678 * Check user privileges on a schema given
1679 * name username, text schemaname, and text priv name.
1682 has_schema_privilege_name_name(PG_FUNCTION_ARGS)
1684 Name username = PG_GETARG_NAME(0);
1685 text *schemaname = PG_GETARG_TEXT_P(1);
1686 text *priv_type_text = PG_GETARG_TEXT_P(2);
1690 AclResult aclresult;
1692 usesysid = get_usesysid(NameStr(*username));
1693 schemaoid = convert_schema_name(schemaname);
1694 mode = convert_schema_priv_string(priv_type_text);
1696 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1698 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1702 * has_schema_privilege_name
1703 * Check user privileges on a schema given
1704 * text schemaname and text priv name.
1705 * current_user is assumed
1708 has_schema_privilege_name(PG_FUNCTION_ARGS)
1710 text *schemaname = PG_GETARG_TEXT_P(0);
1711 text *priv_type_text = PG_GETARG_TEXT_P(1);
1715 AclResult aclresult;
1717 usesysid = GetUserId();
1718 schemaoid = convert_schema_name(schemaname);
1719 mode = convert_schema_priv_string(priv_type_text);
1721 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1723 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1727 * has_schema_privilege_name_id
1728 * Check user privileges on a schema given
1729 * name usename, schema oid, and text priv name.
1732 has_schema_privilege_name_id(PG_FUNCTION_ARGS)
1734 Name username = PG_GETARG_NAME(0);
1735 Oid schemaoid = PG_GETARG_OID(1);
1736 text *priv_type_text = PG_GETARG_TEXT_P(2);
1739 AclResult aclresult;
1741 usesysid = get_usesysid(NameStr(*username));
1742 mode = convert_schema_priv_string(priv_type_text);
1744 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1746 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1750 * has_schema_privilege_id
1751 * Check user privileges on a schema given
1752 * schema oid, and text priv name.
1753 * current_user is assumed
1756 has_schema_privilege_id(PG_FUNCTION_ARGS)
1758 Oid schemaoid = PG_GETARG_OID(0);
1759 text *priv_type_text = PG_GETARG_TEXT_P(1);
1762 AclResult aclresult;
1764 usesysid = GetUserId();
1765 mode = convert_schema_priv_string(priv_type_text);
1767 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1769 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1773 * has_schema_privilege_id_name
1774 * Check user privileges on a schema given
1775 * usesysid, text schemaname, and text priv name.
1778 has_schema_privilege_id_name(PG_FUNCTION_ARGS)
1780 int32 usesysid = PG_GETARG_INT32(0);
1781 text *schemaname = PG_GETARG_TEXT_P(1);
1782 text *priv_type_text = PG_GETARG_TEXT_P(2);
1785 AclResult aclresult;
1787 schemaoid = convert_schema_name(schemaname);
1788 mode = convert_schema_priv_string(priv_type_text);
1790 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1792 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1796 * has_schema_privilege_id_id
1797 * Check user privileges on a schema given
1798 * usesysid, schema oid, and text priv name.
1801 has_schema_privilege_id_id(PG_FUNCTION_ARGS)
1803 int32 usesysid = PG_GETARG_INT32(0);
1804 Oid schemaoid = PG_GETARG_OID(1);
1805 text *priv_type_text = PG_GETARG_TEXT_P(2);
1807 AclResult aclresult;
1809 mode = convert_schema_priv_string(priv_type_text);
1811 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1813 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1817 * Support routines for has_schema_privilege family.
1821 * Given a schema name expressed as a string, look it up and return Oid
1824 convert_schema_name(text *schemaname)
1829 nspname = DatumGetCString(DirectFunctionCall1(textout,
1830 PointerGetDatum(schemaname)));
1832 oid = GetSysCacheOid(NAMESPACENAME,
1833 CStringGetDatum(nspname),
1835 if (!OidIsValid(oid))
1836 elog(ERROR, "schema \"%s\" does not exist", nspname);
1842 * convert_schema_priv_string
1843 * Convert text string to AclMode value.
1846 convert_schema_priv_string(text *priv_type_text)
1850 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1851 PointerGetDatum(priv_type_text)));
1854 * Return mode from priv_type string
1856 if (strcasecmp(priv_type, "CREATE") == 0)
1858 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1859 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1861 if (strcasecmp(priv_type, "USAGE") == 0)
1863 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1864 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1866 elog(ERROR, "has_schema_privilege: invalid privilege type %s",
1868 return ACL_NO_RIGHTS; /* keep compiler quiet */