1 /*-------------------------------------------------------------------------
4 * functions for working with ObjectAddresses
6 * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/catalog/objectaddress.c
13 *-------------------------------------------------------------------------
18 #include "access/sysattr.h"
19 #include "catalog/catalog.h"
20 #include "catalog/indexing.h"
21 #include "catalog/objectaddress.h"
22 #include "catalog/pg_authid.h"
23 #include "catalog/pg_cast.h"
24 #include "catalog/pg_collation.h"
25 #include "catalog/pg_constraint.h"
26 #include "catalog/pg_conversion.h"
27 #include "catalog/pg_database.h"
28 #include "catalog/pg_extension.h"
29 #include "catalog/pg_foreign_data_wrapper.h"
30 #include "catalog/pg_foreign_server.h"
31 #include "catalog/pg_language.h"
32 #include "catalog/pg_largeobject.h"
33 #include "catalog/pg_largeobject_metadata.h"
34 #include "catalog/pg_namespace.h"
35 #include "catalog/pg_opclass.h"
36 #include "catalog/pg_opfamily.h"
37 #include "catalog/pg_operator.h"
38 #include "catalog/pg_proc.h"
39 #include "catalog/pg_rewrite.h"
40 #include "catalog/pg_tablespace.h"
41 #include "catalog/pg_trigger.h"
42 #include "catalog/pg_ts_config.h"
43 #include "catalog/pg_ts_dict.h"
44 #include "catalog/pg_ts_parser.h"
45 #include "catalog/pg_ts_template.h"
46 #include "catalog/pg_type.h"
47 #include "commands/dbcommands.h"
48 #include "commands/defrem.h"
49 #include "commands/extension.h"
50 #include "commands/proclang.h"
51 #include "commands/tablespace.h"
52 #include "commands/trigger.h"
53 #include "foreign/foreign.h"
54 #include "libpq/be-fsstubs.h"
55 #include "miscadmin.h"
56 #include "nodes/makefuncs.h"
57 #include "parser/parse_func.h"
58 #include "parser/parse_oper.h"
59 #include "parser/parse_type.h"
60 #include "rewrite/rewriteSupport.h"
61 #include "storage/lmgr.h"
62 #include "storage/sinval.h"
63 #include "utils/acl.h"
64 #include "utils/builtins.h"
65 #include "utils/fmgroids.h"
66 #include "utils/lsyscache.h"
67 #include "utils/syscache.h"
68 #include "utils/tqual.h"
73 * This array provides a common part of system object structure; to help
74 * consolidate routines to handle various kind of object classes.
78 Oid class_oid; /* oid of catalog */
79 Oid oid_index_oid; /* oid of index on system oid column */
80 int oid_catcache_id; /* id of catcache on system oid column */
81 AttrNumber attnum_namespace; /* attnum of namespace field */
84 static ObjectPropertyType ObjectProperty[] =
96 Anum_pg_collation_collnamespace
100 ConstraintOidIndexId,
102 Anum_pg_constraint_connamespace
105 ConversionRelationId,
106 ConversionOidIndexId,
108 Anum_pg_conversion_connamespace
120 InvalidAttrNumber /* extension doesn't belong to extnamespace */
123 ForeignDataWrapperRelationId,
124 ForeignDataWrapperOidIndexId,
125 FOREIGNDATAWRAPPEROID,
129 ForeignServerRelationId,
130 ForeignServerOidIndexId,
138 Anum_pg_proc_pronamespace
147 LargeObjectMetadataRelationId,
148 LargeObjectMetadataOidIndexId,
153 OperatorClassRelationId,
156 Anum_pg_opclass_opcnamespace,
162 Anum_pg_operator_oprnamespace
165 OperatorFamilyRelationId,
168 Anum_pg_opfamily_opfnamespace
192 Anum_pg_class_relnamespace
195 TableSpaceRelationId,
196 TablespaceOidIndexId,
210 Anum_pg_ts_config_cfgnamespace
213 TSDictionaryRelationId,
214 TSDictionaryOidIndexId,
216 Anum_pg_ts_dict_dictnamespace
222 Anum_pg_ts_parser_prsnamespace
225 TSTemplateRelationId,
226 TSTemplateOidIndexId,
228 Anum_pg_ts_template_tmplnamespace,
234 Anum_pg_type_typnamespace
238 static ObjectAddress get_object_address_unqualified(ObjectType objtype,
239 List *qualname, bool missing_ok);
240 static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
241 List *objname, Relation *relp,
242 LOCKMODE lockmode, bool missing_ok);
243 static ObjectAddress get_object_address_relobject(ObjectType objtype,
244 List *objname, Relation *relp, bool missing_ok);
245 static ObjectAddress get_object_address_attribute(ObjectType objtype,
246 List *objname, Relation *relp,
247 LOCKMODE lockmode, bool missing_ok);
248 static ObjectAddress get_object_address_type(ObjectType objtype,
249 List *objname, bool missing_ok);
250 static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
251 List *objargs, bool missing_ok);
252 static ObjectPropertyType *get_object_property_data(Oid class_id);
255 * Translate an object name and arguments (as passed by the parser) to an
258 * The returned object will be locked using the specified lockmode. If a
259 * sub-object is looked up, the parent object will be locked instead.
261 * If the object is a relation or a child object of a relation (e.g. an
262 * attribute or contraint), the relation is also opened and *relp receives
263 * the open relcache entry pointer; otherwise, *relp is set to NULL. This
264 * is a bit grotty but it makes life simpler, since the caller will
265 * typically need the relcache entry too. Caller must close the relcache
266 * entry when done with it. The relation is locked with the specified lockmode
267 * if the target object is the relation itself or an attribute, but for other
268 * child objects, only AccessShareLock is acquired on the relation.
270 * We don't currently provide a function to release the locks acquired here;
271 * typically, the lock must be held until commit to guard against a concurrent
275 get_object_address(ObjectType objtype, List *objname, List *objargs,
276 Relation *relp, LOCKMODE lockmode, bool missing_ok)
278 ObjectAddress address;
279 ObjectAddress old_address = {InvalidOid, InvalidOid, 0};
280 Relation relation = NULL;
283 /* Some kind of lock must be taken. */
284 Assert(lockmode != NoLock);
289 * Remember this value, so that, after looking up the object name and
290 * locking it, we can check whether any invalidation messages have
291 * been processed that might require a do-over.
293 inval_count = SharedInvalidMessageCounter;
295 /* Look up object address. */
299 case OBJECT_SEQUENCE:
302 case OBJECT_FOREIGN_TABLE:
304 get_relation_by_qualified_name(objtype, objname,
310 get_object_address_attribute(objtype, objname,
316 case OBJECT_CONSTRAINT:
317 address = get_object_address_relobject(objtype, objname,
318 &relation, missing_ok);
320 case OBJECT_DATABASE:
321 case OBJECT_EXTENSION:
322 case OBJECT_TABLESPACE:
325 case OBJECT_LANGUAGE:
327 case OBJECT_FOREIGN_SERVER:
328 address = get_object_address_unqualified(objtype,
329 objname, missing_ok);
333 address = get_object_address_type(objtype, objname, missing_ok);
335 case OBJECT_AGGREGATE:
336 address.classId = ProcedureRelationId;
338 LookupAggNameTypeNames(objname, objargs, missing_ok);
339 address.objectSubId = 0;
341 case OBJECT_FUNCTION:
342 address.classId = ProcedureRelationId;
344 LookupFuncNameTypeNames(objname, objargs, missing_ok);
345 address.objectSubId = 0;
347 case OBJECT_OPERATOR:
348 Assert(list_length(objargs) == 2);
349 address.classId = OperatorRelationId;
351 LookupOperNameTypeNames(NULL, objname,
352 (TypeName *) linitial(objargs),
353 (TypeName *) lsecond(objargs),
355 address.objectSubId = 0;
357 case OBJECT_COLLATION:
358 address.classId = CollationRelationId;
359 address.objectId = get_collation_oid(objname, missing_ok);
360 address.objectSubId = 0;
362 case OBJECT_CONVERSION:
363 address.classId = ConversionRelationId;
364 address.objectId = get_conversion_oid(objname, missing_ok);
365 address.objectSubId = 0;
368 case OBJECT_OPFAMILY:
369 address = get_object_address_opcf(objtype,
370 objname, objargs, missing_ok);
372 case OBJECT_LARGEOBJECT:
373 Assert(list_length(objname) == 1);
374 address.classId = LargeObjectRelationId;
375 address.objectId = oidparse(linitial(objname));
376 address.objectSubId = 0;
377 if (!LargeObjectExists(address.objectId))
381 (errcode(ERRCODE_UNDEFINED_OBJECT),
382 errmsg("large object %u does not exist",
388 TypeName *sourcetype = (TypeName *) linitial(objname);
389 TypeName *targettype = (TypeName *) linitial(objargs);
390 Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
391 Oid targettypeid = typenameTypeId(NULL, targettype);
393 address.classId = CastRelationId;
395 get_cast_oid(sourcetypeid, targettypeid, missing_ok);
396 address.objectSubId = 0;
399 case OBJECT_TSPARSER:
400 address.classId = TSParserRelationId;
401 address.objectId = get_ts_parser_oid(objname, missing_ok);
402 address.objectSubId = 0;
404 case OBJECT_TSDICTIONARY:
405 address.classId = TSDictionaryRelationId;
406 address.objectId = get_ts_dict_oid(objname, missing_ok);
407 address.objectSubId = 0;
409 case OBJECT_TSTEMPLATE:
410 address.classId = TSTemplateRelationId;
411 address.objectId = get_ts_template_oid(objname, missing_ok);
412 address.objectSubId = 0;
414 case OBJECT_TSCONFIGURATION:
415 address.classId = TSConfigRelationId;
416 address.objectId = get_ts_config_oid(objname, missing_ok);
417 address.objectSubId = 0;
420 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
421 /* placate compiler, in case it thinks elog might return */
422 address.classId = InvalidOid;
423 address.objectId = InvalidOid;
424 address.objectSubId = 0;
428 * If we could not find the supplied object, return without locking.
430 if (!OidIsValid(address.objectId))
437 * If we're retrying, see if we got the same answer as last time. If
438 * so, we're done; if not, we locked the wrong thing, so give up our
441 if (OidIsValid(old_address.classId))
443 if (old_address.classId == address.classId
444 && old_address.objectId == address.objectId
445 && old_address.objectSubId == address.objectSubId)
447 if (old_address.classId != RelationRelationId)
449 if (IsSharedRelation(old_address.classId))
450 UnlockSharedObject(old_address.classId,
451 old_address.objectId,
454 UnlockDatabaseObject(old_address.classId,
455 old_address.objectId,
461 * If we're dealing with a relation or attribute, then the relation is
462 * already locked. Otherwise, we lock it now.
464 if (address.classId != RelationRelationId)
466 if (IsSharedRelation(address.classId))
467 LockSharedObject(address.classId, address.objectId, 0,
470 LockDatabaseObject(address.classId, address.objectId, 0,
475 * At this point, we've resolved the name to an OID and locked the
476 * corresponding database object. However, it's possible that by the
477 * time we acquire the lock on the object, concurrent DDL has modified
478 * the database in such a way that the name we originally looked up no
479 * longer resolves to that OID.
481 * We can be certain that this isn't an issue if (a) no shared
482 * invalidation messages have been processed or (b) we've locked a
483 * relation somewhere along the line. All the relation name lookups
484 * in this module ultimately use RangeVarGetRelid() to acquire a
485 * relation lock, and that function protects against the same kinds of
486 * races we're worried about here. Even when operating on a
487 * constraint, rule, or trigger, we still acquire AccessShareLock on
488 * the relation, which is enough to freeze out any concurrent DDL.
490 * In all other cases, however, it's possible that the name we looked
491 * up no longer refers to the object we locked, so we retry the lookup
492 * and see whether we get the same answer.
494 if (inval_count == SharedInvalidMessageCounter || relation != NULL)
496 old_address = address;
499 /* Return the object address and the relation. */
505 * Find an ObjectAddress for a type of object that is identified by an
509 get_object_address_unqualified(ObjectType objtype,
510 List *qualname, bool missing_ok)
513 ObjectAddress address;
516 * The types of names handled by this function are not permitted to be
517 * schema-qualified or catalog-qualified.
519 if (list_length(qualname) != 1)
525 case OBJECT_DATABASE:
526 msg = gettext_noop("database name cannot be qualified");
528 case OBJECT_EXTENSION:
529 msg = gettext_noop("extension name cannot be qualified");
531 case OBJECT_TABLESPACE:
532 msg = gettext_noop("tablespace name cannot be qualified");
535 msg = gettext_noop("role name cannot be qualified");
538 msg = gettext_noop("schema name cannot be qualified");
540 case OBJECT_LANGUAGE:
541 msg = gettext_noop("language name cannot be qualified");
544 msg = gettext_noop("foreign-data wrapper name cannot be qualified");
546 case OBJECT_FOREIGN_SERVER:
547 msg = gettext_noop("server name cannot be qualified");
550 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
551 msg = NULL; /* placate compiler */
554 (errcode(ERRCODE_SYNTAX_ERROR),
555 errmsg("%s", _(msg))));
558 /* Format is valid, extract the actual name. */
559 name = strVal(linitial(qualname));
561 /* Translate name to OID. */
564 case OBJECT_DATABASE:
565 address.classId = DatabaseRelationId;
566 address.objectId = get_database_oid(name, missing_ok);
567 address.objectSubId = 0;
569 case OBJECT_EXTENSION:
570 address.classId = ExtensionRelationId;
571 address.objectId = get_extension_oid(name, missing_ok);
572 address.objectSubId = 0;
574 case OBJECT_TABLESPACE:
575 address.classId = TableSpaceRelationId;
576 address.objectId = get_tablespace_oid(name, missing_ok);
577 address.objectSubId = 0;
580 address.classId = AuthIdRelationId;
581 address.objectId = get_role_oid(name, missing_ok);
582 address.objectSubId = 0;
585 address.classId = NamespaceRelationId;
586 address.objectId = get_namespace_oid(name, missing_ok);
587 address.objectSubId = 0;
589 case OBJECT_LANGUAGE:
590 address.classId = LanguageRelationId;
591 address.objectId = get_language_oid(name, missing_ok);
592 address.objectSubId = 0;
595 address.classId = ForeignDataWrapperRelationId;
596 address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
597 address.objectSubId = 0;
599 case OBJECT_FOREIGN_SERVER:
600 address.classId = ForeignServerRelationId;
601 address.objectId = get_foreign_server_oid(name, missing_ok);
602 address.objectSubId = 0;
605 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
606 /* placate compiler, which doesn't know elog won't return */
607 address.classId = InvalidOid;
608 address.objectId = InvalidOid;
609 address.objectSubId = 0;
616 * Locate a relation by qualified name.
619 get_relation_by_qualified_name(ObjectType objtype, List *objname,
620 Relation *relp, LOCKMODE lockmode,
624 ObjectAddress address;
626 address.classId = RelationRelationId;
627 address.objectId = InvalidOid;
628 address.objectSubId = 0;
630 relation = relation_openrv_extended(makeRangeVarFromNameList(objname),
631 lockmode, missing_ok);
638 if (relation->rd_rel->relkind != RELKIND_INDEX)
640 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
641 errmsg("\"%s\" is not an index",
642 RelationGetRelationName(relation))));
644 case OBJECT_SEQUENCE:
645 if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
647 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
648 errmsg("\"%s\" is not a sequence",
649 RelationGetRelationName(relation))));
652 if (relation->rd_rel->relkind != RELKIND_RELATION)
654 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
655 errmsg("\"%s\" is not a table",
656 RelationGetRelationName(relation))));
659 if (relation->rd_rel->relkind != RELKIND_VIEW)
661 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
662 errmsg("\"%s\" is not a view",
663 RelationGetRelationName(relation))));
665 case OBJECT_FOREIGN_TABLE:
666 if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
668 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
669 errmsg("\"%s\" is not a foreign table",
670 RelationGetRelationName(relation))));
673 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
678 address.objectId = RelationGetRelid(relation);
685 * Find object address for an object that is attached to a relation.
687 * Note that we take only an AccessShareLock on the relation. We need not
688 * pass down the LOCKMODE from get_object_address(), because that is the lock
689 * mode for the object itself, not the relation to which it is attached.
692 get_object_address_relobject(ObjectType objtype, List *objname,
693 Relation *relp, bool missing_ok)
695 ObjectAddress address;
696 Relation relation = NULL;
700 /* Extract name of dependent object. */
701 depname = strVal(lfirst(list_tail(objname)));
703 /* Separate relation name from dependent object name. */
704 nnames = list_length(objname);
710 * For compatibility with very old releases, we sometimes allow users
711 * to attempt to specify a rule without mentioning the relation name.
712 * If there's only rule by that name in the entire database, this will
713 * work. But objects other than rules don't get this special
716 if (objtype != OBJECT_RULE)
717 elog(ERROR, "must specify relation and object name");
718 address.classId = RewriteRelationId;
720 get_rewrite_oid_without_relid(depname, &reloid, missing_ok);
721 address.objectSubId = 0;
724 * Caller is expecting to get back the relation, even though we didn't
725 * end up using it to find the rule.
727 if (OidIsValid(address.objectId))
728 relation = heap_open(reloid, AccessShareLock);
735 /* Extract relation name and open relation. */
736 relname = list_truncate(list_copy(objname), nnames - 1);
737 relation = heap_openrv(makeRangeVarFromNameList(relname),
739 reloid = RelationGetRelid(relation);
744 address.classId = RewriteRelationId;
745 address.objectId = get_rewrite_oid(reloid, depname, missing_ok);
746 address.objectSubId = 0;
749 address.classId = TriggerRelationId;
750 address.objectId = get_trigger_oid(reloid, depname, missing_ok);
751 address.objectSubId = 0;
753 case OBJECT_CONSTRAINT:
754 address.classId = ConstraintRelationId;
756 get_relation_constraint_oid(reloid, depname, missing_ok);
757 address.objectSubId = 0;
760 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
761 /* placate compiler, which doesn't know elog won't return */
762 address.classId = InvalidOid;
763 address.objectId = InvalidOid;
764 address.objectSubId = 0;
767 /* Avoid relcache leak when object not found. */
768 if (!OidIsValid(address.objectId))
770 heap_close(relation, AccessShareLock);
771 relation = NULL; /* department of accident prevention */
782 * Find the ObjectAddress for an attribute.
785 get_object_address_attribute(ObjectType objtype, List *objname,
786 Relation *relp, LOCKMODE lockmode,
789 ObjectAddress address;
796 /* Extract relation name and open relation. */
797 if (list_length(objname) < 2)
799 (errcode(ERRCODE_SYNTAX_ERROR),
800 errmsg("column name must be qualified")));
801 attname = strVal(lfirst(list_tail(objname)));
802 relname = list_truncate(list_copy(objname), list_length(objname) - 1);
803 relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
804 reloid = RelationGetRelid(relation);
806 /* Look up attribute and construct return value. */
807 attnum = get_attnum(reloid, attname);
808 if (attnum == InvalidAttrNumber)
812 (errcode(ERRCODE_UNDEFINED_COLUMN),
813 errmsg("column \"%s\" of relation \"%s\" does not exist",
814 attname, NameListToString(relname))));
816 address.classId = RelationRelationId;
817 address.objectId = InvalidOid;
818 address.objectSubId = InvalidAttrNumber;
822 address.classId = RelationRelationId;
823 address.objectId = reloid;
824 address.objectSubId = attnum;
831 * Find the ObjectAddress for a type or domain
834 get_object_address_type(ObjectType objtype,
835 List *objname, bool missing_ok)
837 ObjectAddress address;
841 typename = makeTypeNameFromNameList(objname);
843 address.classId = TypeRelationId;
844 address.objectId = InvalidOid;
845 address.objectSubId = 0;
847 tup = LookupTypeName(NULL, typename, NULL);
848 if (!HeapTupleIsValid(tup))
852 (errcode(ERRCODE_UNDEFINED_OBJECT),
853 errmsg("type \"%s\" does not exist",
854 TypeNameToString(typename))));
857 address.objectId = typeTypeId(tup);
859 if (objtype == OBJECT_DOMAIN)
861 if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
863 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
864 errmsg("\"%s\" is not a domain",
865 TypeNameToString(typename))));
868 ReleaseSysCache(tup);
874 * Find the ObjectAddress for an opclass or opfamily.
877 get_object_address_opcf(ObjectType objtype,
878 List *objname, List *objargs, bool missing_ok)
881 ObjectAddress address;
883 Assert(list_length(objargs) == 1);
884 amoid = get_am_oid(strVal(linitial(objargs)), false);
889 address.classId = OperatorClassRelationId;
890 address.objectId = get_opclass_oid(amoid, objname, missing_ok);
891 address.objectSubId = 0;
893 case OBJECT_OPFAMILY:
894 address.classId = OperatorFamilyRelationId;
895 address.objectId = get_opfamily_oid(amoid, objname, missing_ok);
896 address.objectSubId = 0;
899 elog(ERROR, "unrecognized objtype: %d", (int) objtype);
900 /* placate compiler, which doesn't know elog won't return */
901 address.classId = InvalidOid;
902 address.objectId = InvalidOid;
903 address.objectSubId = 0;
910 * Check ownership of an object previously identified by get_object_address.
913 check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
914 List *objname, List *objargs, Relation relation)
919 case OBJECT_SEQUENCE:
922 case OBJECT_FOREIGN_TABLE:
926 case OBJECT_CONSTRAINT:
927 if (!pg_class_ownercheck(RelationGetRelid(relation), roleid))
928 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
929 RelationGetRelationName(relation));
931 case OBJECT_DATABASE:
932 if (!pg_database_ownercheck(address.objectId, roleid))
933 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
934 NameListToString(objname));
938 case OBJECT_ATTRIBUTE:
939 if (!pg_type_ownercheck(address.objectId, roleid))
940 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
941 format_type_be(address.objectId));
943 case OBJECT_AGGREGATE:
944 case OBJECT_FUNCTION:
945 if (!pg_proc_ownercheck(address.objectId, roleid))
946 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
947 NameListToString(objname));
949 case OBJECT_OPERATOR:
950 if (!pg_oper_ownercheck(address.objectId, roleid))
951 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
952 NameListToString(objname));
955 if (!pg_namespace_ownercheck(address.objectId, roleid))
956 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
957 NameListToString(objname));
959 case OBJECT_COLLATION:
960 if (!pg_collation_ownercheck(address.objectId, roleid))
961 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
962 NameListToString(objname));
964 case OBJECT_CONVERSION:
965 if (!pg_conversion_ownercheck(address.objectId, roleid))
966 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
967 NameListToString(objname));
969 case OBJECT_EXTENSION:
970 if (!pg_extension_ownercheck(address.objectId, roleid))
971 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
972 NameListToString(objname));
975 if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
976 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW,
977 NameListToString(objname));
979 case OBJECT_FOREIGN_SERVER:
980 if (!pg_foreign_server_ownercheck(address.objectId, roleid))
981 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
982 NameListToString(objname));
984 case OBJECT_LANGUAGE:
985 if (!pg_language_ownercheck(address.objectId, roleid))
986 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
987 NameListToString(objname));
990 if (!pg_opclass_ownercheck(address.objectId, roleid))
991 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
992 NameListToString(objname));
994 case OBJECT_OPFAMILY:
995 if (!pg_opfamily_ownercheck(address.objectId, roleid))
996 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
997 NameListToString(objname));
999 case OBJECT_LARGEOBJECT:
1000 if (!lo_compat_privileges &&
1001 !pg_largeobject_ownercheck(address.objectId, roleid))
1003 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1004 errmsg("must be owner of large object %u",
1005 address.objectId)));
1009 /* We can only check permissions on the source/target types */
1010 TypeName *sourcetype = (TypeName *) linitial(objname);
1011 TypeName *targettype = (TypeName *) linitial(objargs);
1012 Oid sourcetypeid = typenameTypeId(NULL, sourcetype);
1013 Oid targettypeid = typenameTypeId(NULL, targettype);
1015 if (!pg_type_ownercheck(sourcetypeid, roleid)
1016 && !pg_type_ownercheck(targettypeid, roleid))
1018 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1019 errmsg("must be owner of type %s or type %s",
1020 format_type_be(sourcetypeid),
1021 format_type_be(targettypeid))));
1024 case OBJECT_TABLESPACE:
1025 if (!pg_tablespace_ownercheck(address.objectId, roleid))
1026 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
1027 NameListToString(objname));
1029 case OBJECT_TSDICTIONARY:
1030 if (!pg_ts_dict_ownercheck(address.objectId, roleid))
1031 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
1032 NameListToString(objname));
1034 case OBJECT_TSCONFIGURATION:
1035 if (!pg_ts_config_ownercheck(address.objectId, roleid))
1036 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
1037 NameListToString(objname));
1042 * We treat roles as being "owned" by those with CREATEROLE priv,
1043 * except that superusers are only owned by superusers.
1045 if (superuser_arg(address.objectId))
1047 if (!superuser_arg(roleid))
1049 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1050 errmsg("must be superuser")));
1054 if (!has_createrole_privilege(roleid))
1056 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1057 errmsg("must have CREATEROLE privilege")));
1060 case OBJECT_TSPARSER:
1061 case OBJECT_TSTEMPLATE:
1062 /* We treat these object types as being owned by superusers */
1063 if (!superuser_arg(roleid))
1065 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1066 errmsg("must be superuser")));
1069 elog(ERROR, "unrecognized object type: %d",
1075 * get_object_namespace
1077 * Find the schema containing the specified object. For non-schema objects,
1078 * this function returns InvalidOid.
1081 get_object_namespace(const ObjectAddress *address)
1087 ObjectPropertyType *property;
1089 /* If not owned by a namespace, just return InvalidOid. */
1090 property = get_object_property_data(address->classId);
1091 if (property->attnum_namespace == InvalidAttrNumber)
1094 /* Currently, we can only handle object types with system caches. */
1095 cache = property->oid_catcache_id;
1096 Assert(cache != -1);
1098 /* Fetch tuple from syscache and extract namespace attribute. */
1099 tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId));
1100 if (!HeapTupleIsValid(tuple))
1101 elog(ERROR, "cache lookup failed for cache %d oid %u",
1102 cache, address->objectId);
1103 oid = DatumGetObjectId(SysCacheGetAttr(cache,
1105 property->attnum_namespace,
1108 ReleaseSysCache(tuple);
1114 * Find ObjectProperty structure by class_id.
1116 static ObjectPropertyType *
1117 get_object_property_data(Oid class_id)
1121 for (index = 0; index < lengthof(ObjectProperty); index++)
1122 if (ObjectProperty[index].class_oid == class_id)
1123 return &ObjectProperty[index];
1125 elog(ERROR, "unrecognized class id: %u", class_id);
1126 return NULL; /* not reached */