On lör, 2011-12-10 at 16:16 +0100, Yeb Havinga wrote: > > * Cannot restrict access to array types. After revoking usage from the > element type, the error is perhaps a bit misleading. (smallint[] vs > smallint) > > postgres=> create table a (a int2[]); > ERROR: permission denied for type smallint[]
This matter was still outstanding. The problem with fixing this is that you need to duplicate the array type to element type conversion in two dozen places. So I have refactored this into a separate function, which also takes care of the call to format_type_be, which is equally duplicated in as many places.
diff --git i/src/backend/access/common/tupdesc.c w/src/backend/access/common/tupdesc.c index 1f40b7c..aa1ce80 100644 --- i/src/backend/access/common/tupdesc.c +++ w/src/backend/access/common/tupdesc.c @@ -573,8 +573,7 @@ aclresult = pg_type_aclcheck(atttypid, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(atttypid)); + aclcheck_error_type(aclresult, atttypid); attcollation = GetColumnDefCollation(NULL, entry, atttypid); attdim = list_length(entry->typeName->arrayBounds); diff --git i/src/backend/catalog/aclchk.c w/src/backend/catalog/aclchk.c index 9315e79..89b71b4 100644 --- i/src/backend/catalog/aclchk.c +++ w/src/backend/catalog/aclchk.c @@ -3389,6 +3389,19 @@ static AclMode pg_aclmask(AclObjectKind objkind, Oid table_oid, AttrNumber attnu } +/* + * Special common handling for types: use element type instead of array type, + * and format nicely + */ +void +aclcheck_error_type(AclResult aclerr, Oid typeOid) +{ + Oid element_type = get_element_type(typeOid); + + aclcheck_error(aclerr, ACL_KIND_TYPE, format_type_be(element_type ? element_type : typeOid)); +} + + /* Check if given user has rolcatupdate privilege according to pg_authid */ static bool has_rolcatupdate(Oid roleid) diff --git i/src/backend/catalog/objectaddress.c w/src/backend/catalog/objectaddress.c index 250069f..3c3fd05 100644 --- i/src/backend/catalog/objectaddress.c +++ w/src/backend/catalog/objectaddress.c @@ -932,8 +932,7 @@ static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname, case OBJECT_DOMAIN: case OBJECT_ATTRIBUTE: if (!pg_type_ownercheck(address.objectId, roleid)) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(address.objectId)); + aclcheck_error_type(ACLCHECK_NOT_OWNER, address.objectId); break; case OBJECT_AGGREGATE: case OBJECT_FUNCTION: diff --git i/src/backend/catalog/pg_aggregate.c w/src/backend/catalog/pg_aggregate.c index 9ff70a5..82a2c9f 100644 --- i/src/backend/catalog/pg_aggregate.c +++ w/src/backend/catalog/pg_aggregate.c @@ -208,19 +208,16 @@ static Oid lookup_agg_function(List *fnName, int nargs, Oid *input_types, { aclresult = pg_type_aclcheck(aggArgTypes[i], GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(aggArgTypes[i])); + aclcheck_error_type(aclresult, aggArgTypes[i]); } aclresult = pg_type_aclcheck(aggTransType, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(aggTransType)); + aclcheck_error_type(aclresult, aggTransType); aclresult = pg_type_aclcheck(finaltype, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(finaltype)); + aclcheck_error_type(aclresult, finaltype); /* diff --git i/src/backend/commands/functioncmds.c w/src/backend/commands/functioncmds.c index 5f1c19e..2a075a1 100644 --- i/src/backend/commands/functioncmds.c +++ w/src/backend/commands/functioncmds.c @@ -154,8 +154,7 @@ static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup, aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(rettype)); + aclcheck_error_type(aclresult, rettype); *prorettype_p = rettype; *returnsSet_p = returnType->setof; @@ -247,8 +246,7 @@ static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup, aclresult = pg_type_aclcheck(toid, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(toid)); + aclcheck_error_type(aclresult, toid); if (t->setof) ereport(ERROR, @@ -1509,13 +1507,11 @@ static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup, aclresult = pg_type_aclcheck(sourcetypeid, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(sourcetypeid)); + aclcheck_error_type(aclresult, sourcetypeid); aclresult = pg_type_aclcheck(targettypeid, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(targettypeid)); + aclcheck_error_type(aclresult, targettypeid); /* Domains are allowed for historical reasons, but we warn */ if (sourcetyptype == TYPTYPE_DOMAIN) diff --git i/src/backend/commands/opclasscmds.c w/src/backend/commands/opclasscmds.c index 87c8896..84dcf6e 100644 --- i/src/backend/commands/opclasscmds.c +++ w/src/backend/commands/opclasscmds.c @@ -414,8 +414,7 @@ static void AlterOpFamilyOwner_internal(Relation rel, HeapTuple tuple, /* XXX this is unnecessary given the superuser check above */ /* Check we have ownership of the datatype */ if (!pg_type_ownercheck(typeoid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(typeoid)); + aclcheck_error_type(ACLCHECK_NOT_OWNER, typeoid); #endif /* @@ -565,8 +564,7 @@ static void AlterOpFamilyOwner_internal(Relation rel, HeapTuple tuple, /* XXX this is unnecessary given the superuser check above */ /* Check we have ownership of the datatype */ if (!pg_type_ownercheck(storageoid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(storageoid)); + aclcheck_error_type(ACLCHECK_NOT_OWNER, storageoid); #endif break; default: diff --git i/src/backend/commands/operatorcmds.c w/src/backend/commands/operatorcmds.c index afae5e4..410c708 100644 --- i/src/backend/commands/operatorcmds.c +++ w/src/backend/commands/operatorcmds.c @@ -181,16 +181,14 @@ { aclresult = pg_type_aclcheck(typeId1, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(typeId1)); + aclcheck_error_type(aclresult, typeId1); } if (typeName2) { aclresult = pg_type_aclcheck(typeId2, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(typeId2)); + aclcheck_error_type(aclresult, typeId2); } /* @@ -227,8 +225,7 @@ rettype = get_func_rettype(functionOid); aclresult = pg_type_aclcheck(rettype, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(rettype)); + aclcheck_error_type(aclresult, rettype); /* * Look up restriction estimator if specified diff --git i/src/backend/commands/tablecmds.c w/src/backend/commands/tablecmds.c index 6148bd6..a597c22 100644 --- i/src/backend/commands/tablecmds.c +++ w/src/backend/commands/tablecmds.c @@ -526,8 +526,7 @@ static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, aclresult = pg_type_aclcheck(ofTypeId, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(ofTypeId)); + aclcheck_error_type(aclresult, ofTypeId); } else ofTypeId = InvalidOid; @@ -4496,8 +4495,7 @@ static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, aclresult = pg_type_aclcheck(typeOid, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(typeOid)); + aclcheck_error_type(aclresult, typeOid); collOid = GetColumnDefCollation(NULL, colDef, typeOid); @@ -7243,8 +7241,7 @@ static void RangeVarCallbackForAlterRelation(const RangeVar *rv, Oid relid, aclresult = pg_type_aclcheck(targettype, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(targettype)); + aclcheck_error_type(aclresult, targettype); /* And the collation */ targetcollid = GetColumnDefCollation(NULL, def, targettype); diff --git i/src/backend/commands/typecmds.c w/src/backend/commands/typecmds.c index 140b3f8..91ac742 100644 --- i/src/backend/commands/typecmds.c +++ w/src/backend/commands/typecmds.c @@ -757,8 +757,7 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace, aclresult = pg_type_aclcheck(basetypeoid, GetUserId(), ACL_USAGE); if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_TYPE, - format_type_be(basetypeoid)); + aclcheck_error_type(aclresult, basetypeoid); /* * Identify the collation if any @@ -1207,8 +1206,7 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace, /* Permission check: must own type */ if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(HeapTupleGetOid(tup))); + aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup)); } @@ -2807,8 +2805,7 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace, /* Permission check: must own type */ if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(HeapTupleGetOid(tup))); + aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup)); } /* @@ -3114,8 +3111,7 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace, /* check permissions on type */ if (!pg_type_ownercheck(typeOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(typeOid)); + aclcheck_error_type(ACLCHECK_NOT_OWNER, typeOid); /* ALTER DOMAIN used on a non-domain? */ if (stmt->renameType == OBJECT_DOMAIN && typTup->typtype != TYPTYPE_DOMAIN) @@ -3236,8 +3232,7 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace, { /* Otherwise, must be owner of the existing object */ if (!pg_type_ownercheck(HeapTupleGetOid(tup), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(HeapTupleGetOid(tup))); + aclcheck_error_type(ACLCHECK_NOT_OWNER, HeapTupleGetOid(tup)); /* Must be able to become new owner */ check_is_member_of_role(GetUserId(), newOwnerId); @@ -3365,8 +3360,7 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace, /* check permissions on type */ if (!pg_type_ownercheck(typeOid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(typeOid)); + aclcheck_error_type(ACLCHECK_NOT_OWNER, typeOid); /* don't allow direct alteration of array types */ elemOid = get_element_type(typeOid); diff --git i/src/include/utils/acl.h w/src/include/utils/acl.h index ff3c6aa..8e3316f 100644 --- i/src/include/utils/acl.h +++ w/src/include/utils/acl.h @@ -302,6 +302,8 @@ extern void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, extern void aclcheck_error_col(AclResult aclerr, AclObjectKind objectkind, const char *objectname, const char *colname); +extern void aclcheck_error_type(AclResult aclerr, Oid typeOid); + /* ownercheck routines just return true (owner) or false (not) */ extern bool pg_class_ownercheck(Oid class_oid, Oid roleid); extern bool pg_type_ownercheck(Oid type_oid, Oid roleid); diff --git i/src/test/regress/expected/privileges.out w/src/test/regress/expected/privileges.out index dfaf3a7..f99ebde 100644 --- i/src/test/regress/expected/privileges.out +++ w/src/test/regress/expected/privileges.out @@ -547,7 +547,7 @@ ERROR: permission denied for type testdomain1 CREATE TABLE test6a OF testtype1; ERROR: permission denied for type testtype1 CREATE TABLE test10a (a int[], b testtype1[]); -ERROR: permission denied for type testtype1[] +ERROR: permission denied for type testtype1 CREATE TABLE test9a (a int, b int); ALTER TABLE test9a ADD COLUMN c testdomain1; ERROR: permission denied for type testdomain1
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers