1 /*-------------------------------------------------------------------------
4 * Basic access control list data structures manipulation routines.
6 * Portions Copyright (c) 1996-2003, 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.94 2003/08/04 02:40:04 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 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) ||
87 in_quotes = !in_quotes;
90 if (len >= NAMEDATALEN - 1)
92 (errcode(ERRCODE_NAME_TOO_LONG),
93 errmsg("identifier too long"),
94 errdetail("Identifier must be less than %d characters.",
101 while (isspace((unsigned char) *s))
107 * Write a user or group Name at *p, surrounding it with double quotes if
108 * needed. There must be at least NAMEDATALEN+2 bytes available at *p.
111 putid(char *p, const char *s)
116 for (src = s; *src; src++)
118 /* This test had better match what getid() does, above */
119 if (!isalnum((unsigned char) *src) && *src != '_')
127 for (src = s; *src; src++)
136 * Consumes and parses an ACL specification of the form:
137 * [group|user] [A-Za-z0-9]*=[rwaR]*
138 * from string 's', ignoring any leading white space or white space
139 * between the optional id type keyword (group|user) and the actual
142 * This routine is called by the parser as well as aclitemin(), hence
143 * the added generality.
146 * the string position in 's' immediately following the ACL
147 * specification. Also:
148 * - loads the structure pointed to by 'aip' with the appropriate
149 * UID/GID, id type identifier and mode type values.
152 aclparse(const char *s, AclItem *aip)
158 char name[NAMEDATALEN];
159 char name2[NAMEDATALEN];
164 elog(LOG, "aclparse: input = \"%s\"", s);
166 idtype = ACL_IDTYPE_UID;
170 /* we just read a keyword, not a name */
171 if (strcmp(name, ACL_IDTYPE_GID_KEYWORD) == 0)
172 idtype = ACL_IDTYPE_GID;
173 else if (strcmp(name, ACL_IDTYPE_UID_KEYWORD) != 0)
175 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
176 errmsg("unrecognized keyword: \"%s\"", name),
177 errhint("ACL keyword must be \"group\" or \"user\".")));
178 s = getid(s, name); /* move s to the name beyond the keyword */
181 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
182 errmsg("missing name"),
183 errhint("A name must follow the [group|user] keyword.")));
186 idtype = ACL_IDTYPE_WORLD;
190 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
191 errmsg("missing \"=\" sign")));
193 privs = goption = ACL_NO_RIGHTS;
195 for (++s, read = 0; isalpha((unsigned char) *s) || *s == '*'; s++)
217 case ACL_REFERENCES_CHR:
218 read = ACL_REFERENCES;
220 case ACL_TRIGGER_CHR:
223 case ACL_EXECUTE_CHR:
232 case ACL_CREATE_TEMP_CHR:
233 read = ACL_CREATE_TEMP;
237 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
238 errmsg("invalid mode character: must be one of \"%s\"",
239 ACL_ALL_RIGHTS_STR)));
248 aip->ai_grantee = get_usesysid(name);
251 aip->ai_grantee = get_grosysid(name);
253 case ACL_IDTYPE_WORLD:
254 aip->ai_grantee = ACL_ID_WORLD;
259 * XXX Allow a degree of backward compatibility by defaulting the
260 * grantor to the superuser.
264 s = getid(s + 1, name2);
265 if (name2[0] == '\0')
267 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
268 errmsg("a name must follow the \"/\" sign")));
270 aip->ai_grantor = get_usesysid(name2);
274 aip->ai_grantor = BOOTSTRAP_USESYSID;
276 (errcode(ERRCODE_INVALID_GRANTOR),
277 errmsg("defaulting grantor to %u", BOOTSTRAP_USESYSID)));
280 ACLITEM_SET_PRIVS_IDTYPE(*aip, privs, goption, idtype);
283 elog(LOG, "aclparse: correctly read [%x %d %x]",
284 idtype, aip->ai_grantee, privs);
291 * Allocates storage for a new Acl with 'n' entries.
303 elog(ERROR, "invalid size: %d", n);
304 size = ACL_N_SIZE(n);
305 new_acl = (Acl *) palloc0(size);
306 new_acl->size = size;
309 new_acl->elemtype = ACLITEMOID;
310 ARR_LBOUND(new_acl)[0] = 0;
311 ARR_DIMS(new_acl)[0] = n;
317 * Allocates storage for, and fills in, a new AclItem given a string
318 * 's' that contains an ACL specification. See aclparse for details.
324 aclitemin(PG_FUNCTION_ARGS)
326 const char *s = PG_GETARG_CSTRING(0);
329 aip = (AclItem *) palloc(sizeof(AclItem));
330 s = aclparse(s, aip);
331 while (isspace((unsigned char) *s))
335 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
336 errmsg("extra garbage at the end of the ACL specification")));
338 PG_RETURN_ACLITEM_P(aip);
343 * Allocates storage for, and fills in, a new null-delimited string
344 * containing a formatted ACL specification. See aclparse for details.
350 aclitemout(PG_FUNCTION_ARGS)
352 AclItem *aip = PG_GETARG_ACLITEM_P(0);
359 out = palloc(strlen("group =/") +
361 2 * (NAMEDATALEN + 2) +
367 switch (ACLITEM_GET_IDTYPE(*aip))
370 htup = SearchSysCache(SHADOWSYSID,
371 ObjectIdGetDatum(aip->ai_grantee),
373 if (HeapTupleIsValid(htup))
375 putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
376 ReleaseSysCache(htup);
380 /* Generate numeric UID if we don't find an entry */
381 sprintf(p, "%d", aip->ai_grantee);
387 tmpname = get_groname(aip->ai_grantee);
392 /* Generate numeric GID if we don't find an entry */
393 sprintf(p, "%d", aip->ai_grantee);
396 case ACL_IDTYPE_WORLD:
399 elog(ERROR, "unrecognized idtype: %d",
400 (int) ACLITEM_GET_IDTYPE(*aip));
408 for (i = 0; i < N_ACL_RIGHTS; ++i)
410 if (ACLITEM_GET_PRIVS(*aip) & (1 << i))
411 *p++ = ACL_ALL_RIGHTS_STR[i];
412 if (ACLITEM_GET_GOPTIONS(*aip) & (1 << i))
419 htup = SearchSysCache(SHADOWSYSID,
420 ObjectIdGetDatum(aip->ai_grantor),
422 if (HeapTupleIsValid(htup))
424 putid(p, NameStr(((Form_pg_shadow) GETSTRUCT(htup))->usename));
425 ReleaseSysCache(htup);
429 /* Generate numeric UID if we don't find an entry */
430 sprintf(p, "%d", aip->ai_grantor);
437 PG_RETURN_CSTRING(out);
442 * Two AclItems are considered to match iff they have the same
443 * grantee and grantor; the privileges are ignored.
446 aclitem_match(const AclItem *a1, const AclItem *a2)
448 return ACLITEM_GET_IDTYPE(*a1) == ACLITEM_GET_IDTYPE(*a2) &&
449 a1->ai_grantee == a2->ai_grantee &&
450 a1->ai_grantor == a2->ai_grantor;
454 * aclitem equality operator
457 aclitem_eq(PG_FUNCTION_ARGS)
459 AclItem *a1 = PG_GETARG_ACLITEM_P(0);
460 AclItem *a2 = PG_GETARG_ACLITEM_P(1);
463 result = a1->ai_privs == a2->ai_privs &&
464 a1->ai_grantee == a2->ai_grantee &&
465 a1->ai_grantor == a2->ai_grantor;
466 PG_RETURN_BOOL(result);
470 * acldefault() --- create an ACL describing default access permissions
472 * Change this routine if you want to alter the default access policy for
473 * newly-created objects (or any object with a NULL acl entry).
476 acldefault(GrantObjectType objtype, AclId ownerid)
478 AclMode world_default;
479 AclMode owner_default;
485 case ACL_OBJECT_RELATION:
486 world_default = ACL_NO_RIGHTS;
487 owner_default = ACL_ALL_RIGHTS_RELATION;
489 case ACL_OBJECT_DATABASE:
490 world_default = ACL_CREATE_TEMP; /* not NO_RIGHTS! */
491 owner_default = ACL_ALL_RIGHTS_DATABASE;
493 case ACL_OBJECT_FUNCTION:
494 /* Grant EXECUTE by default, for now */
495 world_default = ACL_EXECUTE;
496 owner_default = ACL_ALL_RIGHTS_FUNCTION;
498 case ACL_OBJECT_LANGUAGE:
499 /* Grant USAGE by default, for now */
500 world_default = ACL_USAGE;
501 owner_default = ACL_ALL_RIGHTS_LANGUAGE;
503 case ACL_OBJECT_NAMESPACE:
504 world_default = ACL_NO_RIGHTS;
505 owner_default = ACL_ALL_RIGHTS_NAMESPACE;
508 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
509 world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
510 owner_default = ACL_NO_RIGHTS;
514 acl = allocacl((world_default != ACL_NO_RIGHTS ? 1 : 0)
515 + (ownerid ? 1 : 0));
518 if (world_default != ACL_NO_RIGHTS)
520 aip[0].ai_grantee = ACL_ID_WORLD;
521 aip[0].ai_grantor = ownerid;
522 ACLITEM_SET_PRIVS_IDTYPE(aip[0], world_default, ACL_NO_RIGHTS, ACL_IDTYPE_WORLD);
527 int index = (world_default != ACL_NO_RIGHTS ? 1 : 0);
529 aip[index].ai_grantee = ownerid;
530 aip[index].ai_grantor = ownerid;
531 /* owner gets default privileges with grant option */
532 ACLITEM_SET_PRIVS_IDTYPE(aip[index], owner_default, owner_default, ACL_IDTYPE_UID);
540 * Add or replace an item in an ACL array. The result is a modified copy;
541 * the input object is not changed.
543 * NB: caller is responsible for having detoasted the input ACL, if needed.
546 aclinsert3(const Acl *old_acl, const AclItem *mod_aip, unsigned modechg, DropBehavior behavior)
554 /* These checks for null input are probably dead code, but... */
555 if (!old_acl || ACL_NUM(old_acl) < 1)
556 old_acl = allocacl(1);
559 new_acl = allocacl(ACL_NUM(old_acl));
560 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
564 num = ACL_NUM(old_acl);
565 old_aip = ACL_DAT(old_acl);
568 * Search the ACL for an existing entry for this grantee and grantor.
569 * If one exists, just modify the entry in-place (well, in the same
570 * position, since we actually return a copy); otherwise, insert the
571 * new entry at the end.
574 for (dst = 0; dst < num; ++dst)
576 if (aclitem_match(mod_aip, old_aip + dst))
578 /* found a match, so modify existing item */
579 new_acl = allocacl(num);
580 new_aip = ACL_DAT(new_acl);
581 memcpy(new_acl, old_acl, ACL_SIZE(old_acl));
588 /* need to append a new item */
589 new_acl = allocacl(num + 1);
590 new_aip = ACL_DAT(new_acl);
591 memcpy(new_aip, old_aip, num * sizeof(AclItem));
593 /* initialize the new entry with no permissions */
594 new_aip[dst].ai_grantee = mod_aip->ai_grantee;
595 new_aip[dst].ai_grantor = mod_aip->ai_grantor;
596 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst], ACL_NO_RIGHTS, ACL_NO_RIGHTS,
597 ACLITEM_GET_IDTYPE(*mod_aip));
598 num++; /* set num to the size of new_acl */
601 /* apply the permissions mod */
604 case ACL_MODECHG_ADD:
605 ACLITEM_SET_PRIVS(new_aip[dst], ACLITEM_GET_PRIVS(new_aip[dst]) | ACLITEM_GET_PRIVS(*mod_aip));
606 ACLITEM_SET_GOPTIONS(new_aip[dst], ACLITEM_GET_GOPTIONS(new_aip[dst]) | ACLITEM_GET_GOPTIONS(*mod_aip));
608 case ACL_MODECHG_DEL:
609 ACLITEM_SET_PRIVS(new_aip[dst], ACLITEM_GET_PRIVS(new_aip[dst]) & ~ACLITEM_GET_PRIVS(*mod_aip));
610 ACLITEM_SET_GOPTIONS(new_aip[dst], ACLITEM_GET_GOPTIONS(new_aip[dst]) & ~ACLITEM_GET_GOPTIONS(*mod_aip));
612 case ACL_MODECHG_EQL:
613 ACLITEM_SET_PRIVS_IDTYPE(new_aip[dst],
614 ACLITEM_GET_PRIVS(*mod_aip),
615 ACLITEM_GET_GOPTIONS(*mod_aip),
616 ACLITEM_GET_IDTYPE(new_aip[dst]));
621 * If the adjusted entry has no permissions, delete it from the list.
623 if (ACLITEM_GET_PRIVS(new_aip[dst]) == ACL_NO_RIGHTS)
625 memmove(new_aip + dst,
627 (num - dst - 1) * sizeof(AclItem));
628 ARR_DIMS(new_acl)[0] = num - 1;
629 ARR_SIZE(new_acl) -= sizeof(AclItem);
633 * Remove abandoned privileges (cascading revoke)
635 if (modechg != ACL_MODECHG_ADD
636 && ACLITEM_GET_IDTYPE(*mod_aip) == ACL_IDTYPE_UID
637 && ACLITEM_GET_GOPTIONS(*mod_aip))
638 new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee, ACLITEM_GET_GOPTIONS(*mod_aip), behavior);
645 * Ensure that no privilege is "abandoned". A privilege is abandoned
646 * if the user that granted the privilege loses the grant option. (So
647 * the chain through which it was granted is broken.) Either the
648 * abandoned privileges are revoked as well, or an error message is
649 * printed, depending on the drop behavior option.
652 recursive_revoke(Acl *acl,
654 AclMode revoke_privs,
655 DropBehavior behavior)
660 for (i = 0; i < ACL_NUM(acl); i++)
662 AclItem *aip = ACL_DAT(acl);
664 if (aip[i].ai_grantor == grantee
665 && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
669 if (behavior == DROP_RESTRICT)
671 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
672 errmsg("dependent privileges exist"),
673 errhint("Use CASCADE to revoke them too.")));
675 mod_acl.ai_grantor = grantee;
676 mod_acl.ai_grantee = aip[i].ai_grantee;
677 ACLITEM_SET_PRIVS_IDTYPE(mod_acl,
680 ACLITEM_GET_IDTYPE(aip[i]));
682 acl = aclinsert3(acl, &mod_acl, ACL_MODECHG_DEL, behavior);
692 * aclinsert (exported function)
695 aclinsert(PG_FUNCTION_ARGS)
697 Acl *old_acl = PG_GETARG_ACL_P(0);
698 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
700 PG_RETURN_ACL_P(aclinsert3(old_acl, mod_aip, ACL_MODECHG_EQL, DROP_CASCADE));
704 aclremove(PG_FUNCTION_ARGS)
706 Acl *old_acl = PG_GETARG_ACL_P(0);
707 AclItem *mod_aip = PG_GETARG_ACLITEM_P(1);
715 /* These checks for null input should be dead code, but... */
716 if (!old_acl || ACL_NUM(old_acl) < 1)
717 old_acl = allocacl(1);
720 new_acl = allocacl(ACL_NUM(old_acl));
721 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
722 PG_RETURN_ACL_P(new_acl);
725 old_num = ACL_NUM(old_acl);
726 old_aip = ACL_DAT(old_acl);
728 /* Search for the matching entry */
730 dst < old_num && !aclitem_match(mod_aip, old_aip + dst);
736 /* Not found, so return copy of source ACL */
737 new_acl = allocacl(old_num);
738 memcpy((char *) new_acl, (char *) old_acl, ACL_SIZE(old_acl));
742 new_num = old_num - 1;
743 new_acl = allocacl(new_num);
744 new_aip = ACL_DAT(new_acl);
748 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
749 errmsg("cannot remove the world ACL")));
751 else if (dst == old_num - 1)
753 memcpy((char *) new_aip,
755 new_num * sizeof(AclItem));
759 memcpy((char *) new_aip,
761 dst * sizeof(AclItem));
762 memcpy((char *) (new_aip + dst),
763 (char *) (old_aip + dst + 1),
764 (new_num - dst) * sizeof(AclItem));
768 PG_RETURN_ACL_P(new_acl);
772 aclcontains(PG_FUNCTION_ARGS)
774 Acl *acl = PG_GETARG_ACL_P(0);
775 AclItem *aip = PG_GETARG_ACLITEM_P(1);
781 aidat = ACL_DAT(acl);
782 for (i = 0; i < num; ++i)
784 if (aip->ai_grantee == aidat[i].ai_grantee
785 && ACLITEM_GET_IDTYPE(*aip) == ACLITEM_GET_IDTYPE(aidat[i])
786 && aip->ai_grantor == aidat[i].ai_grantor
787 && (ACLITEM_GET_PRIVS(*aip) & ACLITEM_GET_PRIVS(aidat[i])) == ACLITEM_GET_PRIVS(*aip)
788 && (ACLITEM_GET_GOPTIONS(*aip) & ACLITEM_GET_GOPTIONS(aidat[i])) == ACLITEM_GET_GOPTIONS(*aip))
789 PG_RETURN_BOOL(true);
791 PG_RETURN_BOOL(false);
795 makeaclitem(PG_FUNCTION_ARGS)
797 int32 u_grantee = PG_GETARG_INT32(0);
798 int32 g_grantee = PG_GETARG_INT32(1);
799 int32 grantor = PG_GETARG_INT32(2);
800 text *privtext = PG_GETARG_TEXT_P(3);
801 bool goption = PG_GETARG_BOOL(4);
805 priv = convert_priv_string(privtext);
807 aclitem = (AclItem *) palloc(sizeof(*aclitem));
809 if (u_grantee == 0 && g_grantee == 0)
811 aclitem ->ai_grantee = 0;
813 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_WORLD);
815 else if (u_grantee != 0 && g_grantee != 0)
818 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
819 errmsg("cannot specify both user and group")));
821 else if (u_grantee != 0)
823 aclitem ->ai_grantee = u_grantee;
825 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_UID);
827 else if (g_grantee != 0)
829 aclitem ->ai_grantee = g_grantee;
831 ACLITEM_SET_IDTYPE(*aclitem, ACL_IDTYPE_GID);
834 aclitem ->ai_grantor = grantor;
836 ACLITEM_SET_PRIVS(*aclitem, priv);
838 ACLITEM_SET_GOPTIONS(*aclitem, priv);
840 ACLITEM_SET_GOPTIONS(*aclitem, ACL_NO_RIGHTS);
842 PG_RETURN_ACLITEM_P(aclitem);
846 convert_priv_string(text *priv_type_text)
850 priv_type = DatumGetCString(DirectFunctionCall1(textout,
851 PointerGetDatum(priv_type_text)));
853 if (strcasecmp(priv_type, "SELECT") == 0)
855 if (strcasecmp(priv_type, "INSERT") == 0)
857 if (strcasecmp(priv_type, "UPDATE") == 0)
859 if (strcasecmp(priv_type, "DELETE") == 0)
861 if (strcasecmp(priv_type, "RULE") == 0)
863 if (strcasecmp(priv_type, "REFERENCES") == 0)
864 return ACL_REFERENCES;
865 if (strcasecmp(priv_type, "TRIGGER") == 0)
867 if (strcasecmp(priv_type, "EXECUTE") == 0)
869 if (strcasecmp(priv_type, "USAGE") == 0)
871 if (strcasecmp(priv_type, "CREATE") == 0)
873 if (strcasecmp(priv_type, "TEMP") == 0)
874 return ACL_CREATE_TEMP;
875 if (strcasecmp(priv_type, "TEMPORARY") == 0)
876 return ACL_CREATE_TEMP;
879 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
880 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
881 return ACL_NO_RIGHTS; /* keep compiler quiet */
886 * has_table_privilege variants
887 * These are all named "has_table_privilege" at the SQL level.
888 * They take various combinations of relation name, relation OID,
889 * user name, user sysid, or implicit user = current_user.
891 * The result is a boolean value: true if user has the indicated
892 * privilege, false if not.
896 * has_table_privilege_name_name
897 * Check user privileges on a table given
898 * name username, text tablename, and text priv name.
901 has_table_privilege_name_name(PG_FUNCTION_ARGS)
903 Name username = PG_GETARG_NAME(0);
904 text *tablename = PG_GETARG_TEXT_P(1);
905 text *priv_type_text = PG_GETARG_TEXT_P(2);
911 usesysid = get_usesysid(NameStr(*username));
912 tableoid = convert_table_name(tablename);
913 mode = convert_table_priv_string(priv_type_text);
915 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
917 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
921 * has_table_privilege_name
922 * Check user privileges on a table given
923 * text tablename and text priv name.
924 * current_user is assumed
927 has_table_privilege_name(PG_FUNCTION_ARGS)
929 text *tablename = PG_GETARG_TEXT_P(0);
930 text *priv_type_text = PG_GETARG_TEXT_P(1);
936 usesysid = GetUserId();
937 tableoid = convert_table_name(tablename);
938 mode = convert_table_priv_string(priv_type_text);
940 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
942 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
946 * has_table_privilege_name_id
947 * Check user privileges on a table given
948 * name usename, table oid, and text priv name.
951 has_table_privilege_name_id(PG_FUNCTION_ARGS)
953 Name username = PG_GETARG_NAME(0);
954 Oid tableoid = PG_GETARG_OID(1);
955 text *priv_type_text = PG_GETARG_TEXT_P(2);
960 usesysid = get_usesysid(NameStr(*username));
961 mode = convert_table_priv_string(priv_type_text);
963 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
965 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
969 * has_table_privilege_id
970 * Check user privileges on a table given
971 * table oid, and text priv name.
972 * current_user is assumed
975 has_table_privilege_id(PG_FUNCTION_ARGS)
977 Oid tableoid = PG_GETARG_OID(0);
978 text *priv_type_text = PG_GETARG_TEXT_P(1);
983 usesysid = GetUserId();
984 mode = convert_table_priv_string(priv_type_text);
986 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
988 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
992 * has_table_privilege_id_name
993 * Check user privileges on a table given
994 * usesysid, text tablename, and text priv name.
997 has_table_privilege_id_name(PG_FUNCTION_ARGS)
999 int32 usesysid = PG_GETARG_INT32(0);
1000 text *tablename = PG_GETARG_TEXT_P(1);
1001 text *priv_type_text = PG_GETARG_TEXT_P(2);
1004 AclResult aclresult;
1006 tableoid = convert_table_name(tablename);
1007 mode = convert_table_priv_string(priv_type_text);
1009 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
1011 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1015 * has_table_privilege_id_id
1016 * Check user privileges on a table given
1017 * usesysid, table oid, and text priv name.
1020 has_table_privilege_id_id(PG_FUNCTION_ARGS)
1022 int32 usesysid = PG_GETARG_INT32(0);
1023 Oid tableoid = PG_GETARG_OID(1);
1024 text *priv_type_text = PG_GETARG_TEXT_P(2);
1026 AclResult aclresult;
1028 mode = convert_table_priv_string(priv_type_text);
1030 aclresult = pg_class_aclcheck(tableoid, usesysid, mode);
1032 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1036 * Support routines for has_table_privilege family.
1040 * Given a table name expressed as a string, look it up and return Oid
1043 convert_table_name(text *tablename)
1047 relrv = makeRangeVarFromNameList(textToQualifiedNameList(tablename,
1048 "has_table_privilege"));
1050 return RangeVarGetRelid(relrv, false);
1054 * convert_table_priv_string
1055 * Convert text string to AclMode value.
1058 convert_table_priv_string(text *priv_type_text)
1062 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1063 PointerGetDatum(priv_type_text)));
1066 * Return mode from priv_type string
1068 if (strcasecmp(priv_type, "SELECT") == 0)
1070 if (strcasecmp(priv_type, "SELECT WITH GRANT OPTION") == 0)
1071 return ACL_GRANT_OPTION_FOR(ACL_SELECT);
1073 if (strcasecmp(priv_type, "INSERT") == 0)
1075 if (strcasecmp(priv_type, "INSERT WITH GRANT OPTION") == 0)
1076 return ACL_GRANT_OPTION_FOR(ACL_INSERT);
1078 if (strcasecmp(priv_type, "UPDATE") == 0)
1080 if (strcasecmp(priv_type, "UPDATE WITH GRANT OPTION") == 0)
1081 return ACL_GRANT_OPTION_FOR(ACL_UPDATE);
1083 if (strcasecmp(priv_type, "DELETE") == 0)
1085 if (strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0)
1086 return ACL_GRANT_OPTION_FOR(ACL_DELETE);
1088 if (strcasecmp(priv_type, "RULE") == 0)
1090 if (strcasecmp(priv_type, "RULE WITH GRANT OPTION") == 0)
1091 return ACL_GRANT_OPTION_FOR(ACL_RULE);
1093 if (strcasecmp(priv_type, "REFERENCES") == 0)
1094 return ACL_REFERENCES;
1095 if (strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0)
1096 return ACL_GRANT_OPTION_FOR(ACL_REFERENCES);
1098 if (strcasecmp(priv_type, "TRIGGER") == 0)
1100 if (strcasecmp(priv_type, "TRIGGER WITH GRANT OPTION") == 0)
1101 return ACL_GRANT_OPTION_FOR(ACL_TRIGGER);
1104 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1105 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1106 return ACL_NO_RIGHTS; /* keep compiler quiet */
1111 * has_database_privilege variants
1112 * These are all named "has_database_privilege" at the SQL level.
1113 * They take various combinations of database name, database OID,
1114 * user name, user sysid, or implicit user = current_user.
1116 * The result is a boolean value: true if user has the indicated
1117 * privilege, false if not.
1121 * has_database_privilege_name_name
1122 * Check user privileges on a database given
1123 * name username, text databasename, and text priv name.
1126 has_database_privilege_name_name(PG_FUNCTION_ARGS)
1128 Name username = PG_GETARG_NAME(0);
1129 text *databasename = PG_GETARG_TEXT_P(1);
1130 text *priv_type_text = PG_GETARG_TEXT_P(2);
1134 AclResult aclresult;
1136 usesysid = get_usesysid(NameStr(*username));
1137 databaseoid = convert_database_name(databasename);
1138 mode = convert_database_priv_string(priv_type_text);
1140 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1142 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1146 * has_database_privilege_name
1147 * Check user privileges on a database given
1148 * text databasename and text priv name.
1149 * current_user is assumed
1152 has_database_privilege_name(PG_FUNCTION_ARGS)
1154 text *databasename = PG_GETARG_TEXT_P(0);
1155 text *priv_type_text = PG_GETARG_TEXT_P(1);
1159 AclResult aclresult;
1161 usesysid = GetUserId();
1162 databaseoid = convert_database_name(databasename);
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_name_id
1172 * Check user privileges on a database given
1173 * name usename, database oid, and text priv name.
1176 has_database_privilege_name_id(PG_FUNCTION_ARGS)
1178 Name username = PG_GETARG_NAME(0);
1179 Oid databaseoid = PG_GETARG_OID(1);
1180 text *priv_type_text = PG_GETARG_TEXT_P(2);
1183 AclResult aclresult;
1185 usesysid = get_usesysid(NameStr(*username));
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
1195 * Check user privileges on a database given
1196 * database oid, and text priv name.
1197 * current_user is assumed
1200 has_database_privilege_id(PG_FUNCTION_ARGS)
1202 Oid databaseoid = PG_GETARG_OID(0);
1203 text *priv_type_text = PG_GETARG_TEXT_P(1);
1206 AclResult aclresult;
1208 usesysid = GetUserId();
1209 mode = convert_database_priv_string(priv_type_text);
1211 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1213 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1217 * has_database_privilege_id_name
1218 * Check user privileges on a database given
1219 * usesysid, text databasename, and text priv name.
1222 has_database_privilege_id_name(PG_FUNCTION_ARGS)
1224 int32 usesysid = PG_GETARG_INT32(0);
1225 text *databasename = PG_GETARG_TEXT_P(1);
1226 text *priv_type_text = PG_GETARG_TEXT_P(2);
1229 AclResult aclresult;
1231 databaseoid = convert_database_name(databasename);
1232 mode = convert_database_priv_string(priv_type_text);
1234 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1236 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1240 * has_database_privilege_id_id
1241 * Check user privileges on a database given
1242 * usesysid, database oid, and text priv name.
1245 has_database_privilege_id_id(PG_FUNCTION_ARGS)
1247 int32 usesysid = PG_GETARG_INT32(0);
1248 Oid databaseoid = PG_GETARG_OID(1);
1249 text *priv_type_text = PG_GETARG_TEXT_P(2);
1251 AclResult aclresult;
1253 mode = convert_database_priv_string(priv_type_text);
1255 aclresult = pg_database_aclcheck(databaseoid, usesysid, mode);
1257 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1261 * Support routines for has_database_privilege family.
1265 * Given a database name expressed as a string, look it up and return Oid
1268 convert_database_name(text *databasename)
1273 dbname = DatumGetCString(DirectFunctionCall1(textout,
1274 PointerGetDatum(databasename)));
1276 oid = get_database_oid(dbname);
1277 if (!OidIsValid(oid))
1279 (errcode(ERRCODE_UNDEFINED_DATABASE),
1280 errmsg("database \"%s\" does not exist", dbname)));
1286 * convert_database_priv_string
1287 * Convert text string to AclMode value.
1290 convert_database_priv_string(text *priv_type_text)
1294 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1295 PointerGetDatum(priv_type_text)));
1298 * Return mode from priv_type string
1300 if (strcasecmp(priv_type, "CREATE") == 0)
1302 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1303 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1305 if (strcasecmp(priv_type, "TEMPORARY") == 0)
1306 return ACL_CREATE_TEMP;
1307 if (strcasecmp(priv_type, "TEMPORARY WITH GRANT OPTION") == 0)
1308 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1310 if (strcasecmp(priv_type, "TEMP") == 0)
1311 return ACL_CREATE_TEMP;
1312 if (strcasecmp(priv_type, "TEMP WITH GRANT OPTION") == 0)
1313 return ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP);
1316 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1317 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1318 return ACL_NO_RIGHTS; /* keep compiler quiet */
1323 * has_function_privilege variants
1324 * These are all named "has_function_privilege" at the SQL level.
1325 * They take various combinations of function name, function OID,
1326 * user name, user sysid, or implicit user = current_user.
1328 * The result is a boolean value: true if user has the indicated
1329 * privilege, false if not.
1333 * has_function_privilege_name_name
1334 * Check user privileges on a function given
1335 * name username, text functionname, and text priv name.
1338 has_function_privilege_name_name(PG_FUNCTION_ARGS)
1340 Name username = PG_GETARG_NAME(0);
1341 text *functionname = PG_GETARG_TEXT_P(1);
1342 text *priv_type_text = PG_GETARG_TEXT_P(2);
1346 AclResult aclresult;
1348 usesysid = get_usesysid(NameStr(*username));
1349 functionoid = convert_function_name(functionname);
1350 mode = convert_function_priv_string(priv_type_text);
1352 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1354 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1358 * has_function_privilege_name
1359 * Check user privileges on a function given
1360 * text functionname and text priv name.
1361 * current_user is assumed
1364 has_function_privilege_name(PG_FUNCTION_ARGS)
1366 text *functionname = PG_GETARG_TEXT_P(0);
1367 text *priv_type_text = PG_GETARG_TEXT_P(1);
1371 AclResult aclresult;
1373 usesysid = GetUserId();
1374 functionoid = convert_function_name(functionname);
1375 mode = convert_function_priv_string(priv_type_text);
1377 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1379 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1383 * has_function_privilege_name_id
1384 * Check user privileges on a function given
1385 * name usename, function oid, and text priv name.
1388 has_function_privilege_name_id(PG_FUNCTION_ARGS)
1390 Name username = PG_GETARG_NAME(0);
1391 Oid functionoid = PG_GETARG_OID(1);
1392 text *priv_type_text = PG_GETARG_TEXT_P(2);
1395 AclResult aclresult;
1397 usesysid = get_usesysid(NameStr(*username));
1398 mode = convert_function_priv_string(priv_type_text);
1400 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1402 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1406 * has_function_privilege_id
1407 * Check user privileges on a function given
1408 * function oid, and text priv name.
1409 * current_user is assumed
1412 has_function_privilege_id(PG_FUNCTION_ARGS)
1414 Oid functionoid = PG_GETARG_OID(0);
1415 text *priv_type_text = PG_GETARG_TEXT_P(1);
1418 AclResult aclresult;
1420 usesysid = GetUserId();
1421 mode = convert_function_priv_string(priv_type_text);
1423 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1425 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1429 * has_function_privilege_id_name
1430 * Check user privileges on a function given
1431 * usesysid, text functionname, and text priv name.
1434 has_function_privilege_id_name(PG_FUNCTION_ARGS)
1436 int32 usesysid = PG_GETARG_INT32(0);
1437 text *functionname = PG_GETARG_TEXT_P(1);
1438 text *priv_type_text = PG_GETARG_TEXT_P(2);
1441 AclResult aclresult;
1443 functionoid = convert_function_name(functionname);
1444 mode = convert_function_priv_string(priv_type_text);
1446 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1448 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1452 * has_function_privilege_id_id
1453 * Check user privileges on a function given
1454 * usesysid, function oid, and text priv name.
1457 has_function_privilege_id_id(PG_FUNCTION_ARGS)
1459 int32 usesysid = PG_GETARG_INT32(0);
1460 Oid functionoid = PG_GETARG_OID(1);
1461 text *priv_type_text = PG_GETARG_TEXT_P(2);
1463 AclResult aclresult;
1465 mode = convert_function_priv_string(priv_type_text);
1467 aclresult = pg_proc_aclcheck(functionoid, usesysid, mode);
1469 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1473 * Support routines for has_function_privilege family.
1477 * Given a function name expressed as a string, look it up and return Oid
1480 convert_function_name(text *functionname)
1485 funcname = DatumGetCString(DirectFunctionCall1(textout,
1486 PointerGetDatum(functionname)));
1488 oid = DatumGetObjectId(DirectFunctionCall1(regprocedurein,
1489 CStringGetDatum(funcname)));
1491 if (!OidIsValid(oid))
1493 (errcode(ERRCODE_UNDEFINED_FUNCTION),
1494 errmsg("function \"%s\" does not exist", funcname)));
1500 * convert_function_priv_string
1501 * Convert text string to AclMode value.
1504 convert_function_priv_string(text *priv_type_text)
1508 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1509 PointerGetDatum(priv_type_text)));
1512 * Return mode from priv_type string
1514 if (strcasecmp(priv_type, "EXECUTE") == 0)
1516 if (strcasecmp(priv_type, "EXECUTE WITH GRANT OPTION") == 0)
1517 return ACL_GRANT_OPTION_FOR(ACL_EXECUTE);
1520 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1521 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1522 return ACL_NO_RIGHTS; /* keep compiler quiet */
1527 * has_language_privilege variants
1528 * These are all named "has_language_privilege" at the SQL level.
1529 * They take various combinations of language name, language OID,
1530 * user name, user sysid, or implicit user = current_user.
1532 * The result is a boolean value: true if user has the indicated
1533 * privilege, false if not.
1537 * has_language_privilege_name_name
1538 * Check user privileges on a language given
1539 * name username, text languagename, and text priv name.
1542 has_language_privilege_name_name(PG_FUNCTION_ARGS)
1544 Name username = PG_GETARG_NAME(0);
1545 text *languagename = PG_GETARG_TEXT_P(1);
1546 text *priv_type_text = PG_GETARG_TEXT_P(2);
1550 AclResult aclresult;
1552 usesysid = get_usesysid(NameStr(*username));
1553 languageoid = convert_language_name(languagename);
1554 mode = convert_language_priv_string(priv_type_text);
1556 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1558 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1562 * has_language_privilege_name
1563 * Check user privileges on a language given
1564 * text languagename and text priv name.
1565 * current_user is assumed
1568 has_language_privilege_name(PG_FUNCTION_ARGS)
1570 text *languagename = PG_GETARG_TEXT_P(0);
1571 text *priv_type_text = PG_GETARG_TEXT_P(1);
1575 AclResult aclresult;
1577 usesysid = GetUserId();
1578 languageoid = convert_language_name(languagename);
1579 mode = convert_language_priv_string(priv_type_text);
1581 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1583 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1587 * has_language_privilege_name_id
1588 * Check user privileges on a language given
1589 * name usename, language oid, and text priv name.
1592 has_language_privilege_name_id(PG_FUNCTION_ARGS)
1594 Name username = PG_GETARG_NAME(0);
1595 Oid languageoid = PG_GETARG_OID(1);
1596 text *priv_type_text = PG_GETARG_TEXT_P(2);
1599 AclResult aclresult;
1601 usesysid = get_usesysid(NameStr(*username));
1602 mode = convert_language_priv_string(priv_type_text);
1604 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1606 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1610 * has_language_privilege_id
1611 * Check user privileges on a language given
1612 * language oid, and text priv name.
1613 * current_user is assumed
1616 has_language_privilege_id(PG_FUNCTION_ARGS)
1618 Oid languageoid = PG_GETARG_OID(0);
1619 text *priv_type_text = PG_GETARG_TEXT_P(1);
1622 AclResult aclresult;
1624 usesysid = GetUserId();
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 * has_language_privilege_id_name
1634 * Check user privileges on a language given
1635 * usesysid, text languagename, and text priv name.
1638 has_language_privilege_id_name(PG_FUNCTION_ARGS)
1640 int32 usesysid = PG_GETARG_INT32(0);
1641 text *languagename = PG_GETARG_TEXT_P(1);
1642 text *priv_type_text = PG_GETARG_TEXT_P(2);
1645 AclResult aclresult;
1647 languageoid = convert_language_name(languagename);
1648 mode = convert_language_priv_string(priv_type_text);
1650 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1652 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1656 * has_language_privilege_id_id
1657 * Check user privileges on a language given
1658 * usesysid, language oid, and text priv name.
1661 has_language_privilege_id_id(PG_FUNCTION_ARGS)
1663 int32 usesysid = PG_GETARG_INT32(0);
1664 Oid languageoid = PG_GETARG_OID(1);
1665 text *priv_type_text = PG_GETARG_TEXT_P(2);
1667 AclResult aclresult;
1669 mode = convert_language_priv_string(priv_type_text);
1671 aclresult = pg_language_aclcheck(languageoid, usesysid, mode);
1673 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1677 * Support routines for has_language_privilege family.
1681 * Given a language name expressed as a string, look it up and return Oid
1684 convert_language_name(text *languagename)
1689 langname = DatumGetCString(DirectFunctionCall1(textout,
1690 PointerGetDatum(languagename)));
1692 oid = GetSysCacheOid(LANGNAME,
1693 CStringGetDatum(langname),
1695 if (!OidIsValid(oid))
1697 (errcode(ERRCODE_UNDEFINED_OBJECT),
1698 errmsg("language \"%s\" does not exist", langname)));
1704 * convert_language_priv_string
1705 * Convert text string to AclMode value.
1708 convert_language_priv_string(text *priv_type_text)
1712 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1713 PointerGetDatum(priv_type_text)));
1716 * Return mode from priv_type string
1718 if (strcasecmp(priv_type, "USAGE") == 0)
1720 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1721 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1724 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1725 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1726 return ACL_NO_RIGHTS; /* keep compiler quiet */
1731 * has_schema_privilege variants
1732 * These are all named "has_schema_privilege" at the SQL level.
1733 * They take various combinations of schema name, schema OID,
1734 * user name, user sysid, or implicit user = current_user.
1736 * The result is a boolean value: true if user has the indicated
1737 * privilege, false if not.
1741 * has_schema_privilege_name_name
1742 * Check user privileges on a schema given
1743 * name username, text schemaname, and text priv name.
1746 has_schema_privilege_name_name(PG_FUNCTION_ARGS)
1748 Name username = PG_GETARG_NAME(0);
1749 text *schemaname = PG_GETARG_TEXT_P(1);
1750 text *priv_type_text = PG_GETARG_TEXT_P(2);
1754 AclResult aclresult;
1756 usesysid = get_usesysid(NameStr(*username));
1757 schemaoid = convert_schema_name(schemaname);
1758 mode = convert_schema_priv_string(priv_type_text);
1760 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1762 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1766 * has_schema_privilege_name
1767 * Check user privileges on a schema given
1768 * text schemaname and text priv name.
1769 * current_user is assumed
1772 has_schema_privilege_name(PG_FUNCTION_ARGS)
1774 text *schemaname = PG_GETARG_TEXT_P(0);
1775 text *priv_type_text = PG_GETARG_TEXT_P(1);
1779 AclResult aclresult;
1781 usesysid = GetUserId();
1782 schemaoid = convert_schema_name(schemaname);
1783 mode = convert_schema_priv_string(priv_type_text);
1785 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1787 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1791 * has_schema_privilege_name_id
1792 * Check user privileges on a schema given
1793 * name usename, schema oid, and text priv name.
1796 has_schema_privilege_name_id(PG_FUNCTION_ARGS)
1798 Name username = PG_GETARG_NAME(0);
1799 Oid schemaoid = PG_GETARG_OID(1);
1800 text *priv_type_text = PG_GETARG_TEXT_P(2);
1803 AclResult aclresult;
1805 usesysid = get_usesysid(NameStr(*username));
1806 mode = convert_schema_priv_string(priv_type_text);
1808 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1810 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1814 * has_schema_privilege_id
1815 * Check user privileges on a schema given
1816 * schema oid, and text priv name.
1817 * current_user is assumed
1820 has_schema_privilege_id(PG_FUNCTION_ARGS)
1822 Oid schemaoid = PG_GETARG_OID(0);
1823 text *priv_type_text = PG_GETARG_TEXT_P(1);
1826 AclResult aclresult;
1828 usesysid = GetUserId();
1829 mode = convert_schema_priv_string(priv_type_text);
1831 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1833 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1837 * has_schema_privilege_id_name
1838 * Check user privileges on a schema given
1839 * usesysid, text schemaname, and text priv name.
1842 has_schema_privilege_id_name(PG_FUNCTION_ARGS)
1844 int32 usesysid = PG_GETARG_INT32(0);
1845 text *schemaname = PG_GETARG_TEXT_P(1);
1846 text *priv_type_text = PG_GETARG_TEXT_P(2);
1849 AclResult aclresult;
1851 schemaoid = convert_schema_name(schemaname);
1852 mode = convert_schema_priv_string(priv_type_text);
1854 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1856 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1860 * has_schema_privilege_id_id
1861 * Check user privileges on a schema given
1862 * usesysid, schema oid, and text priv name.
1865 has_schema_privilege_id_id(PG_FUNCTION_ARGS)
1867 int32 usesysid = PG_GETARG_INT32(0);
1868 Oid schemaoid = PG_GETARG_OID(1);
1869 text *priv_type_text = PG_GETARG_TEXT_P(2);
1871 AclResult aclresult;
1873 mode = convert_schema_priv_string(priv_type_text);
1875 aclresult = pg_namespace_aclcheck(schemaoid, usesysid, mode);
1877 PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
1881 * Support routines for has_schema_privilege family.
1885 * Given a schema name expressed as a string, look it up and return Oid
1888 convert_schema_name(text *schemaname)
1893 nspname = DatumGetCString(DirectFunctionCall1(textout,
1894 PointerGetDatum(schemaname)));
1896 oid = GetSysCacheOid(NAMESPACENAME,
1897 CStringGetDatum(nspname),
1899 if (!OidIsValid(oid))
1901 (errcode(ERRCODE_UNDEFINED_SCHEMA),
1902 errmsg("schema \"%s\" does not exist", nspname)));
1908 * convert_schema_priv_string
1909 * Convert text string to AclMode value.
1912 convert_schema_priv_string(text *priv_type_text)
1916 priv_type = DatumGetCString(DirectFunctionCall1(textout,
1917 PointerGetDatum(priv_type_text)));
1920 * Return mode from priv_type string
1922 if (strcasecmp(priv_type, "CREATE") == 0)
1924 if (strcasecmp(priv_type, "CREATE WITH GRANT OPTION") == 0)
1925 return ACL_GRANT_OPTION_FOR(ACL_CREATE);
1927 if (strcasecmp(priv_type, "USAGE") == 0)
1929 if (strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
1930 return ACL_GRANT_OPTION_FOR(ACL_USAGE);
1933 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1934 errmsg("unrecognized privilege type: \"%s\"", priv_type)));
1935 return ACL_NO_RIGHTS; /* keep compiler quiet */