diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/aclchk.c | 35 | ||||
-rw-r--r-- | src/backend/catalog/pg_type.c | 41 | ||||
-rw-r--r-- | src/backend/commands/typecmds.c | 42 |
3 files changed, 100 insertions, 18 deletions
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 590affb79a5..1e44a71f61c 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -2447,11 +2447,17 @@ ExecGrant_Type_check(InternalGrant *istmt, HeapTuple tuple) pg_type_tuple = (Form_pg_type) GETSTRUCT(tuple); + /* Disallow GRANT on dependent types */ if (IsTrueArrayType(pg_type_tuple)) ereport(ERROR, (errcode(ERRCODE_INVALID_GRANT_OPERATION), errmsg("cannot set privileges of array types"), errhint("Set the privileges of the element type instead."))); + if (pg_type_tuple->typtype == TYPTYPE_MULTIRANGE) + ereport(ERROR, + (errcode(ERRCODE_INVALID_GRANT_OPERATION), + errmsg("cannot set privileges of multirange types"), + errhint("Set the privileges of the range type instead."))); /* Used GRANT DOMAIN on a non-domain? */ if (istmt->objtype == OBJECT_DOMAIN && @@ -3807,6 +3813,35 @@ pg_type_aclmask_ext(Oid type_oid, Oid roleid, AclMode mask, AclMaskHow how, } /* + * Likewise, multirange types don't manage their own permissions; consult + * the associated range type. (Note we must do this after the array step + * to get the right answer for arrays of multiranges.) + */ + if (typeForm->typtype == TYPTYPE_MULTIRANGE) + { + Oid rangetype = get_multirange_range(typeForm->oid); + + ReleaseSysCache(tuple); + + tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(rangetype)); + if (!HeapTupleIsValid(tuple)) + { + if (is_missing != NULL) + { + /* return "no privileges" instead of throwing an error */ + *is_missing = true; + return 0; + } + else + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type with OID %u does not exist", + rangetype))); + } + typeForm = (Form_pg_type) GETSTRUCT(tuple); + } + + /* * Now get the type's owner and ACL from the tuple */ ownerId = typeForm->typowner; diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index d7167108fb1..fe47be38d0e 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -326,14 +326,15 @@ TypeCreate(Oid newTypeOid, errmsg("fixed-size types must have storage PLAIN"))); /* - * This is a dependent type if it's an implicitly-created array type, or - * if it's a relation rowtype that's not a composite type. For such types - * we'll leave the ACL empty, and we'll skip creating some dependency - * records because there will be a dependency already through the - * depended-on type or relation. (Caution: this is closely intertwined - * with some behavior in GenerateTypeDependencies.) + * This is a dependent type if it's an implicitly-created array type or + * multirange type, or if it's a relation rowtype that's not a composite + * type. For such types we'll leave the ACL empty, and we'll skip + * creating some dependency records because there will be a dependency + * already through the depended-on type or relation. (Caution: this is + * closely intertwined with some behavior in GenerateTypeDependencies.) */ isDependentType = isImplicitArray || + typeType == TYPTYPE_MULTIRANGE || (OidIsValid(relationOid) && relationKind != RELKIND_COMPOSITE_TYPE); /* @@ -534,8 +535,9 @@ TypeCreate(Oid newTypeOid, * relationKind and isImplicitArray are likewise somewhat expensive to deduce * from the tuple, so we make callers pass those (they're not optional). * - * isDependentType is true if this is an implicit array or relation rowtype; - * that means it doesn't need its own dependencies on owner etc. + * isDependentType is true if this is an implicit array, multirange, or + * relation rowtype; that means it doesn't need its own dependencies on owner + * etc. * * We make an extension-membership dependency if we're in an extension * script and makeExtensionDep is true (and isDependentType isn't true). @@ -601,18 +603,23 @@ GenerateTypeDependencies(HeapTuple typeTuple, * Make dependencies on namespace, owner, ACL, extension. * * Skip these for a dependent type, since it will have such dependencies - * indirectly through its depended-on type or relation. + * indirectly through its depended-on type or relation. An exception is + * that multiranges need their own namespace dependency, since we don't + * force them to be in the same schema as their range type. */ - /* placeholder for all normal dependencies */ + /* collects normal dependencies for bulk recording */ addrs_normal = new_object_addresses(); - if (!isDependentType) + if (!isDependentType || typeForm->typtype == TYPTYPE_MULTIRANGE) { ObjectAddressSet(referenced, NamespaceRelationId, typeForm->typnamespace); - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + add_exact_object_address(&referenced, addrs_normal); + } + if (!isDependentType) + { recordDependencyOnOwner(TypeRelationId, typeObjectId, typeForm->typowner); @@ -727,6 +734,16 @@ GenerateTypeDependencies(HeapTuple typeTuple, recordDependencyOn(&myself, &referenced, isImplicitArray ? DEPENDENCY_INTERNAL : DEPENDENCY_NORMAL); } + + /* + * Note: you might expect that we should record an internal dependency of + * a multirange on its range type here, by analogy with the cases above. + * But instead, that is done by RangeCreate(), which also handles + * recording of other range-type-specific dependencies. That's pretty + * bogus. It's okay for now, because there are no cases where we need to + * regenerate the dependencies of a range or multirange type. But someday + * we might need to move that logic here to allow such regeneration. + */ } /* diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index a400fb39f67..e0275e5fe9c 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -3647,6 +3647,8 @@ RenameType(RenameStmt *stmt) errhint("You can alter type %s, which will alter the array type as well.", format_type_be(typTup->typelem)))); + /* we do allow separate renaming of multirange types, though */ + /* * If type is composite we need to rename associated pg_class entry too. * RenameRelationInternal will call RenameTypeInternal automatically. @@ -3730,6 +3732,21 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype) errhint("You can alter type %s, which will alter the array type as well.", format_type_be(typTup->typelem)))); + /* don't allow direct alteration of multirange types, either */ + if (typTup->typtype == TYPTYPE_MULTIRANGE) + { + Oid rangetype = get_multirange_range(typeOid); + + /* We don't expect get_multirange_range to fail, but cope if so */ + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot alter multirange type %s", + format_type_be(typeOid)), + OidIsValid(rangetype) ? + errhint("You can alter type %s, which will alter the multirange type as well.", + format_type_be(rangetype)) : 0)); + } + /* * If the new owner is the same as the existing owner, consider the * command to have succeeded. This is for dump restoration purposes. @@ -3769,13 +3786,13 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype) /* * AlterTypeOwner_oid - change type owner unconditionally * - * This function recurses to handle a pg_class entry, if necessary. It - * invokes any necessary access object hooks. If hasDependEntry is true, this - * function modifies the pg_shdepend entry appropriately (this should be - * passed as false only for table rowtypes and array types). + * This function recurses to handle dependent types (arrays and multiranges). + * It invokes any necessary access object hooks. If hasDependEntry is true, + * this function modifies the pg_shdepend entry appropriately (this should be + * passed as false only for table rowtypes and dependent types). * * This is used by ALTER TABLE/TYPE OWNER commands, as well as by REASSIGN - * OWNED BY. It assumes the caller has done all needed check. + * OWNED BY. It assumes the caller has done all needed checks. */ void AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry) @@ -3815,7 +3832,7 @@ AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry) * AlterTypeOwnerInternal - bare-bones type owner change. * * This routine simply modifies the owner of a pg_type entry, and recurses - * to handle a possible array type. + * to handle any dependent types. */ void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) @@ -3865,6 +3882,19 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId) if (OidIsValid(typTup->typarray)) AlterTypeOwnerInternal(typTup->typarray, newOwnerId); + /* If it is a range type, update the associated multirange too */ + if (typTup->typtype == TYPTYPE_RANGE) + { + Oid multirange_typeid = get_range_multirange(typeOid); + + if (!OidIsValid(multirange_typeid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("could not find multirange type for data type %s", + format_type_be(typeOid)))); + AlterTypeOwnerInternal(multirange_typeid, newOwnerId); + } + /* Clean up */ table_close(rel, RowExclusiveLock); } |