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 "catalog/catalog.h"
21#include "catalog/namespace.h"
23#include "catalog/pg_authid.h"
24#include "catalog/pg_class.h"
25#include "catalog/pg_database.h"
28#include "catalog/pg_language.h"
31#include "catalog/pg_proc.h"
33#include "catalog/pg_type.h"
34#include "commands/proclang.h"
35#include "commands/tablespace.h"
36#include "common/hashfn.h"
37#include "foreign/foreign.h"
38#include "funcapi.h"
39#include "lib/bloomfilter.h"
40#include "lib/qunique.h"
41#include "miscadmin.h"
43#include "utils/acl.h"
44#include "utils/array.h"
45#include "utils/builtins.h"
46#include "utils/catcache.h"
47#include "utils/inval.h"
48#include "utils/lsyscache.h"
49#include "utils/memutils.h"
50#include "utils/snapmgr.h"
51#include "utils/syscache.h"
52#include "utils/varlena.h"
53
54typedef struct
55{
56 const char *name;
58} priv_map;
59
60/*
61 * We frequently need to test whether a given role is a member of some other
62 * role. In most of these tests the "given role" is the same, namely the
63 * active current user. So we can optimize it by keeping cached lists of all
64 * the roles the "given role" is a member of, directly or indirectly.
65 *
66 * Possibly this mechanism should be generalized to allow caching membership
67 * info for multiple roles?
68 *
69 * Each element of cached_roles is an OID list of constituent roles for the
70 * corresponding element of cached_role (always including the cached_role
71 * itself). There's a separate cache for each RoleRecurseType, with the
72 * corresponding semantics.
73 */
75{
76 ROLERECURSE_MEMBERS = 0, /* recurse unconditionally */
77 ROLERECURSE_PRIVS = 1, /* recurse through inheritable grants */
78 ROLERECURSE_SETROLE = 2 /* recurse through grants with set_option */
79};
81static List *cached_roles[] = {NIL, NIL, NIL};
83
84/*
85 * If the list of roles gathered by roles_is_member_of() grows larger than the
86 * below threshold, a Bloom filter is created to speed up list membership
87 * checks. This threshold is set arbitrarily high to avoid the overhead of
88 * creating the Bloom filter until it seems likely to provide a net benefit.
89 */
90#define ROLES_LIST_BLOOM_THRESHOLD 1024
91
92static const char *getid(const char *s, char *n, Node *escontext);
93static void putid(char *p, const char *s);
94static Acl *allocacl(int n);
95static void check_acl(const Acl *acl);
96static const char *aclparse(const char *s, AclItem *aip, Node *escontext);
97static bool aclitem_match(const AclItem *a1, const AclItem *a2);
98static int aclitemComparator(const void *arg1, const void *arg2);
99static void check_circularity(const Acl *old_acl, const AclItem *mod_aip,
100 Oid ownerId);
102 Oid ownerId, DropBehavior behavior);
103
105 const priv_map *privileges);
106
107static Oid convert_table_name(text *tablename);
110static AttrNumber convert_column_name(Oid tableoid, text *column);
120static Oid convert_schema_name(text *schemaname);
122static Oid convert_server_name(text *servername);
124static Oid convert_tablespace_name(text *tablespacename);
126static Oid convert_type_name(text *typename);
132
134 uint32 hashvalue);
135
136
137/*
138 * Test whether an identifier char can be left unquoted in ACLs.
139 *
140 * Formerly, we used isalnum() even on non-ASCII characters, resulting in
141 * unportable behavior. To ensure dump compatibility with old versions,
142 * we now treat high-bit-set characters as always requiring quoting during
143 * putid(), but getid() will always accept them without quotes.
144 */
145static inline bool
146is_safe_acl_char(unsigned char c, bool is_getid)
147{
148 if (IS_HIGHBIT_SET(c))
149 return is_getid;
150 return isalnum(c) || c == '_';
151}
152
153/*
154 * getid
155 * Consumes the first alphanumeric string (identifier) found in string
156 * 's', ignoring any leading white space. If it finds a double quote
157 * it returns the word inside the quotes.
158 *
159 * RETURNS:
160 * the string position in 's' that points to the next non-space character
161 * in 's', after any quotes. Also:
162 * - loads the identifier into 'n'. (If no identifier is found, 'n'
163 * contains an empty string.) 'n' must be NAMEDATALEN bytes.
164 *
165 * Errors are reported via ereport, unless escontext is an ErrorSaveData node,
166 * in which case we log the error there and return NULL.
167 */
168static const char *
169getid(const char *s, char *n, Node *escontext)
170{
171 int len = 0;
172 bool in_quotes = false;
173
174 Assert(s && n);
175
176 while (isspace((unsigned char) *s))
177 s++;
178 for (;
179 *s != '\0' &&
180 (in_quotes || *s == '"' || is_safe_acl_char(*s, true));
181 s++)
182 {
183 if (*s == '"')
184 {
185 if (!in_quotes)
186 {
187 in_quotes = true;
188 continue;
189 }
190 /* safe to look at next char (could be '\0' though) */
191 if (*(s + 1) != '"')
192 {
193 in_quotes = false;
194 continue;
195 }
196 /* it's an escaped double quote; skip the escaping char */
197 s++;
198 }
199
200 /* Add the character to the string */
201 if (len >= NAMEDATALEN - 1)
202 ereturn(escontext, NULL,
204 errmsg("identifier too long"),
205 errdetail("Identifier must be less than %d characters.",
206 NAMEDATALEN)));
207
208 n[len++] = *s;
209 }
210 n[len] = '\0';
211 while (isspace((unsigned char) *s))
212 s++;
213 return s;
214}
215
216/*
217 * Write a role name at *p, adding double quotes if needed.
218 * There must be at least (2*NAMEDATALEN)+2 bytes available at *p.
219 * This needs to be kept in sync with dequoteAclUserName in pg_dump/dumputils.c
220 */
221static void
222putid(char *p, const char *s)
223{
224 const char *src;
225 bool safe = true;
226
227 /* Detect whether we need to use double quotes */
228 for (src = s; *src; src++)
229 {
230 if (!is_safe_acl_char(*src, false))
231 {
232 safe = false;
233 break;
234 }
235 }
236 if (!safe)
237 *p++ = '"';
238 for (src = s; *src; src++)
239 {
240 /* A double quote character in a username is encoded as "" */
241 if (*src == '"')
242 *p++ = '"';
243 *p++ = *src;
244 }
245 if (!safe)
246 *p++ = '"';
247 *p = '\0';
248}
249
250/*
251 * aclparse
252 * Consumes and parses an ACL specification of the form:
253 * [group|user] [A-Za-z0-9]*=[rwaR]*
254 * from string 's', ignoring any leading white space or white space
255 * between the optional id type keyword (group|user) and the actual
256 * ACL specification.
257 *
258 * The group|user decoration is unnecessary in the roles world,
259 * but we still accept it for backward compatibility.
260 *
261 * This routine is called by the parser as well as aclitemin(), hence
262 * the added generality.
263 *
264 * RETURNS:
265 * the string position in 's' immediately following the ACL
266 * specification. Also:
267 * - loads the structure pointed to by 'aip' with the appropriate
268 * UID/GID, id type identifier and mode type values.
269 *
270 * Errors are reported via ereport, unless escontext is an ErrorSaveData node,
271 * in which case we log the error there and return NULL.
272 */
273static const char *
274aclparse(const char *s, AclItem *aip, Node *escontext)
275{
277 goption,
278 read;
279 char name[NAMEDATALEN];
280 char name2[NAMEDATALEN];
281
282 Assert(s && aip);
283
284 s = getid(s, name, escontext);
285 if (s == NULL)
286 return NULL;
287 if (*s != '=')
288 {
289 /* we just read a keyword, not a name */
290 if (strcmp(name, "group") != 0 && strcmp(name, "user") != 0)
291 ereturn(escontext, NULL,
293 errmsg("unrecognized key word: \"%s\"", name),
294 errhint("ACL key word must be \"group\" or \"user\".")));
295 /* move s to the name beyond the keyword */
296 s = getid(s, name, escontext);
297 if (s == NULL)
298 return NULL;
299 if (name[0] == '\0')
300 ereturn(escontext, NULL,
302 errmsg("missing name"),
303 errhint("A name must follow the \"group\" or \"user\" key word.")));
304 }
305
306 if (*s != '=')
307 ereturn(escontext, NULL,
309 errmsg("missing \"=\" sign")));
310
312
313 for (++s, read = 0; isalpha((unsigned char) *s) || *s == '*'; s++)
314 {
315 switch (*s)
316 {
317 case '*':
318 goption |= read;
319 break;
320 case ACL_INSERT_CHR:
322 break;
323 case ACL_SELECT_CHR:
325 break;
326 case ACL_UPDATE_CHR:
328 break;
329 case ACL_DELETE_CHR:
331 break;
332 case ACL_TRUNCATE_CHR:
334 break;
337 break;
338 case ACL_TRIGGER_CHR:
340 break;
341 case ACL_EXECUTE_CHR:
343 break;
344 case ACL_USAGE_CHR:
345 read = ACL_USAGE;
346 break;
347 case ACL_CREATE_CHR:
349 break;
352 break;
353 case ACL_CONNECT_CHR:
355 break;
356 case ACL_SET_CHR:
357 read = ACL_SET;
358 break;
361 break;
362 case ACL_MAINTAIN_CHR:
364 break;
365 default:
366 ereturn(escontext, NULL,
368 errmsg("invalid mode character: must be one of \"%s\"",
370 }
371
372 privs |= read;
373 }
374
375 if (name[0] == '\0')
376 aip->ai_grantee = ACL_ID_PUBLIC;
377 else
378 {
379 aip->ai_grantee = get_role_oid(name, true);
380 if (!OidIsValid(aip->ai_grantee))
381 ereturn(escontext, NULL,
383 errmsg("role \"%s\" does not exist", name)));
384 }
385
386 /*
387 * XXX Allow a degree of backward compatibility by defaulting the grantor
388 * to the superuser.
389 */
390 if (*s == '/')
391 {
392 s = getid(s + 1, name2, escontext);
393 if (s == NULL)
394 return NULL;
395 if (name2[0] == '\0')
396 ereturn(escontext, NULL,
398 errmsg("a name must follow the \"/\" sign")));
399 aip->ai_grantor = get_role_oid(name2, true);
400 if (!OidIsValid(aip->ai_grantor))
401 ereturn(escontext, NULL,
403 errmsg("role \"%s\" does not exist", name2)));
404 }
405 else
406 {
407 aip->ai_grantor = BOOTSTRAP_SUPERUSERID;
410 errmsg("defaulting grantor to user ID %u",
412 }
413
415
416 return s;
417}
418
419/*
420 * allocacl
421 * Allocates storage for a new Acl with 'n' entries.
422 *
423 * RETURNS:
424 * the new Acl
425 */
426static Acl *
428{
429 Acl *new_acl;
430 Size size;
431
432 if (n < 0)
433 elog(ERROR, "invalid size: %d", n);
434 size = ACL_N_SIZE(n);
435 new_acl = (Acl *) palloc0(size);
436 SET_VARSIZE(new_acl, size);
437 new_acl->ndim = 1;
438 new_acl->dataoffset = 0; /* we never put in any nulls */
439 new_acl->elemtype = ACLITEMOID;
440 ARR_LBOUND(new_acl)[0] = 1;
441 ARR_DIMS(new_acl)[0] = n;
442 return new_acl;
443}
444
445/*
446 * Create a zero-entry ACL
447 */
448Acl *
450{
451 return allocacl(0);
452}
453
454/*
455 * Copy an ACL
456 */
457Acl *
459{
461
463
466 ACL_NUM(orig_acl) * sizeof(AclItem));
467
468 return result_acl;
469}
470
471/*
472 * Concatenate two ACLs
473 *
474 * This is a bit cheesy, since we may produce an ACL with redundant entries.
475 * Be careful what the result is used for!
476 */
477Acl *
479{
481
483
486 ACL_NUM(left_acl) * sizeof(AclItem));
487
490 ACL_NUM(right_acl) * sizeof(AclItem));
491
492 return result_acl;
493}
494
495/*
496 * Merge two ACLs
497 *
498 * This produces a properly merged ACL with no redundant entries.
499 * Returns NULL on NULL input.
500 */
501Acl *
502aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
503{
505 AclItem *aip;
506 int i,
507 num;
508
509 /* Check for cases where one or both are empty/null */
510 if (left_acl == NULL || ACL_NUM(left_acl) == 0)
511 {
512 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
513 return NULL;
514 else
515 return aclcopy(right_acl);
516 }
517 else
518 {
519 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
520 return aclcopy(left_acl);
521 }
522
523 /* Merge them the hard way, one item at a time */
525
527 num = ACL_NUM(right_acl);
528
529 for (i = 0; i < num; i++, aip++)
530 {
531 Acl *tmp_acl;
532
534 ownerId, DROP_RESTRICT);
537 }
538
539 return result_acl;
540}
541
542/*
543 * Sort the items in an ACL (into an arbitrary but consistent order)
544 */
545void
547{
548 if (acl != NULL && ACL_NUM(acl) > 1)
549 qsort(ACL_DAT(acl), ACL_NUM(acl), sizeof(AclItem), aclitemComparator);
550}
551
552/*
553 * Check if two ACLs are exactly equal
554 *
555 * This will not detect equality if the two arrays contain the same items
556 * in different orders. To handle that case, sort both inputs first,
557 * using aclitemsort().
558 */
559bool
561{
562 /* Check for cases where one or both are empty/null */
563 if (left_acl == NULL || ACL_NUM(left_acl) == 0)
564 {
565 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
566 return true;
567 else
568 return false;
569 }
570 else
571 {
572 if (right_acl == NULL || ACL_NUM(right_acl) == 0)
573 return false;
574 }
575
577 return false;
578
581 ACL_NUM(left_acl) * sizeof(AclItem)) == 0)
582 return true;
583
584 return false;
585}
586
587/*
588 * Verify that an ACL array is acceptable (one-dimensional and has no nulls)
589 */
590static void
591check_acl(const Acl *acl)
592{
593 if (ARR_ELEMTYPE(acl) != ACLITEMOID)
596 errmsg("ACL array contains wrong data type")));
597 if (ARR_NDIM(acl) != 1)
600 errmsg("ACL arrays must be one-dimensional")));
601 if (ARR_HASNULL(acl))
604 errmsg("ACL arrays must not contain null values")));
605}
606
607/*
608 * aclitemin
609 * Allocates storage for, and fills in, a new AclItem given a string
610 * 's' that contains an ACL specification. See aclparse for details.
611 *
612 * RETURNS:
613 * the new AclItem
614 */
615Datum
617{
618 const char *s = PG_GETARG_CSTRING(0);
619 Node *escontext = fcinfo->context;
620 AclItem *aip;
621
623
624 s = aclparse(s, aip, escontext);
625 if (s == NULL)
627
628 while (isspace((unsigned char) *s))
629 ++s;
630 if (*s)
631 ereturn(escontext, (Datum) 0,
633 errmsg("extra garbage at the end of the ACL specification")));
634
636}
637
638/*
639 * aclitemout
640 * Allocates storage for, and fills in, a new null-delimited string
641 * containing a formatted ACL specification. See aclparse for details.
642 *
643 * RETURNS:
644 * the new string
645 */
646Datum
648{
650 char *p;
651 char *out;
652 HeapTuple htup;
653 unsigned i;
654
655 out = palloc(strlen("=/") +
656 2 * N_ACL_RIGHTS +
657 2 * (2 * NAMEDATALEN + 2) +
658 1);
659
660 p = out;
661 *p = '\0';
662
663 if (aip->ai_grantee != ACL_ID_PUBLIC)
664 {
665 htup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(aip->ai_grantee));
666 if (HeapTupleIsValid(htup))
667 {
669 ReleaseSysCache(htup);
670 }
671 else
672 {
673 /* Generate numeric OID if we don't find an entry */
674 sprintf(p, "%u", aip->ai_grantee);
675 }
676 }
677 while (*p)
678 ++p;
679
680 *p++ = '=';
681
682 for (i = 0; i < N_ACL_RIGHTS; ++i)
683 {
684 if (ACLITEM_GET_PRIVS(*aip) & (UINT64CONST(1) << i))
685 *p++ = ACL_ALL_RIGHTS_STR[i];
686 if (ACLITEM_GET_GOPTIONS(*aip) & (UINT64CONST(1) << i))
687 *p++ = '*';
688 }
689
690 *p++ = '/';
691 *p = '\0';
692
693 htup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(aip->ai_grantor));
694 if (HeapTupleIsValid(htup))
695 {
697 ReleaseSysCache(htup);
698 }
699 else
700 {
701 /* Generate numeric OID if we don't find an entry */
702 sprintf(p, "%u", aip->ai_grantor);
703 }
704
706}
707
708/*
709 * aclitem_match
710 * Two AclItems are considered to match iff they have the same
711 * grantee and grantor; the privileges are ignored.
712 */
713static bool
715{
716 return a1->ai_grantee == a2->ai_grantee &&
717 a1->ai_grantor == a2->ai_grantor;
718}
719
720/*
721 * aclitemComparator
722 * qsort comparison function for AclItems
723 */
724static int
725aclitemComparator(const void *arg1, const void *arg2)
726{
727 const AclItem *a1 = (const AclItem *) arg1;
728 const AclItem *a2 = (const AclItem *) arg2;
729
730 if (a1->ai_grantee > a2->ai_grantee)
731 return 1;
732 if (a1->ai_grantee < a2->ai_grantee)
733 return -1;
734 if (a1->ai_grantor > a2->ai_grantor)
735 return 1;
736 if (a1->ai_grantor < a2->ai_grantor)
737 return -1;
738 if (a1->ai_privs > a2->ai_privs)
739 return 1;
740 if (a1->ai_privs < a2->ai_privs)
741 return -1;
742 return 0;
743}
744
745/*
746 * aclitem equality operator
747 */
748Datum
750{
753 bool result;
754
755 result = a1->ai_privs == a2->ai_privs &&
756 a1->ai_grantee == a2->ai_grantee &&
757 a1->ai_grantor == a2->ai_grantor;
758 PG_RETURN_BOOL(result);
759}
760
761/*
762 * aclitem hash function
763 *
764 * We make aclitems hashable not so much because anyone is likely to hash
765 * them, as because we want array equality to work on aclitem arrays, and
766 * with the typcache mechanism we must have a hash or btree opclass.
767 */
768Datum
770{
772
773 /* not very bright, but avoids any issue of padding in struct */
774 PG_RETURN_UINT32((uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor));
775}
776
777/*
778 * 64-bit hash function for aclitem.
779 *
780 * Similar to hash_aclitem, but accepts a seed and returns a uint64 value.
781 */
782Datum
784{
786 uint64 seed = PG_GETARG_INT64(1);
787 uint32 sum = (uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor);
788
789 return (seed == 0) ? UInt64GetDatum(sum) : hash_uint32_extended(sum, seed);
790}
791
792/*
793 * acldefault() --- create an ACL describing default access permissions
794 *
795 * Change this routine if you want to alter the default access policy for
796 * newly-created objects (or any object with a NULL acl entry). When
797 * you make a change here, don't forget to update the GRANT man page,
798 * which explains all the default permissions.
799 *
800 * Note that these are the hard-wired "defaults" that are used in the
801 * absence of any pg_default_acl entry.
802 */
803Acl *
804acldefault(ObjectType objtype, Oid ownerId)
805{
808 int nacl;
809 Acl *acl;
810 AclItem *aip;
811
812 switch (objtype)
813 {
814 case OBJECT_COLUMN:
815 /* by default, columns have no extra privileges */
818 break;
819 case OBJECT_TABLE:
822 break;
823 case OBJECT_SEQUENCE:
826 break;
827 case OBJECT_DATABASE:
828 /* for backwards compatibility, grant some rights by default */
831 break;
832 case OBJECT_FUNCTION:
833 /* Grant EXECUTE by default, for now */
836 break;
837 case OBJECT_LANGUAGE:
838 /* Grant USAGE by default, for now */
841 break;
845 break;
846 case OBJECT_SCHEMA:
849 break;
853 break;
854 case OBJECT_FDW:
857 break;
861 break;
862 case OBJECT_DOMAIN:
863 case OBJECT_TYPE:
866 break;
870 break;
871 default:
872 elog(ERROR, "unrecognized object type: %d", (int) objtype);
873 world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
875 break;
876 }
877
878 nacl = 0;
880 nacl++;
882 nacl++;
883
884 acl = allocacl(nacl);
885 aip = ACL_DAT(acl);
886
888 {
889 aip->ai_grantee = ACL_ID_PUBLIC;
890 aip->ai_grantor = ownerId;
892 aip++;
893 }
894
895 /*
896 * Note that the owner's entry shows all ordinary privileges but no grant
897 * options. This is because his grant options come "from the system" and
898 * not from his own efforts. (The SQL spec says that the owner's rights
899 * come from a "_SYSTEM" authid.) However, we do consider that the
900 * owner's ordinary privileges are self-granted; this lets him revoke
901 * them. We implement the owner's grant options without any explicit
902 * "_SYSTEM"-like ACL entry, by internally special-casing the owner
903 * wherever we are testing grant options.
904 */
906 {
907 aip->ai_grantee = ownerId;
908 aip->ai_grantor = ownerId;
910 }
911
912 return acl;
913}
914
915
916/*
917 * SQL-accessible version of acldefault(). Hackish mapping from "char" type to
918 * OBJECT_* values.
919 */
920Datum
922{
923 char objtypec = PG_GETARG_CHAR(0);
924 Oid owner = PG_GETARG_OID(1);
925 ObjectType objtype = 0;
926
927 switch (objtypec)
928 {
929 case 'c':
930 objtype = OBJECT_COLUMN;
931 break;
932 case 'r':
933 objtype = OBJECT_TABLE;
934 break;
935 case 's':
936 objtype = OBJECT_SEQUENCE;
937 break;
938 case 'd':
939 objtype = OBJECT_DATABASE;
940 break;
941 case 'f':
942 objtype = OBJECT_FUNCTION;
943 break;
944 case 'l':
945 objtype = OBJECT_LANGUAGE;
946 break;
947 case 'L':
948 objtype = OBJECT_LARGEOBJECT;
949 break;
950 case 'n':
951 objtype = OBJECT_SCHEMA;
952 break;
953 case 'p':
954 objtype = OBJECT_PARAMETER_ACL;
955 break;
956 case 't':
957 objtype = OBJECT_TABLESPACE;
958 break;
959 case 'F':
960 objtype = OBJECT_FDW;
961 break;
962 case 'S':
963 objtype = OBJECT_FOREIGN_SERVER;
964 break;
965 case 'T':
966 objtype = OBJECT_TYPE;
967 break;
968 default:
969 elog(ERROR, "unrecognized object type abbreviation: %c", objtypec);
970 }
971
972 PG_RETURN_ACL_P(acldefault(objtype, owner));
973}
974
975
976/*
977 * Update an ACL array to add or remove specified privileges.
978 *
979 * old_acl: the input ACL array
980 * mod_aip: defines the privileges to be added, removed, or substituted
981 * modechg: ACL_MODECHG_ADD, ACL_MODECHG_DEL, or ACL_MODECHG_EQL
982 * ownerId: Oid of object owner
983 * behavior: RESTRICT or CASCADE behavior for recursive removal
984 *
985 * ownerid and behavior are only relevant when the update operation specifies
986 * deletion of grant options.
987 *
988 * The result is a modified copy; the input object is not changed.
989 *
990 * NB: caller is responsible for having detoasted the input ACL, if needed.
991 */
992Acl *
994 int modechg, Oid ownerId, DropBehavior behavior)
995{
996 Acl *new_acl = NULL;
998 *new_aip = NULL;
1001 new_rights,
1003 int dst,
1004 num;
1005
1006 /* Caller probably already checked old_acl, but be safe */
1008
1009 /* If granting grant options, check for circularity */
1010 if (modechg != ACL_MODECHG_DEL &&
1013
1014 num = ACL_NUM(old_acl);
1016
1017 /*
1018 * Search the ACL for an existing entry for this grantee and grantor. If
1019 * one exists, just modify the entry in-place (well, in the same position,
1020 * since we actually return a copy); otherwise, insert the new entry at
1021 * the end.
1022 */
1023
1024 for (dst = 0; dst < num; ++dst)
1025 {
1027 {
1028 /* found a match, so modify existing item */
1029 new_acl = allocacl(num);
1032 break;
1033 }
1034 }
1035
1036 if (dst == num)
1037 {
1038 /* need to append a new item */
1039 new_acl = allocacl(num + 1);
1041 memcpy(new_aip, old_aip, num * sizeof(AclItem));
1042
1043 /* initialize the new entry with no permissions */
1044 new_aip[dst].ai_grantee = mod_aip->ai_grantee;
1045 new_aip[dst].ai_grantor = mod_aip->ai_grantor;
1048 num++; /* set num to the size of new_acl */
1049 }
1050
1053
1054 /* apply the specified permissions change */
1055 switch (modechg)
1056 {
1057 case ACL_MODECHG_ADD:
1060 break;
1061 case ACL_MODECHG_DEL:
1064 break;
1065 case ACL_MODECHG_EQL:
1068 break;
1069 }
1070
1073
1074 /*
1075 * If the adjusted entry has no permissions, delete it from the list.
1076 */
1078 {
1080 new_aip + dst + 1,
1081 (num - dst - 1) * sizeof(AclItem));
1082 /* Adjust array size to be 'num - 1' items */
1083 ARR_DIMS(new_acl)[0] = num - 1;
1084 SET_VARSIZE(new_acl, ACL_N_SIZE(num - 1));
1085 }
1086
1087 /*
1088 * Remove abandoned privileges (cascading revoke). Currently we can only
1089 * handle this when the grantee is not PUBLIC.
1090 */
1091 if ((old_goptions & ~new_goptions) != 0)
1092 {
1093 Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
1094 new_acl = recursive_revoke(new_acl, mod_aip->ai_grantee,
1096 ownerId, behavior);
1097 }
1098
1099 return new_acl;
1100}
1101
1102/*
1103 * Update an ACL array to reflect a change of owner to the parent object
1104 *
1105 * old_acl: the input ACL array (must not be NULL)
1106 * oldOwnerId: Oid of the old object owner
1107 * newOwnerId: Oid of the new object owner
1108 *
1109 * The result is a modified copy; the input object is not changed.
1110 *
1111 * NB: caller is responsible for having detoasted the input ACL, if needed.
1112 *
1113 * Note: the name of this function is a bit of a misnomer, since it will
1114 * happily make the specified role substitution whether the old role is
1115 * really the owner of the parent object or merely mentioned in its ACL.
1116 * But the vast majority of callers use it in connection with ALTER OWNER
1117 * operations, so we'll keep the name.
1118 */
1119Acl *
1121{
1122 Acl *new_acl;
1128 bool newpresent = false;
1129 int dst,
1130 src,
1131 targ,
1132 num;
1133
1135
1136 /*
1137 * Make a copy of the given ACL, substituting new owner ID for old
1138 * wherever it appears as either grantor or grantee. Also note if the new
1139 * owner ID is already present.
1140 */
1141 num = ACL_NUM(old_acl);
1143 new_acl = allocacl(num);
1145 memcpy(new_aip, old_aip, num * sizeof(AclItem));
1146 for (dst = 0, dst_aip = new_aip; dst < num; dst++, dst_aip++)
1147 {
1148 if (dst_aip->ai_grantor == oldOwnerId)
1149 dst_aip->ai_grantor = newOwnerId;
1150 else if (dst_aip->ai_grantor == newOwnerId)
1151 newpresent = true;
1152 if (dst_aip->ai_grantee == oldOwnerId)
1153 dst_aip->ai_grantee = newOwnerId;
1154 else if (dst_aip->ai_grantee == newOwnerId)
1155 newpresent = true;
1156 }
1157
1158 /*
1159 * If the old ACL contained any references to the new owner, then we may
1160 * now have generated an ACL containing duplicate entries. Find them and
1161 * merge them so that there are not duplicates. (This is relatively
1162 * expensive since we use a stupid O(N^2) algorithm, but it's unlikely to
1163 * be the normal case.)
1164 *
1165 * To simplify deletion of duplicate entries, we temporarily leave them in
1166 * the array but set their privilege masks to zero; when we reach such an
1167 * entry it's just skipped. (Thus, a side effect of this code will be to
1168 * remove privilege-free entries, should there be any in the input.) dst
1169 * is the next output slot, targ is the currently considered input slot
1170 * (always >= dst), and src scans entries to the right of targ looking for
1171 * duplicates. Once an entry has been emitted to dst it is known
1172 * duplicate-free and need not be considered anymore.
1173 */
1174 if (newpresent)
1175 {
1176 dst = 0;
1177 for (targ = 0, targ_aip = new_aip; targ < num; targ++, targ_aip++)
1178 {
1179 /* ignore if deleted in an earlier pass */
1181 continue;
1182 /* find and merge any duplicates */
1183 for (src = targ + 1, src_aip = targ_aip + 1; src < num;
1184 src++, src_aip++)
1185 {
1187 continue;
1189 {
1193 /* mark the duplicate deleted */
1195 }
1196 }
1197 /* and emit to output */
1198 new_aip[dst] = *targ_aip;
1199 dst++;
1200 }
1201 /* Adjust array size to be 'dst' items */
1202 ARR_DIMS(new_acl)[0] = dst;
1204 }
1205
1206 return new_acl;
1207}
1208
1209
1210/*
1211 * When granting grant options, we must disallow attempts to set up circular
1212 * chains of grant options. Suppose A (the object owner) grants B some
1213 * privileges with grant option, and B re-grants them to C. If C could
1214 * grant the privileges to B as well, then A would be unable to effectively
1215 * revoke the privileges from B, since recursive_revoke would consider that
1216 * B still has 'em from C.
1217 *
1218 * We check for this by recursively deleting all grant options belonging to
1219 * the target grantee, and then seeing if the would-be grantor still has the
1220 * grant option or not.
1221 */
1222static void
1224 Oid ownerId)
1225{
1226 Acl *acl;
1227 AclItem *aip;
1228 int i,
1229 num;
1231
1233
1234 /*
1235 * For now, grant options can only be granted to roles, not PUBLIC.
1236 * Otherwise we'd have to work a bit harder here.
1237 */
1238 Assert(mod_aip->ai_grantee != ACL_ID_PUBLIC);
1239
1240 /* The owner always has grant options, no need to check */
1241 if (mod_aip->ai_grantor == ownerId)
1242 return;
1243
1244 /* Make a working copy */
1245 acl = allocacl(ACL_NUM(old_acl));
1247
1248 /* Zap all grant options of target grantee, plus what depends on 'em */
1250 num = ACL_NUM(acl);
1251 aip = ACL_DAT(acl);
1252 for (i = 0; i < num; i++)
1253 {
1254 if (aip[i].ai_grantee == mod_aip->ai_grantee &&
1256 {
1257 Acl *new_acl;
1258
1259 /* We'll actually zap ordinary privs too, but no matter */
1261 ownerId, DROP_CASCADE);
1262
1263 pfree(acl);
1264 acl = new_acl;
1265
1266 goto cc_restart;
1267 }
1268 }
1269
1270 /* Now we can compute grantor's independently-derived privileges */
1271 own_privs = aclmask(acl,
1272 mod_aip->ai_grantor,
1273 ownerId,
1275 ACLMASK_ALL);
1277
1278 if ((ACLITEM_GET_GOPTIONS(*mod_aip) & ~own_privs) != 0)
1279 ereport(ERROR,
1281 errmsg("grant options cannot be granted back to your own grantor")));
1282
1283 pfree(acl);
1284}
1285
1286
1287/*
1288 * Ensure that no privilege is "abandoned". A privilege is abandoned
1289 * if the user that granted the privilege loses the grant option. (So
1290 * the chain through which it was granted is broken.) Either the
1291 * abandoned privileges are revoked as well, or an error message is
1292 * printed, depending on the drop behavior option.
1293 *
1294 * acl: the input ACL list
1295 * grantee: the user from whom some grant options have been revoked
1296 * revoke_privs: the grant options being revoked
1297 * ownerId: Oid of object owner
1298 * behavior: RESTRICT or CASCADE behavior for recursive removal
1299 *
1300 * The input Acl object is pfree'd if replaced.
1301 */
1302static Acl *
1304 Oid grantee,
1306 Oid ownerId,
1307 DropBehavior behavior)
1308{
1310 AclItem *aip;
1311 int i,
1312 num;
1313
1314 check_acl(acl);
1315
1316 /* The owner can never truly lose grant options, so short-circuit */
1317 if (grantee == ownerId)
1318 return acl;
1319
1320 /* The grantee might still have some grant options via another grantor */
1321 still_has = aclmask(acl, grantee, ownerId,
1323 ACLMASK_ALL);
1326 return acl;
1327
1328restart:
1329 num = ACL_NUM(acl);
1330 aip = ACL_DAT(acl);
1331 for (i = 0; i < num; i++)
1332 {
1333 if (aip[i].ai_grantor == grantee
1334 && (ACLITEM_GET_PRIVS(aip[i]) & revoke_privs) != 0)
1335 {
1337 Acl *new_acl;
1338
1339 if (behavior == DROP_RESTRICT)
1340 ereport(ERROR,
1342 errmsg("dependent privileges exist"),
1343 errhint("Use CASCADE to revoke them too.")));
1344
1345 mod_acl.ai_grantor = grantee;
1346 mod_acl.ai_grantee = aip[i].ai_grantee;
1349 revoke_privs);
1350
1352 ownerId, behavior);
1353
1354 pfree(acl);
1355 acl = new_acl;
1356
1357 goto restart;
1358 }
1359 }
1360
1361 return acl;
1362}
1363
1364
1365/*
1366 * aclmask --- compute bitmask of all privileges held by roleid.
1367 *
1368 * When 'how' = ACLMASK_ALL, this simply returns the privilege bits
1369 * held by the given roleid according to the given ACL list, ANDed
1370 * with 'mask'. (The point of passing 'mask' is to let the routine
1371 * exit early if all privileges of interest have been found.)
1372 *
1373 * When 'how' = ACLMASK_ANY, returns as soon as any bit in the mask
1374 * is known true. (This lets us exit soonest in cases where the
1375 * caller is only going to test for zero or nonzero result.)
1376 *
1377 * Usage patterns:
1378 *
1379 * To see if any of a set of privileges are held:
1380 * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ANY) != 0)
1381 *
1382 * To see if all of a set of privileges are held:
1383 * if (aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL) == privs)
1384 *
1385 * To determine exactly which of a set of privileges are held:
1386 * heldprivs = aclmask(acl, roleid, ownerId, privs, ACLMASK_ALL);
1387 */
1388AclMode
1389aclmask(const Acl *acl, Oid roleid, Oid ownerId,
1390 AclMode mask, AclMaskHow how)
1391{
1392 AclMode result;
1394 AclItem *aidat;
1395 int i,
1396 num;
1397
1398 /*
1399 * Null ACL should not happen, since caller should have inserted
1400 * appropriate default
1401 */
1402 if (acl == NULL)
1403 elog(ERROR, "null ACL");
1404
1405 check_acl(acl);
1406
1407 /* Quick exit for mask == 0 */
1408 if (mask == 0)
1409 return 0;
1410
1411 result = 0;
1412
1413 /* Owner always implicitly has all grant options */
1414 if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
1415 has_privs_of_role(roleid, ownerId))
1416 {
1417 result = mask & ACLITEM_ALL_GOPTION_BITS;
1418 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1419 return result;
1420 }
1421
1422 num = ACL_NUM(acl);
1423 aidat = ACL_DAT(acl);
1424
1425 /*
1426 * Check privileges granted directly to roleid or to public
1427 */
1428 for (i = 0; i < num; i++)
1429 {
1430 AclItem *aidata = &aidat[i];
1431
1432 if (aidata->ai_grantee == ACL_ID_PUBLIC ||
1433 aidata->ai_grantee == roleid)
1434 {
1435 result |= aidata->ai_privs & mask;
1436 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1437 return result;
1438 }
1439 }
1440
1441 /*
1442 * Check privileges granted indirectly via role memberships. We do this in
1443 * a separate pass to minimize expensive indirect membership tests. In
1444 * particular, it's worth testing whether a given ACL entry grants any
1445 * privileges still of interest before we perform the has_privs_of_role
1446 * test.
1447 */
1448 remaining = mask & ~result;
1449 for (i = 0; i < num; i++)
1450 {
1451 AclItem *aidata = &aidat[i];
1452
1453 if (aidata->ai_grantee == ACL_ID_PUBLIC ||
1454 aidata->ai_grantee == roleid)
1455 continue; /* already checked it */
1456
1457 if ((aidata->ai_privs & remaining) &&
1458 has_privs_of_role(roleid, aidata->ai_grantee))
1459 {
1460 result |= aidata->ai_privs & mask;
1461 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1462 return result;
1463 remaining = mask & ~result;
1464 }
1465 }
1466
1467 return result;
1468}
1469
1470
1471/*
1472 * aclmask_direct --- compute bitmask of all privileges held by roleid.
1473 *
1474 * This is exactly like aclmask() except that we consider only privileges
1475 * held *directly* by roleid, not those inherited via role membership.
1476 */
1477static AclMode
1478aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId,
1479 AclMode mask, AclMaskHow how)
1480{
1481 AclMode result;
1482 AclItem *aidat;
1483 int i,
1484 num;
1485
1486 /*
1487 * Null ACL should not happen, since caller should have inserted
1488 * appropriate default
1489 */
1490 if (acl == NULL)
1491 elog(ERROR, "null ACL");
1492
1493 check_acl(acl);
1494
1495 /* Quick exit for mask == 0 */
1496 if (mask == 0)
1497 return 0;
1498
1499 result = 0;
1500
1501 /* Owner always implicitly has all grant options */
1502 if ((mask & ACLITEM_ALL_GOPTION_BITS) &&
1503 roleid == ownerId)
1504 {
1505 result = mask & ACLITEM_ALL_GOPTION_BITS;
1506 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1507 return result;
1508 }
1509
1510 num = ACL_NUM(acl);
1511 aidat = ACL_DAT(acl);
1512
1513 /*
1514 * Check privileges granted directly to roleid (and not to public)
1515 */
1516 for (i = 0; i < num; i++)
1517 {
1518 AclItem *aidata = &aidat[i];
1519
1520 if (aidata->ai_grantee == roleid)
1521 {
1522 result |= aidata->ai_privs & mask;
1523 if ((how == ACLMASK_ALL) ? (result == mask) : (result != 0))
1524 return result;
1525 }
1526 }
1527
1528 return result;
1529}
1530
1531
1532/*
1533 * aclmembers
1534 * Find out all the roleids mentioned in an Acl.
1535 * Note that we do not distinguish grantors from grantees.
1536 *
1537 * *roleids is set to point to a palloc'd array containing distinct OIDs
1538 * in sorted order. The length of the array is the function result.
1539 */
1540int
1542{
1543 Oid *list;
1544 const AclItem *acldat;
1545 int i,
1546 j;
1547
1548 if (acl == NULL || ACL_NUM(acl) == 0)
1549 {
1550 *roleids = NULL;
1551 return 0;
1552 }
1553
1554 check_acl(acl);
1555
1556 /* Allocate the worst-case space requirement */
1557 list = palloc(ACL_NUM(acl) * 2 * sizeof(Oid));
1558 acldat = ACL_DAT(acl);
1559
1560 /*
1561 * Walk the ACL collecting mentioned RoleIds.
1562 */
1563 j = 0;
1564 for (i = 0; i < ACL_NUM(acl); i++)
1565 {
1566 const AclItem *ai = &acldat[i];
1567
1568 if (ai->ai_grantee != ACL_ID_PUBLIC)
1569 list[j++] = ai->ai_grantee;
1570 /* grantor is currently never PUBLIC, but let's check anyway */
1571 if (ai->ai_grantor != ACL_ID_PUBLIC)
1572 list[j++] = ai->ai_grantor;
1573 }
1574
1575 /* Sort the array */
1576 qsort(list, j, sizeof(Oid), oid_cmp);
1577
1578 /*
1579 * We could repalloc the array down to minimum size, but it's hardly worth
1580 * it since it's only transient memory.
1581 */
1582 *roleids = list;
1583
1584 /* Remove duplicates from the array */
1585 return qunique(list, j, sizeof(Oid), oid_cmp);
1586}
1587
1588
1589/*
1590 * aclinsert (exported function)
1591 */
1592Datum
1594{
1595 ereport(ERROR,
1597 errmsg("aclinsert is no longer supported")));
1598
1599 PG_RETURN_NULL(); /* keep compiler quiet */
1600}
1601
1602Datum
1604{
1605 ereport(ERROR,
1607 errmsg("aclremove is no longer supported")));
1608
1609 PG_RETURN_NULL(); /* keep compiler quiet */
1610}
1611
1612Datum
1614{
1615 Acl *acl = PG_GETARG_ACL_P(0);
1617 AclItem *aidat;
1618 int i,
1619 num;
1620
1621 check_acl(acl);
1622 num = ACL_NUM(acl);
1623 aidat = ACL_DAT(acl);
1624 for (i = 0; i < num; ++i)
1625 {
1626 if (aip->ai_grantee == aidat[i].ai_grantee &&
1627 aip->ai_grantor == aidat[i].ai_grantor &&
1629 PG_RETURN_BOOL(true);
1630 }
1631 PG_RETURN_BOOL(false);
1632}
1633
1634Datum
1636{
1638 Oid grantor = PG_GETARG_OID(1);
1640 bool goption = PG_GETARG_BOOL(3);
1641 AclItem *result;
1642 AclMode priv;
1643 static const priv_map any_priv_map[] = {
1644 {"SELECT", ACL_SELECT},
1645 {"INSERT", ACL_INSERT},
1646 {"UPDATE", ACL_UPDATE},
1647 {"DELETE", ACL_DELETE},
1648 {"TRUNCATE", ACL_TRUNCATE},
1649 {"REFERENCES", ACL_REFERENCES},
1650 {"TRIGGER", ACL_TRIGGER},
1651 {"EXECUTE", ACL_EXECUTE},
1652 {"USAGE", ACL_USAGE},
1653 {"CREATE", ACL_CREATE},
1654 {"TEMP", ACL_CREATE_TEMP},
1655 {"TEMPORARY", ACL_CREATE_TEMP},
1656 {"CONNECT", ACL_CONNECT},
1657 {"SET", ACL_SET},
1658 {"ALTER SYSTEM", ACL_ALTER_SYSTEM},
1659 {"MAINTAIN", ACL_MAINTAIN},
1660 {NULL, 0}
1661 };
1662
1664
1665 result = palloc_object(AclItem);
1666
1667 result->ai_grantee = grantee;
1668 result->ai_grantor = grantor;
1669
1670 ACLITEM_SET_PRIVS_GOPTIONS(*result, priv,
1671 (goption ? priv : ACL_NO_RIGHTS));
1672
1673 PG_RETURN_ACLITEM_P(result);
1674}
1675
1676
1677/*
1678 * convert_any_priv_string: recognize privilege strings for has_foo_privilege
1679 *
1680 * We accept a comma-separated list of case-insensitive privilege names,
1681 * producing a bitmask of the OR'd privilege bits. We are liberal about
1682 * whitespace between items, not so much about whitespace within items.
1683 * The allowed privilege names are given as an array of priv_map structs,
1684 * terminated by one with a NULL name pointer.
1685 */
1686static AclMode
1688 const priv_map *privileges)
1689{
1690 AclMode result = 0;
1692 char *chunk;
1693 char *next_chunk;
1694
1695 /* We rely on priv_type being a private, modifiable string */
1697 {
1698 int chunk_len;
1699 const priv_map *this_priv;
1700
1701 /* Split string at commas */
1702 next_chunk = strchr(chunk, ',');
1703 if (next_chunk)
1704 *next_chunk++ = '\0';
1705
1706 /* Drop leading/trailing whitespace in this chunk */
1707 while (*chunk && isspace((unsigned char) *chunk))
1708 chunk++;
1710 while (chunk_len > 0 && isspace((unsigned char) chunk[chunk_len - 1]))
1711 chunk_len--;
1712 chunk[chunk_len] = '\0';
1713
1714 /* Match to the privileges list */
1715 for (this_priv = privileges; this_priv->name; this_priv++)
1716 {
1717 if (pg_strcasecmp(this_priv->name, chunk) == 0)
1718 {
1719 result |= this_priv->value;
1720 break;
1721 }
1722 }
1723 if (!this_priv->name)
1724 ereport(ERROR,
1726 errmsg("unrecognized privilege type: \"%s\"", chunk)));
1727 }
1728
1730 return result;
1731}
1732
1733
1734static const char *
1736{
1737 switch (aclright)
1738 {
1739 case ACL_INSERT:
1740 return "INSERT";
1741 case ACL_SELECT:
1742 return "SELECT";
1743 case ACL_UPDATE:
1744 return "UPDATE";
1745 case ACL_DELETE:
1746 return "DELETE";
1747 case ACL_TRUNCATE:
1748 return "TRUNCATE";
1749 case ACL_REFERENCES:
1750 return "REFERENCES";
1751 case ACL_TRIGGER:
1752 return "TRIGGER";
1753 case ACL_EXECUTE:
1754 return "EXECUTE";
1755 case ACL_USAGE:
1756 return "USAGE";
1757 case ACL_CREATE:
1758 return "CREATE";
1759 case ACL_CREATE_TEMP:
1760 return "TEMPORARY";
1761 case ACL_CONNECT:
1762 return "CONNECT";
1763 case ACL_SET:
1764 return "SET";
1765 case ACL_ALTER_SYSTEM:
1766 return "ALTER SYSTEM";
1767 case ACL_MAINTAIN:
1768 return "MAINTAIN";
1769 default:
1770 elog(ERROR, "unrecognized aclright: %d", aclright);
1771 return NULL;
1772 }
1773}
1774
1775
1776/*----------
1777 * Convert an aclitem[] to a table.
1778 *
1779 * Example:
1780 *
1781 * aclexplode('{=r/joe,foo=a*w/joe}'::aclitem[])
1782 *
1783 * returns the table
1784 *
1785 * {{ OID(joe), 0::OID, 'SELECT', false },
1786 * { OID(joe), OID(foo), 'INSERT', true },
1787 * { OID(joe), OID(foo), 'UPDATE', false }}
1788 *----------
1789 */
1790Datum
1792{
1793 Acl *acl = PG_GETARG_ACL_P(0);
1795 int *idx;
1796 AclItem *aidat;
1797
1798 if (SRF_IS_FIRSTCALL())
1799 {
1800 TupleDesc tupdesc;
1801 MemoryContext oldcontext;
1802
1803 check_acl(acl);
1804
1806 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1807
1808 /*
1809 * build tupdesc for result tuples (matches out parameters in pg_proc
1810 * entry)
1811 */
1812 tupdesc = CreateTemplateTupleDesc(4);
1813 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "grantor",
1814 OIDOID, -1, 0);
1815 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "grantee",
1816 OIDOID, -1, 0);
1817 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "privilege_type",
1818 TEXTOID, -1, 0);
1819 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "is_grantable",
1820 BOOLOID, -1, 0);
1821
1822 funcctx->tuple_desc = BlessTupleDesc(tupdesc);
1823
1824 /* allocate memory for user context */
1825 idx = palloc_array(int, 2);
1826 idx[0] = 0; /* ACL array item index */
1827 idx[1] = -1; /* privilege type counter */
1828 funcctx->user_fctx = idx;
1829
1830 MemoryContextSwitchTo(oldcontext);
1831 }
1832
1834 idx = (int *) funcctx->user_fctx;
1835 aidat = ACL_DAT(acl);
1836
1837 /* need test here in case acl has no items */
1838 while (idx[0] < ACL_NUM(acl))
1839 {
1840 AclItem *aidata;
1842
1843 idx[1]++;
1844 if (idx[1] == N_ACL_RIGHTS)
1845 {
1846 idx[1] = 0;
1847 idx[0]++;
1848 if (idx[0] >= ACL_NUM(acl)) /* done */
1849 break;
1850 }
1851 aidata = &aidat[idx[0]];
1852 priv_bit = UINT64CONST(1) << idx[1];
1853
1855 {
1856 Datum result;
1857 Datum values[4];
1858 bool nulls[4] = {0};
1859 HeapTuple tuple;
1860
1861 values[0] = ObjectIdGetDatum(aidata->ai_grantor);
1862 values[1] = ObjectIdGetDatum(aidata->ai_grantee);
1865
1866 tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
1867 result = HeapTupleGetDatum(tuple);
1868
1869 SRF_RETURN_NEXT(funcctx, result);
1870 }
1871 }
1872
1874}
1875
1876
1877/*
1878 * has_table_privilege variants
1879 * These are all named "has_table_privilege" at the SQL level.
1880 * They take various combinations of relation name, relation OID,
1881 * user name, user OID, or implicit user = current_user.
1882 *
1883 * The result is a boolean value: true if user has the indicated
1884 * privilege, false if not. The variants that take a relation OID
1885 * return NULL if the OID doesn't exist (rather than failing, as
1886 * they did before Postgres 8.4).
1887 */
1888
1889/*
1890 * has_table_privilege_name_name
1891 * Check user privileges on a table given
1892 * name username, text tablename, and text priv name.
1893 */
1894Datum
1896{
1897 Name rolename = PG_GETARG_NAME(0);
1898 text *tablename = PG_GETARG_TEXT_PP(1);
1900 Oid roleid;
1901 Oid tableoid;
1902 AclMode mode;
1904
1905 roleid = get_role_oid_or_public(NameStr(*rolename));
1906 tableoid = convert_table_name(tablename);
1908
1909 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1910
1912}
1913
1914/*
1915 * has_table_privilege_name
1916 * Check user privileges on a table given
1917 * text tablename and text priv name.
1918 * current_user is assumed
1919 */
1920Datum
1922{
1923 text *tablename = PG_GETARG_TEXT_PP(0);
1925 Oid roleid;
1926 Oid tableoid;
1927 AclMode mode;
1929
1930 roleid = GetUserId();
1931 tableoid = convert_table_name(tablename);
1933
1934 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
1935
1937}
1938
1939/*
1940 * has_table_privilege_name_id
1941 * Check user privileges on a table given
1942 * name usename, table oid, and text priv name.
1943 */
1944Datum
1946{
1948 Oid tableoid = PG_GETARG_OID(1);
1950 Oid roleid;
1951 AclMode mode;
1953 bool is_missing = false;
1954
1957
1958 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
1959
1960 if (is_missing)
1962
1964}
1965
1966/*
1967 * has_table_privilege_id
1968 * Check user privileges on a table given
1969 * table oid, and text priv name.
1970 * current_user is assumed
1971 */
1972Datum
1974{
1975 Oid tableoid = PG_GETARG_OID(0);
1977 Oid roleid;
1978 AclMode mode;
1980 bool is_missing = false;
1981
1982 roleid = GetUserId();
1984
1985 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
1986
1987 if (is_missing)
1989
1991}
1992
1993/*
1994 * has_table_privilege_id_name
1995 * Check user privileges on a table given
1996 * roleid, text tablename, and text priv name.
1997 */
1998Datum
2000{
2001 Oid roleid = PG_GETARG_OID(0);
2002 text *tablename = PG_GETARG_TEXT_PP(1);
2004 Oid tableoid;
2005 AclMode mode;
2007
2008 tableoid = convert_table_name(tablename);
2010
2011 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2012
2014}
2015
2016/*
2017 * has_table_privilege_id_id
2018 * Check user privileges on a table given
2019 * roleid, table oid, and text priv name.
2020 */
2021Datum
2023{
2024 Oid roleid = PG_GETARG_OID(0);
2025 Oid tableoid = PG_GETARG_OID(1);
2027 AclMode mode;
2029 bool is_missing = false;
2030
2032
2033 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2034
2035 if (is_missing)
2037
2039}
2040
2041/*
2042 * Support routines for has_table_privilege family.
2043 */
2044
2045/*
2046 * Given a table name expressed as a string, look it up and return Oid
2047 */
2048static Oid
2050{
2051 RangeVar *relrv;
2052
2054
2055 /* We might not even have permissions on this relation; don't lock it. */
2056 return RangeVarGetRelid(relrv, NoLock, false);
2057}
2058
2059/*
2060 * convert_table_priv_string
2061 * Convert text string to AclMode value.
2062 */
2063static AclMode
2065{
2066 static const priv_map table_priv_map[] = {
2067 {"SELECT", ACL_SELECT},
2068 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2069 {"INSERT", ACL_INSERT},
2070 {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
2071 {"UPDATE", ACL_UPDATE},
2072 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2073 {"DELETE", ACL_DELETE},
2074 {"DELETE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_DELETE)},
2075 {"TRUNCATE", ACL_TRUNCATE},
2076 {"TRUNCATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRUNCATE)},
2077 {"REFERENCES", ACL_REFERENCES},
2078 {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
2079 {"TRIGGER", ACL_TRIGGER},
2080 {"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)},
2081 {"MAINTAIN", ACL_MAINTAIN},
2082 {"MAINTAIN WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_MAINTAIN)},
2083 {NULL, 0}
2084 };
2085
2087}
2088
2089/*
2090 * has_sequence_privilege variants
2091 * These are all named "has_sequence_privilege" at the SQL level.
2092 * They take various combinations of relation name, relation OID,
2093 * user name, user OID, or implicit user = current_user.
2094 *
2095 * The result is a boolean value: true if user has the indicated
2096 * privilege, false if not. The variants that take a relation OID
2097 * return NULL if the OID doesn't exist.
2098 */
2099
2100/*
2101 * has_sequence_privilege_name_name
2102 * Check user privileges on a sequence given
2103 * name username, text sequencename, and text priv name.
2104 */
2105Datum
2129
2130/*
2131 * has_sequence_privilege_name
2132 * Check user privileges on a sequence given
2133 * text sequencename and text priv name.
2134 * current_user is assumed
2135 */
2136Datum
2159
2160/*
2161 * has_sequence_privilege_name_id
2162 * Check user privileges on a sequence given
2163 * name usename, sequence oid, and text priv name.
2164 */
2165Datum
2167{
2171 Oid roleid;
2172 AclMode mode;
2174 char relkind;
2175 bool is_missing = false;
2176
2179 relkind = get_rel_relkind(sequenceoid);
2180 if (relkind == '\0')
2182 else if (relkind != RELKIND_SEQUENCE)
2183 ereport(ERROR,
2185 errmsg("\"%s\" is not a sequence",
2187
2189
2190 if (is_missing)
2192
2194}
2195
2196/*
2197 * has_sequence_privilege_id
2198 * Check user privileges on a sequence given
2199 * sequence oid, and text priv name.
2200 * current_user is assumed
2201 */
2202Datum
2204{
2207 Oid roleid;
2208 AclMode mode;
2210 char relkind;
2211 bool is_missing = false;
2212
2213 roleid = GetUserId();
2215 relkind = get_rel_relkind(sequenceoid);
2216 if (relkind == '\0')
2218 else if (relkind != RELKIND_SEQUENCE)
2219 ereport(ERROR,
2221 errmsg("\"%s\" is not a sequence",
2223
2225
2226 if (is_missing)
2228
2230}
2231
2232/*
2233 * has_sequence_privilege_id_name
2234 * Check user privileges on a sequence given
2235 * roleid, text sequencename, and text priv name.
2236 */
2237Datum
2259
2260/*
2261 * has_sequence_privilege_id_id
2262 * Check user privileges on a sequence given
2263 * roleid, sequence oid, and text priv name.
2264 */
2265Datum
2267{
2268 Oid roleid = PG_GETARG_OID(0);
2271 AclMode mode;
2273 char relkind;
2274 bool is_missing = false;
2275
2277 relkind = get_rel_relkind(sequenceoid);
2278 if (relkind == '\0')
2280 else if (relkind != RELKIND_SEQUENCE)
2281 ereport(ERROR,
2283 errmsg("\"%s\" is not a sequence",
2285
2287
2288 if (is_missing)
2290
2292}
2293
2294/*
2295 * convert_sequence_priv_string
2296 * Convert text string to AclMode value.
2297 */
2298static AclMode
2300{
2301 static const priv_map sequence_priv_map[] = {
2302 {"USAGE", ACL_USAGE},
2303 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
2304 {"SELECT", ACL_SELECT},
2305 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2306 {"UPDATE", ACL_UPDATE},
2307 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2308 {NULL, 0}
2309 };
2310
2312}
2313
2314
2315/*
2316 * has_any_column_privilege variants
2317 * These are all named "has_any_column_privilege" at the SQL level.
2318 * They take various combinations of relation name, relation OID,
2319 * user name, user OID, or implicit user = current_user.
2320 *
2321 * The result is a boolean value: true if user has the indicated
2322 * privilege for any column of the table, false if not. The variants
2323 * that take a relation OID return NULL if the OID doesn't exist.
2324 */
2325
2326/*
2327 * has_any_column_privilege_name_name
2328 * Check user privileges on any column of a table given
2329 * name username, text tablename, and text priv name.
2330 */
2331Datum
2333{
2334 Name rolename = PG_GETARG_NAME(0);
2335 text *tablename = PG_GETARG_TEXT_PP(1);
2337 Oid roleid;
2338 Oid tableoid;
2339 AclMode mode;
2341
2342 roleid = get_role_oid_or_public(NameStr(*rolename));
2343 tableoid = convert_table_name(tablename);
2345
2346 /* First check at table level, then examine each column if needed */
2347 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2348 if (aclresult != ACLCHECK_OK)
2349 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2350 ACLMASK_ANY);
2351
2353}
2354
2355/*
2356 * has_any_column_privilege_name
2357 * Check user privileges on any column of a table given
2358 * text tablename and text priv name.
2359 * current_user is assumed
2360 */
2361Datum
2363{
2364 text *tablename = PG_GETARG_TEXT_PP(0);
2366 Oid roleid;
2367 Oid tableoid;
2368 AclMode mode;
2370
2371 roleid = GetUserId();
2372 tableoid = convert_table_name(tablename);
2374
2375 /* First check at table level, then examine each column if needed */
2376 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2377 if (aclresult != ACLCHECK_OK)
2378 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2379 ACLMASK_ANY);
2380
2382}
2383
2384/*
2385 * has_any_column_privilege_name_id
2386 * Check user privileges on any column of a table given
2387 * name usename, table oid, and text priv name.
2388 */
2389Datum
2391{
2393 Oid tableoid = PG_GETARG_OID(1);
2395 Oid roleid;
2396 AclMode mode;
2398 bool is_missing = false;
2399
2402
2403 /* First check at table level, then examine each column if needed */
2404 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2405 if (aclresult != ACLCHECK_OK)
2406 {
2407 if (is_missing)
2409 aclresult = pg_attribute_aclcheck_all_ext(tableoid, roleid, mode,
2411 if (is_missing)
2413 }
2414
2416}
2417
2418/*
2419 * has_any_column_privilege_id
2420 * Check user privileges on any column of a table given
2421 * table oid, and text priv name.
2422 * current_user is assumed
2423 */
2424Datum
2426{
2427 Oid tableoid = PG_GETARG_OID(0);
2429 Oid roleid;
2430 AclMode mode;
2432 bool is_missing = false;
2433
2434 roleid = GetUserId();
2436
2437 /* First check at table level, then examine each column if needed */
2438 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2439 if (aclresult != ACLCHECK_OK)
2440 {
2441 if (is_missing)
2443 aclresult = pg_attribute_aclcheck_all_ext(tableoid, roleid, mode,
2445 if (is_missing)
2447 }
2448
2450}
2451
2452/*
2453 * has_any_column_privilege_id_name
2454 * Check user privileges on any column of a table given
2455 * roleid, text tablename, and text priv name.
2456 */
2457Datum
2459{
2460 Oid roleid = PG_GETARG_OID(0);
2461 text *tablename = PG_GETARG_TEXT_PP(1);
2463 Oid tableoid;
2464 AclMode mode;
2466
2467 tableoid = convert_table_name(tablename);
2469
2470 /* First check at table level, then examine each column if needed */
2471 aclresult = pg_class_aclcheck(tableoid, roleid, mode);
2472 if (aclresult != ACLCHECK_OK)
2473 aclresult = pg_attribute_aclcheck_all(tableoid, roleid, mode,
2474 ACLMASK_ANY);
2475
2477}
2478
2479/*
2480 * has_any_column_privilege_id_id
2481 * Check user privileges on any column of a table given
2482 * roleid, table oid, and text priv name.
2483 */
2484Datum
2486{
2487 Oid roleid = PG_GETARG_OID(0);
2488 Oid tableoid = PG_GETARG_OID(1);
2490 AclMode mode;
2492 bool is_missing = false;
2493
2495
2496 /* First check at table level, then examine each column if needed */
2497 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2498 if (aclresult != ACLCHECK_OK)
2499 {
2500 if (is_missing)
2502 aclresult = pg_attribute_aclcheck_all_ext(tableoid, roleid, mode,
2504 if (is_missing)
2506 }
2507
2509}
2510
2511
2512/*
2513 * has_column_privilege variants
2514 * These are all named "has_column_privilege" at the SQL level.
2515 * They take various combinations of relation name, relation OID,
2516 * column name, column attnum, user name, user OID, or
2517 * implicit user = current_user.
2518 *
2519 * The result is a boolean value: true if user has the indicated
2520 * privilege, false if not. The variants that take a relation OID
2521 * return NULL (rather than throwing an error) if that relation OID
2522 * doesn't exist. Likewise, the variants that take an integer attnum
2523 * return NULL (rather than throwing an error) if there is no such
2524 * pg_attribute entry. All variants return NULL if an attisdropped
2525 * column is selected. These rules are meant to avoid unnecessary
2526 * failures in queries that scan pg_attribute.
2527 */
2528
2529/*
2530 * column_privilege_check: check column privileges, but don't throw an error
2531 * for dropped column or table
2532 *
2533 * Returns 1 if have the privilege, 0 if not, -1 if dropped column/table.
2534 */
2535static int
2537 Oid roleid, AclMode mode)
2538{
2540 bool is_missing = false;
2541
2542 /*
2543 * If convert_column_name failed, we can just return -1 immediately.
2544 */
2546 return -1;
2547
2548 /*
2549 * Check for column-level privileges first. This serves in part as a check
2550 * on whether the column even exists, so we need to do it before checking
2551 * table-level privilege.
2552 */
2553 aclresult = pg_attribute_aclcheck_ext(tableoid, attnum, roleid,
2554 mode, &is_missing);
2555 if (aclresult == ACLCHECK_OK)
2556 return 1;
2557 else if (is_missing)
2558 return -1;
2559
2560 /* Next check if we have the privilege at the table level */
2561 aclresult = pg_class_aclcheck_ext(tableoid, roleid, mode, &is_missing);
2562 if (aclresult == ACLCHECK_OK)
2563 return 1;
2564 else if (is_missing)
2565 return -1;
2566 else
2567 return 0;
2568}
2569
2570/*
2571 * has_column_privilege_name_name_name
2572 * Check user privileges on a column given
2573 * name username, text tablename, text colname, and text priv name.
2574 */
2575Datum
2577{
2578 Name rolename = PG_GETARG_NAME(0);
2579 text *tablename = PG_GETARG_TEXT_PP(1);
2582 Oid roleid;
2583 Oid tableoid;
2585 AclMode mode;
2586 int privresult;
2587
2588 roleid = get_role_oid_or_public(NameStr(*rolename));
2589 tableoid = convert_table_name(tablename);
2592
2593 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2594 if (privresult < 0)
2597}
2598
2599/*
2600 * has_column_privilege_name_name_attnum
2601 * Check user privileges on a column given
2602 * name username, text tablename, int attnum, and text priv name.
2603 */
2604Datum
2606{
2607 Name rolename = PG_GETARG_NAME(0);
2608 text *tablename = PG_GETARG_TEXT_PP(1);
2611 Oid roleid;
2612 Oid tableoid;
2613 AclMode mode;
2614 int privresult;
2615
2616 roleid = get_role_oid_or_public(NameStr(*rolename));
2617 tableoid = convert_table_name(tablename);
2619
2620 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2621 if (privresult < 0)
2624}
2625
2626/*
2627 * has_column_privilege_name_id_name
2628 * Check user privileges on a column given
2629 * name username, table oid, text colname, and text priv name.
2630 */
2631Datum
2652
2653/*
2654 * has_column_privilege_name_id_attnum
2655 * Check user privileges on a column given
2656 * name username, table oid, int attnum, and text priv name.
2657 */
2658Datum
2677
2678/*
2679 * has_column_privilege_id_name_name
2680 * Check user privileges on a column given
2681 * oid roleid, text tablename, text colname, and text priv name.
2682 */
2683Datum
2685{
2686 Oid roleid = PG_GETARG_OID(0);
2687 text *tablename = PG_GETARG_TEXT_PP(1);
2690 Oid tableoid;
2692 AclMode mode;
2693 int privresult;
2694
2695 tableoid = convert_table_name(tablename);
2698
2699 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2700 if (privresult < 0)
2703}
2704
2705/*
2706 * has_column_privilege_id_name_attnum
2707 * Check user privileges on a column given
2708 * oid roleid, text tablename, int attnum, and text priv name.
2709 */
2710Datum
2712{
2713 Oid roleid = PG_GETARG_OID(0);
2714 text *tablename = PG_GETARG_TEXT_PP(1);
2717 Oid tableoid;
2718 AclMode mode;
2719 int privresult;
2720
2721 tableoid = convert_table_name(tablename);
2723
2724 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2725 if (privresult < 0)
2728}
2729
2730/*
2731 * has_column_privilege_id_id_name
2732 * Check user privileges on a column given
2733 * oid roleid, table oid, text colname, and text priv name.
2734 */
2735Datum
2754
2755/*
2756 * has_column_privilege_id_id_attnum
2757 * Check user privileges on a column given
2758 * oid roleid, table oid, int attnum, and text priv name.
2759 */
2760Datum
2777
2778/*
2779 * has_column_privilege_name_name
2780 * Check user privileges on a column given
2781 * text tablename, text colname, and text priv name.
2782 * current_user is assumed
2783 */
2784Datum
2786{
2787 text *tablename = PG_GETARG_TEXT_PP(0);
2790 Oid roleid;
2791 Oid tableoid;
2793 AclMode mode;
2794 int privresult;
2795
2796 roleid = GetUserId();
2797 tableoid = convert_table_name(tablename);
2800
2801 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2802 if (privresult < 0)
2805}
2806
2807/*
2808 * has_column_privilege_name_attnum
2809 * Check user privileges on a column given
2810 * text tablename, int attnum, and text priv name.
2811 * current_user is assumed
2812 */
2813Datum
2815{
2816 text *tablename = PG_GETARG_TEXT_PP(0);
2819 Oid roleid;
2820 Oid tableoid;
2821 AclMode mode;
2822 int privresult;
2823
2824 roleid = GetUserId();
2825 tableoid = convert_table_name(tablename);
2827
2828 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2829 if (privresult < 0)
2832}
2833
2834/*
2835 * has_column_privilege_id_name
2836 * Check user privileges on a column given
2837 * table oid, text colname, and text priv name.
2838 * current_user is assumed
2839 */
2840Datum
2842{
2843 Oid tableoid = PG_GETARG_OID(0);
2846 Oid roleid;
2848 AclMode mode;
2849 int privresult;
2850
2851 roleid = GetUserId();
2854
2855 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2856 if (privresult < 0)
2859}
2860
2861/*
2862 * has_column_privilege_id_attnum
2863 * Check user privileges on a column given
2864 * table oid, int attnum, and text priv name.
2865 * current_user is assumed
2866 */
2867Datum
2869{
2870 Oid tableoid = PG_GETARG_OID(0);
2873 Oid roleid;
2874 AclMode mode;
2875 int privresult;
2876
2877 roleid = GetUserId();
2879
2880 privresult = column_privilege_check(tableoid, colattnum, roleid, mode);
2881 if (privresult < 0)
2884}
2885
2886/*
2887 * Support routines for has_column_privilege family.
2888 */
2889
2890/*
2891 * Given a table OID and a column name expressed as a string, look it up
2892 * and return the column number. Returns InvalidAttrNumber in cases
2893 * where caller should return NULL instead of failing.
2894 */
2895static AttrNumber
2897{
2898 char *colname;
2901
2902 colname = text_to_cstring(column);
2903
2904 /*
2905 * We don't use get_attnum() here because it will report that dropped
2906 * columns don't exist. We need to treat dropped columns differently from
2907 * nonexistent columns.
2908 */
2910 ObjectIdGetDatum(tableoid),
2911 CStringGetDatum(colname));
2913 {
2915
2917 /* We want to return NULL for dropped columns */
2918 if (attributeForm->attisdropped)
2920 else
2921 attnum = attributeForm->attnum;
2923 }
2924 else
2925 {
2926 char *tablename = get_rel_name(tableoid);
2927
2928 /*
2929 * If the table OID is bogus, or it's just been dropped, we'll get
2930 * NULL back. In such cases we want has_column_privilege to return
2931 * NULL too, so just return InvalidAttrNumber.
2932 */
2933 if (tablename != NULL)
2934 {
2935 /* tableoid exists, colname does not, so throw error */
2936 ereport(ERROR,
2938 errmsg("column \"%s\" of relation \"%s\" does not exist",
2939 colname, tablename)));
2940 }
2941 /* tableoid doesn't exist, so act like attisdropped case */
2943 }
2944
2945 pfree(colname);
2946 return attnum;
2947}
2948
2949/*
2950 * convert_column_priv_string
2951 * Convert text string to AclMode value.
2952 */
2953static AclMode
2955{
2956 static const priv_map column_priv_map[] = {
2957 {"SELECT", ACL_SELECT},
2958 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
2959 {"INSERT", ACL_INSERT},
2960 {"INSERT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_INSERT)},
2961 {"UPDATE", ACL_UPDATE},
2962 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
2963 {"REFERENCES", ACL_REFERENCES},
2964 {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)},
2965 {NULL, 0}
2966 };
2967
2969}
2970
2971
2972/*
2973 * has_database_privilege variants
2974 * These are all named "has_database_privilege" at the SQL level.
2975 * They take various combinations of database name, database OID,
2976 * user name, user OID, or implicit user = current_user.
2977 *
2978 * The result is a boolean value: true if user has the indicated
2979 * privilege, false if not, or NULL if object doesn't exist.
2980 */
2981
2982/*
2983 * has_database_privilege_name_name
2984 * Check user privileges on a database given
2985 * name username, text databasename, and text priv name.
2986 */
2987Datum
3006
3007/*
3008 * has_database_privilege_name
3009 * Check user privileges on a database given
3010 * text databasename and text priv name.
3011 * current_user is assumed
3012 */
3013Datum
3031
3032/*
3033 * has_database_privilege_name_id
3034 * Check user privileges on a database given
3035 * name usename, database oid, and text priv name.
3036 */
3037Datum
3060
3061/*
3062 * has_database_privilege_id
3063 * Check user privileges on a database given
3064 * database oid, and text priv name.
3065 * current_user is assumed
3066 */
3067Datum
3089
3090/*
3091 * has_database_privilege_id_name
3092 * Check user privileges on a database given
3093 * roleid, text databasename, and text priv name.
3094 */
3095Datum
3112
3113/*
3114 * has_database_privilege_id_id
3115 * Check user privileges on a database given
3116 * roleid, database oid, and text priv name.
3117 */
3118Datum
3139
3140/*
3141 * Support routines for has_database_privilege family.
3142 */
3143
3144/*
3145 * Given a database name expressed as a string, look it up and return Oid
3146 */
3147static Oid
3154
3155/*
3156 * convert_database_priv_string
3157 * Convert text string to AclMode value.
3158 */
3159static AclMode
3161{
3162 static const priv_map database_priv_map[] = {
3163 {"CREATE", ACL_CREATE},
3164 {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
3165 {"TEMPORARY", ACL_CREATE_TEMP},
3166 {"TEMPORARY WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
3167 {"TEMP", ACL_CREATE_TEMP},
3168 {"TEMP WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE_TEMP)},
3169 {"CONNECT", ACL_CONNECT},
3170 {"CONNECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CONNECT)},
3171 {NULL, 0}
3172 };
3173
3175}
3176
3177
3178/*
3179 * has_foreign_data_wrapper_privilege variants
3180 * These are all named "has_foreign_data_wrapper_privilege" at the SQL level.
3181 * They take various combinations of foreign-data wrapper name,
3182 * fdw OID, user name, user OID, or implicit user = current_user.
3183 *
3184 * The result is a boolean value: true if user has the indicated
3185 * privilege, false if not.
3186 */
3187
3188/*
3189 * has_foreign_data_wrapper_privilege_name_name
3190 * Check user privileges on a foreign-data wrapper given
3191 * name username, text fdwname, and text priv name.
3192 */
3193Datum
3212
3213/*
3214 * has_foreign_data_wrapper_privilege_name
3215 * Check user privileges on a foreign-data wrapper given
3216 * text fdwname and text priv name.
3217 * current_user is assumed
3218 */
3219Datum
3237
3238/*
3239 * has_foreign_data_wrapper_privilege_name_id
3240 * Check user privileges on a foreign-data wrapper given
3241 * name usename, foreign-data wrapper oid, and text priv name.
3242 */
3243Datum
3266
3267/*
3268 * has_foreign_data_wrapper_privilege_id
3269 * Check user privileges on a foreign-data wrapper given
3270 * foreign-data wrapper oid, and text priv name.
3271 * current_user is assumed
3272 */
3273Datum
3295
3296/*
3297 * has_foreign_data_wrapper_privilege_id_name
3298 * Check user privileges on a foreign-data wrapper given
3299 * roleid, text fdwname, and text priv name.
3300 */
3301Datum
3318
3319/*
3320 * has_foreign_data_wrapper_privilege_id_id
3321 * Check user privileges on a foreign-data wrapper given
3322 * roleid, fdw oid, and text priv name.
3323 */
3324Datum
3345
3346/*
3347 * Support routines for has_foreign_data_wrapper_privilege family.
3348 */
3349
3350/*
3351 * Given a FDW name expressed as a string, look it up and return Oid
3352 */
3353static Oid
3355{
3356 char *fdwstr = text_to_cstring(fdwname);
3357
3358 return get_foreign_data_wrapper_oid(fdwstr, false);
3359}
3360
3361/*
3362 * convert_foreign_data_wrapper_priv_string
3363 * Convert text string to AclMode value.
3364 */
3365static AclMode
3367{
3368 static const priv_map foreign_data_wrapper_priv_map[] = {
3369 {"USAGE", ACL_USAGE},
3370 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3371 {NULL, 0}
3372 };
3373
3375}
3376
3377
3378/*
3379 * has_function_privilege variants
3380 * These are all named "has_function_privilege" at the SQL level.
3381 * They take various combinations of function name, function OID,
3382 * user name, user OID, or implicit user = current_user.
3383 *
3384 * The result is a boolean value: true if user has the indicated
3385 * privilege, false if not, or NULL if object doesn't exist.
3386 */
3387
3388/*
3389 * has_function_privilege_name_name
3390 * Check user privileges on a function given
3391 * name username, text functionname, and text priv name.
3392 */
3393Datum
3412
3413/*
3414 * has_function_privilege_name
3415 * Check user privileges on a function given
3416 * text functionname and text priv name.
3417 * current_user is assumed
3418 */
3419Datum
3437
3438/*
3439 * has_function_privilege_name_id
3440 * Check user privileges on a function given
3441 * name usename, function oid, and text priv name.
3442 */
3443Datum
3466
3467/*
3468 * has_function_privilege_id
3469 * Check user privileges on a function given
3470 * function oid, and text priv name.
3471 * current_user is assumed
3472 */
3473Datum
3495
3496/*
3497 * has_function_privilege_id_name
3498 * Check user privileges on a function given
3499 * roleid, text functionname, and text priv name.
3500 */
3501Datum
3518
3519/*
3520 * has_function_privilege_id_id
3521 * Check user privileges on a function given
3522 * roleid, function oid, and text priv name.
3523 */
3524Datum
3545
3546/*
3547 * Support routines for has_function_privilege family.
3548 */
3549
3550/*
3551 * Given a function name expressed as a string, look it up and return Oid
3552 */
3553static Oid
3555{
3557 Oid oid;
3558
3561
3562 if (!OidIsValid(oid))
3563 ereport(ERROR,
3565 errmsg("function \"%s\" does not exist", funcname)));
3566
3567 return oid;
3568}
3569
3570/*
3571 * convert_function_priv_string
3572 * Convert text string to AclMode value.
3573 */
3574static AclMode
3576{
3577 static const priv_map function_priv_map[] = {
3578 {"EXECUTE", ACL_EXECUTE},
3579 {"EXECUTE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_EXECUTE)},
3580 {NULL, 0}
3581 };
3582
3584}
3585
3586
3587/*
3588 * has_language_privilege variants
3589 * These are all named "has_language_privilege" at the SQL level.
3590 * They take various combinations of language name, language OID,
3591 * user name, user OID, or implicit user = current_user.
3592 *
3593 * The result is a boolean value: true if user has the indicated
3594 * privilege, false if not, or NULL if object doesn't exist.
3595 */
3596
3597/*
3598 * has_language_privilege_name_name
3599 * Check user privileges on a language given
3600 * name username, text languagename, and text priv name.
3601 */
3602Datum
3621
3622/*
3623 * has_language_privilege_name
3624 * Check user privileges on a language given
3625 * text languagename and text priv name.
3626 * current_user is assumed
3627 */
3628Datum
3646
3647/*
3648 * has_language_privilege_name_id
3649 * Check user privileges on a language given
3650 * name usename, language oid, and text priv name.
3651 */
3652Datum
3675
3676/*
3677 * has_language_privilege_id
3678 * Check user privileges on a language given
3679 * language oid, and text priv name.
3680 * current_user is assumed
3681 */
3682Datum
3704
3705/*
3706 * has_language_privilege_id_name
3707 * Check user privileges on a language given
3708 * roleid, text languagename, and text priv name.
3709 */
3710Datum
3727
3728/*
3729 * has_language_privilege_id_id
3730 * Check user privileges on a language given
3731 * roleid, language oid, and text priv name.
3732 */
3733Datum
3754
3755/*
3756 * Support routines for has_language_privilege family.
3757 */
3758
3759/*
3760 * Given a language name expressed as a string, look it up and return Oid
3761 */
3762static Oid
3764{
3765 char *langname = text_to_cstring(languagename);
3766
3767 return get_language_oid(langname, false);
3768}
3769
3770/*
3771 * convert_language_priv_string
3772 * Convert text string to AclMode value.
3773 */
3774static AclMode
3776{
3777 static const priv_map language_priv_map[] = {
3778 {"USAGE", ACL_USAGE},
3779 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3780 {NULL, 0}
3781 };
3782
3784}
3785
3786
3787/*
3788 * has_schema_privilege variants
3789 * These are all named "has_schema_privilege" at the SQL level.
3790 * They take various combinations of schema name, schema OID,
3791 * user name, user OID, or implicit user = current_user.
3792 *
3793 * The result is a boolean value: true if user has the indicated
3794 * privilege, false if not, or NULL if object doesn't exist.
3795 */
3796
3797/*
3798 * has_schema_privilege_name_name
3799 * Check user privileges on a schema given
3800 * name username, text schemaname, and text priv name.
3801 */
3802Datum
3821
3822/*
3823 * has_schema_privilege_name
3824 * Check user privileges on a schema given
3825 * text schemaname and text priv name.
3826 * current_user is assumed
3827 */
3828Datum
3846
3847/*
3848 * has_schema_privilege_name_id
3849 * Check user privileges on a schema given
3850 * name usename, schema oid, and text priv name.
3851 */
3852Datum
3875
3876/*
3877 * has_schema_privilege_id
3878 * Check user privileges on a schema given
3879 * schema oid, and text priv name.
3880 * current_user is assumed
3881 */
3882Datum
3904
3905/*
3906 * has_schema_privilege_id_name
3907 * Check user privileges on a schema given
3908 * roleid, text schemaname, and text priv name.
3909 */
3910Datum
3927
3928/*
3929 * has_schema_privilege_id_id
3930 * Check user privileges on a schema given
3931 * roleid, schema oid, and text priv name.
3932 */
3933Datum
3954
3955/*
3956 * Support routines for has_schema_privilege family.
3957 */
3958
3959/*
3960 * Given a schema name expressed as a string, look it up and return Oid
3961 */
3962static Oid
3964{
3965 char *nspname = text_to_cstring(schemaname);
3966
3967 return get_namespace_oid(nspname, false);
3968}
3969
3970/*
3971 * convert_schema_priv_string
3972 * Convert text string to AclMode value.
3973 */
3974static AclMode
3976{
3977 static const priv_map schema_priv_map[] = {
3978 {"CREATE", ACL_CREATE},
3979 {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
3980 {"USAGE", ACL_USAGE},
3981 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
3982 {NULL, 0}
3983 };
3984
3986}
3987
3988
3989/*
3990 * has_server_privilege variants
3991 * These are all named "has_server_privilege" at the SQL level.
3992 * They take various combinations of foreign server name,
3993 * server OID, user name, user OID, or implicit user = current_user.
3994 *
3995 * The result is a boolean value: true if user has the indicated
3996 * privilege, false if not.
3997 */
3998
3999/*
4000 * has_server_privilege_name_name
4001 * Check user privileges on a foreign server given
4002 * name username, text servername, and text priv name.
4003 */
4004Datum
4006{
4008 text *servername = PG_GETARG_TEXT_PP(1);
4010 Oid roleid;
4011 Oid serverid;
4012 AclMode mode;
4014
4016 serverid = convert_server_name(servername);
4018
4020
4022}
4023
4024/*
4025 * has_server_privilege_name
4026 * Check user privileges on a foreign server given
4027 * text servername and text priv name.
4028 * current_user is assumed
4029 */
4030Datum
4032{
4033 text *servername = PG_GETARG_TEXT_PP(0);
4035 Oid roleid;
4036 Oid serverid;
4037 AclMode mode;
4039
4040 roleid = GetUserId();
4041 serverid = convert_server_name(servername);
4043
4045
4047}
4048
4049/*
4050 * has_server_privilege_name_id
4051 * Check user privileges on a foreign server given
4052 * name usename, foreign server oid, and text priv name.
4053 */
4054Datum
4077
4078/*
4079 * has_server_privilege_id
4080 * Check user privileges on a foreign server given
4081 * server oid, and text priv name.
4082 * current_user is assumed
4083 */
4084Datum
4086{
4087 Oid serverid = PG_GETARG_OID(0);
4089 Oid roleid;
4090 AclMode mode;
4092 bool is_missing = false;
4093
4094 roleid = GetUserId();
4096
4098 roleid, mode,
4099 &is_missing);
4100
4101 if (is_missing)
4103
4105}
4106
4107/*
4108 * has_server_privilege_id_name
4109 * Check user privileges on a foreign server given
4110 * roleid, text servername, and text priv name.
4111 */
4112Datum
4114{
4115 Oid roleid = PG_GETARG_OID(0);
4116 text *servername = PG_GETARG_TEXT_PP(1);
4118 Oid serverid;
4119 AclMode mode;
4121
4122 serverid = convert_server_name(servername);
4124
4126
4128}
4129
4130/*
4131 * has_server_privilege_id_id
4132 * Check user privileges on a foreign server given
4133 * roleid, server oid, and text priv name.
4134 */
4135Datum
4137{
4138 Oid roleid = PG_GETARG_OID(0);
4139 Oid serverid = PG_GETARG_OID(1);
4141 AclMode mode;
4143 bool is_missing = false;
4144
4146
4148 roleid, mode,
4149 &is_missing);
4150
4151 if (is_missing)
4153
4155}
4156
4157/*
4158 * Support routines for has_server_privilege family.
4159 */
4160
4161/*
4162 * Given a server name expressed as a string, look it up and return Oid
4163 */
4164static Oid
4166{
4167 char *serverstr = text_to_cstring(servername);
4168
4169 return get_foreign_server_oid(serverstr, false);
4170}
4171
4172/*
4173 * convert_server_priv_string
4174 * Convert text string to AclMode value.
4175 */
4176static AclMode
4178{
4179 static const priv_map server_priv_map[] = {
4180 {"USAGE", ACL_USAGE},
4181 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
4182 {NULL, 0}
4183 };
4184
4186}
4187
4188
4189/*
4190 * has_tablespace_privilege variants
4191 * These are all named "has_tablespace_privilege" at the SQL level.
4192 * They take various combinations of tablespace name, tablespace OID,
4193 * user name, user OID, or implicit user = current_user.
4194 *
4195 * The result is a boolean value: true if user has the indicated
4196 * privilege, false if not.
4197 */
4198
4199/*
4200 * has_tablespace_privilege_name_name
4201 * Check user privileges on a tablespace given
4202 * name username, text tablespacename, and text priv name.
4203 */
4204Datum
4223
4224/*
4225 * has_tablespace_privilege_name
4226 * Check user privileges on a tablespace given
4227 * text tablespacename and text priv name.
4228 * current_user is assumed
4229 */
4230Datum
4248
4249/*
4250 * has_tablespace_privilege_name_id
4251 * Check user privileges on a tablespace given
4252 * name usename, tablespace oid, and text priv name.
4253 */
4254Datum
4277
4278/*
4279 * has_tablespace_privilege_id
4280 * Check user privileges on a tablespace given
4281 * tablespace oid, and text priv name.
4282 * current_user is assumed
4283 */
4284Datum
4306
4307/*
4308 * has_tablespace_privilege_id_name
4309 * Check user privileges on a tablespace given
4310 * roleid, text tablespacename, and text priv name.
4311 */
4312Datum
4329
4330/*
4331 * has_tablespace_privilege_id_id
4332 * Check user privileges on a tablespace given
4333 * roleid, tablespace oid, and text priv name.
4334 */
4335Datum
4356
4357/*
4358 * Support routines for has_tablespace_privilege family.
4359 */
4360
4361/*
4362 * Given a tablespace name expressed as a string, look it up and return Oid
4363 */
4364static Oid
4366{
4367 char *spcname = text_to_cstring(tablespacename);
4368
4369 return get_tablespace_oid(spcname, false);
4370}
4371
4372/*
4373 * convert_tablespace_priv_string
4374 * Convert text string to AclMode value.
4375 */
4376static AclMode
4378{
4379 static const priv_map tablespace_priv_map[] = {
4380 {"CREATE", ACL_CREATE},
4381 {"CREATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4382 {NULL, 0}
4383 };
4384
4386}
4387
4388/*
4389 * has_type_privilege variants
4390 * These are all named "has_type_privilege" at the SQL level.
4391 * They take various combinations of type name, type OID,
4392 * user name, user OID, or implicit user = current_user.
4393 *
4394 * The result is a boolean value: true if user has the indicated
4395 * privilege, false if not, or NULL if object doesn't exist.
4396 */
4397
4398/*
4399 * has_type_privilege_name_name
4400 * Check user privileges on a type given
4401 * name username, text typename, and text priv name.
4402 */
4403Datum
4405{
4407 text *typename = PG_GETARG_TEXT_PP(1);
4409 Oid roleid;
4410 Oid typeoid;
4411 AclMode mode;
4413
4415 typeoid = convert_type_name(typename);
4417
4418 aclresult = object_aclcheck(TypeRelationId, typeoid, roleid, mode);
4419
4421}
4422
4423/*
4424 * has_type_privilege_name
4425 * Check user privileges on a type given
4426 * text typename and text priv name.
4427 * current_user is assumed
4428 */
4429Datum
4431{
4432 text *typename = PG_GETARG_TEXT_PP(0);
4434 Oid roleid;
4435 Oid typeoid;
4436 AclMode mode;
4438
4439 roleid = GetUserId();
4440 typeoid = convert_type_name(typename);
4442
4443 aclresult = object_aclcheck(TypeRelationId, typeoid, roleid, mode);
4444
4446}
4447
4448/*
4449 * has_type_privilege_name_id
4450 * Check user privileges on a type given
4451 * name usename, type oid, and text priv name.
4452 */
4453Datum
4455{
4457 Oid typeoid = PG_GETARG_OID(1);
4459 Oid roleid;
4460 AclMode mode;
4462 bool is_missing = false;
4463
4466
4468 roleid, mode,
4469 &is_missing);
4470
4471 if (is_missing)
4473
4475}
4476
4477/*
4478 * has_type_privilege_id
4479 * Check user privileges on a type given
4480 * type oid, and text priv name.
4481 * current_user is assumed
4482 */
4483Datum
4485{
4486 Oid typeoid = PG_GETARG_OID(0);
4488 Oid roleid;
4489 AclMode mode;
4491 bool is_missing = false;
4492
4493 roleid = GetUserId();
4495
4497 roleid, mode,
4498 &is_missing);
4499
4500 if (is_missing)
4502
4504}
4505
4506/*
4507 * has_type_privilege_id_name
4508 * Check user privileges on a type given
4509 * roleid, text typename, and text priv name.
4510 */
4511Datum
4513{
4514 Oid roleid = PG_GETARG_OID(0);
4515 text *typename = PG_GETARG_TEXT_PP(1);
4517 Oid typeoid;
4518 AclMode mode;
4520
4521 typeoid = convert_type_name(typename);
4523
4524 aclresult = object_aclcheck(TypeRelationId, typeoid, roleid, mode);
4525
4527}
4528
4529/*
4530 * has_type_privilege_id_id
4531 * Check user privileges on a type given
4532 * roleid, type oid, and text priv name.
4533 */
4534Datum
4536{
4537 Oid roleid = PG_GETARG_OID(0);
4538 Oid typeoid = PG_GETARG_OID(1);
4540 AclMode mode;
4542 bool is_missing = false;
4543
4545
4547 roleid, mode,
4548 &is_missing);
4549
4550 if (is_missing)
4552
4554}
4555
4556/*
4557 * Support routines for has_type_privilege family.
4558 */
4559
4560/*
4561 * Given a type name expressed as a string, look it up and return Oid
4562 */
4563static Oid
4565{
4566 char *typname = text_to_cstring(typename);
4567 Oid oid;
4568
4571
4572 if (!OidIsValid(oid))
4573 ereport(ERROR,
4575 errmsg("type \"%s\" does not exist", typname)));
4576
4577 return oid;
4578}
4579
4580/*
4581 * convert_type_priv_string
4582 * Convert text string to AclMode value.
4583 */
4584static AclMode
4586{
4587 static const priv_map type_priv_map[] = {
4588 {"USAGE", ACL_USAGE},
4589 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_USAGE)},
4590 {NULL, 0}
4591 };
4592
4594}
4595
4596/*
4597 * has_parameter_privilege variants
4598 * These are all named "has_parameter_privilege" at the SQL level.
4599 * They take various combinations of parameter name with
4600 * user name, user OID, or implicit user = current_user.
4601 *
4602 * The result is a boolean value: true if user has been granted
4603 * the indicated privilege or false if not.
4604 */
4605
4606/*
4607 * has_param_priv_byname
4608 *
4609 * Helper function to check user privileges on a parameter given the
4610 * role by Oid, parameter by text name, and privileges as AclMode.
4611 */
4612static bool
4614{
4616
4617 return pg_parameter_aclcheck(paramstr, roleid, priv) == ACLCHECK_OK;
4618}
4619
4620/*
4621 * has_parameter_privilege_name_name
4622 * Check user privileges on a parameter given name username, text
4623 * parameter, and text priv name.
4624 */
4625Datum
4635
4636/*
4637 * has_parameter_privilege_name
4638 * Check user privileges on a parameter given text parameter and text priv
4639 * name. current_user is assumed
4640 */
4641Datum
4649
4650/*
4651 * has_parameter_privilege_id_name
4652 * Check user privileges on a parameter given roleid, text parameter, and
4653 * text priv name.
4654 */
4655Datum
4664
4665/*
4666 * Support routines for has_parameter_privilege family.
4667 */
4668
4669/*
4670 * convert_parameter_priv_string
4671 * Convert text string to AclMode value.
4672 */
4673static AclMode
4675{
4676 static const priv_map parameter_priv_map[] = {
4677 {"SET", ACL_SET},
4678 {"SET WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SET)},
4679 {"ALTER SYSTEM", ACL_ALTER_SYSTEM},
4680 {"ALTER SYSTEM WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_ALTER_SYSTEM)},
4681 {NULL, 0}
4682 };
4683
4685}
4686
4687/*
4688 * has_largeobject_privilege variants
4689 * These are all named "has_largeobject_privilege" at the SQL level.
4690 * They take various combinations of large object OID with
4691 * user name, user OID, or implicit user = current_user.
4692 *
4693 * The result is a boolean value: true if user has the indicated
4694 * privilege, false if not, or NULL if object doesn't exist.
4695 */
4696
4697/*
4698 * has_lo_priv_byid
4699 *
4700 * Helper function to check user privileges on a large object given the
4701 * role by Oid, large object by Oid, and privileges as AclMode.
4702 */
4703static bool
4705{
4706 Snapshot snapshot = NULL;
4708
4709 if (priv & ACL_UPDATE)
4710 snapshot = NULL;
4711 else
4712 snapshot = GetActiveSnapshot();
4713
4714 if (!LargeObjectExistsWithSnapshot(lobjId, snapshot))
4715 {
4717 *is_missing = true;
4718 return false;
4719 }
4720
4722 return true;
4723
4725 roleid,
4726 priv,
4727 snapshot);
4728 return aclresult == ACLCHECK_OK;
4729}
4730
4731/*
4732 * has_largeobject_privilege_name_id
4733 * Check user privileges on a large object given
4734 * name username, large object oid, and text priv name.
4735 */
4736Datum
4738{
4743 AclMode mode;
4744 bool is_missing = false;
4745 bool result;
4746
4748 result = has_lo_priv_byid(roleid, lobjId, mode, &is_missing);
4749
4750 if (is_missing)
4752
4753 PG_RETURN_BOOL(result);
4754}
4755
4756/*
4757 * has_largeobject_privilege_id
4758 * Check user privileges on a large object given
4759 * large object oid, and text priv name.
4760 * current_user is assumed
4761 */
4762Datum
4764{
4766 Oid roleid = GetUserId();
4768 AclMode mode;
4769 bool is_missing = false;
4770 bool result;
4771
4773 result = has_lo_priv_byid(roleid, lobjId, mode, &is_missing);
4774
4775 if (is_missing)
4777
4778 PG_RETURN_BOOL(result);
4779}
4780
4781/*
4782 * has_largeobject_privilege_id_id
4783 * Check user privileges on a large object given
4784 * roleid, large object oid, and text priv name.
4785 */
4786Datum
4788{
4789 Oid roleid = PG_GETARG_OID(0);
4792 AclMode mode;
4793 bool is_missing = false;
4794 bool result;
4795
4797 result = has_lo_priv_byid(roleid, lobjId, mode, &is_missing);
4798
4799 if (is_missing)
4801
4802 PG_RETURN_BOOL(result);
4803}
4804
4805/*
4806 * convert_largeobject_priv_string
4807 * Convert text string to AclMode value.
4808 */
4809static AclMode
4811{
4812 static const priv_map largeobject_priv_map[] = {
4813 {"SELECT", ACL_SELECT},
4814 {"SELECT WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_SELECT)},
4815 {"UPDATE", ACL_UPDATE},
4816 {"UPDATE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_UPDATE)},
4817 {NULL, 0}
4818 };
4819
4821}
4822
4823/*
4824 * pg_has_role variants
4825 * These are all named "pg_has_role" at the SQL level.
4826 * They take various combinations of role name, role OID,
4827 * user name, user OID, or implicit user = current_user.
4828 *
4829 * The result is a boolean value: true if user has the indicated
4830 * privilege, false if not.
4831 */
4832
4833/*
4834 * pg_has_role_name_name
4835 * Check user privileges on a role given
4836 * name username, name rolename, and text priv name.
4837 */
4838Datum
4840{
4842 Name rolename = PG_GETARG_NAME(1);
4844 Oid roleid;
4845 Oid roleoid;
4846 AclMode mode;
4848
4849 roleid = get_role_oid(NameStr(*username), false);
4850 roleoid = get_role_oid(NameStr(*rolename), false);
4852
4853 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4854
4856}
4857
4858/*
4859 * pg_has_role_name
4860 * Check user privileges on a role given
4861 * name rolename and text priv name.
4862 * current_user is assumed
4863 */
4864Datum
4866{
4867 Name rolename = PG_GETARG_NAME(0);
4869 Oid roleid;
4870 Oid roleoid;
4871 AclMode mode;
4873
4874 roleid = GetUserId();
4875 roleoid = get_role_oid(NameStr(*rolename), false);
4877
4878 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4879
4881}
4882
4883/*
4884 * pg_has_role_name_id
4885 * Check user privileges on a role given
4886 * name usename, role oid, and text priv name.
4887 */
4888Datum
4890{
4892 Oid roleoid = PG_GETARG_OID(1);
4894 Oid roleid;
4895 AclMode mode;
4897
4898 roleid = get_role_oid(NameStr(*username), false);
4900
4901 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4902
4904}
4905
4906/*
4907 * pg_has_role_id
4908 * Check user privileges on a role given
4909 * role oid, and text priv name.
4910 * current_user is assumed
4911 */
4912Datum
4914{
4915 Oid roleoid = PG_GETARG_OID(0);
4917 Oid roleid;
4918 AclMode mode;
4920
4921 roleid = GetUserId();
4923
4924 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4925
4927}
4928
4929/*
4930 * pg_has_role_id_name
4931 * Check user privileges on a role given
4932 * roleid, name rolename, and text priv name.
4933 */
4934Datum
4936{
4937 Oid roleid = PG_GETARG_OID(0);
4938 Name rolename = PG_GETARG_NAME(1);
4940 Oid roleoid;
4941 AclMode mode;
4943
4944 roleoid = get_role_oid(NameStr(*rolename), false);
4946
4947 aclresult = pg_role_aclcheck(roleoid, roleid, mode);
4948
4950}
4951
4952/*
4953 * pg_has_role_id_id
4954 * Check user privileges on a role given
4955 * roleid, role oid, and text priv name.
4956 */
4957Datum
4972
4973/*
4974 * Support routines for pg_has_role family.
4975 */
4976
4977/*
4978 * convert_role_priv_string
4979 * Convert text string to AclMode value.
4980 *
4981 * We use USAGE to denote whether the privileges of the role are accessible
4982 * (has_privs_of_role), MEMBER to denote is_member, and MEMBER WITH GRANT
4983 * (or ADMIN) OPTION to denote is_admin. There is no ACL bit corresponding
4984 * to MEMBER so we cheat and use ACL_CREATE for that. This convention
4985 * is shared only with pg_role_aclcheck, below.
4986 */
4987static AclMode
4989{
4990 static const priv_map role_priv_map[] = {
4991 {"USAGE", ACL_USAGE},
4992 {"MEMBER", ACL_CREATE},
4993 {"SET", ACL_SET},
4994 {"USAGE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4995 {"USAGE WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4996 {"MEMBER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4997 {"MEMBER WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4998 {"SET WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
4999 {"SET WITH ADMIN OPTION", ACL_GRANT_OPTION_FOR(ACL_CREATE)},
5000 {NULL, 0}
5001 };
5002
5004}
5005
5006/*
5007 * pg_role_aclcheck
5008 * Quick-and-dirty support for pg_has_role
5009 */
5010static AclResult
5012{
5014 {
5015 if (is_admin_of_role(roleid, role_oid))
5016 return ACLCHECK_OK;
5017 }
5018 if (mode & ACL_CREATE)
5019 {
5020 if (is_member_of_role(roleid, role_oid))
5021 return ACLCHECK_OK;
5022 }
5023 if (mode & ACL_USAGE)
5024 {
5025 if (has_privs_of_role(roleid, role_oid))
5026 return ACLCHECK_OK;
5027 }
5028 if (mode & ACL_SET)
5029 {
5030 if (member_can_set_role(roleid, role_oid))
5031 return ACLCHECK_OK;
5032 }
5033 return ACLCHECK_NO_PRIV;
5034}
5035
5036
5037/*
5038 * initialization function (called by InitPostgres)
5039 */
5040void
5042{
5044 {
5048
5049 /*
5050 * In normal mode, set a callback on any syscache invalidation of rows
5051 * of pg_auth_members (for roles_is_member_of()) pg_database (for
5052 * roles_is_member_of())
5053 */
5056 (Datum) 0);
5059 (Datum) 0);
5062 (Datum) 0);
5063 }
5064}
5065
5066/*
5067 * RoleMembershipCacheCallback
5068 * Syscache inval callback function
5069 */
5070static void
5072 uint32 hashvalue)
5073{
5074 if (cacheid == DATABASEOID &&
5075 hashvalue != cached_db_hash &&
5076 hashvalue != 0)
5077 {
5078 return; /* ignore pg_database changes for other DBs */
5079 }
5080
5081 /* Force membership caches to be recomputed on next use */
5085}
5086
5087/*
5088 * A helper function for roles_is_member_of() that provides an optimized
5089 * implementation of list_append_unique_oid() via a Bloom filter. The caller
5090 * (i.e., roles_is_member_of()) is responsible for freeing bf once it is done
5091 * using this function.
5092 */
5093static inline List *
5095{
5096 unsigned char *roleptr = (unsigned char *) &role;
5097
5098 /*
5099 * If there is a previously-created Bloom filter, use it to try to
5100 * determine whether the role is missing from the list. If it says yes,
5101 * that's a hard fact and we can go ahead and add the role. If it says
5102 * no, that's only probabilistic and we'd better search the list. Without
5103 * a filter, we must always do an ordinary linear search through the
5104 * existing list.
5105 */
5106 if ((*bf && bloom_lacks_element(*bf, roleptr, sizeof(Oid))) ||
5108 {
5109 /*
5110 * If the list is large, we take on the overhead of creating and
5111 * populating a Bloom filter to speed up future calls to this
5112 * function.
5113 */
5114 if (*bf == NULL &&
5116 {
5118 foreach_oid(roleid, roles_list)
5119 bloom_add_element(*bf, (unsigned char *) &roleid, sizeof(Oid));
5120 }
5121
5122 /*
5123 * Finally, add the role to the list and the Bloom filter, if it
5124 * exists.
5125 */
5127 if (*bf)
5128 bloom_add_element(*bf, roleptr, sizeof(Oid));
5129 }
5130
5131 return roles_list;
5132}
5133
5134/*
5135 * Get a list of roles that the specified roleid is a member of
5136 *
5137 * Type ROLERECURSE_MEMBERS recurses through all grants; ROLERECURSE_PRIVS
5138 * recurses only through inheritable grants; and ROLERECURSE_SETROLE recurses
5139 * only through grants with set_option.
5140 *
5141 * Since indirect membership testing is relatively expensive, we cache
5142 * a list of memberships. Hence, the result is only guaranteed good until
5143 * the next call of roles_is_member_of()!
5144 *
5145 * For the benefit of select_best_grantor, the result is defined to be
5146 * in breadth-first order, ie, closer relationships earlier.
5147 *
5148 * If admin_of is not InvalidOid, this function sets *admin_role, either
5149 * to the OID of the first role in the result list that directly possesses
5150 * ADMIN OPTION on the role corresponding to admin_of, or to InvalidOid if
5151 * there is no such role.
5152 */
5153static List *
5156{
5157 Oid dba;
5159 ListCell *l;
5162 bloom_filter *bf = NULL;
5163
5165 if (admin_role != NULL)
5167
5168 /* If cache is valid and ADMIN OPTION not sought, just return the list */
5169 if (cached_role[type] == roleid && !OidIsValid(admin_of) &&
5171 return cached_roles[type];
5172
5173 /*
5174 * Role expansion happens in a non-database backend when guc.c checks
5175 * ROLE_PG_READ_ALL_SETTINGS for a physical walsender SHOW command. In
5176 * that case, no role gets pg_database_owner.
5177 */
5179 dba = InvalidOid;
5180 else
5181 {
5183
5185 if (!HeapTupleIsValid(dbtup))
5186 elog(ERROR, "cache lookup failed for database %u", MyDatabaseId);
5189 }
5190
5191 /*
5192 * Find all the roles that roleid is a member of, including multi-level
5193 * recursion. The role itself will always be the first element of the
5194 * resulting list.
5195 *
5196 * Each element of the list is scanned to see if it adds any indirect
5197 * memberships. We can use a single list as both the record of
5198 * already-found memberships and the agenda of roles yet to be scanned.
5199 * This is a bit tricky but works because the foreach() macro doesn't
5200 * fetch the next list element until the bottom of the loop.
5201 */
5202 roles_list = list_make1_oid(roleid);
5203
5204 foreach(l, roles_list)
5205 {
5206 Oid memberid = lfirst_oid(l);
5208 int i;
5209
5210 /* Find roles that memberid is directly a member of */
5213 for (i = 0; i < memlist->n_members; i++)
5214 {
5215 HeapTuple tup = &memlist->members[i]->tuple;
5217 Oid otherid = form->roleid;
5218
5219 /*
5220 * While otherid==InvalidOid shouldn't appear in the catalog, the
5221 * OidIsValid() avoids crashing if that arises.
5222 */
5223 if (otherid == admin_of && form->admin_option &&
5226
5227 /* If we're supposed to ignore non-heritable grants, do so. */
5228 if (type == ROLERECURSE_PRIVS && !form->inherit_option)
5229 continue;
5230
5231 /* If we're supposed to ignore non-SET grants, do so. */
5232 if (type == ROLERECURSE_SETROLE && !form->set_option)
5233 continue;
5234
5235 /*
5236 * Even though there shouldn't be any loops in the membership
5237 * graph, we must test for having already seen this role. It is
5238 * legal for instance to have both A->B and A->C->B.
5239 */
5241 }
5243
5244 /* implement pg_database_owner implicit membership */
5245 if (memberid == dba && OidIsValid(dba))
5248 }
5249
5250 /*
5251 * Free the Bloom filter created by roles_list_append(), if there is one.
5252 */
5253 if (bf)
5254 bloom_free(bf);
5255
5256 /*
5257 * Copy the completed list into TopMemoryContext so it will persist.
5258 */
5263
5264 /*
5265 * Now safe to assign to state variable
5266 */
5267 cached_role[type] = InvalidOid; /* just paranoia */
5270 cached_role[type] = roleid;
5271
5272 /* And now we can return the answer */
5273 return cached_roles[type];
5274}
5275
5276
5277/*
5278 * Does member have the privileges of role (directly or indirectly)?
5279 *
5280 * This is defined not to recurse through grants that are not inherited,
5281 * and only inherited grants confer the associated privileges automatically.
5282 *
5283 * See also member_can_set_role, below.
5284 */
5285bool
5287{
5288 /* Fast path for simple case */
5289 if (member == role)
5290 return true;
5291
5292 /* Superusers have every privilege, so are part of every role */
5293 if (superuser_arg(member))
5294 return true;
5295
5296 /*
5297 * Find all the roles that member has the privileges of, including
5298 * multi-level recursion, then see if target role is any one of them.
5299 */
5301 InvalidOid, NULL),
5302 role);
5303}
5304
5305/*
5306 * Can member use SET ROLE to this role?
5307 *
5308 * There must be a chain of grants from 'member' to 'role' each of which
5309 * permits SET ROLE; that is, each of which has set_option = true.
5310 *
5311 * It doesn't matter whether the grants are inheritable. That's a separate
5312 * question; see has_privs_of_role.
5313 *
5314 * This function should be used to determine whether the session user can
5315 * use SET ROLE to become the target user. We also use it to determine whether
5316 * the session user can change an existing object to be owned by the target
5317 * user, or create new objects owned by the target user.
5318 */
5319bool
5321{
5322 /* Fast path for simple case */
5323 if (member == role)
5324 return true;
5325
5326 /* Superusers have every privilege, so can always SET ROLE */
5327 if (superuser_arg(member))
5328 return true;
5329
5330 /*
5331 * Find all the roles that member can access via SET ROLE, including
5332 * multi-level recursion, then see if target role is any one of them.
5333 */
5335 InvalidOid, NULL),
5336 role);
5337}
5338
5339/*
5340 * Permission violation error unless able to SET ROLE to target role.
5341 */
5342void
5344{
5345 if (!member_can_set_role(member, role))
5346 ereport(ERROR,
5348 errmsg("must be able to SET ROLE \"%s\"",
5349 GetUserNameFromId(role, false))));
5350}
5351
5352/*
5353 * Is member a member of role (directly or indirectly)?
5354 *
5355 * This is defined to recurse through grants whether they are inherited or not.
5356 *
5357 * Do not use this for privilege checking, instead use has_privs_of_role().
5358 * Don't use it for determining whether it's possible to SET ROLE to some
5359 * other role; for that, use member_can_set_role(). And don't use it for
5360 * determining whether it's OK to create an object owned by some other role:
5361 * use member_can_set_role() for that, too.
5362 *
5363 * In short, calling this function is the wrong thing to do nearly everywhere.
5364 */
5365bool
5367{
5368 /* Fast path for simple case */
5369 if (member == role)
5370 return true;
5371
5372 /* Superusers have every privilege, so are part of every role */
5373 if (superuser_arg(member))
5374 return true;
5375
5376 /*
5377 * Find all the roles that member is a member of, including multi-level
5378 * recursion, then see if target role is any one of them.
5379 */
5381 InvalidOid, NULL),
5382 role);
5383}
5384
5385/*
5386 * Is member a member of role, not considering superuserness?
5387 *
5388 * This is identical to is_member_of_role except we ignore superuser
5389 * status.
5390 *
5391 * Do not use this for privilege checking, instead use has_privs_of_role()
5392 */
5393bool
5395{
5396 /* Fast path for simple case */
5397 if (member == role)
5398 return true;
5399
5400 /*
5401 * Find all the roles that member is a member of, including multi-level
5402 * recursion, then see if target role is any one of them.
5403 */
5405 InvalidOid, NULL),
5406 role);
5407}
5408
5409
5410/*
5411 * Is member an admin of role? That is, is member the role itself (subject to
5412 * restrictions below), a member (directly or indirectly) WITH ADMIN OPTION,
5413 * or a superuser?
5414 */
5415bool
5417{
5419
5420 if (superuser_arg(member))
5421 return true;
5422
5423 /* By policy, a role cannot have WITH ADMIN OPTION on itself. */
5424 if (member == role)
5425 return false;
5426
5428 return OidIsValid(admin_role);
5429}
5430
5431/*
5432 * Find a role whose privileges "member" inherits which has ADMIN OPTION
5433 * on "role", ignoring super-userness.
5434 *
5435 * There might be more than one such role; prefer one which involves fewer
5436 * hops. That is, if member has ADMIN OPTION, prefer that over all other
5437 * options; if not, prefer a role from which member inherits more directly
5438 * over more indirect inheritance.
5439 */
5440Oid
5442{
5444
5445 /* By policy, a role cannot have WITH ADMIN OPTION on itself. */
5446 if (member == role)
5447 return InvalidOid;
5448
5450 return admin_role;
5451}
5452
5453/*
5454 * Select the effective grantor ID for a GRANT or REVOKE operation.
5455 *
5456 * The grantor must always be either the object owner or some role that has
5457 * been explicitly granted grant options. This ensures that all granted
5458 * privileges appear to flow from the object owner, and there are never
5459 * multiple "original sources" of a privilege. Therefore, if the would-be
5460 * grantor is a member of a role that has the needed grant options, we have
5461 * to do the grant as that role instead.
5462 *
5463 * It is possible that the would-be grantor is a member of several roles
5464 * that have different subsets of the desired grant options, but no one
5465 * role has 'em all. In this case we pick a role with the largest number
5466 * of desired options. Ties are broken in favor of closer ancestors.
5467 *
5468 * roleId: the role attempting to do the GRANT/REVOKE
5469 * privileges: the privileges to be granted/revoked
5470 * acl: the ACL of the object in question
5471 * ownerId: the role owning the object in question
5472 * *grantorId: receives the OID of the role to do the grant as
5473 * *grantOptions: receives the grant options actually held by grantorId
5474 *
5475 * If no grant options exist, we set grantorId to roleId, grantOptions to 0.
5476 */
5477void
5479 const Acl *acl, Oid ownerId,
5481{
5484 int nrights;
5485 ListCell *l;
5486
5487 /*
5488 * The object owner is always treated as having all grant options, so if
5489 * roleId is the owner it's easy. Also, if roleId is a superuser it's
5490 * easy: superusers are implicitly members of every role, so they act as
5491 * the object owner.
5492 */
5493 if (roleId == ownerId || superuser_arg(roleId))
5494 {
5495 *grantorId = ownerId;
5497 return;
5498 }
5499
5500 /*
5501 * Otherwise we have to do a careful search to see if roleId has the
5502 * privileges of any suitable role. Note: we can hang onto the result of
5503 * roles_is_member_of() throughout this loop, because aclmask_direct()
5504 * doesn't query any role memberships.
5505 */
5507 InvalidOid, NULL);
5508
5509 /* initialize candidate result as default */
5510 *grantorId = roleId;
5512 nrights = 0;
5513
5514 foreach(l, roles_list)
5515 {
5518
5519 otherprivs = aclmask_direct(acl, otherrole, ownerId,
5522 {
5523 /* Found a suitable grantor */
5526 return;
5527 }
5528
5529 /*
5530 * If it has just some of the needed privileges, remember best
5531 * candidate.
5532 */
5534 {
5536
5537 if (nnewrights > nrights)
5538 {
5542 }
5543 }
5544 }
5545}
5546
5547/*
5548 * get_role_oid - Given a role name, look up the role's OID.
5549 *
5550 * If missing_ok is false, throw an error if role name not found. If
5551 * true, just return InvalidOid.
5552 */
5553Oid
5554get_role_oid(const char *rolname, bool missing_ok)
5555{
5556 Oid oid;
5557
5560 if (!OidIsValid(oid) && !missing_ok)
5561 ereport(ERROR,
5563 errmsg("role \"%s\" does not exist", rolname)));
5564 return oid;
5565}
5566
5567/*
5568 * get_role_oid_or_public - As above, but return ACL_ID_PUBLIC if the
5569 * role name is "public".
5570 */
5571Oid
5573{
5574 if (strcmp(rolname, "public") == 0)
5575 return ACL_ID_PUBLIC;
5576
5577 return get_role_oid(rolname, false);
5578}
5579
5580/*
5581 * Given a RoleSpec node, return the OID it corresponds to. If missing_ok is
5582 * true, return InvalidOid if the role does not exist.
5583 *
5584 * PUBLIC is always disallowed here. Routines wanting to handle the PUBLIC
5585 * case must check the case separately.
5586 */
5587Oid
5588get_rolespec_oid(const RoleSpec *role, bool missing_ok)
5589{
5590 Oid oid;
5591
5592 switch (role->roletype)
5593 {
5594 case ROLESPEC_CSTRING:
5595 Assert(role->rolename);
5596 oid = get_role_oid(role->rolename, missing_ok);
5597 break;
5598
5601 oid = GetUserId();
5602 break;
5603
5605 oid = GetSessionUserId();
5606 break;
5607
5608 case ROLESPEC_PUBLIC:
5609 ereport(ERROR,
5611 errmsg("role \"%s\" does not exist", "public")));
5612 oid = InvalidOid; /* make compiler happy */
5613 break;
5614
5615 default:
5616 elog(ERROR, "unexpected role type %d", role->roletype);
5617 }
5618
5619 return oid;
5620}
5621
5622/*
5623 * Given a RoleSpec node, return the pg_authid HeapTuple it corresponds to.
5624 * Caller must ReleaseSysCache when done with the result tuple.
5625 */
5628{
5629 HeapTuple tuple;
5630
5631 switch (role->roletype)
5632 {
5633 case ROLESPEC_CSTRING:
5634 Assert(role->rolename);
5636 if (!HeapTupleIsValid(tuple))
5637 ereport(ERROR,
5639 errmsg("role \"%s\" does not exist", role->rolename)));
5640 break;
5641
5645 if (!HeapTupleIsValid(tuple))
5646 elog(ERROR, "cache lookup failed for role %u", GetUserId());
5647 break;
5648
5651 if (!HeapTupleIsValid(tuple))
5652 elog(ERROR, "cache lookup failed for role %u", GetSessionUserId());
5653 break;
5654
5655 case ROLESPEC_PUBLIC:
5656 ereport(ERROR,
5658 errmsg("role \"%s\" does not exist", "public")));
5659 tuple = NULL; /* make compiler happy */
5660 break;
5661
5662 default:
5663 elog(ERROR, "unexpected role type %d", role->roletype);
5664 }
5665
5666 return tuple;
5667}
5668
5669/*
5670 * Given a RoleSpec, returns a palloc'ed copy of the corresponding role's name.
5671 */
5672char *
5674{
5675 HeapTuple tp;
5677 char *rolename;
5678
5679 tp = get_rolespec_tuple(role);
5681 rolename = pstrdup(NameStr(authForm->rolname));
5682 ReleaseSysCache(tp);
5683
5684 return rolename;
5685}
5686
5687/*
5688 * Given a RoleSpec, throw an error if the name is reserved, using detail_msg,
5689 * if provided (which must be already translated).
5690 *
5691 * If node is NULL, no error is thrown. If detail_msg is NULL then no detail
5692 * message is provided.
5693 */
5694void
5695check_rolespec_name(const RoleSpec *role, const char *detail_msg)
5696{
5697 if (!role)
5698 return;
5699
5700 if (role->roletype != ROLESPEC_CSTRING)
5701 return;
5702
5703 if (IsReservedName(role->rolename))
5704 {
5705 if (detail_msg)
5706 ereport(ERROR,
5708 errmsg("role name \"%s\" is reserved",
5709 role->rolename),
5711 else
5712 ereport(ERROR,
5714 errmsg("role name \"%s\" is reserved",
5715 role->rolename)));
5716 }
5717}
Datum idx(PG_FUNCTION_ARGS)
Definition _int_op.c:262
static List * roles_is_member_of(Oid roleid, enum RoleRecurseType type, Oid admin_of, Oid *admin_role)
Definition acl.c:5154
Datum pg_has_role_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4958
Datum has_schema_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3883
Datum has_largeobject_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4787
Datum hash_aclitem(PG_FUNCTION_ARGS)
Definition acl.c:769
void initialize_acl(void)
Definition acl.c:5041
Datum has_sequence_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:2137
Datum has_table_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:2022
Datum has_server_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:4085
Datum has_tablespace_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4336
Datum has_column_privilege_id_id_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2761
Datum has_server_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4005
Datum aclinsert(PG_FUNCTION_ARGS)
Definition acl.c:1593
static AclMode convert_function_priv_string(text *priv_type_text)
Definition acl.c:3575
Datum has_largeobject_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4737
static const char * getid(const char *s, char *n, Node *escontext)
Definition acl.c:169
bool is_admin_of_role(Oid member, Oid role)
Definition acl.c:5416
Datum has_column_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2841
static bool aclitem_match(const AclItem *a1, const AclItem *a2)
Definition acl.c:714
Datum pg_has_role_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4839
Datum has_language_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:3603
Acl * aclconcat(const Acl *left_acl, const Acl *right_acl)
Definition acl.c:478
Datum has_schema_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:3803
Acl * aclmerge(const Acl *left_acl, const Acl *right_acl, Oid ownerId)
Definition acl.c:502
Datum aclitem_eq(PG_FUNCTION_ARGS)
Definition acl.c:749
Datum has_tablespace_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4255
Datum makeaclitem(PG_FUNCTION_ARGS)
Definition acl.c:1635
Datum has_table_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:1999
Datum has_server_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4055
Datum has_column_privilege_name_id_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2659
Datum has_language_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3711
static int column_privilege_check(Oid tableoid, AttrNumber attnum, Oid roleid, AclMode mode)
Definition acl.c:2536
static Oid convert_type_name(text *typename)
Definition acl.c:4564
Oid select_best_admin(Oid member, Oid role)
Definition acl.c:5441
Datum aclexplode(PG_FUNCTION_ARGS)
Definition acl.c:1791
static Oid convert_database_name(text *databasename)
Definition acl.c:3148
Acl * acldefault(ObjectType objtype, Oid ownerId)
Definition acl.c:804
Datum aclitemout(PG_FUNCTION_ARGS)
Definition acl.c:647
Oid get_role_oid_or_public(const char *rolname)
Definition acl.c:5572
Datum has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3244
Datum has_foreign_data_wrapper_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3325
bool aclequal(const Acl *left_acl, const Acl *right_acl)
Definition acl.c:560
Datum hash_aclitem_extended(PG_FUNCTION_ARGS)
Definition acl.c:783
static void check_acl(const Acl *acl)
Definition acl.c:591
Datum has_parameter_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4626
Datum has_foreign_data_wrapper_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3274
#define ROLES_LIST_BLOOM_THRESHOLD
Definition acl.c:90
Datum has_database_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3014
static uint32 cached_db_hash
Definition acl.c:82
Datum has_type_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4404
Datum has_column_privilege_name_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2576
Datum pg_has_role_name(PG_FUNCTION_ARGS)
Definition acl.c:4865
Datum has_sequence_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:2203
static AclMode convert_largeobject_priv_string(text *priv_type_text)
Definition acl.c:4810
static List * roles_list_append(List *roles_list, bloom_filter **bf, Oid role)
Definition acl.c:5094
static AclMode convert_type_priv_string(text *priv_type_text)
Definition acl.c:4585
Datum has_tablespace_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:4231
static AclMode convert_table_priv_string(text *priv_type_text)
Definition acl.c:2064
static AclMode convert_server_priv_string(text *priv_type_text)
Definition acl.c:4177
Datum has_table_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:1945
Datum has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:3194
Datum has_tablespace_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4313
Acl * aclupdate(const Acl *old_acl, const AclItem *mod_aip, int modechg, Oid ownerId, DropBehavior behavior)
Definition acl.c:993
static Acl * recursive_revoke(Acl *acl, Oid grantee, AclMode revoke_privs, Oid ownerId, DropBehavior behavior)
Definition acl.c:1303
Datum has_database_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3038
static Oid convert_schema_name(text *schemaname)
Definition acl.c:3963
Datum has_column_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2785
static void putid(char *p, const char *s)
Definition acl.c:222
Datum has_schema_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3911
static void check_circularity(const Acl *old_acl, const AclItem *mod_aip, Oid ownerId)
Definition acl.c:1223
static bool has_param_priv_byname(Oid roleid, const text *parameter, AclMode priv)
Definition acl.c:4613
bool is_member_of_role(Oid member, Oid role)
Definition acl.c:5366
Datum has_sequence_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2238
Datum has_database_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3096
static Oid convert_foreign_data_wrapper_name(text *fdwname)
Definition acl.c:3354
Datum has_language_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3683
static AclMode convert_database_priv_string(text *priv_type_text)
Definition acl.c:3160
Datum has_foreign_data_wrapper_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3220
Datum has_column_privilege_name_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2814
Datum has_column_privilege_id_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2868
RoleRecurseType
Definition acl.c:75
@ ROLERECURSE_PRIVS
Definition acl.c:77
@ ROLERECURSE_MEMBERS
Definition acl.c:76
@ ROLERECURSE_SETROLE
Definition acl.c:78
Datum has_type_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4454
Datum has_any_column_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:2390
Datum has_server_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4113
Datum has_language_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3653
Datum has_foreign_data_wrapper_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3302
Datum has_schema_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3853
Datum has_function_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:3394
void select_best_grantor(Oid roleId, AclMode privileges, const Acl *acl, Oid ownerId, Oid *grantorId, AclMode *grantOptions)
Definition acl.c:5478
Datum has_any_column_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2332
bool is_member_of_role_nosuper(Oid member, Oid role)
Definition acl.c:5394
Datum has_sequence_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:2166
Datum has_schema_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3829
Datum acldefault_sql(PG_FUNCTION_ARGS)
Definition acl.c:921
bool has_privs_of_role(Oid member, Oid role)
Definition acl.c:5286
Acl * make_empty_acl(void)
Definition acl.c:449
static Oid convert_language_name(text *languagename)
Definition acl.c:3763
Datum has_language_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3734
static AclMode convert_any_priv_string(text *priv_type_text, const priv_map *privileges)
Definition acl.c:1687
Datum has_database_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3119
Datum has_function_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3420
static bool is_safe_acl_char(unsigned char c, bool is_getid)
Definition acl.c:146
int aclmembers(const Acl *acl, Oid **roleids)
Definition acl.c:1541
Datum has_language_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:3629
Acl * aclnewowner(const Acl *old_acl, Oid oldOwnerId, Oid newOwnerId)
Definition acl.c:1120
Datum has_server_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:4031
bool member_can_set_role(Oid member, Oid role)
Definition acl.c:5320
Datum aclremove(PG_FUNCTION_ARGS)
Definition acl.c:1603
static const char * convert_aclright_to_string(int aclright)
Definition acl.c:1735
Acl * aclcopy(const Acl *orig_acl)
Definition acl.c:458
Datum has_function_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3474
void aclitemsort(Acl *acl)
Definition acl.c:546
Datum has_table_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:1973
Datum has_function_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3525
AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition acl.c:1389
static Oid convert_server_name(text *servername)
Definition acl.c:4165
static Oid convert_tablespace_name(text *tablespacename)
Definition acl.c:4365
Datum has_column_privilege_name_name_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2605
static AclMode convert_parameter_priv_string(text *priv_text)
Definition acl.c:4674
static Oid convert_table_name(text *tablename)
Definition acl.c:2049
Datum has_column_privilege_name_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2632
static AclMode convert_tablespace_priv_string(text *priv_type_text)
Definition acl.c:4377
static AclMode convert_language_priv_string(text *priv_type_text)
Definition acl.c:3775
Datum aclitemin(PG_FUNCTION_ARGS)
Definition acl.c:616
static AclMode convert_sequence_priv_string(text *priv_type_text)
Definition acl.c:2299
Datum pg_has_role_id(PG_FUNCTION_ARGS)
Definition acl.c:4913
Datum has_parameter_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4656
static Acl * allocacl(int n)
Definition acl.c:427
static AttrNumber convert_column_name(Oid tableoid, text *column)
Definition acl.c:2896
static AclMode convert_role_priv_string(text *priv_type_text)
Definition acl.c:4988
static bool has_lo_priv_byid(Oid roleid, Oid lobjId, AclMode priv, bool *is_missing)
Definition acl.c:4704
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition acl.c:5554
static Oid cached_role[]
Definition acl.c:80
Datum has_tablespace_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:4205
Datum has_parameter_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:4642
static void RoleMembershipCacheCallback(Datum arg, SysCacheIdentifier cacheid, uint32 hashvalue)
Definition acl.c:5071
Datum has_any_column_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:2362
Datum has_sequence_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2106
Datum has_function_privilege_name_id(PG_FUNCTION_ARGS)
Definition acl.c:3444
Datum has_type_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4535
char * get_rolespec_name(const RoleSpec *role)
Definition acl.c:5673
Datum has_server_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:4136
static AclResult pg_role_aclcheck(Oid role_oid, Oid roleid, AclMode mode)
Definition acl.c:5011
Datum has_function_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:3502
Datum has_table_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:1921
Datum has_type_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4512
Datum has_column_privilege_id_name_attnum(PG_FUNCTION_ARGS)
Definition acl.c:2711
void check_can_set_role(Oid member, Oid role)
Definition acl.c:5343
static const char * aclparse(const char *s, AclItem *aip, Node *escontext)
Definition acl.c:274
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition acl.c:5695
Datum has_type_privilege_name(PG_FUNCTION_ARGS)
Definition acl.c:4430
static List * cached_roles[]
Definition acl.c:81
static AclMode aclmask_direct(const Acl *acl, Oid roleid, Oid ownerId, AclMode mask, AclMaskHow how)
Definition acl.c:1478
Datum has_tablespace_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:4285
Datum pg_has_role_name_id(PG_FUNCTION_ARGS)
Definition acl.c:4889
Datum aclcontains(PG_FUNCTION_ARGS)
Definition acl.c:1613
static Oid convert_function_name(text *functionname)
Definition acl.c:3554
Datum has_column_privilege_id_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2684
Datum has_schema_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:3934
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition acl.c:5588
Datum has_any_column_privilege_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2458
Datum has_largeobject_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:4763
Datum has_database_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:2988
Datum has_column_privilege_id_id_name(PG_FUNCTION_ARGS)
Definition acl.c:2736
static AclMode convert_schema_priv_string(text *priv_type_text)
Definition acl.c:3975
Datum has_table_privilege_name_name(PG_FUNCTION_ARGS)
Definition acl.c:1895
Datum has_any_column_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:2485
static AclMode convert_foreign_data_wrapper_priv_string(text *priv_type_text)
Definition acl.c:3366
Datum has_database_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:3068
static int aclitemComparator(const void *arg1, const void *arg2)
Definition acl.c:725
Datum has_type_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:4484
Datum has_any_column_privilege_id(PG_FUNCTION_ARGS)
Definition acl.c:2425
Datum pg_has_role_id_name(PG_FUNCTION_ARGS)
Definition acl.c:4935
Datum has_sequence_privilege_id_id(PG_FUNCTION_ARGS)
Definition acl.c:2266
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition acl.c:5627
static AclMode convert_column_priv_string(text *priv_type_text)
Definition acl.c:2954
#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:170
AclResult
Definition acl.h:182
@ ACLCHECK_NO_PRIV
Definition acl.h:184
@ ACLCHECK_OK
Definition acl.h:183
#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:169
#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_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:171
#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:175
@ ACLMASK_ANY
Definition acl.h:177
@ ACLMASK_ALL
Definition acl.h:176
#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:3864
AclResult pg_largeobject_aclcheck_snapshot(Oid lobj_oid, Oid roleid, AclMode mode, Snapshot snapshot)
Definition aclchk.c:4094
AclResult pg_class_aclcheck_ext(Oid table_oid, Oid roleid, AclMode mode, bool *is_missing)
Definition aclchk.c:4067
AclResult pg_attribute_aclcheck_all_ext(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how, bool *is_missing)
Definition aclchk.c:3939
AclResult pg_attribute_aclcheck_all(Oid table_oid, Oid roleid, AclMode mode, AclMaskHow how)
Definition aclchk.c:3928
AclResult pg_parameter_aclcheck(const char *name, Oid roleid, AclMode mode)
Definition aclchk.c:4082
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
Definition aclchk.c:3854
AclResult pg_attribute_aclcheck_ext(Oid table_oid, AttrNumber attnum, Oid roleid, AclMode mode, bool *is_missing)
Definition aclchk.c:3898
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition aclchk.c:4057
#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:147
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define NameStr(name)
Definition c.h:777
#define IS_HIGHBIT_SET(ch)
Definition c.h:1172
#define Assert(condition)
Definition c.h:885
uint64_t uint64
Definition c.h:559
uint32_t uint32
Definition c.h:558
#define UINT64CONST(x)
Definition c.h:573
#define OidIsValid(objectId)
Definition c.h:800
size_t Size
Definition c.h:631
bool IsReservedName(const char *name)
Definition catalog.c:278
Oid get_database_oid(const char *dbname, bool missing_ok)
Datum arg
Definition elog.c:1322
int errcode(int sqlerrcode)
Definition elog.c:874
int errmsg(const char *fmt,...)
Definition elog.c:1093
#define ereturn(context, dummy_value,...)
Definition elog.h:278
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:36
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define ereport(elevel,...)
Definition elog.h:150
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
#define palloc_object(type)
Definition fe_memutils.h:74
#define palloc_array(type, count)
Definition fe_memutils.h:76
#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:684
#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:705
Oid get_foreign_data_wrapper_oid(const char *fdwname, bool missing_ok)
Definition foreign.c:682
#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:131
Oid MyDatabaseId
Definition globals.c:94
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:1117
#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:1816
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:2078
char get_rel_relkind(Oid relid)
Definition lsyscache.c:2153
char * pstrdup(const char *in)
Definition mcxt.c:1781
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc0(Size size)
Definition mcxt.c:1417
MemoryContext TopMemoryContext
Definition mcxt.c:166
void * palloc(Size size)
Definition mcxt.c:1387
#define IsBootstrapProcessingMode()
Definition miscadmin.h:477
Oid GetUserId(void)
Definition miscinit.c:469
Oid GetSessionUserId(void)
Definition miscinit.c:508
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition miscinit.c:988
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
int oid_cmp(const void *p1, const void *p2)
Definition oid.c:287
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
@ ROLESPEC_CURRENT_USER
Definition parsenodes.h:421
@ ROLESPEC_CSTRING
Definition parsenodes.h:419
@ ROLESPEC_SESSION_USER
Definition parsenodes.h:422
@ ROLESPEC_CURRENT_ROLE
Definition parsenodes.h:420
@ ROLESPEC_PUBLIC
Definition parsenodes.h:423
#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_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:242
#define foreach_oid(var, lst)
Definition pg_list.h:471
#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:262
#define qsort(a, b, c, d)
Definition port.h:495
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:252
static Datum UInt64GetDatum(uint64 X)
Definition postgres.h:443
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:380
#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
Oid ai_grantee
Definition acl.h:56
AclMode ai_privs
Definition acl.h:58
Oid ai_grantor
Definition acl.h:57
Definition pg_list.h:54
Definition nodes.h:135
RoleSpecType roletype
Definition parsenodes.h:429
char * rolename
Definition parsenodes.h:430
Definition c.h:772
Definition acl.c:55
const char * name
Definition acl.c:56
AclMode value
Definition acl.c:57
Definition c.h:718
bool superuser_arg(Oid roleid)
Definition superuser.c:57
void ReleaseSysCache(HeapTuple tuple)
Definition syscache.c:264
HeapTuple SearchSysCache2(SysCacheIdentifier cacheId, Datum key1, Datum key2)
Definition syscache.c:230
HeapTuple SearchSysCache1(SysCacheIdentifier cacheId, Datum key1)
Definition syscache.c:220
#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 TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:825
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432
char * text_to_cstring(const text *t)
Definition varlena.c:215
List * textToQualifiedNameList(text *textval)
Definition varlena.c:2717
const char * type
const char * name