PostgreSQL Source Code git master
Loading...
Searching...
No Matches
acl.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * acl.c
4 * Basic access control list data structures manipulation routines.
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/adt/acl.c
12 *
13 *-------------------------------------------------------------------------
14 */
15#include "postgres.h"
16
17#include <ctype.h>
18
19#include "access/htup_details.h"
20#include "bootstrap/bootstrap.h"
21#include "catalog/catalog.h"
22#include "catalog/namespace.h"
24#include "catalog/pg_authid.h"
25#include "catalog/pg_class.h"
26#include "catalog/pg_database.h"
29#include "catalog/pg_language.h"
32#include "catalog/pg_proc.h"
34#include "catalog/pg_type.h"
35#include "commands/proclang.h"
36#include "commands/tablespace.h"
37#include "common/hashfn.h"
38#include "foreign/foreign.h"
39#include "funcapi.h"
40#include "lib/bloomfilter.h"
41#include "lib/qunique.h"
42#include "miscadmin.h"
43#include "port/pg_bitutils.h"
45#include "utils/acl.h"
46#include "utils/array.h"
47#include "utils/builtins.h"
48#include "utils/catcache.h"
49#include "utils/inval.h"
50#include "utils/lsyscache.h"
51#include "utils/memutils.h"
52#include "utils/snapmgr.h"
53#include "utils/syscache.h"
54#include "utils/varlena.h"
55
56typedef struct
57{
58 const char *name;
60} priv_map;
61
62/*
63 * We frequently need to test whether a given role is a member of some other
64 * role. In most of these tests the "given role" is the same, namely the
65 * active current user. So we can optimize it by keeping cached lists of all
66 * the roles the "given role" is a member of, directly or indirectly.
67 *
68 * Possibly this mechanism should be generalized to allow caching membership
69 * info for multiple roles?
70 *
71 * Each element of cached_roles is an OID list of constituent roles for the
72 * corresponding element of cached_role (always including the cached_role
73 * itself). There's a separate cache for each RoleRecurseType, with the
74 * corresponding semantics.
75 */
77{
78 ROLERECURSE_MEMBERS = 0, /* recurse unconditionally */
79 ROLERECURSE_PRIVS = 1, /* recurse through inheritable grants */
80 ROLERECURSE_SETROLE = 2 /* recurse through grants with set_option */
81};
83static List *cached_roles[] = {NIL, NIL, NIL};
85
86/*
87 * If the list of roles gathered by roles_is_member_of() grows larger than the
88 * below threshold, a Bloom filter is created to speed up list membership
89 * checks. This threshold is set arbitrarily high to avoid the overhead of
90 * creating the Bloom filter until it seems likely to provide a net benefit.
91 */
92#define ROLES_LIST_BLOOM_THRESHOLD 1024
93
94static const char *getid(const char *s, char *n, Node *escontext);
95static void putid(char *p, const char *s);
96static Acl *allocacl(int n);
97static void check_acl(const Acl *acl);
98static const char *aclparse(const char *s, AclItem *aip, Node *escontext);
99static bool aclitem_match(const AclItem *a1, const AclItem *a2);
100static int aclitemComparator(const void *arg1, const void *arg2);
101static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
102 Oid ownerId);
104 Oid ownerId, DropBehavior behavior);
105
107 const priv_map *privileges);
108
109static Oid convert_table_name(text *tablename);
112static AttrNumber convert_column_name(Oid tableoid, text *column);
122static Oid convert_schema_name(text *schemaname);
124static Oid convert_server_name(text *servername);
126static Oid convert_tablespace_name(text *tablespacename);
128static Oid convert_type_name(text *typename);
134
136 uint32 hashvalue);
137
138
139/*
140 * Test whether an identifier char can be left unquoted in ACLs.
141 *
142 * Formerly, we used isalnum() even on non-ASCII characters, resulting in
143 * unportable behavior. To ensure dump compatibility with old versions,
144 * we now treat high-bit-set characters as always requiring quoting during
145 * putid(), but getid() will always accept them without quotes.
146 */
147static inline bool
148is_safe_acl_char(unsigned char c, bool is_getid)
149{
150 if (IS_HIGHBIT_SET(c))
151 return is_getid;
152 return isalnum(c) || c == '_';
153}
154
155/*
156 * getid
157 * Consumes the first alphanumeric string (identifier) found in string
158 * 's', ignoring any leading white space. If it finds a double quote
159 * it returns the word inside the quotes.
160 *
161 * RETURNS:
162 * the string position in 's' that points to the next non-space character
163 * in 's', after any quotes. Also:
164 * - loads the identifier into 'n'. (If no identifier is found, 'n'
165 * contains an empty string.) 'n' must be NAMEDATALEN bytes.
166 *
167 * Errors are reported via ereport, unless escontext is an ErrorSaveData node,
168 * in which case we log the error there and return NULL.
169 */
170static const char *
171getid(const char *s, char *n, Node *escontext)
172{
173 int len = 0;
174 bool in_quotes = false;
175
176 Assert(s && n);
177
178 while (isspace((unsigned char) *s))
179 s++;
180 for (;
181 *s != '\0' &&
182 (in_quotes || *s == '"' || is_safe_acl_char(*s, true));
183 s++)
184 {
185 if (*s == '"')
186 {
187 if (!in_quotes)
188 {
189 in_quotes = true;
190 continue;
191 }
192 /* safe to look at next char (could be '\0' though) */
193 if (*(s + 1) != '"')
194 {
195 in_quotes = false;
196 continue;
197 }
198 /* it's an escaped double quote; skip the escaping char */
199 s++;
200 }
201
202 /* Add the character to the string */
203 if (len >= NAMEDATALEN - 1)
204 ereturn(escontext, NULL,
206 errmsg("identifier too long"),
207 errdetail("Identifier must be less than %d characters.",
208 NAMEDATALEN)));
209
210 n[len++] = *s;
211 }
212 n[len] = '\0';
213 while (isspace((unsigned char) *s))
214 s++;
215 return s;
216}
217
218/*
219 * Write a role name at *p, adding double quotes if needed.
220 * There must be at least (2*NAMEDATALEN)+2 bytes available at *p.
221 * This needs to be kept in sync with dequoteAclUserName in pg_dump/dumputils.c
222 */
223static void
224putid(char *p, const char *s)
225{
226 const char *src;
227 bool safe = true;
228
229 /* Detect whether we need to use double quotes */
230 for (src = s; *src; src++)
231 {
232 if (!is_safe_acl_char(*src, false))
233 {
234 safe = false;
235 break;
236 }
237 }
238 if (!safe)
239 *p++ = '"';
240 for (src = s; *src; src++)
241 {
242 /* A double quote character in a username is encoded as "" */
243 if (*src == '"')
244 *p++ = '"';
245 *p++ = *src;
246 }
247 if (!safe)
248 *p++ = '"';
249 *p = '\0';
250}
251
252/*
253 * aclparse
254 * Consumes and parses an ACL specification of the form:
255 * [group|user] [A-Za-z0-9]*=[rwaR]*
256 * from string 's', ignoring any leading white space or white space
257 * between the optional id type keyword (group|user) and the actual
258 * ACL specification.
259 *
260 * The group|user decoration is unnecessary in the roles world,
261 * but we still accept it for backward compatibility.
262 *
263 * This routine is called by the parser as well as aclitemin(), hence
264 * the added generality.
265 *
266 * In bootstrap mode, we consult a hard-wired list of role names
267 * (see bootstrap.c) rather than trying to access the catalogs.
268 *
269 * RETURNS:
270 * the string position in 's' immediately following the ACL
271 * specification. Also:
272 * - loads the structure pointed to by 'aip' with the appropriate
273 * UID/GID, id type identifier and mode type values.
274 *
275 * Errors are reported via ereport, unless escontext is an ErrorSaveData node,
276 * in which case we log the error there and return NULL.
277 */
278static const char *
279aclparse(const char *s, AclItem *aip, Node *escontext)
280{
282 goption,
283 read;
284 char name[NAMEDATALEN];
285 char name2[NAMEDATALEN];
286
287 Assert(s && aip);
288
289 s = getid(s, name, escontext);
290 if (s == NULL)
291 return NULL;
292 if (*s != '=')
293 {
294 /* we just read a keyword, not a name */
295 if (strcmp(name, "group") != 0 && strcmp(name, "user") != 0)
296 ereturn(escontext, NULL,
298 errmsg("unrecognized key word: \"%s\"", name),
299 errhint("ACL key word must be \"group\" or \"user\".")));
300 /* move s to the name beyond the keyword */
301 s = getid(s, name, escontext);
302 if (s == NULL)
303 return NULL;
304 if (name[0] == '\0')
305 ereturn(escontext, NULL,
307 errmsg("missing name"),
308 errhint("A name must follow the \"group\" or \"user\" key word.")));
309 }
310
311 if (*s != '=')
312 ereturn(escontext, NULL,
314 errmsg("missing \"=\" sign")));
315
317
318 for (++s, read = 0; isalpha((unsigned char) *s) || *s == '*'; s++)
319 {
320 switch (*s)
321 {
322 case '*':
323 goption |= read;
324 break;
325 case ACL_INSERT_CHR:
327 break;
328 case ACL_SELECT_CHR:
330 break;
331 case ACL_UPDATE_CHR:
333 break;
334 case ACL_DELETE_CHR:
336 break;
337 case ACL_TRUNCATE_CHR:
339 break;
342 break;
343 case ACL_TRIGGER_CHR:
345 break;
346 case ACL_EXECUTE_CHR:
348 break;
349 case ACL_USAGE_CHR:
350 read = ACL_USAGE;
351 break;
352 case ACL_CREATE_CHR:
354 break;
357 break;
358 case ACL_CONNECT_CHR:
360 break;
361 case ACL_SET_CHR:
362 read = ACL_SET;
363 break;
366 break;
367 case ACL_MAINTAIN_CHR:
369 break;
370 default:
371 ereturn(escontext, NULL,
373 errmsg("invalid mode character: must be one of \"%s\"",
375 }
376
377 privs |= read;
378 }
379
380 if (name[0] == '\0')
381 aip->ai_grantee = ACL_ID_PUBLIC;
382 else
383 {
385 aip->ai_grantee = boot_get_role_oid(name);
386 else
387 aip->ai_grantee = get_role_oid(name, true);
388 if (!OidIsValid(aip->ai_grantee))
389 ereturn(escontext, NULL,
391 errmsg("role \"%s\" does not exist", name)));
392 }
393
394 /*
395 * XXX Allow a degree of backward compatibility by defaulting the grantor
396 * to the superuser. We condone that practice in the catalog .dat files
397 * (i.e., in bootstrap mode) for brevity; otherwise, issue a warning.
398 */
399 if (*s == '/')
400 {
401 s = getid(s + 1, name2, escontext);
402 if (s == NULL)
403 return NULL;
404 if (name2[0] == '\0')
405 ereturn(escontext, NULL,
407 errmsg("a name must follow the \"/\" sign")));
409 aip->ai_grantor = boot_get_role_oid(name2);
410 else
411 aip->ai_grantor = get_role_oid(name2, true);
412 if (!OidIsValid(aip->ai_grantor))
413 ereturn(escontext, NULL,
415 errmsg("role \"%s\" does not exist", name2)));
416 }
417 else
418 {
419 aip->ai_grantor = BOOTSTRAP_SUPERUSERID;
423 errmsg("defaulting grantor to user ID %u",
425 }
426
428
429 return s;
430}
431
432/*
433 * allocacl
434 * Allocates storage for a new Acl with 'n' entries.
435 *
436 * RETURNS:
437 * the new Acl
438 */
439static Acl *
441{
442 Acl *new_acl;
443 Size size;
444
445 if (n < 0)
446 elog(ERROR, "invalid size: %d", n);
447 size = ACL_N_SIZE(n);
448 new_acl = (Acl *) palloc0(size);
449 SET_VARSIZE(new_acl, size);
450 new_acl->ndim = 1;
451 new_acl->dataoffset = 0; /* we never put in any nulls */
452 new_acl->elemtype = ACLITEMOID;
453 ARR_LBOUND(new_acl)[0] = 1;
454 ARR_DIMS(new_acl)[0] = n;
455 return new_acl;
456}
457
458/*
459 * Create a zero-entry ACL
460 */
461Acl *
463{
464 return allocacl(0);
465}
466
467/*
468 * Copy an ACL
469 */
470Acl *
472{
474
476
479 ACL_NUM(orig_acl) * sizeof(AclItem));
480
481 return result_acl;
482}
483
484/*
485 * Concatenate two ACLs
486 *
487 * This is a bit cheesy, since we may produce an ACL with redundant entries.
488 * Be careful what the result is used for!
489 */
490Acl *
492{
494
496
499 ACL_NUM(left_acl) * sizeof(AclItem));
500
503 ACL_NUM(right_acl) * sizeof(AclItem));
504
505 return result_acl;
506}
507
508/*
509 * Merge two ACLs
510 *
511 * This produces a properly merged ACL with no redundant entries.
512 * Returns NULL on NULL input.
513 */
514Acl *
515aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
516{
518 AclItem *aip;
519 int i,
520 num;
521
522 /* Check for cases where one or both are empty/null */
523 if (left_acl == NULL || ACL_NUM(left_acl) == 0)
524 {
525 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
526 return NULL;
527 else
528 return aclcopy(right_acl);
529 }
530 else
531 {
532 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
533 return aclcopy(left_acl);
534 }
535
536 /* Merge them the hard way, one item at a time */
538
540 num = ACL_NUM(right_acl);
541
542 for (i = 0; i < num; i++, aip++)
543 {
544 Acl *tmp_acl;
545
547 ownerId, DROP_RESTRICT);
550 }
551
552 return result_acl;
553}
554
555/*
556 * Sort the items in an ACL (into an arbitrary but consistent order)
557 */
558void
560{
561 if (acl != NULL && ACL_NUM(acl) > 1)
562 qsort(ACL_DAT(acl), ACL_NUM(acl), sizeof(AclItem), aclitemComparator);
563}
564
565/*
566 * Check if two ACLs are exactly equal
567 *
568 * This will not detect equality if the two arrays contain the same items
569 * in different orders. To handle that case, sort both inputs first,
570 * using aclitemsort().
571 */
572bool
574{
575 /* Check for cases where one or both are empty/null */
576 if (left_acl == NULL || ACL_NUM(left_acl) == 0)
577 {
578 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
579 return true;
580 else
581 return false;
582 }
583 else
584 {
585 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
586 return false;
587 }
588
590 return false;
591
594 ACL_NUM(left_acl) * sizeof(AclItem)) == 0)
595 return true;
596
597 return false;
598}
599
600/*
601 * Verify that an ACL array is acceptable (one-dimensional and has no nulls)
602 */
603static void
604check_acl(const Acl *acl)
605{
606 if (ARR_ELEMTYPE(acl) != ACLITEMOID)
609 errmsg("ACL array contains wrong data type")));
610 if (ARR_NDIM(acl) != 1)
613 errmsg("ACL arrays must be one-dimensional")));
614 if (ARR_HASNULL(acl))
617 errmsg("ACL arrays must not contain null values")));
618}
619
620/*
621 * aclitemin
622 * Allocates storage for, and fills in, a new AclItem given a string
623 * 's' that contains an ACL specification. See aclparse for details.
624 *
625 * RETURNS:
626 * the new AclItem
627 */
628Datum
630{
631 const char *s = PG_GETARG_CSTRING(0);
632 Node *escontext = fcinfo->context;
633 AclItem *aip;
634
636
637 s = aclparse(s, aip, escontext);
638 if (s == NULL)
640
641 while (isspace((unsigned char) *s))
642 ++s;
643 if (*s)
644 ereturn(escontext, (Datum) 0,
646 errmsg("extra garbage at the end of the ACL specification")));
647
649}
650
651/*
652 * aclitemout
653 * Allocates storage for, and fills in, a new null-delimited string
654 * containing a formatted ACL specification. See aclparse for details.
655 *
656 * In bootstrap mode, this is called for debug printouts (initdb -d).
657 * We could ask bootstrap.c to provide an inverse of boot_get_role_oid(),
658 * but it seems at least as useful to just print numeric role OIDs.
659 *
660 * RETURNS:
661 * the new string
662 */
663Datum
665{
667 char *p;
668 char *out;
669 HeapTuple htup;
670 unsigned i;
671
672 out = palloc(strlen("=/") +
673 2 * N_ACL_RIGHTS +
674 2 * (2 * NAMEDATALEN + 2) +
675 1);
676
677 p = out;
678 *p = '\0';
679
680 if (aip->ai_grantee != ACL_ID_PUBLIC)
681 {
683 htup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(aip->ai_grantee));
684 else
685 htup = NULL;
686 if (HeapTupleIsValid(htup))
687 {
689 ReleaseSysCache(htup);
690 }
691 else
692 {
693 /* No such entry, or bootstrap mode: print numeric OID */
694 sprintf(p, "%u", aip->ai_grantee);
695 }
696 }
697 while (*p)
698 ++p;
699
700 *p++ = '=';
701
702 for (i = 0; i < N_ACL_RIGHTS; ++i)
703 {
704 if (ACLITEM_GET_PRIVS(*aip) & (UINT64CONST(1) << i))
705 *p++ = ACL_ALL_RIGHTS_STR[i];
706 if (ACLITEM_GET_GOPTIONS(*aip) & (UINT64CONST(1) << i))
707 *p++ = '*';
708 }
709
710 *p++ = '/';
711 *p = '\0';
712
714 htup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(aip->ai_grantor));
715 else
716 htup = NULL;
717 if (HeapTupleIsValid(htup))
718 {
720 ReleaseSysCache(htup);
721 }
722 else
723 {
724 /* No such entry, or bootstrap mode: print numeric OID */
725 sprintf(p, "%u", aip->ai_grantor);
726 }
727
729}
730
731/*
732 * aclitem_match
733 * Two AclItems are considered to match iff they have the same
734 * grantee and grantor; the privileges are ignored.
735 */
736static bool
738{
739 return a1->ai_grantee == a2->ai_grantee &&
740 a1->ai_grantor == a2->ai_grantor;
741}
742
743/*
744 * aclitemComparator
745 * qsort comparison function for AclItems
746 */
747static int
748aclitemComparator(const void *arg1, const void *arg2)
749{
750 const AclItem *a1 = (const AclItem *) arg1;
751 const AclItem *a2 = (const AclItem *) arg2;
752
753 if (a1->ai_grantee > a2->ai_grantee)
754 return 1;
755 if (a1->ai_grantee < a2->ai_grantee)
756 return -1;
757 if (a1->ai_grantor > a2->ai_grantor)
758 return 1;
759 if (a1->ai_grantor < a2->ai_grantor)
760 return -1;
761 if (a1->ai_privs > a2->ai_privs)
762 return 1;
763 if (a1->ai_privs < a2->ai_privs)
764 return -1;
765 return 0;
766}
767
768/*
769 * aclitem equality operator
770 */
771Datum
773{
776 bool result;
777
778 result = a1->ai_privs == a2->ai_privs &&
779 a1->ai_grantee == a2->ai_grantee &&
780 a1->ai_grantor == a2->ai_grantor;
782}
783
784/*
785 * aclitem hash function
786 *
787 * We make aclitems hashable not so much because anyone is likely to hash
788 * them, as because we want array equality to work on aclitem arrays, and
789 * with the typcache mechanism we must have a hash or btree opclass.
790 */
791Datum
793{
795
796 /* not very bright, but avoids any issue of padding in struct */
797 PG_RETURN_UINT32((uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor));
798}
799
800/*
801 * 64-bit hash function for aclitem.
802 *
803 * Similar to hash_aclitem, but accepts a seed and returns a uint64 value.
804 */
805Datum
807{
809 uint64 seed = PG_GETARG_INT64(1);
810 uint32 sum = (uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor);
811
812 return (seed == 0) ? UInt64GetDatum(sum) : hash_uint32_extended(sum, seed);
813}
814
815/*
816 * acldefault() --- create an ACL describing default access permissions
817 *
818 * Change this routine if you want to alter the default access policy for
819 * newly-created objects (or any object with a NULL acl entry). When
820 * you make a change here, don't forget to update the GRANT man page,
821 * which explains all the default permissions.
822 *
823 * Note that these are the hard-wired "defaults" that are used in the
824 * absence of any pg_default_acl entry.
825 */
826Acl *
827acldefault(ObjectType objtype, Oid ownerId)
828{
831 int nacl;
832 Acl *acl;
833 AclItem *aip;
834
835 switch (objtype)
836 {
837 case OBJECT_COLUMN:
838 /* by default, columns have no extra privileges */
841 break;
842 case OBJECT_TABLE:
845 break;
846 case OBJECT_SEQUENCE:
849 break;
850 case OBJECT_DATABASE:
851 /* for backwards compatibility, grant some rights by default */
854 break;
855 case OBJECT_FUNCTION:
856 /* Grant EXECUTE by default, for now */
859 break;
860 case OBJECT_LANGUAGE:
861 /* Grant USAGE by default, for now */
864 break;
868 break;
869 case OBJECT_SCHEMA:
872 break;
876 break;
877 case OBJECT_FDW:
880 break;
884 break;
885 case OBJECT_DOMAIN:
886 case OBJECT_TYPE:
889 break;
893 break;
894 case OBJECT_PROPGRAPH:
897 break;
898 default:
899 elog(ERROR, "unrecognized object type: %d", (int) objtype);
900 world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
902 break;
903 }
904
905 nacl = 0;
907 nacl++;
909 nacl++;
910
911 acl = allocacl(nacl);
912 aip = ACL_DAT(acl);
913
915 {
916 aip->ai_grantee = ACL_ID_PUBLIC;
917 aip->ai_grantor = ownerId;
919 aip++;
920 }
921
922 /*
923 * Note that the owner's entry shows all ordinary privileges but no grant
924 * options. This is because his grant options come "from the system" and
925 * not from his own efforts. (The SQL spec says that the owner's rights
926 * come from a "_SYSTEM" authid.) However, we do consider that the
927 * owner's ordinary privileges are self-granted; this lets him revoke
928 * them. We implement the owner's grant options without any explicit
929 * "_SYSTEM"-like ACL entry, by internally special-casing the owner
930 * wherever we are testing grant options.
931 */
933 {
934 aip->ai_grantee = ownerId;
935 aip->ai_grantor = ownerId;
937 }
938
939 return acl;
940}
941
942
943/*
944 * SQL-accessible version of acldefault(). Hackish mapping from "char" type to
945 * OBJECT_* values.
946 */
947Datum
949{
950 char objtypec = PG_GETARG_CHAR(0);
951 Oid owner = PG_GETARG_OID(1);
952 ObjectType objtype = 0;
953
954 switch (objtypec)
955 {
956 case 'c':
957 objtype = OBJECT_COLUMN;
958 break;
959 case 'g':
960 objtype = OBJECT_PROPGRAPH;
961 break;
962 case 'r':
963 objtype = OBJECT_TABLE;
964 break;
965 case 's':
966 objtype = OBJECT_SEQUENCE;
967 break;
968 case 'd':
969 objtype = OBJECT_DATABASE;
970 break;
971 case 'f':
972 objtype = OBJECT_FUNCTION;
973 break;
974 case 'l':
975 objtype = OBJECT_LANGUAGE;
976 break;
977 case 'L':
978 objtype = OBJECT_LARGEOBJECT;
979 break;
980 case 'n':
981 objtype = OBJECT_SCHEMA;
982 break;
983 case 'p':
984 objtype = OBJECT_PARAMETER_ACL;
985 break;
986 case 't':
987 objtype = OBJECT_TABLESPACE;
988 break;
989 case 'F':
990 objtype = OBJECT_FDW;
991 break;
992 case 'S':
993 objtype = OBJECT_FOREIGN_SERVER;
994 break;
995 case 'T':
996 objtype = OBJECT_TYPE;
997 break;
998 default:
999 elog(ERROR, "unrecognized object type abbreviation: %c", objtypec);
1000 }
1001
1002 PG_RETURN_ACL_P(acldefault(objtype, owner));
1003}
1004
1005
1006/*
1007 * Update an ACL array to add or remove specified privileges.
1008 *
1009 * old_acl: the input ACL array
1010 * mod_aip: defines the privileges to be added, removed, or substituted
1011 * modechg: ACL_MODECHG_ADD, ACL_MODECHG_DEL, or ACL_MODECHG_EQL
1012 * ownerId: Oid of object owner
1013 * behavior: RESTRICT or CASCADE behavior for recursive removal
1014 *
1015 * ownerid and behavior are only relevant when the update operation specifies
1016 * deletion of grant options.
1017 *
1018 * The result is a modified copy; the input object is not changed.
1019 *
1020 * NB: caller is responsible for having detoasted the input ACL, if needed.
1021 */
1022Acl *
1024 int modechg, Oid ownerId, DropBehavior behavior)
1025{
1026 Acl *new_acl = NULL;
1028 *new_aip = NULL;
1031 new_rights,
1033 int dst,
1034 num;
1035
1036 /* Caller probably already checked old_acl, but be safe */
1038
1039 /* If granting grant options, check for circularity */
1040 if (modechg != ACL_MODECHG_DEL &&
1043
1044 num = ACL_NUM(old_acl);
1046
1047 /*
1048 * Search the ACL for an existing entry for this grantee and grantor. If
1049 * one exists, just modify the entry in-place (well, in the same position,
1050 * since we actually return a copy); otherwise, insert the new entry at
1051 * the end.
1052 */
1053
1054 for (dst = 0; dst < num; ++dst)
1055 {
1057 {
1058 /* found a match, so modify existing item */
1059 new_acl = allocacl(num);
1062 break;
1063 }
1064 }
1065
1066 if (dst == num)
1067 {
1068 /* need to append a new item */
1069 new_acl = allocacl(num + 1);
1071 memcpy(new_aip, old_aip, num * sizeof(AclItem));
1072
1073 /* initialize the new entry with no permissions */
1074 new_aip[dst].ai_grantee = mod_aip->ai_grantee;
1075 new_aip[dst].ai_grantor = mod_aip->ai_grantor;
1078 num++; /* set num to the size of new_acl */
1079 }
1080
1083
1084 /* apply the specified permissions change */
1085 switch (modechg)
1086 {
1087 case ACL_MODECHG_ADD:
1090 break;
1091 case ACL_MODECHG_DEL:
1094 break;
1095 case ACL_MODECHG_EQL:
1098 break;
1099 }
1100
1103
1104 /*
1105 * If the adjusted entry has no permissions, delete it from the list.
1106 */
1108 {
1110 new_aip + dst + 1,
1111 (num - dst - 1) * sizeof(AclItem));
1112 /* Adjust array size to be 'num - 1' items */
1113 ARR_DIMS(new_acl)[0] = num - 1;
1114 SET_VARSIZE(new_acl, ACL_N_SIZE(num - 1));
1115 }
1116
1117 /*
1118 * Remove abandoned privileges (cascading revoke). Currently we can only
1119 * handle this when the grantee is not PUBLIC.
1120 */
1121 if ((old_goptions & ~new_goptions) != 0)
1122 {
1123 Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
1124 new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee,
1126 ownerId, behavior);
1127 }
1128
1129 return new_acl;
1130}
1131
1132/*
1133 * Update an ACL array to reflect a change of owner to the parent object
1134 *
1135 * old_acl: the input ACL array (must not be NULL)
1136 * oldOwnerId: Oid of the old object owner
1137 * newOwnerId: Oid of the new object owner
1138 *
1139 * The result is a modified copy; the input object is not changed.
1140 *
1141 * NB: caller is responsible for having detoasted the input ACL, if needed.
1142 *
1143 * Note: the name of this function is a bit of a misnomer, since it will
1144 * happily make the specified role substitution whether the old role is
1145 * really the owner of the parent object or merely mentioned in its ACL.
1146 * But the vast majority of callers use it in connection with ALTER OWNER
1147 * operations, so we'll keep the name.
1148 */
1149Acl *
1151{
1152 Acl *new_acl;
1158 bool newpresent = false;
1159 int dst,
1160 src,
1161 targ,
1162 num;
1163
1165
1166 /*
1167 * Make a copy of the given ACL, substituting new owner ID for old
1168 * wherever it appears as either grantor or grantee. Also note if the new
1169 * owner ID is already present.
1170 */
1171 num = ACL_NUM(old_acl);
1173 new_acl = allocacl(num);
1175 memcpy(new_aip, old_aip, num * sizeof(AclItem));
1176 for (dst = 0, dst_aip = new_aip; dst < num; dst++, dst_aip++)
1177 {
1178 if (dst_aip->ai_grantor == oldOwnerId)
1179 dst_aip->ai_grantor = newOwnerId;
1180 else if (dst_aip->ai_grantor == newOwnerId)
1181 newpresent = true;
1182 if (dst_aip->ai_grantee == oldOwnerId)
1183 dst_aip->ai_grantee = newOwnerId;
1184 else if (dst_aip->ai_grantee == newOwnerId)
1185 newpresent = true;
1186 }
1187
1188 /*
1189 * If the old ACL contained any references to the new owner, then we may
1190 * now have generated an ACL containing duplicate entries. Find them and
1191 * merge them so that there are not duplicates. (This is relatively
1192 * expensive since we use a stupid O(N^2) algorithm, but it's unlikely to
1193 * be the normal case.)
1194 *
1195 * To simplify deletion of duplicate entries, we temporarily leave them in
1196 * the array but set their privilege masks to zero; when we reach such an
1197 * entry it's just skipped. (Thus, a side effect of this code will be to
1198 * remove privilege-free entries, should there be any in the input.) dst
1199 * is the next output slot, targ is the currently considered input slot
1200 * (always >= dst), and src scans entries to the right of targ looking for
1201 * duplicates. Once an entry has been emitted to dst it is known
1202 * duplicate-free and need not be considered anymore.
1203 */
1204 if (newpresent)
1205 {
1206 dst = 0;
1207 for (targ = 0, targ_aip = new_aip; targ < num; targ++, targ_aip++)
1208 {
1209 /* ignore if deleted in an earlier pass */
1211 continue;
1212 /* find and merge any duplicates */
1213 for (src = targ + 1, src_aip = targ_aip + 1; src < num;
1214 src++, src_aip++)
1215 {
1217 continue;
1219 {
1223 /* mark the duplicate deleted */
1225 }
1226 }
1227 /* and emit to output */
1228 new_aip[dst] = *targ_aip;
1229 dst++;
1230 }
1231 /* Adjust array size to be 'dst' items */
1232 ARR_DIMS(new_acl)[0] = dst;
1234 }
1235
1236 return new_acl;
1237}
1238
1239
1240/*
1241 * When granting grant options, we must disallow attempts to set up circular
1242 * chains of grant options. Suppose A (the object owner) grants B some
1243 * privileges with grant option, and B re-grants them to C. If C could
1244 * grant the privileges to B as well, then A would be unable to effectively
1245 * revoke the privileges from B, since recursive_revoke would consider that
1246 * B still has 'em from C.
1247 *
1248 * We check for this by recursively deleting all grant options belonging to
1249 * the target grantee, and then seeing if the would-be grantor still has the
1250 * grant option or not.
1251 */
1252static void
1254 Oid ownerId)
1255{
1256 Acl *acl;
1257 AclItem *aip;
1258 int i,
1259 num;
1261
1263
1264 /*
1265 * For now, grant options can only be granted to roles, not PUBLIC.
1266 * Otherwise we'd have to work a bit harder here.
1267 */
1268 Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
1269
1270 /* The owner always has grant options, no need to check */
1271 if (mod_aip->ai_grantor == ownerId)
1272 return;
1273
1274 /* Make a working copy */
1275 acl = allocacl(ACL_NUM(old_acl));
1277
1278 /* Zap all grant options of target grantee, plus what depends on 'em */
1280 num = ACL_NUM(acl);
1281 aip = ACL_DAT(acl);
1282 for (i = 0; i < num; i++)
1283 {
1284 if (aip[i].ai_grantee == mod_aip->ai_grantee &&
1286 {
1287 Acl *new_acl;
1288
1289 /* We'll actually zap ordinary privs too, but no matter */
1291 ownerId, DROP_CASCADE);
1292
1293 pfree(acl);
1294 acl = new_acl;
1295
1296 goto cc_restart;
1297 }
1298 }
1299
1300 /* Now we can compute grantor's independently-derived privileges */
1301 own_privs = aclmask(acl,
1302 mod_aip->ai_grantor,
1303 ownerId,
1305 ACLMASK_ALL);
1307
1308 if ((ACLITEM_GET_GOPTIONS(*mod_aip) & ~own_privs) != 0)
1309 ereport(ERROR,
1311 errmsg("grant options cannot be granted back to your own grantor")));
1312
1313 pfree(acl);
1314}
1315
1316
1317/*
1318 * Ensure that no privilege is "abandoned". A privilege is abandoned
1319 * if the user that granted the privilege loses the grant option. (So
1320 * the chain through which it was granted is broken.) Either the
1321 * abandoned privileges are revoked as well, or an error message is
1322 * printed, depending on the drop behavior option.
1323 *
1324 * acl: the input ACL list
1325 * grantee: the user from whom some grant options have been revoked
1326 * revoke_privs: the grant options being revoked
1327 * ownerId: Oid of object owner
1328 * behavior: RESTRICT or CASCADE behavior for recursive removal
1329 *
1330 * The input Acl object is pfree'd if replaced.
1331 */
1332static Acl *
1334 Oid grantee,
1336 Oid ownerId,
1337 DropBehavior behavior)
1338{
1340 AclItem *aip;
1341 int i,
1342 num;
1343
1344 check_acl(acl);
1345
1346 /* The owner can never truly lose grant options, so short-circuit */
1347 if (grantee == ownerId)
1348 return acl;
1349
1350 /* The grantee might still have some grant options via another grantor */
1351 still_has = aclmask(acl, grantee, ownerId,
1353 ACLMASK_ALL);
1356 return acl;
1357
1358restart:
1359 num = ACL_NUM(acl);
1360 aip = ACL_DAT(acl);
1361 for (i = 0; i < num; i++)
1362 {
1363 if (aip[i].ai_grantor == grantee
1364 && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
1365 {
1367 Acl *new_acl;
1368
1369 if (behavior == DROP_RESTRICT)
1370 ereport(ERROR,
1372 errmsg("dependent privileges exist"),
1373 errhint("Use CASCADE to revoke them too.")));
1374
1375 mod_acl.ai_grantor = grantee;
1376 mod_acl.ai_grantee = aip[i].ai_grantee;
1379 revoke_privs);
1380
1382 ownerId, behavior);
1383
1384 pfree(acl);
1385 acl = new_acl;
1386
1387 goto restart;
1388 }
1389 }
1390
1391 return acl;
1392}
1393
1394
1395/*
1396 * aclmask --- compute bitmask of all privileges held by roleid.
1397 *
1398 * When 'how' = ACLMASK_ALL, this simply returns the privilege bits
1399 * held by the given roleid according to the given ACL list, ANDed
1400 * with 'mask'. (The point of passing 'mask' is to let the routine
1401 * exit early if all privileges of interest have been found.)
1402 *
1403 * When 'how' = ACLMASK_ANY, returns as soon as any bit in the mask
1404 * is known true. (This lets us exit soonest in cases where the
1405 * caller is only going to test for zero or nonzero result.)
1406 *
1407 * Usage patterns:
1408 *
1409 * To see if any of a set of privileges are held:
1410 * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ANY) != 0)
1411 *
1412 * To see if all of a set of privileges are held:
1413 * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL) == privs)
1414 *
1415 * To determine exactly which of a set of privileges are held:
1416 * heldprivs = aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL);
1417 */
1418AclMode
1419aclmask(const Acl *acl, Oid roleid, Oid ownerId,
1420 AclMode mask, AclMaskHow how)
1421{
1424 AclItem *aidat;
1425 int i,
1426 num;
1427
1428 /*
1429 * Null ACL should not happen, since caller should have inserted
1430 * appropriate default
1431 */
1432 if (acl == NULL)
1433 elog(ERROR, "null ACL");
1434
1435 check_acl(acl);
1436
1437 /* Quick exit for mask == 0 */
1438 if (mask == 0)
1439 return 0;
1440
1441 result = 0;
1442
1443 /* Owner always implicitly has all grant options */
1444 if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
1445 has_privs_of_role(roleid, ownerId))
1446 {
1448 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1449 return result;
1450 }
1451
1452 num = ACL_NUM(acl);
1453 aidat = ACL_DAT(acl);
1454
1455 /*
1456 * Check privileges granted directly to roleid or to public
1457 */
1458 for (i = 0; i < num; i++)
1459 {
1460 AclItem *aidata = &aidat[i];
1461
1462 if (aidata->ai_grantee == ACL_ID_PUBLIC ||
1463 aidata->ai_grantee == roleid)
1464 {
1465 result |= aidata->ai_privs & mask;
1466 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1467 return result;
1468 }
1469 }
1470
1471 /*
1472 * Check privileges granted indirectly via role memberships. We do this in
1473 * a separate pass to minimize expensive indirect membership tests. In
1474 * particular, it's worth testing whether a given ACL entry grants any
1475 * privileges still of interest before we perform the has_privs_of_role
1476 * test.
1477 */
1478 remaining = mask & ~result;
1479 for (i = 0; i < num; i++)
1480 {
1481 AclItem *aidata = &aidat[i];
1482
1483 if (aidata->ai_grantee == ACL_ID_PUBLIC ||
1484 aidata->ai_grantee == roleid)
1485 continue; /* already checked it */
1486
1487 if ((aidata->ai_privs & remaining) &&
1488 has_privs_of_role(roleid, aidata->ai_grantee))
1489 {
1490 result |= aidata->ai_privs & mask;
1491 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1492 return result;
1493 remaining = mask & ~result;
1494 }
1495 }
1496
1497 return result;
1498}
1499
1500
1501/*
1502 * aclmask_direct --- compute bitmask of all privileges held by roleid.
1503 *
1504 * This is exactly like aclmask() except that we consider only privileges
1505 * held *directly* by roleid, not those inherited via role membership.
1506 */
1507static AclMode
1508aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId,
1509 AclMode mask, AclMaskHow how)
1510{
1512 AclItem *aidat;
1513 int i,
1514 num;
1515
1516 /*
1517 * Null ACL should not happen, since caller should have inserted
1518 * appropriate default
1519 */
1520 if (acl == NULL)
1521 elog(ERROR, "null ACL");
1522
1523 check_acl(acl);
1524
1525 /* Quick exit for mask == 0 */
1526 if (mask == 0)
1527 return 0;
1528
1529 result = 0;
1530
1531 /* Owner always implicitly has all grant options */
1532 if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
1533 roleid == ownerId)
1534 {
1536 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1537 return result;
1538 }
1539
1540 num = ACL_NUM(acl);
1541 aidat = ACL_DAT(acl);
1542
1543 /*
1544 * Check privileges granted directly to roleid (and not to public)
1545 */
1546 for (i = 0; i < num; i++)
1547 {
1548 AclItem *aidata = &aidat[i];
1549
1550 if (aidata->ai_grantee == roleid)
1551 {
1552 result |= aidata->ai_privs & mask;
1553 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1554 return result;
1555 }
1556 }
1557
1558 return result;
1559}
1560
1561
1562/*
1563 * aclmembers
1564 * Find out all the roleids mentioned in an Acl.
1565 * Note that we do not distinguish grantors from grantees.
1566 *
1567 * *roleids is set to point to a palloc'd array containing distinct OIDs
1568 * in sorted order. The length of the array is the function result.
1569 */
1570int
1572{
1573 Oid *list;
1574 const AclItem *acldat;
1575 int i,
1576 j;
1577
1578 if (acl == NULL || ACL_NUM(acl) == 0)
1579 {
1580 *roleids = NULL;
1581 return 0;
1582 }
1583
1584 check_acl(acl);
1585
1586 /* Allocate the worst-case space requirement */
1587 list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
1588 acldat = ACL_DAT(acl);
1589
1590 /*
1591 * Walk the ACL collecting mentioned RoleIds.
1592 */
1593 j = 0;
1594 for (i = 0; i < ACL_NUM(acl); i++)
1595 {
1596 const AclItem *ai = &acldat[i];
1597
1598 if (ai->ai_grantee != ACL_ID_PUBLIC)
1599 list[j++] = ai->ai_grantee;
1600 /* grantor is currently never PUBLIC, but let's check anyway */
1601 if (ai->ai_grantor != ACL_ID_PUBLIC)
1602 list[j++] = ai->ai_grantor;
1603 }
1604
1605 /* Sort the array */
1606 qsort(list, j, sizeof(Oid), oid_cmp);
1607
1608 /*
1609 * We could repalloc the array down to minimum size, but it's hardly worth
1610 * it since it's only transient memory.
1611 */
1612 *roleids = list;
1613
1614 /* Remove duplicates from the array */
1615 return qunique(list, j, sizeof(Oid), oid_cmp);
1616}
1617
1618
1619/*
1620 * aclinsert (exported function)
1621 */
1622Datum
1624{
1625 ereport(ERROR,
1627 errmsg("aclinsert is no longer supported")));
1628
1629 PG_RETURN_NULL(); /* keep compiler quiet */
1630}
1631
1632Datum
1634{
1635 ereport(ERROR,
1637 errmsg("aclremove is no longer supported")));
1638
1639 PG_RETURN_NULL(); /* keep compiler quiet */
1640}
1641
1642Datum
1644{
1645 Acl *acl = PG_GETARG_ACL_P(0);
1647 AclItem *aidat;
1648 int i,
1649 num;
1650
1651 check_acl(acl);
1652 num = ACL_NUM(acl);
1653 aidat = ACL_DAT(acl);
1654 for (i = 0; i < num; ++i)
1655 {
1656 if (aip->ai_grantee == aidat[i].ai_grantee &&
1657 aip->ai_grantor == aidat[i].ai_grantor &&
1659 PG_RETURN_BOOL(true);
1660 }
1661 PG_RETURN_BOOL(false);
1662}
1663
1664Datum
1666{
1668 Oid grantor = PG_GETARG_OID(1);
1670 bool goption = PG_GETARG_BOOL(3);
1671 AclItem *result;
1672 AclMode priv;
1673 static const priv_map any_priv_map[] = {
1674 {"SELECT", ACL_SELECT},
1675 {"INSERT", ACL_INSERT},
1676 {"UPDATE", ACL_UPDATE},
1677 {"DELETE", ACL_DELETE},
1678 {"TRUNCATE", ACL_TRUNCATE},
1679 {"REFERENCES", ACL_REFERENCES},
1680 {"TRIGGER", ACL_TRIGGER},
1681 {"EXECUTE", ACL_EXECUTE},
1682 {"USAGE", ACL_USAGE},
1683 {"CREATE", ACL_CREATE},
1684 {"TEMP", ACL_CREATE_TEMP},
1685 {"TEMPORARY", ACL_CREATE_TEMP},
1686 {"CONNECT", ACL_CONNECT},
1687 {"SET", ACL_SET},
1688 {"ALTER SYSTEM", ACL_ALTER_SYSTEM},
1689 {"MAINTAIN", ACL_MAINTAIN},
1690 {NULL, 0}
1691 };
1692
1694
1696
1697 result->ai_grantee = grantee;
1698 result->ai_grantor = grantor;
1699
1701 (goption ? priv : ACL_NO_RIGHTS));
1702
1704}
1705
1706
1707/*
1708 * convert_any_priv_string: recognize privilege strings for has_foo_privilege
1709 *
1710 * We accept a comma-separated list of case-insensitive privilege names,
1711 * producing a bitmask of the OR'd privilege bits. We are liberal about
1712 * whitespace between items, not so much about whitespace within items.
1713 * The allowed privilege names are given as an array of priv_map structs,
1714 * terminated by one with a NULL name pointer.
1715 */
1716static AclMode
1718 const priv_map *privileges)
1719{
1720 AclMode result = 0;
1722 char *chunk;
1723 char *next_chunk;
1724
1725 /* We rely on priv_type being a private, modifiable string */
1726 for (chunk = priv_type; chunk; chunk = next_chunk)
1727 {
1728 int chunk_len;
1729 const priv_map *this_priv;
1730
1731 /* Split string at commas */
1732 next_chunk = strchr(chunk, ',');
1733 if (next_chunk)
1734 *next_chunk++ = '\0';
1735
1736 /* Drop leading/trailing whitespace in this chunk */
1737 while (*chunk && isspace((unsigned char) *chunk))
1738 chunk++;
1739 chunk_len = strlen(chunk);
1740 while (chunk_len > 0 && isspace((unsigned char) chunk[chunk_len - 1]))
1741 chunk_len--;
1742 chunk[chunk_len] = '\0';
1743
1744 /* Match to the privileges list */
1745 for (this_priv = privileges; this_priv->name; this_priv++)
1746 {
1747 if (pg_strcasecmp(this_priv->name, chunk) == 0)
1748 {
1749 result |= this_priv->value;
1750 break;
1751 }
1752 }
1753 if (!this_priv->name)
1754 ereport(ERROR,
1756 errmsg("unrecognized privilege type: \"%s\"", chunk)));
1757 }
1758
1760 return result;
1761}
1762
1763
1764static const char *
1766{
1767 switch (aclright)
1768 {
1769 case ACL_INSERT:
1770 return "INSERT";
1771 case ACL_SELECT:
1772 return "SELECT";
1773 case ACL_UPDATE:
1774 return "UPDATE";
1775 case ACL_DELETE:
1776 return "DELETE";
1777 case ACL_TRUNCATE:
1778 return "TRUNCATE";
1779 case ACL_REFERENCES:
1780 return "REFERENCES";
1781 case ACL_TRIGGER:
1782 return "TRIGGER";
1783 case ACL_EXECUTE:
1784 return "EXECUTE";
1785 case ACL_USAGE:
1786 return "USAGE";
1787 case ACL_CREATE:
1788 return "CREATE";
1789 case ACL_CREATE_TEMP:
1790 return "TEMPORARY";
1791 case ACL_CONNECT:
1792 return "CONNECT";
1793 case ACL_SET:
1794 return "SET";
1795 case ACL_ALTER_SYSTEM:
1796 return "ALTER SYSTEM";
1797 case ACL_MAINTAIN:
1798 return "MAINTAIN";
1799 default:
1800 elog(ERROR, "unrecognized aclright: %d", aclright);
1801 return NULL;
1802 }
1803}
1804
1805
1806/*----------
1807 * Convert an aclitem[] to a table.
1808 *
1809 * Example:
1810 *
1811 * aclexplode('{=r/joe,foo=a*w/joe}'::aclitem[])
1812 *
1813 * returns the table
1814 *
1815 * {{ OID(joe), 0::OID, 'SELECT', false },
1816 * { OID(joe), OID(foo), 'INSERT', true },
1817 * { OID(joe), OID(foo), 'UPDATE', false }}
1818 *----------
1819 */
1820Datum
1822{
1823 Acl *acl = PG_GETARG_ACL_P(0);
1825 int *idx;
1826 AclItem *aidat;
1827
1828 if (SRF_IS_FIRSTCALL())
1829 {
1830 TupleDesc tupdesc;
1831 MemoryContext oldcontext;
1832
1833 check_acl(acl);
1834
1836 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1837
1838 /*
1839 * build tupdesc for result tuples (matches out parameters in pg_proc
1840 * entry)
1841 */
1842 tupdesc = CreateTemplateTupleDesc(4);
1843 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "grantor",
1844 OIDOID, -1, 0);
1845 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "grantee",
1846 OIDOID, -1, 0);
1847 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "privilege_type",
1848 TEXTOID, -1, 0);
1849 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_grantable",
1850 BOOLOID, -1, 0);
1851
1852 TupleDescFinalize(tupdesc);
1853 funcctx->tuple_desc = BlessTupleDesc(tupdesc);
1854
1855 /* allocate memory for user context */
1856 idx = palloc_array(int, 2);
1857 idx[0] = 0; /* ACL array item index */
1858 idx[1] = -1; /* privilege type counter */
1859 funcctx->user_fctx = idx;
1860
1861 MemoryContextSwitchTo(oldcontext);
1862 }
1863
1865 idx = (int *) funcctx->user_fctx;
1866 aidat = ACL_DAT(acl);
1867
1868 /* need test here in case acl has no items */
1869 while (idx[0] < ACL_NUM(acl))
1870 {
1871 AclItem *aidata;
1873
1874 idx[1]++;
1875 if (idx[1] == N_ACL_RIGHTS)
1876 {
1877 idx[1] = 0;
1878 idx[0]++;
1879 if (idx[0] >= ACL_NUM(acl)) /* done */
1880 break;
1881 }
1882 aidata = &aidat[idx[0]];
1883 priv_bit = UINT64CONST(1) << idx[1];
1884
1886 {
1887 Datum result;
1888 Datum values[4];
1889 bool nulls[4] = {0};
1890 HeapTuple tuple;
1891
1892 values[0] = ObjectIdGetDatum(aidata->ai_grantor);
1893 values[1] = ObjectIdGetDatum(aidata->ai_grantee);
1896
1897 tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
1898 result = HeapTupleGetDatum(tuple);
1899
1901 }
1902 }
1903
1905}
1906
1907
1908/*
1909 * has_table_privilege variants
1910 * These are all named "has_table_privilege" at the SQL level.
1911 * They take various combinations of relation name, relation OID,
1912 * user name, user OID, or implicit user = current_user.
1913 *
1914 * The result is a boolean value: true if user has the indicated
1915 * privilege, false if not. The variants that take a relation OID
1916 * return NULL if the OID doesn't exist (rather than failing, as
1917 * they did before Postgres 8.4).
1918 */
1919
1920/*
1921 * has_table_privilege_name_name
1922 * Check user privileges on a table given
1923 * name username, text tablename, and text priv name.
1924 */
1925Datum
1927{
1928 Name rolename = PG_GETARG_NAME(0);
1929 text *tablename = PG_GETARG_TEXT_PP(1);
1931 Oid roleid;
1932 Oid tableoid;
1933 AclMode mode;
1935
1936 roleid = get_role_oid_or_public(NameStr(*rolename));
1937 tableoid = convert_table_name(tablename);
1939
1940 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1941
1943}
1944
1945/*
1946 * has_table_privilege_name
1947 * Check user privileges on a table given
1948 * text tablename and text priv name.
1949 * current_user is assumed
1950 */
1951Datum
1953{
1954 text *tablename = PG_GETARG_TEXT_PP(0);
1956 Oid roleid;
1957 Oid tableoid;
1958 AclMode mode;
1960
1961 roleid = GetUserId();
1962 tableoid = convert_table_name(tablename);
1964
1965 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1966
1968}
1969
1970/*
1971 * has_table_privilege_name_id
1972 * Check user privileges on a table given
1973 * name usename, table oid, and text priv name.
1974 */
1975Datum
1977{
1979 Oid tableoid = PG_GETARG_OID(1);
1981 Oid roleid;
1982 AclMode mode;
1984 bool is_missing = false;
1985
1988
1989 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
1990
1991 if (is_missing)
1993
1995}
1996
1997/*
1998 * has_table_privilege_id
1999 * Check user privileges on a table given
2000 * table oid, and text priv name.
2001 * current_user is assumed
2002 */
2003Datum
2005{
2006 Oid tableoid = PG_GETARG_OID(0);
2008 Oid roleid;
2009 AclMode mode;
2011 bool is_missing = false;
2012
2013 roleid = GetUserId();
2015
2016 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2017
2018 if (is_missing)
2020
2022}
2023
2024/*
2025 * has_table_privilege_id_name
2026 * Check user privileges on a table given
2027 * roleid, text tablename, and text priv name.
2028 */
2029Datum
2031{
2032 Oid roleid = PG_GETARG_OID(0);
2033 text *tablename = PG_GETARG_TEXT_PP(1);
2035 Oid tableoid;
2036 AclMode mode;
2038
2039 tableoid = convert_table_name(tablename);
2041
2042 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2043
2045}
2046
2047/*
2048 * has_table_privilege_id_id
2049 * Check user privileges on a table given
2050 * roleid, table oid, and text priv name.
2051 */
2052Datum
2054{
2055 Oid roleid = PG_GETARG_OID(0);
2056 Oid tableoid = PG_GETARG_OID(1);
2058 AclMode mode;
2060 bool is_missing = false;
2061
2063
2064 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2065
2066 if (is_missing)
2068
2070}
2071
2072/*
2073 * Support routines for has_table_privilege family.
2074 */
2075
2076/*
2077 * Given a table name expressed as a string, look it up and return Oid
2078 */
2079static Oid
2081{
2082 RangeVar *relrv;
2083
2085
2086 /* We might not even have permissions on this relation; don't lock it. */
2087 return RangeVarGetRelid(relrv, NoLock, false);
2088}
2089
2090/*
2091 * convert_table_priv_string
2092 * Convert text string to AclMode value.
2093 */
2094static AclMode
2096{
2097 static const priv_map table_priv_map[] = {
2098 {"SELECT", ACL_SELECT},
2099 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2100 {"INSERT", ACL_INSERT},
2101 {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
2102 {"UPDATE", ACL_UPDATE},
2103 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2104 {"DELETE", ACL_DELETE},
2105 {"DELETE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_DELETE)},
2106 {"TRUNCATE", ACL_TRUNCATE},
2107 {"TRUNCATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRUNCATE)},
2108 {"REFERENCES", ACL_REFERENCES},
2109 {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
2110 {"TRIGGER", ACL_TRIGGER},
2111 {"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
2112 {"MAINTAIN", ACL_MAINTAIN},
2113 {"MAINTAIN WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_MAINTAIN)},
2114 {NULL, 0}
2115 };
2116
2118}
2119
2120/*
2121 * has_sequence_privilege variants
2122 * These are all named "has_sequence_privilege" at the SQL level.
2123 * They take various combinations of relation name, relation OID,
2124 * user name, user OID, or implicit user = current_user.
2125 *
2126 * The result is a boolean value: true if user has the indicated
2127 * privilege, false if not. The variants that take a relation OID
2128 * return NULL if the OID doesn't exist.
2129 */
2130
2131/*
2132 * has_sequence_privilege_name_name
2133 * Check user privileges on a sequence given
2134 * name username, text sequencename, and text priv name.
2135 */
2136Datum
2160
2161/*
2162 * has_sequence_privilege_name
2163 * Check user privileges on a sequence given
2164 * text sequencename and text priv name.
2165 * current_user is assumed
2166 */
2167Datum
2190
2191/*
2192 * has_sequence_privilege_name_id
2193 * Check user privileges on a sequence given
2194 * name usename, sequence oid, and text priv name.
2195 */
2196Datum
2198{
2202 Oid roleid;
2203 AclMode mode;
2205 char relkind;
2206 bool is_missing = false;
2207
2210 relkind = get_rel_relkind(sequenceoid);
2211 if (relkind == '\0')
2213 else if (relkind != RELKIND_SEQUENCE)
2214 ereport(ERROR,
2216 errmsg("\"%s\" is not a sequence",
2218
2220
2221 if (is_missing)
2223
2225}
2226
2227/*
2228 * has_sequence_privilege_id
2229 * Check user privileges on a sequence given
2230 * sequence oid, and text priv name.
2231 * current_user is assumed
2232 */
2233Datum
2235{
2238 Oid roleid;
2239 AclMode mode;
2241 char relkind;
2242 bool is_missing = false;
2243
2244 roleid = GetUserId();
2246 relkind = get_rel_relkind(sequenceoid);
2247 if (relkind == '\0')
2249 else if (relkind != RELKIND_SEQUENCE)
2250 ereport(ERROR,
2252 errmsg("\"%s\" is not a sequence",
2254
2256
2257 if (is_missing)
2259
2261}
2262
2263/*
2264 * has_sequence_privilege_id_name
2265 * Check user privileges on a sequence given
2266 * roleid, text sequencename, and text priv name.
2267 */
2268Datum
2290
2291/*
2292 * has_sequence_privilege_id_id
2293 * Check user privileges on a sequence given
2294 * roleid, sequence oid, and text priv name.
2295 */
2296Datum
2298{
2299 Oid roleid = PG_GETARG_OID(0);
2302 AclMode mode;
2304 char relkind;
2305 bool is_missing = false;
2306
2308 relkind = get_rel_relkind(sequenceoid);
2309 if (relkind == '\0')
2311 else if (relkind != RELKIND_SEQUENCE)
2312 ereport(ERROR,
2314 errmsg("\"%s\" is not a sequence",
2316
2318
2319 if (is_missing)
2321
2323}
2324
2325/*
2326 * convert_sequence_priv_string
2327 * Convert text string to AclMode value.
2328 */
2329static AclMode
2331{
2332 static const priv_map sequence_priv_map[] = {
2333 {"USAGE", ACL_USAGE},
2334 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
2335 {"SELECT", ACL_SELECT},
2336 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2337 {"UPDATE", ACL_UPDATE},
2338 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2339 {NULL, 0}
2340 };
2341
2343}
2344
2345
2346/*
2347 * has_any_column_privilege variants
2348 * These are all named "has_any_column_privilege" at the SQL level.
2349 * They take various combinations of relation name, relation OID,
2350 * user name, user OID, or implicit user = current_user.
2351 *
2352 * The result is a boolean value: true if user has the indicated
2353 * privilege for any column of the table, false if not. The variants
2354 * that take a relation OID return NULL if the OID doesn't exist.
2355 */
2356
2357/*
2358 * has_any_column_privilege_name_name
2359 * Check user privileges on any column of a table given
2360 * name username, text tablename, and text priv name.
2361 */
2362Datum
2364{
2365 Name rolename = PG_GETARG_NAME(0);
2366 text *tablename = PG_GETARG_TEXT_PP(1);
2368 Oid roleid;
2369 Oid tableoid;
2370 AclMode mode;
2372
2373 roleid = get_role_oid_or_public(NameStr(*rolename));
2374 tableoid = convert_table_name(tablename);
2376
2377 /* First check at table level, then examine each column if needed */
2378 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2379 if (aclresult != ACLCHECK_OK)
2380 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2381 ACLMASK_ANY);
2382
2384}
2385
2386/*
2387 * has_any_column_privilege_name
2388 * Check user privileges on any column of a table given
2389 * text tablename and text priv name.
2390 * current_user is assumed
2391 */
2392Datum
2394{
2395 text *tablename = PG_GETARG_TEXT_PP(0);
2397 Oid roleid;
2398 Oid tableoid;
2399 AclMode mode;
2401
2402 roleid = GetUserId();
2403 tableoid = convert_table_name(tablename);
2405
2406 /* First check at table level, then examine each column if needed */
2407 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2408 if (aclresult != ACLCHECK_OK)
2409 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2410 ACLMASK_ANY);
2411
2413}
2414
2415/*
2416 * has_any_column_privilege_name_id
2417 * Check user privileges on any column of a table given
2418 * name usename, table oid, and text priv name.
2419 */
2420Datum
2422{
2424 Oid tableoid = PG_GETARG_OID(1);
2426 Oid roleid;
2427 AclMode mode;
2429 bool is_missing = false;
2430
2433
2434 /* First check at table level, then examine each column if needed */
2435 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2436 if (aclresult != ACLCHECK_OK)
2437 {
2438 if (is_missing)
2440 aclresult = pg_attribute_aclcheck_all_ext(tableoid, roleid, mode,
2442 if (is_missing)
2444 }
2445
2447}
2448
2449/*
2450 * has_any_column_privilege_id
2451 * Check user privileges on any column of a table given
2452 * table oid, and text priv name.
2453 * current_user is assumed
2454 */
2455Datum
2457{
2458 Oid tableoid = PG_GETARG_OID(0);
2460 Oid roleid;
2461 AclMode mode;
2463 bool is_missing = false;
2464
2465 roleid = GetUserId();
2467
2468 /* First check at table level, then examine each column if needed */
2469 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2470 if (aclresult != ACLCHECK_OK)
2471 {
2472 if (is_missing)
2474 aclresult = pg_attribute_aclcheck_all_ext(tableoid, roleid, mode,
2476 if (is_missing)
2478 }
2479
2481}
2482
2483/*
2484 * has_any_column_privilege_id_name
2485 * Check user privileges on any column of a table given
2486 * roleid, text tablename, and text priv name.
2487 */
2488Datum
2490{
2491 Oid roleid = PG_GETARG_OID(0);
2492 text *tablename = PG_GETARG_TEXT_PP(1);
2494 Oid tableoid;
2495 AclMode mode;
2497
2498 tableoid = convert_table_name(tablename);
2500
2501 /* First check at table level, then examine each column if needed */
2502 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2503 if (aclresult != ACLCHECK_OK)
2504 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2505 ACLMASK_ANY);
2506
2508}
2509
2510/*
2511 * has_any_column_privilege_id_id
2512 * Check user privileges on any column of a table given
2513 * roleid, table oid, and text priv name.
2514 */
2515Datum
2517{
2518 Oid roleid = PG_GETARG_OID(0);
2519 Oid tableoid = PG_GETARG_OID(1);
2521 AclMode mode;
2523 bool is_missing = false;
2524
2526
2527 /* First check at table level, then examine each column if needed */
2528 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2529 if (aclresult != ACLCHECK_OK)
2530 {
2531 if (is_missing)
2533 aclresult = pg_attribute_aclcheck_all_ext(tableoid, roleid, mode,
2535 if (is_missing)
2537 }
2538
2540}
2541
2542
2543/*
2544 * has_column_privilege variants
2545 * These are all named "has_column_privilege" at the SQL level.
2546 * They take various combinations of relation name, relation OID,
2547 * column name, column attnum, user name, user OID, or
2548 * implicit user = current_user.
2549 *
2550 * The result is a boolean value: true if user has the indicated
2551 * privilege, false if not. The variants that take a relation OID
2552 * return NULL (rather than throwing an error) if that relation OID
2553 * doesn't exist. Likewise, the variants that take an integer attnum
2554 * return NULL (rather than throwing an error) if there is no such
2555 * pg_attribute entry. All variants return NULL if an attisdropped
2556 * column is selected. These rules are meant to avoid unnecessary
2557 * failures in queries that scan pg_attribute.
2558 */
2559
2560/*
2561 * column_privilege_check: check column privileges, but don't throw an error
2562 * for dropped column or table
2563 *
2564 * Returns 1 if have the privilege, 0 if not, -1 if dropped column/table.
2565 */
2566static int
2568 Oid roleid, AclMode mode)
2569{
2571 bool is_missing = false;
2572
2573 /*
2574 * If convert_column_name failed, we can just return -1 immediately.
2575 */
2577 return -1;
2578
2579 /*
2580 * Check for column-level privileges first. This serves in part as a check
2581 * on whether the column even exists, so we need to do it before checking
2582 * table-level privilege.
2583 */
2584 aclresult = pg_attribute_aclcheck_ext(tableoid, attnum, roleid,
2585 mode, &is_missing);
2586 if (aclresult == ACLCHECK_OK)
2587 return 1;
2588 else if (is_missing)
2589 return -1;
2590
2591 /* Next check if we have the privilege at the table level */
2592 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2593 if (aclresult == ACLCHECK_OK)
2594 return 1;
2595 else if (is_missing)
2596 return -1;
2597 else
2598 return 0;
2599}
2600
2601/*
2602 * has_column_privilege_name_name_name
2603 * Check user privileges on a column given
2604 * name username, text tablename, text colname, and text priv name.
2605 */
2606Datum
2608{
2609 Name rolename = PG_GETARG_NAME(0);
2610 text *tablename = PG_GETARG_TEXT_PP(1);
2613 Oid roleid;
2614 Oid tableoid;
2616 AclMode mode;
2617 int privresult;
2618
2619 roleid = get_role_oid_or_public(NameStr(*rolename));
2620 tableoid = convert_table_name(tablename);
2623
2624 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2625 if (privresult < 0)
2628}
2629
2630/*
2631 * has_column_privilege_name_name_attnum
2632 * Check user privileges on a column given
2633 * name username, text tablename, int attnum, and text priv name.
2634 */
2635Datum
2637{
2638 Name rolename = PG_GETARG_NAME(0);
2639 text *tablename = PG_GETARG_TEXT_PP(1);
2642 Oid roleid;
2643 Oid tableoid;
2644 AclMode mode;
2645 int privresult;
2646
2647 roleid = get_role_oid_or_public(NameStr(*rolename));
2648 tableoid = convert_table_name(tablename);
2650
2651 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2652 if (privresult < 0)
2655}
2656
2657/*
2658 * has_column_privilege_name_id_name
2659 * Check user privileges on a column given
2660 * name username, table oid, text colname, and text priv name.
2661 */
2662Datum
2683
2684/*
2685 * has_column_privilege_name_id_attnum
2686 * Check user privileges on a column given
2687 * name username, table oid, int attnum, and text priv name.
2688 */
2689Datum
2708
2709/*
2710 * has_column_privilege_id_name_name
2711 * Check user privileges on a column given
2712 * oid roleid, text tablename, text colname, and text priv name.
2713 */
2714Datum
2716{
2717 Oid roleid = PG_GETARG_OID(0);
2718 text *tablename = PG_GETARG_TEXT_PP(1);
2721 Oid tableoid;
2723 AclMode mode;
2724 int privresult;
2725
2726 tableoid = convert_table_name(tablename);
2729
2730 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2731 if (privresult < 0)
2734}
2735
2736/*
2737 * has_column_privilege_id_name_attnum
2738 * Check user privileges on a column given
2739 * oid roleid, text tablename, int attnum, and text priv name.
2740 */
2741Datum
2743{
2744 Oid roleid = PG_GETARG_OID(0);
2745 text *tablename = PG_GETARG_TEXT_PP(1);
2748 Oid tableoid;
2749 AclMode mode;
2750 int privresult;
2751
2752 tableoid = convert_table_name(tablename);
2754
2755 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2756 if (privresult < 0)
2759}
2760
2761/*
2762 * has_column_privilege_id_id_name
2763 * Check user privileges on a column given
2764 * oid roleid, table oid, text colname, and text priv name.
2765 */
2766Datum
2785
2786/*
2787 * has_column_privilege_id_id_attnum
2788 * Check user privileges on a column given
2789 * oid roleid, table oid, int attnum, and text priv name.
2790 */
2791Datum
2808
2809/*
2810 * has_column_privilege_name_name
2811 * Check user privileges on a column given
2812 * text tablename, text colname, and text priv name.
2813 * current_user is assumed
2814 */
2815Datum
2817{
2818 text *tablename = PG_GETARG_TEXT_PP(0);
2821 Oid roleid;
2822 Oid tableoid;
2824 AclMode mode;
2825 int privresult;
2826
2827 roleid = GetUserId();
2828 tableoid = convert_table_name(tablename);
2831
2832 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2833 if (privresult < 0)
2836}
2837
2838/*
2839 * has_column_privilege_name_attnum
2840 * Check user privileges on a column given
2841 * text tablename, int attnum, and text priv name.
2842 * current_user is assumed
2843 */
2844Datum
2846{
2847 text *tablename = PG_GETARG_TEXT_PP(0);
2850 Oid roleid;
2851 Oid tableoid;
2852 AclMode mode;
2853 int privresult;
2854
2855 roleid = GetUserId();
2856 tableoid = convert_table_name(tablename);
2858
2859 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2860 if (privresult < 0)
2863}
2864
2865/*
2866 * has_column_privilege_id_name
2867 * Check user privileges on a column given
2868 * table oid, text colname, and text priv name.
2869 * current_user is assumed
2870 */
2871Datum
2873{
2874 Oid tableoid = PG_GETARG_OID(0);
2877 Oid roleid;
2879 AclMode mode;
2880 int privresult;
2881
2882 roleid = GetUserId();
2885
2886 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2887 if (privresult < 0)
2890}
2891
2892/*
2893 * has_column_privilege_id_attnum
2894 * Check user privileges on a column given
2895 * table oid, int attnum, and text priv name.
2896 * current_user is assumed
2897 */
2898Datum
2900{
2901 Oid tableoid = PG_GETARG_OID(0);
2904 Oid roleid;
2905 AclMode mode;
2906 int privresult;
2907
2908 roleid = GetUserId();
2910
2911 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2912 if (privresult < 0)
2915}
2916
2917/*
2918 * Support routines for has_column_privilege family.
2919 */
2920
2921/*
2922 * Given a table OID and a column name expressed as a string, look it up
2923 * and return the column number. Returns InvalidAttrNumber in cases
2924 * where caller should return NULL instead of failing.
2925 */
2926static AttrNumber
2928{
2929 char *colname;
2932
2933 colname = text_to_cstring(column);
2934
2935 /*
2936 * We don't use get_attnum() here because it will report that dropped
2937 * columns don't exist. We need to treat dropped columns differently from
2938 * nonexistent columns.
2939 */
2941 ObjectIdGetDatum(tableoid),
2942 CStringGetDatum(colname));
2944 {
2946
2948 /* We want to return NULL for dropped columns */
2949 if (attributeForm->attisdropped)
2951 else
2952 attnum = attributeForm->attnum;
2954 }
2955 else
2956 {
2957 char *tablename = get_rel_name(tableoid);
2958
2959 /*
2960 * If the table OID is bogus, or it's just been dropped, we'll get
2961 * NULL back. In such cases we want has_column_privilege to return
2962 * NULL too, so just return InvalidAttrNumber.
2963 */
2964 if (tablename != NULL)
2965 {
2966 /* tableoid exists, colname does not, so throw error */
2967 ereport(ERROR,
2969 errmsg("column \"%s\" of relation \"%s\" does not exist",
2970 colname, tablename)));
2971 }
2972 /* tableoid doesn't exist, so act like attisdropped case */
2974 }
2975
2976 pfree(colname);
2977 return attnum;
2978}
2979
2980/*
2981 * convert_column_priv_string
2982 * Convert text string to AclMode value.
2983 */
2984static AclMode
2986{
2987 static const priv_map column_priv_map[] = {
2988 {"SELECT", ACL_SELECT},
2989 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2990 {"INSERT", ACL_INSERT},
2991 {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
2992 {"UPDATE", ACL_UPDATE},
2993 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2994 {"REFERENCES", ACL_REFERENCES},
2995 {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
2996 {NULL, 0}
2997 };
2998
3000}
3001
3002
3003/*
3004 * has_database_privilege variants
3005 * These are all named "has_database_privilege" at the SQL level.
3006 * They take various combinations of database name, database OID,
3007 * user name, user OID, or implicit user = current_user.
3008 *
3009 * The result is a boolean value: true if user has the indicated
3010 * privilege, false if not, or NULL if object doesn't exist.
3011 */
3012
3013/*
3014 * has_database_privilege_name_name
3015 * Check user privileges on a database given
3016 * name username, text databasename, and text priv name.
3017 */
3018Datum
3037
3038/*
3039 * has_database_privilege_name
3040 * Check user privileges on a database given
3041 * text databasename and text priv name.
3042 * current_user is assumed
3043 */
3044Datum
3062
3063/*
3064 * has_database_privilege_name_id
3065 * Check user privileges on a database given
3066 * name usename, database oid, and text priv name.
3067 */
3068Datum
3091
3092/*
3093 * has_database_privilege_id
3094 * Check user privileges on a database given
3095 * database oid, and text priv name.
3096 * current_user is assumed
3097 */
3098Datum
3120
3121/*
3122 * has_database_privilege_id_name
3123 * Check user privileges on a database given
3124 * roleid, text databasename, and text priv name.
3125 */
3126Datum
3143
3144/*
3145 * has_database_privilege_id_id
3146 * Check user privileges on a database given
3147 * roleid, database oid, and text priv name.
3148 */
3149Datum
3170
3171/*
3172 * Support routines for has_database_privilege family.
3173 */
3174
3175/*
3176 * Given a database name expressed as a string, look it up and return Oid
3177 */
3178static Oid
3185
3186/*
3187 * convert_database_priv_string
3188 * Convert text string to AclMode value.
3189 */
3190static AclMode
3192{
3193 static const priv_map database_priv_map[] = {
3194 {"CREATE", ACL_CREATE},
3195 {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
3196 {"TEMPORARY", ACL_CREATE_TEMP},
3197 {"TEMPORARY WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
3198 {"TEMP", ACL_CREATE_TEMP},
3199 {"TEMP WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
3200 {"CONNECT", ACL_CONNECT},
3201 {"CONNECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CONNECT)},
3202 {NULL, 0}
3203 };
3204
3206}
3207
3208
3209/*
3210 * has_foreign_data_wrapper_privilege variants
3211 * These are all named "has_foreign_data_wrapper_privilege" at the SQL level.
3212 * They take various combinations of foreign-data wrapper name,
3213 * fdw OID, user name, user OID, or implicit user = current_user.
3214 *
3215 * The result is a boolean value: true if user has the indicated
3216 * privilege, false if not.
3217 */
3218
3219/*
3220 * has_foreign_data_wrapper_privilege_name_name
3221 * Check user privileges on a foreign-data wrapper given
3222 * name username, text fdwname, and text priv name.
3223 */
3224Datum
3243
3244/*
3245 * has_foreign_data_wrapper_privilege_name
3246 * Check user privileges on a foreign-data wrapper given
3247 * text fdwname and text priv name.
3248 * current_user is assumed
3249 */
3250Datum
3268
3269/*
3270 * has_foreign_data_wrapper_privilege_name_id
3271 * Check user privileges on a foreign-data wrapper given
3272 * name usename, foreign-data wrapper oid, and text priv name.
3273 */
3274Datum
3297
3298/*
3299 * has_foreign_data_wrapper_privilege_id
3300 * Check user privileges on a foreign-data wrapper given
3301 * foreign-data wrapper oid, and text priv name.
3302 * current_user is assumed
3303 */
3304Datum
3326
3327/*
3328 * has_foreign_data_wrapper_privilege_id_name
3329 * Check user privileges on a foreign-data wrapper given
3330 * roleid, text fdwname, and text priv name.
3331 */
3332Datum
3349
3350/*
3351 * has_foreign_data_wrapper_privilege_id_id
3352 * Check user privileges on a foreign-data wrapper given
3353 * roleid, fdw oid, and text priv name.
3354 */
3355Datum
3376
3377/*
3378 * Support routines for has_foreign_data_wrapper_privilege family.
3379 */
3380
3381/*
3382 * Given a FDW name expressed as a string, look it up and return Oid
3383 */
3384static Oid
3386{
3387 char *fdwstr = text_to_cstring(fdwname);
3388
3389 return get_foreign_data_wrapper_oid(fdwstr, false);
3390}
3391
3392/*
3393 * convert_foreign_data_wrapper_priv_string
3394 * Convert text string to AclMode value.
3395 */
3396static AclMode
3398{
3399 static const priv_map foreign_data_wrapper_priv_map[] = {
3400 {"USAGE", ACL_USAGE},
3401 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3402 {NULL, 0}
3403 };
3404
3406}
3407
3408
3409/*
3410 * has_function_privilege variants
3411 * These are all named "has_function_privilege" at the SQL level.
3412 * They take various combinations of function name, function OID,
3413 * user name, user OID, or implicit user = current_user.
3414 *
3415 * The result is a boolean value: true if user has the indicated
3416 * privilege, false if not, or NULL if object doesn't exist.
3417 */
3418
3419/*
3420 * has_function_privilege_name_name
3421 * Check user privileges on a function given
3422 * name username, text functionname, and text priv name.
3423 */
3424Datum
3443
3444/*
3445 * has_function_privilege_name
3446 * Check user privileges on a function given
3447 * text functionname and text priv name.
3448 * current_user is assumed
3449 */
3450Datum
3468
3469/*
3470 * has_function_privilege_name_id
3471 * Check user privileges on a function given
3472 * name usename, function oid, and text priv name.
3473 */
3474Datum
3497
3498/*
3499 * has_function_privilege_id
3500 * Check user privileges on a function given
3501 * function oid, and text priv name.
3502 * current_user is assumed
3503 */
3504Datum
3526
3527/*
3528 * has_function_privilege_id_name
3529 * Check user privileges on a function given
3530 * roleid, text functionname, and text priv name.
3531 */
3532Datum
3549
3550/*
3551 * has_function_privilege_id_id
3552 * Check user privileges on a function given
3553 * roleid, function oid, and text priv name.
3554 */
3555Datum
3576
3577/*
3578 * Support routines for has_function_privilege family.
3579 */
3580
3581/*
3582 * Given a function name expressed as a string, look it up and return Oid
3583 */
3584static Oid
3586{
3588 Oid oid;
3589
3592
3593 if (!OidIsValid(oid))
3594 ereport(ERROR,
3596 errmsg("function \"%s\" does not exist", funcname)));
3597
3598 return oid;
3599}
3600
3601/*
3602 * convert_function_priv_string
3603 * Convert text string to AclMode value.
3604 */
3605static AclMode
3607{
3608 static const priv_map function_priv_map[] = {
3609 {"EXECUTE", ACL_EXECUTE},
3610 {"EXECUTE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_EXECUTE)},
3611 {NULL, 0}
3612 };
3613
3615}
3616
3617
3618/*
3619 * has_language_privilege variants
3620 * These are all named "has_language_privilege" at the SQL level.
3621 * They take various combinations of language name, language OID,
3622 * user name, user OID, or implicit user = current_user.
3623 *
3624 * The result is a boolean value: true if user has the indicated
3625 * privilege, false if not, or NULL if object doesn't exist.
3626 */
3627
3628/*
3629 * has_language_privilege_name_name
3630 * Check user privileges on a language given
3631 * name username, text languagename, and text priv name.
3632 */
3633Datum
3652
3653/*
3654 * has_language_privilege_name
3655 * Check user privileges on a language given
3656 * text languagename and text priv name.
3657 * current_user is assumed
3658 */
3659Datum
3677
3678/*
3679 * has_language_privilege_name_id
3680 * Check user privileges on a language given
3681 * name usename, language oid, and text priv name.
3682 */
3683Datum
3706
3707/*
3708 * has_language_privilege_id
3709 * Check user privileges on a language given
3710 * language oid, and text priv name.
3711 * current_user is assumed
3712 */
3713Datum
3735
3736/*
3737 * has_language_privilege_id_name
3738 * Check user privileges on a language given
3739 * roleid, text languagename, and text priv name.
3740 */
3741Datum
3758
3759/*
3760 * has_language_privilege_id_id
3761 * Check user privileges on a language given
3762 * roleid, language oid, and text priv name.
3763 */
3764Datum
3785
3786/*
3787 * Support routines for has_language_privilege family.
3788 */
3789
3790/*
3791 * Given a language name expressed as a string, look it up and return Oid
3792 */
3793static Oid
3795{
3796 char *langname = text_to_cstring(languagename);
3797
3798 return get_language_oid(langname, false);
3799}
3800
3801/*
3802 * convert_language_priv_string
3803 * Convert text string to AclMode value.
3804 */
3805static AclMode
3807{
3808 static const priv_map language_priv_map[] = {
3809 {"USAGE", ACL_USAGE},
3810 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3811 {NULL, 0}
3812 };
3813
3815}
3816
3817
3818/*
3819 * has_schema_privilege variants
3820 * These are all named "has_schema_privilege" at the SQL level.
3821 * They take various combinations of schema name, schema OID,
3822 * user name, user OID, or implicit user = current_user.
3823 *
3824 * The result is a boolean value: true if user has the indicated
3825 * privilege, false if not, or NULL if object doesn't exist.
3826 */
3827
3828/*
3829 * has_schema_privilege_name_name
3830 * Check user privileges on a schema given
3831 * name username, text schemaname, and text priv name.
3832 */
3833Datum
3852
3853/*
3854 * has_schema_privilege_name
3855 * Check user privileges on a schema given
3856 * text schemaname and text priv name.
3857 * current_user is assumed
3858 */
3859Datum
3877
3878/*
3879 * has_schema_privilege_name_id
3880 * Check user privileges on a schema given
3881 * name usename, schema oid, and text priv name.
3882 */
3883Datum
3906
3907/*
3908 * has_schema_privilege_id
3909 * Check user privileges on a schema given
3910 * schema oid, and text priv name.
3911 * current_user is assumed
3912 */
3913Datum
3935
3936/*
3937 * has_schema_privilege_id_name
3938 * Check user privileges on a schema given
3939 * roleid, text schemaname, and text priv name.
3940 */
3941Datum
3958
3959/*
3960 * has_schema_privilege_id_id
3961 * Check user privileges on a schema given
3962 * roleid, schema oid, and text priv name.
3963 */
3964Datum
3985
3986/*
3987 * Support routines for has_schema_privilege family.
3988 */
3989
3990/*
3991 * Given a schema name expressed as a string, look it up and return Oid
3992 */
3993static Oid
3995{
3996 char *nspname = text_to_cstring(schemaname);
3997
3998 return get_namespace_oid(nspname, false);
3999}
4000
4001/*
4002 * convert_schema_priv_string
4003 * Convert text string to AclMode value.
4004 */
4005static AclMode
4007{
4008 static const priv_map schema_priv_map[] = {
4009 {"CREATE", ACL_CREATE},
4010 {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4011 {"USAGE", ACL_USAGE},
4012 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
4013 {NULL, 0}
4014 };
4015
4017}
4018
4019
4020/*
4021 * has_server_privilege variants
4022 * These are all named "has_server_privilege" at the SQL level.
4023 * They take various combinations of foreign server name,
4024 * server OID, user name, user OID, or implicit user = current_user.
4025 *
4026 * The result is a boolean value: true if user has the indicated
4027 * privilege, false if not.
4028 */
4029
4030/*
4031 * has_server_privilege_name_name
4032 * Check user privileges on a foreign server given
4033 * name username, text servername, and text priv name.
4034 */
4035Datum
4037{
4039 text *servername = PG_GETARG_TEXT_PP(1);
4041 Oid roleid;
4042 Oid serverid;
4043 AclMode mode;
4045
4047 serverid = convert_server_name(servername);
4049
4051
4053}
4054
4055/*
4056 * has_server_privilege_name
4057 * Check user privileges on a foreign server given
4058 * text servername and text priv name.
4059 * current_user is assumed
4060 */
4061Datum
4063{
4064 text *servername = PG_GETARG_TEXT_PP(0);
4066 Oid roleid;
4067 Oid serverid;
4068 AclMode mode;
4070
4071 roleid = GetUserId();
4072 serverid = convert_server_name(servername);
4074
4076
4078}
4079
4080/*
4081 * has_server_privilege_name_id
4082 * Check user privileges on a foreign server given
4083 * name usename, foreign server oid, and text priv name.
4084 */
4085Datum
4108
4109/*
4110 * has_server_privilege_id
4111 * Check user privileges on a foreign server given
4112 * server oid, and text priv name.
4113 * current_user is assumed
4114 */
4115Datum
4117{
4118 Oid serverid = PG_GETARG_OID(0);
4120 Oid roleid;
4121 AclMode mode;
4123 bool is_missing = false;
4124
4125 roleid = GetUserId();
4127
4129 roleid, mode,
4130 &is_missing);
4131
4132 if (is_missing)
4134
4136}
4137
4138/*
4139 * has_server_privilege_id_name
4140 * Check user privileges on a foreign server given
4141 * roleid, text servername, and text priv name.
4142 */
4143Datum
4145{
4146 Oid roleid = PG_GETARG_OID(0);
4147 text *servername = PG_GETARG_TEXT_PP(1);
4149 Oid serverid;
4150 AclMode mode;
4152
4153 serverid = convert_server_name(servername);
4155
4157
4159}
4160
4161/*
4162 * has_server_privilege_id_id
4163 * Check user privileges on a foreign server given
4164 * roleid, server oid, and text priv name.
4165 */
4166Datum
4168{
4169 Oid roleid = PG_GETARG_OID(0);
4170 Oid serverid = PG_GETARG_OID(1);
4172 AclMode mode;
4174 bool is_missing = false;
4175
4177
4179 roleid, mode,
4180 &is_missing);
4181
4182 if (is_missing)
4184
4186}
4187
4188/*
4189 * Support routines for has_server_privilege family.
4190 */
4191
4192/*
4193 * Given a server name expressed as a string, look it up and return Oid
4194 */
4195static Oid
4197{
4198 char *serverstr = text_to_cstring(servername);
4199
4200 return get_foreign_server_oid(serverstr, false);
4201}
4202
4203/*
4204 * convert_server_priv_string
4205 * Convert text string to AclMode value.
4206 */
4207static AclMode
4209{
4210 static const priv_map server_priv_map[] = {
4211 {"USAGE", ACL_USAGE},
4212 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
4213 {NULL, 0}
4214 };
4215
4217}
4218
4219
4220/*
4221 * has_tablespace_privilege variants
4222 * These are all named "has_tablespace_privilege" at the SQL level.
4223 * They take various combinations of tablespace name, tablespace OID,
4224 * user name, user OID, or implicit user = current_user.
4225 *
4226 * The result is a boolean value: true if user has the indicated
4227 * privilege, false if not.
4228 */
4229
4230/*
4231 * has_tablespace_privilege_name_name
4232 * Check user privileges on a tablespace given
4233 * name username, text tablespacename, and text priv name.
4234 */
4235Datum
4254
4255/*
4256 * has_tablespace_privilege_name
4257 * Check user privileges on a tablespace given
4258 * text tablespacename and text priv name.
4259 * current_user is assumed
4260 */
4261Datum
4279
4280/*
4281 * has_tablespace_privilege_name_id
4282 * Check user privileges on a tablespace given
4283 * name usename, tablespace oid, and text priv name.
4284 */
4285Datum
4308
4309/*
4310 * has_tablespace_privilege_id
4311 * Check user privileges on a tablespace given
4312 * tablespace oid, and text priv name.
4313 * current_user is assumed
4314 */
4315Datum
4337
4338/*
4339 * has_tablespace_privilege_id_name
4340 * Check user privileges on a tablespace given
4341 * roleid, text tablespacename, and text priv name.
4342 */
4343Datum
4360
4361/*
4362 * has_tablespace_privilege_id_id
4363 * Check user privileges on a tablespace given
4364 * roleid, tablespace oid, and text priv name.
4365 */
4366Datum
4387
4388/*
4389 * Support routines for has_tablespace_privilege family.
4390 */
4391
4392/*
4393 * Given a tablespace name expressed as a string, look it up and return Oid
4394 */
4395static Oid
4397{
4398 char *spcname = text_to_cstring(tablespacename);
4399
4400 return get_tablespace_oid(spcname, false);
4401}
4402
4403/*
4404 * convert_tablespace_priv_string
4405 * Convert text string to AclMode value.
4406 */
4407static AclMode
4409{
4410 static const priv_map tablespace_priv_map[] = {
4411 {"CREATE", ACL_CREATE},
4412 {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4413 {NULL, 0}
4414 };
4415
4417}
4418
4419/*
4420 * has_type_privilege variants
4421 * These are all named "has_type_privilege" at the SQL level.
4422 * They take various combinations of type name, type OID,
4423 * user name, user OID, or implicit user = current_user.
4424 *
4425 * The result is a boolean value: true if user has the indicated
4426 * privilege, false if not, or NULL if object doesn't exist.
4427 */
4428
4429/*
4430 * has_type_privilege_name_name
4431 * Check user privileges on a type given
4432 * name username, text typename, and text priv name.
4433 */
4434Datum
4436{
4438 text *typename = PG_GETARG_TEXT_PP(1);
4440 Oid roleid;
4441 Oid typeoid;
4442 AclMode mode;
4444
4446 typeoid = convert_type_name(typename);
4448
4449 aclresult = object_aclcheck(TypeRelationId, typeoid, roleid, mode);
4450
4452}
4453
4454/*
4455 * has_type_privilege_name
4456 * Check user privileges on a type given
4457 * text typename and text priv name.
4458 * current_user is assumed
4459 */
4460Datum
4462{
4463 text *typename = PG_GETARG_TEXT_PP(0);
4465 Oid roleid;
4466 Oid typeoid;
4467 AclMode mode;
4469
4470 roleid = GetUserId();
4471 typeoid = convert_type_name(typename);
4473
4474 aclresult = object_aclcheck(TypeRelationId, typeoid, roleid, mode);
4475
4477}
4478
4479/*
4480 * has_type_privilege_name_id
4481 * Check user privileges on a type given
4482 * name usename, type oid, and text priv name.
4483 */
4484Datum
4486{
4488 Oid typeoid = PG_GETARG_OID(1);
4490 Oid roleid;
4491 AclMode mode;
4493 bool is_missing = false;
4494
4497
4499 roleid, mode,
4500 &is_missing);
4501
4502 if (is_missing)
4504
4506}
4507
4508/*
4509 * has_type_privilege_id
4510 * Check user privileges on a type given
4511 * type oid, and text priv name.
4512 * current_user is assumed
4513 */
4514Datum
4516{
4517 Oid typeoid = PG_GETARG_OID(0);
4519 Oid roleid;
4520 AclMode mode;
4522 bool is_missing = false;
4523
4524 roleid = GetUserId();
4526
4528 roleid, mode,
4529 &is_missing);
4530
4531 if (is_missing)
4533
4535}
4536
4537/*
4538 * has_type_privilege_id_name
4539 * Check user privileges on a type given
4540 * roleid, text typename, and text priv name.
4541 */
4542Datum
4544{
4545 Oid roleid = PG_GETARG_OID(0);
4546 text *typename = PG_GETARG_TEXT_PP(1);
4548 Oid typeoid;
4549 AclMode mode;
4551
4552 typeoid = convert_type_name(typename);
4554
4555 aclresult = object_aclcheck(TypeRelationId, typeoid, roleid, mode);
4556
4558}
4559
4560/*
4561 * has_type_privilege_id_id
4562 * Check user privileges on a type given
4563 * roleid, type oid, and text priv name.
4564 */
4565Datum
4567{
4568 Oid roleid = PG_GETARG_OID(0);
4569 Oid typeoid = PG_GETARG_OID(1);
4571 AclMode mode;
4573 bool is_missing = false;
4574
4576
4578 roleid, mode,
4579 &is_missing);
4580
4581 if (is_missing)
4583
4585}
4586
4587/*
4588 * Support routines for has_type_privilege family.
4589 */
4590
4591/*
4592 * Given a type name expressed as a string, look it up and return Oid
4593 */
4594static Oid
4596{
4597 char *typname = text_to_cstring(typename);
4598 Oid oid;
4599
4602
4603 if (!OidIsValid(oid))
4604 ereport(ERROR,
4606 errmsg("type \"%s\" does not exist", typname)));
4607
4608 return oid;
4609}
4610
4611/*
4612 * convert_type_priv_string
4613 * Convert text string to AclMode value.
4614 */
4615static AclMode
4617{
4618 static const priv_map type_priv_map[] = {
4619 {"USAGE", ACL_USAGE},
4620 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
4621 {NULL, 0}
4622 };
4623
4625}
4626
4627/*
4628 * has_parameter_privilege variants
4629 * These are all named "has_parameter_privilege" at the SQL level.
4630 * They take various combinations of parameter name with
4631 * user name, user OID, or implicit user = current_user.
4632 *
4633 * The result is a boolean value: true if user has been granted
4634 * the indicated privilege or false if not.
4635 */
4636
4637/*
4638 * has_param_priv_byname
4639 *
4640 * Helper function to check user privileges on a parameter given the
4641 * role by Oid, parameter by text name, and privileges as AclMode.
4642 */
4643static bool
4645{
4647
4648 return pg_parameter_aclcheck(paramstr, roleid, priv) == ACLCHECK_OK;
4649}
4650
4651/*
4652 * has_parameter_privilege_name_name
4653 * Check user privileges on a parameter given name username, text
4654 * parameter, and text priv name.
4655 */
4656Datum
4666
4667/*
4668 * has_parameter_privilege_name
4669 * Check user privileges on a parameter given text parameter and text priv
4670 * name. current_user is assumed
4671 */
4672Datum
4680
4681/*
4682 * has_parameter_privilege_id_name
4683 * Check user privileges on a parameter given roleid, text parameter, and
4684 * text priv name.
4685 */
4686Datum
4695
4696/*
4697 * Support routines for has_parameter_privilege family.
4698 */
4699
4700/*
4701 * convert_parameter_priv_string
4702 * Convert text string to AclMode value.
4703 */
4704static AclMode
4706{
4707 static const priv_map parameter_priv_map[] = {
4708 {"SET", ACL_SET},
4709 {"SET WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SET)},
4710 {"ALTER SYSTEM", ACL_ALTER_SYSTEM},
4711 {"ALTER SYSTEM WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_ALTER_SYSTEM)},
4712 {NULL, 0}
4713 };
4714
4716}
4717
4718/*
4719 * has_largeobject_privilege variants
4720 * These are all named "has_largeobject_privilege" at the SQL level.
4721 * They take various combinations of large object OID with
4722 * user name, user OID, or implicit user = current_user.
4723 *
4724 * The result is a boolean value: true if user has the indicated
4725 * privilege, false if not, or NULL if object doesn't exist.
4726 */
4727
4728/*
4729 * has_lo_priv_byid
4730 *
4731 * Helper function to check user privileges on a large object given the
4732 * role by Oid, large object by Oid, and privileges as AclMode.
4733 */
4734static bool
4736{
4737 Snapshot snapshot = NULL;
4739
4740 if (priv & ACL_UPDATE)
4741 snapshot = NULL;
4742 else
4743 snapshot = GetActiveSnapshot();
4744
4745 if (!LargeObjectExistsWithSnapshot(lobjId, snapshot))
4746 {
4748 *is_missing = true;
4749 return false;
4750 }
4751
4753 return true;
4754
4756 roleid,
4757 priv,
4758 snapshot);
4759 return aclresult == ACLCHECK_OK;
4760}
4761
4762/*
4763 * has_largeobject_privilege_name_id
4764 * Check user privileges on a large object given
4765 * name username, large object oid, and text priv name.
4766 */
4767Datum
4786
4787/*
4788 * has_largeobject_privilege_id
4789 * Check user privileges on a large object given
4790 * large object oid, and text priv name.
4791 * current_user is assumed
4792 */
4793Datum
4811
4812/*
4813 * has_largeobject_privilege_id_id
4814 * Check user privileges on a large object given
4815 * roleid, large object oid, and text priv name.
4816 */
4817Datum
4835
4836/*
4837 * convert_largeobject_priv_string
4838 * Convert text string to AclMode value.
4839 */
4840static AclMode
4842{
4843 static const priv_map largeobject_priv_map[] = {
4844 {"SELECT", ACL_SELECT},
4845 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
4846 {"UPDATE", ACL_UPDATE},
4847 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
4848 {NULL, 0}
4849 };
4850
4852}
4853
4854/*
4855 * pg_has_role variants
4856 * These are all named "pg_has_role" at the SQL level.
4857 * They take various combinations of role name, role OID,
4858 * user name, user OID, or implicit user = current_user.
4859 *
4860 * The result is a boolean value: true if user has the indicated
4861 * privilege, false if not.
4862 */
4863
4864/*
4865 * pg_has_role_name_name
4866 * Check user privileges on a role given
4867 * name username, name rolename, and text priv name.
4868 */
4869Datum
4871{
4873 Name rolename = PG_GETARG_NAME(1);
4875 Oid roleid;
4876 Oid roleoid;
4877 AclMode mode;
4879
4880 roleid = get_role_oid(NameStr(*username), false);
4881 roleoid = get_role_oid(NameStr(*rolename), false);
4883
4884 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4885
4887}
4888
4889/*
4890 * pg_has_role_name
4891 * Check user privileges on a role given
4892 * name rolename and text priv name.
4893 * current_user is assumed
4894 */
4895Datum
4897{
4898 Name rolename = PG_GETARG_NAME(0);
4900 Oid roleid;
4901 Oid roleoid;
4902 AclMode mode;
4904
4905 roleid = GetUserId();
4906 roleoid = get_role_oid(NameStr(*rolename), false);
4908
4909 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4910
4912}
4913
4914/*
4915 * pg_has_role_name_id
4916 * Check user privileges on a role given
4917 * name usename, role oid, and text priv name.
4918 */
4919Datum
4921{
4923 Oid roleoid = PG_GETARG_OID(1);
4925 Oid roleid;
4926 AclMode mode;
4928
4929 roleid = get_role_oid(NameStr(*username), false);
4931
4932 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4933
4935}
4936
4937/*
4938 * pg_has_role_id
4939 * Check user privileges on a role given
4940 * role oid, and text priv name.
4941 * current_user is assumed
4942 */
4943Datum
4945{
4946 Oid roleoid = PG_GETARG_OID(0);
4948 Oid roleid;
4949 AclMode mode;
4951
4952 roleid = GetUserId();
4954
4955 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4956
4958}
4959
4960/*
4961 * pg_has_role_id_name
4962 * Check user privileges on a role given
4963 * roleid, name rolename, and text priv name.
4964 */
4965Datum
4967{
4968 Oid roleid = PG_GETARG_OID(0);
4969 Name rolename = PG_GETARG_NAME(1);
4971 Oid roleoid;
4972 AclMode mode;
4974
4975 roleoid = get_role_oid(NameStr(*rolename), false);
4977
4978 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4979
4981}
4982
4983/*
4984 * pg_has_role_id_id
4985 * Check user privileges on a role given
4986 * roleid, role oid, and text priv name.
4987 */
4988Datum
5003
5004/*
5005 * Support routines for pg_has_role family.
5006 */
5007
5008/*
5009 * convert_role_priv_string
5010 * Convert text string to AclMode value.
5011 *
5012 * We use USAGE to denote whether the privileges of the role are accessible
5013 * (has_privs_of_role), MEMBER to denote is_member, and MEMBER WITH GRANT
5014 * (or ADMIN) OPTION to denote is_admin. There is no ACL bit corresponding
5015 * to MEMBER so we cheat and use ACL_CREATE for that. This convention
5016 * is shared only with pg_role_aclcheck, below.
5017 */
5018static AclMode
5020{
5021 static const priv_map role_priv_map[] = {
5022 {"USAGE", ACL_USAGE},
5023 {"MEMBER", ACL_CREATE},
5024 {"SET", ACL_SET},
5025 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
5026 {"USAGE WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
5027 {"MEMBER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
5028 {"MEMBER WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
5029 {"SET WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
5030 {"SET WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
5031 {NULL, 0}
5032 };
5033
5035}
5036
5037/*
5038 * pg_role_aclcheck
5039 * Quick-and-dirty support for pg_has_role
5040 */
5041static AclResult
5043{
5045 {
5046 if (is_admin_of_role(roleid, role_oid))
5047 return ACLCHECK_OK;
5048 }
5049 if (mode & ACL_CREATE)
5050 {
5051 if (is_member_of_role(roleid, role_oid))
5052 return ACLCHECK_OK;
5053 }
5054 if (mode & ACL_USAGE)
5055 {
5056 if (has_privs_of_role(roleid, role_oid))
5057 return ACLCHECK_OK;
5058 }
5059 if (mode & ACL_SET)
5060 {
5061 if (member_can_set_role(roleid, role_oid))
5062 return ACLCHECK_OK;
5063 }
5064 return ACLCHECK_NO_PRIV;
5065}
5066
5067
5068/*
5069 * initialization function (called by InitPostgres)
5070 */
5071void
5073{
5075 {
5079
5080 /*
5081 * In normal mode, set a callback on any syscache invalidation of rows
5082 * of pg_auth_members (for roles_is_member_of()) pg_database (for
5083 * roles_is_member_of())
5084 */
5087 (Datum) 0);
5090 (Datum) 0);
5093 (Datum) 0);
5094 }
5095}
5096
5097/*
5098 * RoleMembershipCacheCallback
5099 * Syscache inval callback function
5100 */
5101static void
5103 uint32 hashvalue)
5104{
5105 if (cacheid == DATABASEOID &&
5106 hashvalue != cached_db_hash &&
5107 hashvalue != 0)
5108 {
5109 return; /* ignore pg_database changes for other DBs */
5110 }
5111
5112 /* Force membership caches to be recomputed on next use */
5116}
5117
5118/*
5119 * A helper function for roles_is_member_of() that provides an optimized
5120 * implementation of list_append_unique_oid() via a Bloom filter. The caller
5121 * (i.e., roles_is_member_of()) is responsible for freeing bf once it is done
5122 * using this function.
5123 */
5124static inline List *
5126{
5127 unsigned char *roleptr = (unsigned char *) &role;
5128
5129 /*
5130 * If there is a previously-created Bloom filter, use it to try to
5131 * determine whether the role is missing from the list. If it says yes,
5132 * that's a hard fact and we can go ahead and add the role. If it says
5133 * no, that's only probabilistic and we'd better search the list. Without
5134 * a filter, we must always do an ordinary linear search through the
5135 * existing list.
5136 */
5137 if ((*bf && bloom_lacks_element(*bf, roleptr, sizeof(Oid))) ||
5139 {
5140 /*
5141 * If the list is large, we take on the overhead of creating and
5142 * populating a Bloom filter to speed up future calls to this
5143 * function.
5144 */
5145 if (*bf == NULL &&
5147 {
5149 foreach_oid(roleid, roles_list)
5150 bloom_add_element(*bf, (unsigned char *) &roleid, sizeof(Oid));
5151 }
5152
5153 /*
5154 * Finally, add the role to the list and the Bloom filter, if it
5155 * exists.
5156 */
5158 if (*bf)
5159 bloom_add_element(*bf, roleptr, sizeof(Oid));
5160 }
5161
5162 return roles_list;
5163}
5164
5165/*
5166 * Get a list of roles that the specified roleid is a member of
5167 *
5168 * Type ROLERECURSE_MEMBERS recurses through all grants; ROLERECURSE_PRIVS
5169 * recurses only through inheritable grants; and ROLERECURSE_SETROLE recurses
5170 * only through grants with set_option.
5171 *
5172 * Since indirect membership testing is relatively expensive, we cache
5173 * a list of memberships. Hence, the result is only guaranteed good until
5174 * the next call of roles_is_member_of()!
5175 *
5176 * For the benefit of select_best_grantor, the result is defined to be
5177 * in breadth-first order, ie, closer relationships earlier.
5178 *
5179 * If admin_of is not InvalidOid, this function sets *admin_role, either
5180 * to the OID of the first role in the result list that directly possesses
5181 * ADMIN OPTION on the role corresponding to admin_of, or to InvalidOid if
5182 * there is no such role.
5183 */
5184static List *
5187{
5188 Oid dba;
5190 ListCell *l;
5193 bloom_filter *bf = NULL;
5194
5196 if (admin_role != NULL)
5198
5199 /* If cache is valid and ADMIN OPTION not sought, just return the list */
5200 if (cached_role[type] == roleid && !OidIsValid(admin_of) &&
5202 return cached_roles[type];
5203
5204 /*
5205 * Role expansion happens in a non-database backend when guc.c checks
5206 * ROLE_PG_READ_ALL_SETTINGS for a physical walsender SHOW command. In
5207 * that case, no role gets pg_database_owner.
5208 */
5210 dba = InvalidOid;
5211 else
5212 {
5214
5216 if (!HeapTupleIsValid(dbtup))
5217 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
5220 }
5221
5222 /*
5223 * Find all the roles that roleid is a member of, including multi-level
5224 * recursion. The role itself will always be the first element of the
5225 * resulting list.
5226 *
5227 * Each element of the list is scanned to see if it adds any indirect
5228 * memberships. We can use a single list as both the record of
5229 * already-found memberships and the agenda of roles yet to be scanned.
5230 * This is a bit tricky but works because the foreach() macro doesn't
5231 * fetch the next list element until the bottom of the loop.
5232 */
5233 roles_list = list_make1_oid(roleid);
5234
5235 foreach(l, roles_list)
5236 {
5237 Oid memberid = lfirst_oid(l);
5239 int i;
5240
5241 /* Find roles that memberid is directly a member of */
5244 for (i = 0; i < memlist->n_members; i++)
5245 {
5246 HeapTuple tup = &memlist->members[i]->tuple;
5248 Oid otherid = form->roleid;
5249
5250 /*
5251 * While otherid==InvalidOid shouldn't appear in the catalog, the
5252 * OidIsValid() avoids crashing if that arises.
5253 */
5254 if (otherid == admin_of && form->admin_option &&
5257
5258 /* If we're supposed to ignore non-heritable grants, do so. */
5259 if (type == ROLERECURSE_PRIVS && !form->inherit_option)
5260 continue;
5261
5262 /* If we're supposed to ignore non-SET grants, do so. */
5263 if (type == ROLERECURSE_SETROLE && !form->set_option)
5264 continue;
5265
5266 /*
5267 * Even though there shouldn't be any loops in the membership
5268 * graph, we must test for having already seen this role. It is
5269 * legal for instance to have both A->B and A->C->B.
5270 */
5272 }
5274
5275 /* implement pg_database_owner implicit membership */
5276 if (memberid == dba && OidIsValid(dba))
5279 }
5280
5281 /*
5282 * Free the Bloom filter created by roles_list_append(), if there is one.
5283 */
5284 if (bf)
5285 bloom_free(bf);
5286
5287 /*
5288 * Copy the completed list into TopMemoryContext so it will persist.
5289 */
5294
5295 /*
5296 * Now safe to assign to state variable
5297 */
5298 cached_role[type] = InvalidOid; /* just paranoia */
5301 cached_role[type] = roleid;
5302
5303 /* And now we can return the answer */
5304 return cached_roles[type];
5305}
5306
5307
5308/*
5309 * Does member have the privileges of role (directly or indirectly)?
5310 *
5311 * This is defined not to recurse through grants that are not inherited,
5312 * and only inherited grants confer the associated privileges automatically.
5313 *
5314 * See also member_can_set_role, below.
5315 */
5316bool
5318{
5319 /* Fast path for simple case */
5320 if (member == role)
5321 return true;
5322
5323 /* Superusers have every privilege, so are part of every role */
5324 if (superuser_arg(member))
5325 return true;
5326
5327 /*
5328 * Find all the roles that member has the privileges of, including
5329 * multi-level recursion, then see if target role is any one of them.
5330 */
5332 InvalidOid, NULL),
5333 role);
5334}
5335
5336/*
5337 * Can member use SET ROLE to this role?
5338 *
5339 * There must be a chain of grants from 'member' to 'role' each of which
5340 * permits SET ROLE; that is, each of which has set_option = true.
5341 *
5342 * It doesn't matter whether the grants are inheritable. That's a separate
5343 * question; see has_privs_of_role.
5344 *
5345 * This function should be used to determine whether the session user can
5346 * use SET ROLE to become the target user. We also use it to determine whether
5347 * the session user can change an existing object to be owned by the target
5348 * user, or create new objects owned by the target user.
5349 */
5350bool
5352{
5353 /* Fast path for simple case */
5354 if (member == role)
5355 return true;
5356
5357 /* Superusers have every privilege, so can always SET ROLE */
5358 if (superuser_arg(member))
5359 return true;
5360
5361 /*
5362 * Find all the roles that member can access via SET ROLE, including
5363 * multi-level recursion, then see if target role is any one of them.
5364 */
5366 InvalidOid, NULL),
5367 role);
5368}
5369
5370/*
5371 * Permission violation error unless able to SET ROLE to target role.
5372 */
5373void
5375{
5376 if (!member_can_set_role(member, role))
5377 ereport(ERROR,
5379 errmsg("must be able to SET ROLE \"%s\"",
5380 GetUserNameFromId(role, false))));
5381}
5382
5383/*
5384 * Is member a member of role (directly or indirectly)?
5385 *
5386 * This is defined to recurse through grants whether they are inherited or not.
5387 *
5388 * Do not use this for privilege checking, instead use has_privs_of_role().
5389 * Don't use it for determining whether it's possible to SET ROLE to some
5390 * other role; for that, use member_can_set_role(). And don't use it for
5391 * determining whether it's OK to create an object owned by some other role:
5392 * use member_can_set_role() for that, too.
5393 *
5394 * In short, calling this function is the wrong thing to do nearly everywhere.
5395 */
5396bool
5398{
5399 /* Fast path for simple case */
5400 if (member == role)
5401 return true;
5402
5403 /* Superusers have every privilege, so are part of every role */
5404 if (superuser_arg(member))
5405 return true;
5406
5407 /*
5408 * Find all the roles that member is a member of, including multi-level
5409 * recursion, then see if target role is any one of them.
5410 */
5412 InvalidOid, NULL),
5413 role);
5414}
5415
5416/*
5417 * Is member a member of role, not considering superuserness?
5418 *
5419 * This is identical to is_member_of_role except we ignore superuser
5420 * status.
5421 *
5422 * Do not use this for privilege checking, instead use has_privs_of_role()
5423 */
5424bool
5426{
5427 /* Fast path for simple case */
5428 if (member == role)
5429 return true;
5430
5431 /*
5432 * Find all the roles that member is a member of, including multi-level
5433 * recursion, then see if target role is any one of them.
5434 */
5436 InvalidOid, NULL),
5437 role);
5438}
5439
5440
5441/*
5442 * Is member an admin of role? That is, is member the role itself (subject to
5443 * restrictions below), a member (directly or indirectly) WITH ADMIN OPTION,
5444 * or a superuser?
5445 */
5446bool
5448{
5450
5451 if (superuser_arg(member))
5452 return true;
5453
5454 /* By policy, a role cannot have WITH ADMIN OPTION on itself. */
5455 if (member == role)
5456 return false;
5457
5459 return OidIsValid(admin_role);
5460}
5461
5462/*
5463 * Find a role whose privileges "member" inherits which has ADMIN OPTION
5464 * on "role", ignoring super-userness.
5465 *
5466 * There might be more than one such role; prefer one which involves fewer
5467 * hops. That is, if member has ADMIN OPTION, prefer that over all other
5468 * options; if not, prefer a role from which member inherits more directly
5469 * over more indirect inheritance.
5470 */
5471Oid
5473{
5475
5476 /* By policy, a role cannot have WITH ADMIN OPTION on itself. */
5477 if (member == role)
5478 return InvalidOid;
5479
5481 return admin_role;
5482}
5483
5484/*
5485 * Select the effective grantor ID for a GRANT or REVOKE operation.
5486 *
5487 * If the GRANT/REVOKE has an explicit GRANTED BY clause, we always use
5488 * exactly that role (which may result in granting/revoking no privileges).
5489 * Otherwise, we seek a "best" grantor, starting with the current user.
5490 *
5491 * The grantor must always be either the object owner or some role that has
5492 * been explicitly granted grant options. This ensures that all granted
5493 * privileges appear to flow from the object owner, and there are never
5494 * multiple "original sources" of a privilege. Therefore, if the would-be
5495 * grantor is a member of a role that has the needed grant options, we have
5496 * to do the grant as that role instead.
5497 *
5498 * It is possible that the would-be grantor is a member of several roles
5499 * that have different subsets of the desired grant options, but no one
5500 * role has 'em all. In this case we pick a role with the largest number
5501 * of desired options. Ties are broken in favor of closer ancestors.
5502 *
5503 * grantedBy: the GRANTED BY clause of GRANT/REVOKE, or NULL if none
5504 * privileges: the privileges to be granted/revoked
5505 * acl: the ACL of the object in question
5506 * ownerId: the role owning the object in question
5507 * *grantorId: receives the OID of the role to do the grant as
5508 * *grantOptions: receives grant options actually held by grantorId (maybe 0)
5509 */
5510void
5512 const Acl *acl, Oid ownerId,
5514{
5515 Oid roleId = GetUserId();
5518 int nrights;
5519 ListCell *l;
5520
5521 /*
5522 * If we have GRANTED BY, resolve it and verify current user is allowed to
5523 * specify that role.
5524 */
5525 if (grantedBy)
5526 {
5527 Oid grantor = get_rolespec_oid(grantedBy, false);
5528
5529 if (!has_privs_of_role(roleId, grantor))
5530 ereport(ERROR,
5532 errmsg("must inherit privileges of role \"%s\"",
5533 GetUserNameFromId(grantor, false))));
5534 /* Use exactly that grantor, whether it has privileges or not */
5535 *grantorId = grantor;
5536 *grantOptions = aclmask_direct(acl, grantor, ownerId,
5538 return;
5539 }
5540
5541 /*
5542 * The object owner is always treated as having all grant options, so if
5543 * roleId is the owner it's easy. Also, if roleId is a superuser it's
5544 * easy: superusers are implicitly members of every role, so they act as
5545 * the object owner.
5546 */
5547 if (roleId == ownerId || superuser_arg(roleId))
5548 {
5549 *grantorId = ownerId;
5551 return;
5552 }
5553
5554 /*
5555 * Otherwise we have to do a careful search to see if roleId has the
5556 * privileges of any suitable role. Note: we can hang onto the result of
5557 * roles_is_member_of() throughout this loop, because aclmask_direct()
5558 * doesn't query any role memberships.
5559 */
5561 InvalidOid, NULL);
5562
5563 /* initialize candidate result as default */
5564 *grantorId = roleId;
5566 nrights = 0;
5567
5568 foreach(l, roles_list)
5569 {
5572
5573 otherprivs = aclmask_direct(acl, otherrole, ownerId,
5576 {
5577 /* Found a suitable grantor */
5580 return;
5581 }
5582
5583 /*
5584 * If it has just some of the needed privileges, remember best
5585 * candidate.
5586 */
5588 {
5590
5591 if (nnewrights > nrights)
5592 {
5596 }
5597 }
5598 }
5599}
5600
5601/*
5602 * get_role_oid - Given a role name, look up the role's OID.
5603 *
5604 * If missing_ok is false, throw an error if role name not found. If
5605 * true, just return InvalidOid.
5606 */
5607Oid
5608get_role_oid(const char *rolname, bool missing_ok)
5609{
5610 Oid oid;
5611
5614 if (!OidIsValid(oid) && !missing_ok)
5615 ereport(ERROR,
5617 errmsg("role \"%s\" does not exist", rolname)));
5618 return oid;
5619}
5620
5621/*
5622 * get_role_oid_or_public - As above, but return ACL_ID_PUBLIC if the
5623 * role name is "public".
5624 */
5625Oid
5627{
5628 if (strcmp(rolname, "public") == 0)
5629 return ACL_ID_PUBLIC;
5630
5631 return get_role_oid(rolname, false);
5632}
5633
5634/*
5635 * Given a RoleSpec node, return the OID it corresponds to. If missing_ok is
5636 * true, return InvalidOid if the role does not exist.
5637 *
5638 * PUBLIC is always disallowed here. Routines wanting to handle the PUBLIC
5639 * case must check the case separately.
5640 */
5641Oid
5642get_rolespec_oid(const RoleSpec *role, bool missing_ok)
5643{
5644 Oid oid;
5645
5646 switch (role->roletype)
5647 {
5648 case ROLESPEC_CSTRING:
5649 Assert(role->rolename);
5650 oid = get_role_oid(role->rolename, missing_ok);
5651 break;
5652
5655 oid = GetUserId();
5656 break;
5657
5659 oid = GetSessionUserId();
5660 break;
5661
5662 case ROLESPEC_PUBLIC:
5663 ereport(ERROR,
5665 errmsg("role \"%s\" does not exist", "public")));
5666 oid = InvalidOid; /* make compiler happy */
5667 break;
5668
5669 default:
5670 elog(ERROR, "unexpected role type %d", role->roletype);
5671 }
5672
5673 return oid;
5674}
5675
5676/*
5677 * Given a RoleSpec node, return the pg_authid HeapTuple it corresponds to.
5678 * Caller must ReleaseSysCache when done with the result tuple.
5679 */
5682{
5683 HeapTuple tuple;
5684
5685 switch (role->roletype)
5686 {
5687 case ROLESPEC_CSTRING:
5688 Assert(role->rolename);
5690 if (!HeapTupleIsValid(tuple))
5691 ereport(ERROR,
5693 errmsg("role \"%s\" does not exist", role->rolename)));
5694 break;
5695
5699 if (!HeapTupleIsValid(tuple))
5700 elog(ERROR, "cache lookup failed for role %u", GetUserId());
5701 break;
5702
5705 if (!HeapTupleIsValid(tuple))
5706 elog(ERROR, "cache lookup failed for role %u", GetSessionUserId());
5707 break;
5708
5709 case ROLESPEC_PUBLIC:
5710 ereport(ERROR,
5712 errmsg("role \"%s\" does not exist", "public")));
5713 tuple = NULL; /* make compiler happy */
5714 break;
5715
5716 default:
5717 elog(ERROR, "unexpected role type %d", role->roletype);
5718 }
5719
5720 return tuple;
5721}
5722
5723/*
5724 * Given a RoleSpec, returns a palloc'ed copy of the corresponding role's name.
5725 */
5726char *
5728{
5729 HeapTuple tp;
5731 char *rolename;
5732
5733 tp = get_rolespec_tuple(role);
5735 rolename = pstrdup(NameStr(authForm->rolname));
5736 ReleaseSysCache(tp);
5737
5738 return rolename;
5739}
5740
5741/*
5742 * Given a RoleSpec, throw an error if the name is reserved, using detail_msg,
5743 * if provided (which must be already translated).
5744 *
5745 * If node is NULL, no error is thrown. If detail_msg is NULL then no detail
5746 * message is provided.
5747 */
5748void
5749check_rolespec_name(const RoleSpec *role, const char *detail_msg)
5750{
5751 if (!role)
5752 return;
5753
5754 if (role->roletype != ROLESPEC_CSTRING)
5755 return;
5756
5757 if (IsReservedName(role->rolename))
5758 {
5759 if (detail_msg)
5760 ereport(ERROR,
5762 errmsg("role name \"%s\" is reserved",
5763 role->rolename),
5765 else
5766 ereport(ERROR,
5768 errmsg("role name \"%s\" is reserved",
5769 role->rolename)));
5770 }
5771}
Datum idx(PG_FUNCTION_ARGS)
Definition _int_op.c:263
static List * roles_is_member_of(Oid roleid, enum RoleRecurseType type, Oid admin_of, Oid *admin_role)
Definition acl.c:5185
Datum pg_has_role_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4989
Datum has_schema_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3914
Datum has_largeobject_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4818
Datum hash_aclitem(PG_FUNCTION_ARGS)
Definition acl.c:792
void initialize_acl(void)
Definition acl.c:5072
Datum has_sequence_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:2168
Datum has_table_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:2053
Datum has_server_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:4116
Datum has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4367
Datum has_column_privilege_id_id_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2792
Datum has_server_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4036
Datum aclinsert(PG_FUNCTION_ARGS)
Definition acl.c:1623
static AclMode convert_function_priv_string(text *priv_type_text)
Definition acl.c:3606
Datum has_largeobject_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4768
static const char * getid(const char *s, char *n, Node *escontext)
Definition acl.c:171
bool is_admin_of_role(Oid member, Oid role)
Definition acl.c:5447
Datum has_column_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2872
static bool aclitem_match(const AclItem *a1, const AclItem *a2)
Definition acl.c:737
Datum pg_has_role_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4870
Datum has_language_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:3634
Acl * aclconcat(const Acl *left_acl, const Acl *right_acl)
Definition acl.c:491
Datum has_schema_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:3834
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition acl.c:515
Datum aclitem_eq(PG_FUNCTION_ARGS)
Definition acl.c:772
Datum has_tablespace_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4286
Datum makeaclitem(PG_FUNCTION_ARGS)
Definition acl.c:1665
Datum has_table_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2030
Datum has_server_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4086
Datum has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2690
Datum has_language_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3742
static int column_privilege_check(Oid tableoid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition acl.c:2567
static Oid convert_type_name(text *typename)
Definition acl.c:4595
Oid select_best_admin(Oid member, Oid role)
Definition acl.c:5472
Datum aclexplode(PG_FUNCTION_ARGS)
Definition acl.c:1821
static Oid convert_database_name(text *databasename)
Definition acl.c:3179
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition acl.c:827
Datum aclitemout(PG_FUNCTION_ARGS)
Definition acl.c:664
Oid get_role_oid_or_public(const char *rolname)
Definition acl.c:5626
Datum has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3275
Datum has_foreign_data_wrapper_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3356
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition acl.c:573
Datum hash_aclitem_extended(PG_FUNCTION_ARGS)
Definition acl.c:806
static void check_acl(const Acl *acl)
Definition acl.c:604
Datum has_parameter_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4657
Datum has_foreign_data_wrapper_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3305
#define ROLES_LIST_BLOOM_THRESHOLD
Definition acl.c:92
Datum has_database_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3045
static uint32 cached_db_hash
Definition acl.c:84
Datum has_type_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4435
Datum has_column_privilege_name_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2607
Datum pg_has_role_name(PG_FUNCTION_ARGS)
Definition acl.c:4896
Datum has_sequence_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:2234
static AclMode convert_largeobject_priv_string(text *priv_type_text)
Definition acl.c:4841
static List * roles_list_append(List *roles_list, bloom_filter **bf, Oid role)
Definition acl.c:5125
static AclMode convert_type_priv_string(text *priv_type_text)
Definition acl.c:4616
Datum has_tablespace_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:4262
static AclMode convert_table_priv_string(text *priv_type_text)
Definition acl.c:2095
static AclMode convert_server_priv_string(text *priv_type_text)
Definition acl.c:4208
Datum has_table_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:1976
Datum has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:3225
Datum has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4344
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition acl.c:1023
static Acl * recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs, Oid ownerId, DropBehavior behavior)
Definition acl.c:1333
Datum has_database_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3069
static Oid convert_schema_name(text *schemaname)
Definition acl.c:3994
Datum has_column_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2816
static void putid(char *p, const char *s)
Definition acl.c:224
Datum has_schema_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3942
static void check_circularity(const Acl *old_acl, const AclItem *mod_aip, Oid ownerId)
Definition acl.c:1253
static bool has_param_priv_byname(Oid roleid, const text *parameter, AclMode priv)
Definition acl.c:4644
bool is_member_of_role(Oid member, Oid role)
Definition acl.c:5397
Datum has_sequence_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2269
Datum has_database_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3127
static Oid convert_foreign_data_wrapper_name(text *fdwname)
Definition acl.c:3385
Datum has_language_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3714
static AclMode convert_database_priv_string(text *priv_type_text)
Definition acl.c:3191
Datum has_foreign_data_wrapper_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3251
Datum has_column_privilege_name_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2845
Datum has_column_privilege_id_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2899
RoleRecurseType
Definition acl.c:77
@ ROLERECURSE_PRIVS
Definition acl.c:79
@ ROLERECURSE_MEMBERS
Definition acl.c:78
@ ROLERECURSE_SETROLE
Definition acl.c:80
Datum has_type_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4485
Datum has_any_column_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:2421
Datum has_server_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4144
Datum has_language_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3684
Datum has_foreign_data_wrapper_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3333
Datum has_schema_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3884
Datum has_function_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:3425
Datum has_any_column_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2363
bool is_member_of_role_nosuper(Oid member, Oid role)
Definition acl.c:5425
Datum has_sequence_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:2197
Datum has_schema_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3860
Datum acldefault_sql(PG_FUNCTION_ARGS)
Definition acl.c:948
bool has_privs_of_role(Oid member, Oid role)
Definition acl.c:5317
Acl * make_empty_acl(void)
Definition acl.c:462
static Oid convert_language_name(text *languagename)
Definition acl.c:3794
Datum has_language_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3765
static AclMode convert_any_priv_string(text *priv_type_text, const priv_map *privileges)
Definition acl.c:1717
Datum has_database_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3150
Datum has_function_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3451
static bool is_safe_acl_char(unsigned char c, bool is_getid)
Definition acl.c:148
int aclmembers(const Acl *acl, Oid **roleids)
Definition acl.c:1571
Datum has_language_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3660
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition acl.c:1150
Datum has_server_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:4062
bool member_can_set_role(Oid member, Oid role)
Definition acl.c:5351
Datum aclremove(PG_FUNCTION_ARGS)
Definition acl.c:1633
static const char * convert_aclright_to_string(int aclright)
Definition acl.c:1765
Acl * aclcopy(const Acl *orig_acl)
Definition acl.c:471
Datum has_function_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3505
void aclitemsort(Acl *acl)
Definition acl.c:559
Datum has_table_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:2004
Datum has_function_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3556
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition acl.c:1419
static Oid convert_server_name(text *servername)
Definition acl.c:4196
static Oid convert_tablespace_name(text *tablespacename)
Definition acl.c:4396
Datum has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2636
static AclMode convert_parameter_priv_string(text *priv_text)
Definition acl.c:4705
static Oid convert_table_name(text *tablename)
Definition acl.c:2080
Datum has_column_privilege_name_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2663
static AclMode convert_tablespace_priv_string(text *priv_type_text)
Definition acl.c:4408
static AclMode convert_language_priv_string(text *priv_type_text)
Definition acl.c:3806
Datum aclitemin(PG_FUNCTION_ARGS)
Definition acl.c:629
static AclMode convert_sequence_priv_string(text *priv_type_text)
Definition acl.c:2330
Datum pg_has_role_id(PG_FUNCTION_ARGS)
Definition acl.c:4944
Datum has_parameter_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4687
static Acl * allocacl(int n)
Definition acl.c:440
static AttrNumber convert_column_name(Oid tableoid, text *column)
Definition acl.c:2927
static AclMode convert_role_priv_string(text *priv_type_text)
Definition acl.c:5019
static bool has_lo_priv_byid(Oid roleid, Oid lobjId, AclMode priv, bool *is_missing)
Definition acl.c:4735
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition acl.c:5608
static Oid cached_role[]
Definition acl.c:82
Datum has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4236
Datum has_parameter_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:4673
static void RoleMembershipCacheCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
Definition acl.c:5102
Datum has_any_column_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:2393
Datum has_sequence_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2137
Datum has_function_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3475
Datum has_type_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4566
char * get_rolespec_name(const RoleSpec *role)
Definition acl.c:5727
void select_best_grantor(const RoleSpec *grantedBy, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition acl.c:5511
Datum has_server_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4167
static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
Definition acl.c:5042
Datum has_function_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3533
Datum has_table_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:1952
Datum has_type_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4543
Datum has_column_privilege_id_name_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2742
void check_can_set_role(Oid member, Oid role)
Definition acl.c:5374
static const char * aclparse(const char *s, AclItem *aip, Node *escontext)
Definition acl.c:279
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition acl.c:5749
Datum has_type_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:4461
static List * cached_roles[]
Definition acl.c:83
static AclMode aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition acl.c:1508
Datum has_tablespace_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:4316
Datum pg_has_role_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4920
Datum aclcontains(PG_FUNCTION_ARGS)
Definition acl.c:1643
static Oid convert_function_name(text *functionname)
Definition acl.c:3585
Datum has_column_privilege_id_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2715
Datum has_schema_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3965
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition acl.c:5642
Datum has_any_column_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2489
Datum has_largeobject_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:4794
Datum has_database_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:3019
Datum has_column_privilege_id_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2767
static AclMode convert_schema_priv_string(text *priv_type_text)
Definition acl.c:4006
Datum has_table_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:1926
Datum has_any_column_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:2516
static AclMode convert_foreign_data_wrapper_priv_string(text *priv_type_text)
Definition acl.c:3397
Datum has_database_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3099
static int aclitemComparator(const void *arg1, const void *arg2)
Definition acl.c:748
Datum has_type_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:4515
Datum has_any_column_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:2456
Datum pg_has_role_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4966
Datum has_sequence_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:2297
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition acl.c:5681
static AclMode convert_column_priv_string(text *priv_type_text)
Definition acl.c:2985
#define ACL_CREATE_CHR
Definition acl.h:146
#define PG_RETURN_ACLITEM_P(x)
Definition acl.h:118
#define ACL_ALL_RIGHTS_STR
Definition acl.h:154
#define ACL_SET_CHR
Definition acl.h:149
#define ACL_REFERENCES_CHR
Definition acl.h:142
#define ACLITEM_ALL_GOPTION_BITS
Definition acl.h:88
#define ACL_SIZE(ACL)
Definition acl.h:111
#define PG_GETARG_ACLITEM_P(n)
Definition acl.h:117
#define ACL_DAT(ACL)
Definition acl.h:109
#define ACL_ALL_RIGHTS_FOREIGN_SERVER
Definition acl.h:164
#define ACL_TRUNCATE_CHR
Definition acl.h:141
#define ACL_ALL_RIGHTS_TABLESPACE
Definition acl.h:171
AclResult
Definition acl.h:183
@ ACLCHECK_NO_PRIV
Definition acl.h:185
@ ACLCHECK_OK
Definition acl.h:184
#define ACLITEM_GET_PRIVS(item)
Definition acl.h:66
#define ACL_ALL_RIGHTS_PARAMETER_ACL
Definition acl.h:168
#define ACL_SELECT_CHR
Definition acl.h:138
#define ACL_ALL_RIGHTS_SCHEMA
Definition acl.h:170
#define ACL_EXECUTE_CHR
Definition acl.h:144
#define ACL_MODECHG_DEL
Definition acl.h:130
#define ACL_DELETE_CHR
Definition acl.h:140
#define ACL_ALL_RIGHTS_SEQUENCE
Definition acl.h:161
#define ACL_ALL_RIGHTS_DATABASE
Definition acl.h:162
#define ACL_ALL_RIGHTS_PROPGRAPH
Definition acl.h:169
#define ACL_MODECHG_ADD
Definition acl.h:129
#define ACL_OPTION_TO_PRIVS(privs)
Definition acl.h:71
#define ACL_INSERT_CHR
Definition acl.h:137
#define ACL_UPDATE_CHR
Definition acl.h:139
#define ACL_ALL_RIGHTS_FUNCTION
Definition acl.h:165
#define ACL_N_SIZE(N)
Definition acl.h:110
#define ACL_ALL_RIGHTS_LANGUAGE
Definition acl.h:166
#define ACL_ALL_RIGHTS_TYPE
Definition acl.h:172
#define ACL_ALTER_SYSTEM_CHR
Definition acl.h:150
#define ACL_ALL_RIGHTS_FDW
Definition acl.h:163
#define ACLITEM_SET_PRIVS_GOPTIONS(item, privs, goptions)
Definition acl.h:82
#define ACL_NUM(ACL)
Definition acl.h:108
#define ACL_USAGE_CHR
Definition acl.h:145
#define PG_GETARG_ACL_P(n)
Definition acl.h:122
#define ACLITEM_GET_GOPTIONS(item)
Definition acl.h:67
#define ACLITEM_GET_RIGHTS(item)
Definition acl.h:68
#define ACL_ALL_RIGHTS_RELATION
Definition acl.h:160
#define ACL_MODECHG_EQL
Definition acl.h:131
#define ACL_ID_PUBLIC
Definition acl.h:46
#define ACL_CONNECT_CHR
Definition acl.h:148
#define ACL_ALL_RIGHTS_LARGEOBJECT
Definition acl.h:167
AclMaskHow
Definition acl.h:176
@ ACLMASK_ANY
Definition acl.h:178
@ ACLMASK_ALL
Definition acl.h:177
#define PG_RETURN_ACL_P(x)
Definition acl.h:124
#define ACL_TRIGGER_CHR
Definition acl.h:143
#define ACL_CREATE_TEMP_CHR
Definition acl.h:147
#define ACL_GRANT_OPTION_FOR(privs)
Definition acl.h:70
#define ACLITEM_SET_RIGHTS(item, rights)
Definition acl.h:79
#define ACL_MAINTAIN_CHR
Definition acl.h:151
AclResult object_aclcheck_ext(Oid classid, Oid objectid, Oid roleid, AclMode mode, bool *is_missing)
Definition aclchk.c:3912
AclResult pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid, AclMode mode, Snapshot snapshot)
Definition aclchk.c:4142
AclResult pg_class_aclcheck_ext(Oid table_oid, Oid roleid, AclMode mode, bool *is_missing)
Definition aclchk.c:4115
AclResult pg_attribute_aclcheck_all_ext(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how, bool *is_missing)
Definition aclchk.c:3987
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition aclchk.c:3976
AclResult pg_parameter_aclcheck(const char *name, Oid roleid, AclMode mode)
Definition aclchk.c:4130
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3902
AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
Definition aclchk.c:3946
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4105
#define ARR_NDIM(a)
Definition array.h:290
#define ARR_ELEMTYPE(a)
Definition array.h:292
#define ARR_DIMS(a)
Definition array.h:294
#define ARR_HASNULL(a)
Definition array.h:291
#define ARR_LBOUND(a)
Definition array.h:296
int16 AttrNumber
Definition attnum.h:21
#define InvalidAttrNumber
Definition attnum.h:23
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
void bloom_free(bloom_filter *filter)
bloom_filter * bloom_create(int64 total_elems, int bloom_work_mem, uint64 seed)
Definition bloomfilter.c:87
bool bloom_lacks_element(bloom_filter *filter, unsigned char *elem, size_t len)
void bloom_add_element(bloom_filter *filter, unsigned char *elem, size_t len)
static Datum values[MAXATTR]
Definition bootstrap.c:190
Oid boot_get_role_oid(const char *rolname)
Definition bootstrap.c:1094
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define NameStr(name)
Definition c.h:894
#define IS_HIGHBIT_SET(ch)
Definition c.h:1284
#define Assert(condition)
Definition c.h:1002
uint64_t uint64
Definition c.h:684
uint32_t uint32
Definition c.h:683
#define UINT64CONST(x)
Definition c.h:690
#define OidIsValid(objectId)
Definition c.h:917
size_t Size
Definition c.h:748
bool IsReservedName(const char *name)
Definition catalog.c:305
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
Oid get_database_oid(const char *dbname, bool missing_ok)
Datum arg
Definition elog.c:1323
int errcode(int sqlerrcode)
Definition elog.c:875
#define ereturn(context, dummy_value,...)
Definition elog.h:280
int int errdetail_internal(const char *fmt,...) pg_attribute_printf(1
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:37
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
#define palloc_object(type)
Definition fe_memutils.h:89
#define palloc_array(type, count)
Definition fe_memutils.h:91
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_RETURN_UINT32(x)
Definition fmgr.h:356
#define PG_GETARG_TEXT_PP(n)
Definition fmgr.h:310
#define PG_GETARG_CHAR(n)
Definition fmgr.h:273
#define PG_RETURN_CSTRING(x)
Definition fmgr.h:364
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:688
#define PG_GETARG_CSTRING(n)
Definition fmgr.h:278
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
#define PG_GETARG_NAME(n)
Definition fmgr.h:279
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
#define PG_GETARG_INT16(n)
Definition fmgr.h:271
Oid get_foreign_server_oid(const char *servername, bool missing_ok)
Definition foreign.c:736
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition foreign.c:713
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
int work_mem
Definition globals.c:133
Oid MyDatabaseId
Definition globals.c:96
static Datum hash_uint32_extended(uint32 k, uint64 seed)
Definition hashfn.h:49
static const FormData_pg_attribute a1
Definition heap.c:144
static const FormData_pg_attribute a2
Definition heap.c:157
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
#define HeapTupleIsValid(tuple)
Definition htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
#define funcname
int remaining
Definition informix.c:692
static char * username
Definition initdb.c:153
#define read(a, b, c)
Definition win32.h:13
bool lo_compat_privileges
Definition inv_api.c:56
void CacheRegisterSyscacheCallback(SysCacheIdentifier cacheid, SyscacheCallbackFunction func, Datum arg)
Definition inval.c:1813
int a
Definition isn.c:73
int j
Definition isn.c:78
int i
Definition isn.c:77
List * list_copy(const List *oldlist)
Definition list.c:1573
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
void list_free(List *list)
Definition list.c:1546
bool list_member_oid(const List *list, Oid datum)
Definition list.c:722
#define NoLock
Definition lockdefs.h:34
char * get_rel_name(Oid relid)
Definition lsyscache.c:2242
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2317
char * pstrdup(const char *in)
Definition mcxt.c:1910
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc0(Size size)
Definition mcxt.c:1420
MemoryContext TopMemoryContext
Definition mcxt.c:167
void * palloc(Size size)
Definition mcxt.c:1390
#define IsBootstrapProcessingMode()
Definition miscadmin.h:486
Oid GetUserId(void)
Definition miscinit.c:470
Oid GetSessionUserId(void)
Definition miscinit.c:509
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition miscinit.c:990
Oid get_namespace_oid(const char *nspname, bool missing_ok)
Definition namespace.c:3607
RangeVar * makeRangeVarFromNameList(const List *names)
Definition namespace.c:3626
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition namespace.h:98
static char * errmsg
int oid_cmp(const void *p1, const void *p2)
Definition oid.c:287
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
@ ROLESPEC_CURRENT_USER
Definition parsenodes.h:425
@ ROLESPEC_CSTRING
Definition parsenodes.h:423
@ ROLESPEC_SESSION_USER
Definition parsenodes.h:426
@ ROLESPEC_CURRENT_ROLE
Definition parsenodes.h:424
@ ROLESPEC_PUBLIC
Definition parsenodes.h:427
#define ACL_CREATE_TEMP
Definition parsenodes.h:86
#define ACL_SET
Definition parsenodes.h:88
#define ACL_DELETE
Definition parsenodes.h:79
uint64 AclMode
Definition parsenodes.h:74
#define ACL_MAINTAIN
Definition parsenodes.h:90
#define ACL_USAGE
Definition parsenodes.h:84
#define ACL_INSERT
Definition parsenodes.h:76
#define ACL_NO_RIGHTS
Definition parsenodes.h:92
#define ACL_UPDATE
Definition parsenodes.h:78
DropBehavior
@ DROP_CASCADE
@ DROP_RESTRICT
ObjectType
@ OBJECT_FDW
@ OBJECT_PROPGRAPH
@ OBJECT_SCHEMA
@ OBJECT_DOMAIN
@ OBJECT_COLUMN
@ OBJECT_TABLESPACE
@ OBJECT_LARGEOBJECT
@ OBJECT_DATABASE
@ OBJECT_SEQUENCE
@ OBJECT_LANGUAGE
@ OBJECT_FOREIGN_SERVER
@ OBJECT_TABLE
@ OBJECT_PARAMETER_ACL
@ OBJECT_TYPE
@ OBJECT_FUNCTION
#define ACL_CONNECT
Definition parsenodes.h:87
#define ACL_ALTER_SYSTEM
Definition parsenodes.h:89
#define ACL_REFERENCES
Definition parsenodes.h:81
#define ACL_SELECT
Definition parsenodes.h:77
#define ACL_TRUNCATE
Definition parsenodes.h:80
#define ACL_EXECUTE
Definition parsenodes.h:83
#define ACL_CREATE
Definition parsenodes.h:85
#define ACL_TRIGGER
Definition parsenodes.h:82
#define N_ACL_RIGHTS
Definition parsenodes.h:91
int16 attnum
FormData_pg_attribute * Form_pg_attribute
END_CATALOG_STRUCT typedef FormData_pg_auth_members * Form_pg_auth_members
NameData rolname
Definition pg_authid.h:36
END_CATALOG_STRUCT typedef FormData_pg_authid * Form_pg_authid
Definition pg_authid.h:60
static int pg_popcount64(uint64 word)
static PgChecksumMode mode
#define NAMEDATALEN
const void size_t len
END_CATALOG_STRUCT typedef FormData_pg_database * Form_pg_database
bool LargeObjectExistsWithSnapshot(Oid loid, Snapshot snapshot)
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define list_make1_oid(x1)
Definition pg_list.h:274
#define foreach_oid(var, lst)
Definition pg_list.h:503
#define lfirst_oid(lc)
Definition pg_list.h:174
NameData typname
Definition pg_type.h:43
int pg_strcasecmp(const char *s1, const char *s2)
#define sprintf
Definition port.h:263
#define qsort(a, b, c, d)
Definition port.h:496
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:242
static Datum UInt64GetDatum(uint64 X)
Definition postgres.h:446
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:383
#define InvalidOid
unsigned int Oid
char * c
static int fb(int x)
Oid get_language_oid(const char *langname, bool missing_ok)
Definition proclang.c:227
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
Definition qunique.h:21
Datum regtypein(PG_FUNCTION_ARGS)
Definition regproc.c:1184
Datum regprocedurein(PG_FUNCTION_ARGS)
Definition regproc.c:229
Snapshot GetActiveSnapshot(void)
Definition snapmgr.c:800
char * dbname
Definition streamutil.c:49
Definition acl.h:55
AclMode ai_privs
Definition acl.h:58
Definition pg_list.h:54
Definition nodes.h:133
RoleSpecType roletype
Definition parsenodes.h:433
char * rolename
Definition parsenodes.h:434
Definition c.h:889
Definition acl.c:57
const char * name
Definition acl.c:58
AclMode value
Definition acl.c:59
Definition c.h:835
bool superuser_arg(Oid roleid)
Definition superuser.c:57
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:265
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:231
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:221
#define ReleaseSysCacheList(x)
Definition syscache.h:134
#define SearchSysCacheList1(cacheId, key1)
Definition syscache.h:127
#define GetSysCacheHashValue1(cacheId, key1)
Definition syscache.h:118
#define GetSysCacheOid1(cacheId, oidcol, key1)
Definition syscache.h:109
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:511
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:909
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432
char * text_to_cstring(const text *t)
Definition varlena.c:217
List * textToQualifiedNameList(text *textval)
Definition varlena.c:2722
const char * type
const char * name