diff options
Diffstat (limited to 'src/backend/commands/comment.c')
-rw-r--r-- | src/backend/commands/comment.c | 222 |
1 files changed, 23 insertions, 199 deletions
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index a0a561c144d..3fbeefa018b 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -22,25 +22,11 @@ #include "catalog/pg_shdescription.h" #include "commands/comment.h" #include "commands/dbcommands.h" -#include "libpq/be-fsstubs.h" #include "miscadmin.h" -#include "parser/parse_func.h" -#include "parser/parse_type.h" -#include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" -#include "utils/rel.h" #include "utils/tqual.h" -/* - * For most object types, the permissions-checking logic is simple enough - * that it makes sense to just include it in CommentObject(). However, a few - * object types require something more complex; for those, we define helper - * functions. - */ -static void CheckAttributeComment(Relation relation); -static void CheckCastComment(List *qualname, List *arguments); - /* * CommentObject -- @@ -76,143 +62,41 @@ CommentObject(CommentStmt *stmt) } /* - * Translate the parser representation which identifies this object into - * an ObjectAddress. get_object_address() will throw an error if the + * Translate the parser representation that identifies this object into + * an ObjectAddress. get_object_address() will throw an error if the * object does not exist, and will also acquire a lock on the target * to guard against concurrent DROP operations. */ address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs, &relation, ShareUpdateExclusiveLock); - /* Privilege and integrity checks. */ + /* Require ownership of the target object. */ + check_object_ownership(GetUserId(), stmt->objtype, address, + stmt->objname, stmt->objargs, relation); + + /* Perform other integrity checks as needed. */ switch (stmt->objtype) { - case OBJECT_INDEX: - case OBJECT_SEQUENCE: - case OBJECT_TABLE: - case OBJECT_VIEW: - case OBJECT_FOREIGN_TABLE: - if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, - RelationGetRelationName(relation)); - break; case OBJECT_COLUMN: - CheckAttributeComment(relation); - break; - case OBJECT_DATABASE: - if (!pg_database_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, - strVal(linitial(stmt->objname))); - break; - case OBJECT_TYPE: - case OBJECT_DOMAIN: - if (!pg_type_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(address.objectId)); - break; - case OBJECT_AGGREGATE: - case OBJECT_FUNCTION: - if (!pg_proc_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, - NameListToString(stmt->objname)); - break; - case OBJECT_OPERATOR: - if (!pg_oper_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER, - NameListToString(stmt->objname)); - break; - case OBJECT_RULE: - case OBJECT_TRIGGER: - case OBJECT_CONSTRAINT: - if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, - RelationGetRelationName(relation)); - break; - case OBJECT_SCHEMA: - if (!pg_namespace_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE, - strVal(linitial(stmt->objname))); - break; - case OBJECT_COLLATION: - if (!pg_collation_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION, - NameListToString(stmt->objname)); - break; - case OBJECT_CONVERSION: - if (!pg_conversion_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION, - NameListToString(stmt->objname)); - break; - case OBJECT_LANGUAGE: - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to comment on procedural language"))); - break; - case OBJECT_EXTENSION: - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to comment on extension"))); - break; - case OBJECT_OPCLASS: - if (!pg_opclass_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS, - NameListToString(stmt->objname)); - break; - case OBJECT_OPFAMILY: - if (!pg_opfamily_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY, - NameListToString(stmt->objname)); - break; - case OBJECT_LARGEOBJECT: - if (!lo_compat_privileges && - !pg_largeobject_ownercheck(address.objectId, GetUserId())) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be owner of large object %u", - address.objectId))); - break; - case OBJECT_CAST: - CheckCastComment(stmt->objname, stmt->objargs); - break; - case OBJECT_TABLESPACE: - if (!pg_tablespace_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE, - strVal(linitial(stmt->objname))); - break; - case OBJECT_ROLE: - if (!has_privs_of_role(GetUserId(), address.objectId)) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be member of role \"%s\" to comment upon it", - strVal(linitial(stmt->objname))))); - break; - case OBJECT_TSPARSER: - if (!superuser()) + /* + * Allow comments only on columns of tables, views, composite + * types, and foreign tables (which are the only relkinds for + * which pg_dump will dump per-column comments). In particular we + * wish to disallow comments on index columns, because the naming + * of an index's columns may change across PG versions, so dumping + * per-column comments could create reload failures. + */ + if (relation->rd_rel->relkind != RELKIND_RELATION && + relation->rd_rel->relkind != RELKIND_VIEW && + relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE && + relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE) ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to comment on text search parser"))); - break; - case OBJECT_TSDICTIONARY: - if (!pg_ts_dict_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY, - NameListToString(stmt->objname)); - break; - case OBJECT_TSTEMPLATE: - if (!superuser()) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be superuser to comment on text search template"))); - break; - case OBJECT_TSCONFIGURATION: - if (!pg_ts_config_ownercheck(address.objectId, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION, - NameListToString(stmt->objname)); + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a table, view, composite type, or foreign table", + RelationGetRelationName(relation)))); break; default: - elog(ERROR, "unrecognized object type: %d", - (int) stmt->objtype); + break; } /* @@ -574,63 +458,3 @@ GetComment(Oid oid, Oid classoid, int32 subid) return comment; } - -/* - * Check whether the user is allowed to comment on an attribute of the - * specified relation. - */ -static void -CheckAttributeComment(Relation relation) -{ - if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, - RelationGetRelationName(relation)); - - /* - * Allow comments only on columns of tables, views, composite types, and - * foreign tables (which are the only relkinds for which pg_dump will dump - * per-column comments). In particular we wish to disallow comments on - * index columns, because the naming of an index's columns may change - * across PG versions, so dumping per-column comments could create reload - * failures. - */ - if (relation->rd_rel->relkind != RELKIND_RELATION && - relation->rd_rel->relkind != RELKIND_VIEW && - relation->rd_rel->relkind != RELKIND_COMPOSITE_TYPE && - relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a table, view, composite type, or foreign table", - RelationGetRelationName(relation)))); -} - -/* - * Check whether the user is allowed to comment on the specified cast. - */ -static void -CheckCastComment(List *qualname, List *arguments) -{ - TypeName *sourcetype; - TypeName *targettype; - Oid sourcetypeid; - Oid targettypeid; - - Assert(list_length(qualname) == 1); - sourcetype = (TypeName *) linitial(qualname); - Assert(IsA(sourcetype, TypeName)); - Assert(list_length(arguments) == 1); - targettype = (TypeName *) linitial(arguments); - Assert(IsA(targettype, TypeName)); - - sourcetypeid = typenameTypeId(NULL, sourcetype); - targettypeid = typenameTypeId(NULL, targettype); - - /* Permission check */ - if (!pg_type_ownercheck(sourcetypeid, GetUserId()) - && !pg_type_ownercheck(targettypeid, GetUserId())) - ereport(ERROR, - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("must be owner of type %s or type %s", - format_type_be(sourcetypeid), - format_type_be(targettypeid)))); -} |