summaryrefslogtreecommitdiff
path: root/src/backend/catalog
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2015-03-11 19:23:47 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2015-03-11 19:23:47 -0300
commit4464303405f1f886d63f8316386621cd7436c5d6 (patch)
tree5e9b0ce63f073d9a4cca047330bcf6a145df30f8 /src/backend/catalog
parentd4d7777548ed3ea2ca579003e37f9df4d0e0ab9e (diff)
downloadpostgresql-4464303405f1f886d63f8316386621cd7436c5d6.tar.gz
Support default ACLs in get_object_address
In the spirit of 890192e99af, this time add support for the things living in the pg_default_acl catalog. These are not really "objects", but they show up as such in event triggers. There is no "DROP DEFAULT PRIVILEGES" or similar command, so it doesn't look like the new representation given would be useful anywhere else, so I didn't try to use it outside objectaddress.c. (That might be a bug in itself, but that would be material for another commit.) Reviewed by Stephen Frost.
Diffstat (limited to 'src/backend/catalog')
-rw-r--r--src/backend/catalog/objectaddress.c137
1 files changed, 129 insertions, 8 deletions
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 67c14020e5..142bc689e9 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -522,7 +522,7 @@ ObjectTypeMap[] =
/* OCLASS_USER_MAPPING */
{ "user mapping", OBJECT_USER_MAPPING },
/* OCLASS_DEFACL */
- { "default acl", -1 }, /* unmapped */
+ { "default acl", OBJECT_DEFACL },
/* OCLASS_EXTENSION */
{ "extension", OBJECT_EXTENSION },
/* OCLASS_EVENT_TRIGGER */
@@ -557,6 +557,8 @@ static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
List *objargs, bool missing_ok);
static ObjectAddress get_object_address_usermapping(List *objname,
List *objargs, bool missing_ok);
+static ObjectAddress get_object_address_defacl(List *objname, List *objargs,
+ bool missing_ok);
static const ObjectPropertyType *get_object_property_data(Oid class_id);
static void getRelationDescription(StringInfo buffer, Oid relid);
@@ -775,6 +777,10 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
address = get_object_address_usermapping(objname, objargs,
missing_ok);
break;
+ case OBJECT_DEFACL:
+ address = get_object_address_defacl(objname, objargs,
+ missing_ok);
+ break;
default:
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
/* placate compiler, in case it thinks elog might return */
@@ -1448,6 +1454,113 @@ get_object_address_usermapping(List *objname, List *objargs, bool missing_ok)
}
/*
+ * Find the ObjectAddress for a default ACL.
+ */
+static ObjectAddress
+get_object_address_defacl(List *objname, List *objargs, bool missing_ok)
+{
+ HeapTuple tp;
+ Oid userid;
+ Oid schemaid;
+ char *username;
+ char *schema;
+ char objtype;
+ char *objtype_str;
+ ObjectAddress address;
+
+ ObjectAddressSet(address, DefaultAclRelationId, InvalidOid);
+
+ /*
+ * First figure out the textual attributes so that they can be used for
+ * error reporting.
+ */
+ username = strVal(linitial(objname));
+ if (list_length(objname) >= 2)
+ schema = (char *) strVal(lsecond(objname));
+ else
+ schema = NULL;
+
+ /*
+ * Decode defaclobjtype. Only first char is considered; the rest of the
+ * string, if any, is blissfully ignored.
+ */
+ objtype = ((char *) strVal(linitial(objargs)))[0];
+ switch (objtype)
+ {
+ case DEFACLOBJ_RELATION:
+ objtype_str = "tables";
+ break;
+ case DEFACLOBJ_SEQUENCE:
+ objtype_str = "sequences";
+ break;
+ case DEFACLOBJ_FUNCTION:
+ objtype_str = "functions";
+ break;
+ case DEFACLOBJ_TYPE:
+ objtype_str = "types";
+ break;
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unrecognized default ACL object type %c", objtype),
+ errhint("Valid object types are 'r', 'S', 'f', and 'T'.")));
+ }
+
+ /*
+ * Look up user ID. Behave as "default ACL not found" if the user doesn't
+ * exist.
+ */
+ tp = SearchSysCache1(AUTHNAME,
+ CStringGetDatum(username));
+ if (!HeapTupleIsValid(tp))
+ goto not_found;
+ userid = HeapTupleGetOid(tp);
+ ReleaseSysCache(tp);
+
+ /*
+ * If a schema name was given, look up its OID. If it doesn't exist,
+ * behave as "default ACL not found".
+ */
+ if (schema)
+ {
+ schemaid = get_namespace_oid(schema, true);
+ if (schemaid == InvalidOid)
+ goto not_found;
+ }
+ else
+ schemaid = InvalidOid;
+
+ /* Finally, look up the pg_default_acl object */
+ tp = SearchSysCache3(DEFACLROLENSPOBJ,
+ ObjectIdGetDatum(userid),
+ ObjectIdGetDatum(schemaid),
+ CharGetDatum(objtype));
+ if (!HeapTupleIsValid(tp))
+ goto not_found;
+
+ address.objectId = HeapTupleGetOid(tp);
+ ReleaseSysCache(tp);
+
+ return address;
+
+not_found:
+ if (!missing_ok)
+ {
+ if (schema)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("default ACL for user \"%s\" in schema \"%s\" on %s does not exist",
+ username, schema, objtype_str)));
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("default ACL for user \"%s\" on %s does not exist",
+ username, objtype_str)));
+ }
+ return address;
+}
+
+/*
* Convert an array of TEXT into a List of string Values, as emitted by the
* parser, which is what get_object_address uses as input.
*/
@@ -1599,6 +1712,7 @@ pg_get_object_address(PG_FUNCTION_ARGS)
case OBJECT_OPFAMILY:
case OBJECT_CAST:
case OBJECT_USER_MAPPING:
+ case OBJECT_DEFACL:
if (list_length(args) != 1)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -4024,10 +4138,8 @@ getObjectIdentityParts(const ObjectAddress *object,
SysScanDesc rcscan;
HeapTuple tup;
Form_pg_default_acl defacl;
-
- /* no objname support */
- if (objname)
- *objname = NIL;
+ char *schema;
+ char *username;
defaclrel = heap_open(DefaultAclRelationId, AccessShareLock);
@@ -4047,19 +4159,20 @@ getObjectIdentityParts(const ObjectAddress *object,
defacl = (Form_pg_default_acl) GETSTRUCT(tup);
+ username = GetUserNameFromId(defacl->defaclrole);
appendStringInfo(&buffer,
"for role %s",
- quote_identifier(GetUserNameFromId(defacl->defaclrole)));
+ quote_identifier(username));
if (OidIsValid(defacl->defaclnamespace))
{
- char *schema;
-
schema = get_namespace_name(defacl->defaclnamespace);
appendStringInfo(&buffer,
" in schema %s",
quote_identifier(schema));
}
+ else
+ schema = NULL;
switch (defacl->defaclobjtype)
{
@@ -4081,6 +4194,14 @@ getObjectIdentityParts(const ObjectAddress *object,
break;
}
+ if (objname)
+ {
+ *objname = list_make1(username);
+ if (schema)
+ *objname = lappend(*objname, schema);
+ *objargs = list_make1(psprintf("%c", defacl->defaclobjtype));
+ }
+
systable_endscan(rcscan);
heap_close(defaclrel, AccessShareLock);
break;