diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/objectaddress.c | 137 | ||||
-rw-r--r-- | src/backend/commands/event_trigger.c | 1 |
2 files changed, 130 insertions, 8 deletions
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 67c14020e5c..142bc689e95 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; diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c index 4e446bd25cd..3fec57ea237 100644 --- a/src/backend/commands/event_trigger.c +++ b/src/backend/commands/event_trigger.c @@ -1065,6 +1065,7 @@ EventTriggerSupportsObjectType(ObjectType obtype) case OBJECT_COLUMN: case OBJECT_COLLATION: case OBJECT_CONVERSION: + case OBJECT_DEFACL: case OBJECT_DEFAULT: case OBJECT_DOMAIN: case OBJECT_DOMCONSTRAINT: |