/src/backend/catalog/objectaddress.c
C | 5379 lines | 4271 code | 628 blank | 480 comment | 363 complexity | 8fb78006420387d04b00a103a56cd642 MD5 | raw file
Possible License(s): AGPL-3.0
Large files files are truncated, but you can click here to view the full file
- /*-------------------------------------------------------------------------
- *
- * objectaddress.c
- * functions for working with ObjectAddresses
- *
- * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * src/backend/catalog/objectaddress.c
- *
- *-------------------------------------------------------------------------
- */
- #include "postgres.h"
- #include "access/genam.h"
- #include "access/htup_details.h"
- #include "access/relation.h"
- #include "access/sysattr.h"
- #include "access/table.h"
- #include "catalog/catalog.h"
- #include "catalog/indexing.h"
- #include "catalog/objectaddress.h"
- #include "catalog/pg_am.h"
- #include "catalog/pg_amop.h"
- #include "catalog/pg_amproc.h"
- #include "catalog/pg_attrdef.h"
- #include "catalog/pg_authid.h"
- #include "catalog/pg_cast.h"
- #include "catalog/pg_collation.h"
- #include "catalog/pg_constraint.h"
- #include "catalog/pg_conversion.h"
- #include "catalog/pg_database.h"
- #include "catalog/pg_default_acl.h"
- #include "catalog/pg_enum.h"
- #include "catalog/pg_event_trigger.h"
- #include "catalog/pg_extension.h"
- #include "catalog/pg_foreign_data_wrapper.h"
- #include "catalog/pg_foreign_server.h"
- #include "catalog/pg_language.h"
- #include "catalog/pg_largeobject.h"
- #include "catalog/pg_largeobject_metadata.h"
- #include "catalog/pg_namespace.h"
- #include "catalog/pg_opclass.h"
- #include "catalog/pg_operator.h"
- #include "catalog/pg_opfamily.h"
- #include "catalog/pg_policy.h"
- #include "catalog/pg_proc.h"
- #include "catalog/pg_publication.h"
- #include "catalog/pg_publication_rel.h"
- #include "catalog/pg_rewrite.h"
- #include "catalog/pg_statistic_ext.h"
- #include "catalog/pg_subscription.h"
- #include "catalog/pg_tablespace.h"
- #include "catalog/pg_transform.h"
- #include "catalog/pg_trigger.h"
- #include "catalog/pg_ts_config.h"
- #include "catalog/pg_ts_dict.h"
- #include "catalog/pg_ts_parser.h"
- #include "catalog/pg_ts_template.h"
- #include "catalog/pg_type.h"
- #include "catalog/pg_user_mapping.h"
- #include "commands/dbcommands.h"
- #include "commands/defrem.h"
- #include "commands/event_trigger.h"
- #include "commands/extension.h"
- #include "commands/policy.h"
- #include "commands/proclang.h"
- #include "commands/tablespace.h"
- #include "commands/trigger.h"
- #include "foreign/foreign.h"
- #include "funcapi.h"
- #include "miscadmin.h"
- #include "nodes/makefuncs.h"
- #include "parser/parse_func.h"
- #include "parser/parse_oper.h"
- #include "parser/parse_type.h"
- #include "rewrite/rewriteSupport.h"
- #include "storage/large_object.h"
- #include "storage/lmgr.h"
- #include "storage/sinval.h"
- #include "utils/acl.h"
- #include "utils/builtins.h"
- #include "utils/fmgroids.h"
- #include "utils/lsyscache.h"
- #include "utils/memutils.h"
- #include "utils/regproc.h"
- #include "utils/syscache.h"
- /*
- * ObjectProperty
- *
- * This array provides a common part of system object structure; to help
- * consolidate routines to handle various kind of object classes.
- */
- typedef struct
- {
- Oid class_oid; /* oid of catalog */
- Oid oid_index_oid; /* oid of index on system oid column */
- int oid_catcache_id; /* id of catcache on system oid column */
- int name_catcache_id; /* id of catcache on (name,namespace), or
- * (name) if the object does not live in a
- * namespace */
- AttrNumber attnum_oid; /* attribute number of oid column */
- AttrNumber attnum_name; /* attnum of name field */
- AttrNumber attnum_namespace; /* attnum of namespace field */
- AttrNumber attnum_owner; /* attnum of owner field */
- AttrNumber attnum_acl; /* attnum of acl field */
- ObjectType objtype; /* OBJECT_* of this object type */
- bool is_nsp_name_unique; /* can the nsp/name combination (or name
- * alone, if there's no namespace) be
- * considered a unique identifier for an
- * object of this class? */
- } ObjectPropertyType;
- static const ObjectPropertyType ObjectProperty[] =
- {
- {
- AccessMethodRelationId,
- AmOidIndexId,
- AMOID,
- AMNAME,
- Anum_pg_am_oid,
- Anum_pg_am_amname,
- InvalidAttrNumber,
- InvalidAttrNumber,
- InvalidAttrNumber,
- -1,
- true
- },
- {
- CastRelationId,
- CastOidIndexId,
- -1,
- -1,
- Anum_pg_cast_oid,
- InvalidAttrNumber,
- InvalidAttrNumber,
- InvalidAttrNumber,
- InvalidAttrNumber,
- -1,
- false
- },
- {
- CollationRelationId,
- CollationOidIndexId,
- COLLOID,
- -1, /* COLLNAMEENCNSP also takes encoding */
- Anum_pg_collation_oid,
- Anum_pg_collation_collname,
- Anum_pg_collation_collnamespace,
- Anum_pg_collation_collowner,
- InvalidAttrNumber,
- OBJECT_COLLATION,
- true
- },
- {
- ConstraintRelationId,
- ConstraintOidIndexId,
- CONSTROID,
- -1,
- Anum_pg_constraint_oid,
- Anum_pg_constraint_conname,
- Anum_pg_constraint_connamespace,
- InvalidAttrNumber,
- InvalidAttrNumber,
- -1,
- false
- },
- {
- ConversionRelationId,
- ConversionOidIndexId,
- CONVOID,
- CONNAMENSP,
- Anum_pg_conversion_oid,
- Anum_pg_conversion_conname,
- Anum_pg_conversion_connamespace,
- Anum_pg_conversion_conowner,
- InvalidAttrNumber,
- OBJECT_CONVERSION,
- true
- },
- {
- DatabaseRelationId,
- DatabaseOidIndexId,
- DATABASEOID,
- -1,
- Anum_pg_database_oid,
- Anum_pg_database_datname,
- InvalidAttrNumber,
- Anum_pg_database_datdba,
- Anum_pg_database_datacl,
- OBJECT_DATABASE,
- true
- },
- {
- ExtensionRelationId,
- ExtensionOidIndexId,
- -1,
- -1,
- Anum_pg_extension_oid,
- Anum_pg_extension_extname,
- InvalidAttrNumber, /* extension doesn't belong to extnamespace */
- Anum_pg_extension_extowner,
- InvalidAttrNumber,
- OBJECT_EXTENSION,
- true
- },
- {
- ForeignDataWrapperRelationId,
- ForeignDataWrapperOidIndexId,
- FOREIGNDATAWRAPPEROID,
- FOREIGNDATAWRAPPERNAME,
- Anum_pg_foreign_data_wrapper_oid,
- Anum_pg_foreign_data_wrapper_fdwname,
- InvalidAttrNumber,
- Anum_pg_foreign_data_wrapper_fdwowner,
- Anum_pg_foreign_data_wrapper_fdwacl,
- OBJECT_FDW,
- true
- },
- {
- ForeignServerRelationId,
- ForeignServerOidIndexId,
- FOREIGNSERVEROID,
- FOREIGNSERVERNAME,
- Anum_pg_foreign_server_oid,
- Anum_pg_foreign_server_srvname,
- InvalidAttrNumber,
- Anum_pg_foreign_server_srvowner,
- Anum_pg_foreign_server_srvacl,
- OBJECT_FOREIGN_SERVER,
- true
- },
- {
- ProcedureRelationId,
- ProcedureOidIndexId,
- PROCOID,
- -1, /* PROCNAMEARGSNSP also takes argument types */
- Anum_pg_proc_oid,
- Anum_pg_proc_proname,
- Anum_pg_proc_pronamespace,
- Anum_pg_proc_proowner,
- Anum_pg_proc_proacl,
- OBJECT_FUNCTION,
- false
- },
- {
- LanguageRelationId,
- LanguageOidIndexId,
- LANGOID,
- LANGNAME,
- Anum_pg_language_oid,
- Anum_pg_language_lanname,
- InvalidAttrNumber,
- Anum_pg_language_lanowner,
- Anum_pg_language_lanacl,
- OBJECT_LANGUAGE,
- true
- },
- {
- LargeObjectMetadataRelationId,
- LargeObjectMetadataOidIndexId,
- -1,
- -1,
- Anum_pg_largeobject_metadata_oid,
- InvalidAttrNumber,
- InvalidAttrNumber,
- Anum_pg_largeobject_metadata_lomowner,
- Anum_pg_largeobject_metadata_lomacl,
- OBJECT_LARGEOBJECT,
- false
- },
- {
- OperatorClassRelationId,
- OpclassOidIndexId,
- CLAOID,
- -1, /* CLAAMNAMENSP also takes opcmethod */
- Anum_pg_opclass_oid,
- Anum_pg_opclass_opcname,
- Anum_pg_opclass_opcnamespace,
- Anum_pg_opclass_opcowner,
- InvalidAttrNumber,
- OBJECT_OPCLASS,
- true
- },
- {
- OperatorRelationId,
- OperatorOidIndexId,
- OPEROID,
- -1, /* OPERNAMENSP also takes left and right type */
- Anum_pg_operator_oid,
- Anum_pg_operator_oprname,
- Anum_pg_operator_oprnamespace,
- Anum_pg_operator_oprowner,
- InvalidAttrNumber,
- OBJECT_OPERATOR,
- false
- },
- {
- OperatorFamilyRelationId,
- OpfamilyOidIndexId,
- OPFAMILYOID,
- -1, /* OPFAMILYAMNAMENSP also takes opfmethod */
- Anum_pg_opfamily_oid,
- Anum_pg_opfamily_opfname,
- Anum_pg_opfamily_opfnamespace,
- Anum_pg_opfamily_opfowner,
- InvalidAttrNumber,
- OBJECT_OPFAMILY,
- true
- },
- {
- AuthIdRelationId,
- AuthIdOidIndexId,
- AUTHOID,
- AUTHNAME,
- Anum_pg_authid_oid,
- Anum_pg_authid_rolname,
- InvalidAttrNumber,
- InvalidAttrNumber,
- InvalidAttrNumber,
- -1,
- true
- },
- {
- RewriteRelationId,
- RewriteOidIndexId,
- -1,
- -1,
- Anum_pg_rewrite_oid,
- Anum_pg_rewrite_rulename,
- InvalidAttrNumber,
- InvalidAttrNumber,
- InvalidAttrNumber,
- -1,
- false
- },
- {
- NamespaceRelationId,
- NamespaceOidIndexId,
- NAMESPACEOID,
- NAMESPACENAME,
- Anum_pg_namespace_oid,
- Anum_pg_namespace_nspname,
- InvalidAttrNumber,
- Anum_pg_namespace_nspowner,
- Anum_pg_namespace_nspacl,
- OBJECT_SCHEMA,
- true
- },
- {
- RelationRelationId,
- ClassOidIndexId,
- RELOID,
- RELNAMENSP,
- Anum_pg_class_oid,
- Anum_pg_class_relname,
- Anum_pg_class_relnamespace,
- Anum_pg_class_relowner,
- Anum_pg_class_relacl,
- OBJECT_TABLE,
- true
- },
- {
- TableSpaceRelationId,
- TablespaceOidIndexId,
- TABLESPACEOID,
- -1,
- Anum_pg_tablespace_oid,
- Anum_pg_tablespace_spcname,
- InvalidAttrNumber,
- Anum_pg_tablespace_spcowner,
- Anum_pg_tablespace_spcacl,
- OBJECT_TABLESPACE,
- true
- },
- {
- TransformRelationId,
- TransformOidIndexId,
- TRFOID,
- InvalidAttrNumber,
- Anum_pg_transform_oid
- },
- {
- TriggerRelationId,
- TriggerOidIndexId,
- -1,
- -1,
- Anum_pg_trigger_oid,
- Anum_pg_trigger_tgname,
- InvalidAttrNumber,
- InvalidAttrNumber,
- InvalidAttrNumber,
- -1,
- false
- },
- {
- PolicyRelationId,
- PolicyOidIndexId,
- -1,
- -1,
- Anum_pg_policy_oid,
- Anum_pg_policy_polname,
- InvalidAttrNumber,
- InvalidAttrNumber,
- InvalidAttrNumber,
- -1,
- false
- },
- {
- EventTriggerRelationId,
- EventTriggerOidIndexId,
- EVENTTRIGGEROID,
- EVENTTRIGGERNAME,
- Anum_pg_event_trigger_oid,
- Anum_pg_event_trigger_evtname,
- InvalidAttrNumber,
- Anum_pg_event_trigger_evtowner,
- InvalidAttrNumber,
- OBJECT_EVENT_TRIGGER,
- true
- },
- {
- TSConfigRelationId,
- TSConfigOidIndexId,
- TSCONFIGOID,
- TSCONFIGNAMENSP,
- Anum_pg_ts_config_oid,
- Anum_pg_ts_config_cfgname,
- Anum_pg_ts_config_cfgnamespace,
- Anum_pg_ts_config_cfgowner,
- InvalidAttrNumber,
- OBJECT_TSCONFIGURATION,
- true
- },
- {
- TSDictionaryRelationId,
- TSDictionaryOidIndexId,
- TSDICTOID,
- TSDICTNAMENSP,
- Anum_pg_ts_dict_oid,
- Anum_pg_ts_dict_dictname,
- Anum_pg_ts_dict_dictnamespace,
- Anum_pg_ts_dict_dictowner,
- InvalidAttrNumber,
- OBJECT_TSDICTIONARY,
- true
- },
- {
- TSParserRelationId,
- TSParserOidIndexId,
- TSPARSEROID,
- TSPARSERNAMENSP,
- Anum_pg_ts_parser_oid,
- Anum_pg_ts_parser_prsname,
- Anum_pg_ts_parser_prsnamespace,
- InvalidAttrNumber,
- InvalidAttrNumber,
- -1,
- true
- },
- {
- TSTemplateRelationId,
- TSTemplateOidIndexId,
- TSTEMPLATEOID,
- TSTEMPLATENAMENSP,
- Anum_pg_ts_template_oid,
- Anum_pg_ts_template_tmplname,
- Anum_pg_ts_template_tmplnamespace,
- InvalidAttrNumber,
- InvalidAttrNumber,
- -1,
- true,
- },
- {
- TypeRelationId,
- TypeOidIndexId,
- TYPEOID,
- TYPENAMENSP,
- Anum_pg_type_oid,
- Anum_pg_type_typname,
- Anum_pg_type_typnamespace,
- Anum_pg_type_typowner,
- Anum_pg_type_typacl,
- OBJECT_TYPE,
- true
- },
- {
- PublicationRelationId,
- PublicationObjectIndexId,
- PUBLICATIONOID,
- PUBLICATIONNAME,
- Anum_pg_publication_oid,
- Anum_pg_publication_pubname,
- InvalidAttrNumber,
- Anum_pg_publication_pubowner,
- InvalidAttrNumber,
- OBJECT_PUBLICATION,
- true
- },
- {
- SubscriptionRelationId,
- SubscriptionObjectIndexId,
- SUBSCRIPTIONOID,
- SUBSCRIPTIONNAME,
- Anum_pg_subscription_oid,
- Anum_pg_subscription_subname,
- InvalidAttrNumber,
- Anum_pg_subscription_subowner,
- InvalidAttrNumber,
- OBJECT_SUBSCRIPTION,
- true
- },
- {
- StatisticExtRelationId,
- StatisticExtOidIndexId,
- STATEXTOID,
- STATEXTNAMENSP,
- Anum_pg_statistic_ext_oid,
- Anum_pg_statistic_ext_stxname,
- Anum_pg_statistic_ext_stxnamespace,
- Anum_pg_statistic_ext_stxowner,
- InvalidAttrNumber, /* no ACL (same as relation) */
- OBJECT_STATISTIC_EXT,
- true
- }
- };
- /*
- * This struct maps the string object types as returned by
- * getObjectTypeDescription into ObjectType enum values. Note that some enum
- * values can be obtained by different names, and that some string object types
- * do not have corresponding values in the output enum. The user of this map
- * must be careful to test for invalid values being returned.
- *
- * To ease maintenance, this follows the order of getObjectTypeDescription.
- */
- static const struct object_type_map
- {
- const char *tm_name;
- ObjectType tm_type;
- }
- ObjectTypeMap[] =
- {
- /* OCLASS_CLASS, all kinds of relations */
- {
- "table", OBJECT_TABLE
- },
- {
- "index", OBJECT_INDEX
- },
- {
- "sequence", OBJECT_SEQUENCE
- },
- {
- "toast table", -1
- }, /* unmapped */
- {
- "view", OBJECT_VIEW
- },
- {
- "materialized view", OBJECT_MATVIEW
- },
- {
- "composite type", -1
- }, /* unmapped */
- {
- "foreign table", OBJECT_FOREIGN_TABLE
- },
- {
- "table column", OBJECT_COLUMN
- },
- {
- "index column", -1
- }, /* unmapped */
- {
- "sequence column", -1
- }, /* unmapped */
- {
- "toast table column", -1
- }, /* unmapped */
- {
- "view column", -1
- }, /* unmapped */
- {
- "materialized view column", -1
- }, /* unmapped */
- {
- "composite type column", -1
- }, /* unmapped */
- {
- "foreign table column", OBJECT_COLUMN
- },
- /* OCLASS_PROC */
- {
- "aggregate", OBJECT_AGGREGATE
- },
- {
- "function", OBJECT_FUNCTION
- },
- {
- "procedure", OBJECT_PROCEDURE
- },
- /* OCLASS_TYPE */
- {
- "type", OBJECT_TYPE
- },
- /* OCLASS_CAST */
- {
- "cast", OBJECT_CAST
- },
- /* OCLASS_COLLATION */
- {
- "collation", OBJECT_COLLATION
- },
- /* OCLASS_CONSTRAINT */
- {
- "table constraint", OBJECT_TABCONSTRAINT
- },
- {
- "domain constraint", OBJECT_DOMCONSTRAINT
- },
- /* OCLASS_CONVERSION */
- {
- "conversion", OBJECT_CONVERSION
- },
- /* OCLASS_DEFAULT */
- {
- "default value", OBJECT_DEFAULT
- },
- /* OCLASS_LANGUAGE */
- {
- "language", OBJECT_LANGUAGE
- },
- /* OCLASS_LARGEOBJECT */
- {
- "large object", OBJECT_LARGEOBJECT
- },
- /* OCLASS_OPERATOR */
- {
- "operator", OBJECT_OPERATOR
- },
- /* OCLASS_OPCLASS */
- {
- "operator class", OBJECT_OPCLASS
- },
- /* OCLASS_OPFAMILY */
- {
- "operator family", OBJECT_OPFAMILY
- },
- /* OCLASS_AM */
- {
- "access method", OBJECT_ACCESS_METHOD
- },
- /* OCLASS_AMOP */
- {
- "operator of access method", OBJECT_AMOP
- },
- /* OCLASS_AMPROC */
- {
- "function of access method", OBJECT_AMPROC
- },
- /* OCLASS_REWRITE */
- {
- "rule", OBJECT_RULE
- },
- /* OCLASS_TRIGGER */
- {
- "trigger", OBJECT_TRIGGER
- },
- /* OCLASS_SCHEMA */
- {
- "schema", OBJECT_SCHEMA
- },
- /* OCLASS_TSPARSER */
- {
- "text search parser", OBJECT_TSPARSER
- },
- /* OCLASS_TSDICT */
- {
- "text search dictionary", OBJECT_TSDICTIONARY
- },
- /* OCLASS_TSTEMPLATE */
- {
- "text search template", OBJECT_TSTEMPLATE
- },
- /* OCLASS_TSCONFIG */
- {
- "text search configuration", OBJECT_TSCONFIGURATION
- },
- /* OCLASS_ROLE */
- {
- "role", OBJECT_ROLE
- },
- /* OCLASS_DATABASE */
- {
- "database", OBJECT_DATABASE
- },
- /* OCLASS_TBLSPACE */
- {
- "tablespace", OBJECT_TABLESPACE
- },
- /* OCLASS_FDW */
- {
- "foreign-data wrapper", OBJECT_FDW
- },
- /* OCLASS_FOREIGN_SERVER */
- {
- "server", OBJECT_FOREIGN_SERVER
- },
- /* OCLASS_USER_MAPPING */
- {
- "user mapping", OBJECT_USER_MAPPING
- },
- /* OCLASS_DEFACL */
- {
- "default acl", OBJECT_DEFACL
- },
- /* OCLASS_EXTENSION */
- {
- "extension", OBJECT_EXTENSION
- },
- /* OCLASS_EVENT_TRIGGER */
- {
- "event trigger", OBJECT_EVENT_TRIGGER
- },
- /* OCLASS_POLICY */
- {
- "policy", OBJECT_POLICY
- },
- /* OCLASS_PUBLICATION */
- {
- "publication", OBJECT_PUBLICATION
- },
- /* OCLASS_PUBLICATION_REL */
- {
- "publication relation", OBJECT_PUBLICATION_REL
- },
- /* OCLASS_SUBSCRIPTION */
- {
- "subscription", OBJECT_SUBSCRIPTION
- },
- /* OCLASS_TRANSFORM */
- {
- "transform", OBJECT_TRANSFORM
- },
- /* OCLASS_STATISTIC_EXT */
- {
- "statistics object", OBJECT_STATISTIC_EXT
- }
- };
- const ObjectAddress InvalidObjectAddress =
- {
- InvalidOid,
- InvalidOid,
- 0
- };
- static ObjectAddress get_object_address_unqualified(ObjectType objtype,
- Value *strval, bool missing_ok);
- static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
- List *object, Relation *relp,
- LOCKMODE lockmode, bool missing_ok);
- static ObjectAddress get_object_address_relobject(ObjectType objtype,
- List *object, Relation *relp, bool missing_ok);
- static ObjectAddress get_object_address_attribute(ObjectType objtype,
- List *object, Relation *relp,
- LOCKMODE lockmode, bool missing_ok);
- static ObjectAddress get_object_address_attrdef(ObjectType objtype,
- List *object, Relation *relp, LOCKMODE lockmode,
- bool missing_ok);
- static ObjectAddress get_object_address_type(ObjectType objtype,
- TypeName *typename, bool missing_ok);
- static ObjectAddress get_object_address_opcf(ObjectType objtype, List *object,
- bool missing_ok);
- static ObjectAddress get_object_address_opf_member(ObjectType objtype,
- List *object, bool missing_ok);
- static ObjectAddress get_object_address_usermapping(List *object,
- bool missing_ok);
- static ObjectAddress get_object_address_publication_rel(List *object,
- Relation *relp,
- bool missing_ok);
- static ObjectAddress get_object_address_defacl(List *object,
- bool missing_ok);
- static const ObjectPropertyType *get_object_property_data(Oid class_id);
- static void getRelationDescription(StringInfo buffer, Oid relid);
- static void getOpFamilyDescription(StringInfo buffer, Oid opfid);
- static void getRelationTypeDescription(StringInfo buffer, Oid relid,
- int32 objectSubId);
- static void getProcedureTypeDescription(StringInfo buffer, Oid procid);
- static void getConstraintTypeDescription(StringInfo buffer, Oid constroid);
- static void getOpFamilyIdentity(StringInfo buffer, Oid opfid, List **object);
- static void getRelationIdentity(StringInfo buffer, Oid relid, List **object);
- /*
- * Translate an object name and arguments (as passed by the parser) to an
- * ObjectAddress.
- *
- * The returned object will be locked using the specified lockmode. If a
- * sub-object is looked up, the parent object will be locked instead.
- *
- * If the object is a relation or a child object of a relation (e.g. an
- * attribute or constraint), the relation is also opened and *relp receives
- * the open relcache entry pointer; otherwise, *relp is set to NULL. This
- * is a bit grotty but it makes life simpler, since the caller will
- * typically need the relcache entry too. Caller must close the relcache
- * entry when done with it. The relation is locked with the specified lockmode
- * if the target object is the relation itself or an attribute, but for other
- * child objects, only AccessShareLock is acquired on the relation.
- *
- * If the object is not found, an error is thrown, unless missing_ok is
- * true. In this case, no lock is acquired, relp is set to NULL, and the
- * returned address has objectId set to InvalidOid.
- *
- * We don't currently provide a function to release the locks acquired here;
- * typically, the lock must be held until commit to guard against a concurrent
- * drop operation.
- *
- * Note: If the object is not found, we don't give any indication of the
- * reason. (It might have been a missing schema if the name was qualified, or
- * a nonexistent type name in case of a cast, function or operator; etc).
- * Currently there is only one caller that might be interested in such info, so
- * we don't spend much effort here. If more callers start to care, it might be
- * better to add some support for that in this function.
- */
- ObjectAddress
- get_object_address(ObjectType objtype, Node *object,
- Relation *relp, LOCKMODE lockmode, bool missing_ok)
- {
- ObjectAddress address;
- ObjectAddress old_address = {InvalidOid, InvalidOid, 0};
- Relation relation = NULL;
- uint64 inval_count;
- /* Some kind of lock must be taken. */
- Assert(lockmode != NoLock);
- for (;;)
- {
- /*
- * Remember this value, so that, after looking up the object name and
- * locking it, we can check whether any invalidation messages have
- * been processed that might require a do-over.
- */
- inval_count = SharedInvalidMessageCounter;
- /* Look up object address. */
- switch (objtype)
- {
- case OBJECT_INDEX:
- case OBJECT_SEQUENCE:
- case OBJECT_TABLE:
- case OBJECT_VIEW:
- case OBJECT_MATVIEW:
- case OBJECT_FOREIGN_TABLE:
- address =
- get_relation_by_qualified_name(objtype, castNode(List, object),
- &relation, lockmode,
- missing_ok);
- break;
- case OBJECT_COLUMN:
- address =
- get_object_address_attribute(objtype, castNode(List, object),
- &relation, lockmode,
- missing_ok);
- break;
- case OBJECT_DEFAULT:
- address =
- get_object_address_attrdef(objtype, castNode(List, object),
- &relation, lockmode,
- missing_ok);
- break;
- case OBJECT_RULE:
- case OBJECT_TRIGGER:
- case OBJECT_TABCONSTRAINT:
- case OBJECT_POLICY:
- address = get_object_address_relobject(objtype, castNode(List, object),
- &relation, missing_ok);
- break;
- case OBJECT_DOMCONSTRAINT:
- {
- List *objlist;
- ObjectAddress domaddr;
- char *constrname;
- objlist = castNode(List, object);
- domaddr = get_object_address_type(OBJECT_DOMAIN,
- linitial_node(TypeName, objlist),
- missing_ok);
- constrname = strVal(lsecond(objlist));
- address.classId = ConstraintRelationId;
- address.objectId = get_domain_constraint_oid(domaddr.objectId,
- constrname, missing_ok);
- address.objectSubId = 0;
- }
- break;
- case OBJECT_DATABASE:
- case OBJECT_EXTENSION:
- case OBJECT_TABLESPACE:
- case OBJECT_ROLE:
- case OBJECT_SCHEMA:
- case OBJECT_LANGUAGE:
- case OBJECT_FDW:
- case OBJECT_FOREIGN_SERVER:
- case OBJECT_EVENT_TRIGGER:
- case OBJECT_ACCESS_METHOD:
- case OBJECT_PUBLICATION:
- case OBJECT_SUBSCRIPTION:
- address = get_object_address_unqualified(objtype,
- (Value *) object, missing_ok);
- break;
- case OBJECT_TYPE:
- case OBJECT_DOMAIN:
- address = get_object_address_type(objtype, castNode(TypeName, object), missing_ok);
- break;
- case OBJECT_AGGREGATE:
- case OBJECT_FUNCTION:
- case OBJECT_PROCEDURE:
- case OBJECT_ROUTINE:
- address.classId = ProcedureRelationId;
- address.objectId = LookupFuncWithArgs(objtype, castNode(ObjectWithArgs, object), missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_OPERATOR:
- address.classId = OperatorRelationId;
- address.objectId = LookupOperWithArgs(castNode(ObjectWithArgs, object), missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_COLLATION:
- address.classId = CollationRelationId;
- address.objectId = get_collation_oid(castNode(List, object), missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_CONVERSION:
- address.classId = ConversionRelationId;
- address.objectId = get_conversion_oid(castNode(List, object), missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_OPCLASS:
- case OBJECT_OPFAMILY:
- address = get_object_address_opcf(objtype, castNode(List, object), missing_ok);
- break;
- case OBJECT_AMOP:
- case OBJECT_AMPROC:
- address = get_object_address_opf_member(objtype, castNode(List, object), missing_ok);
- break;
- case OBJECT_LARGEOBJECT:
- address.classId = LargeObjectRelationId;
- address.objectId = oidparse(object);
- address.objectSubId = 0;
- if (!LargeObjectExists(address.objectId))
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("large object %u does not exist",
- address.objectId)));
- }
- break;
- case OBJECT_CAST:
- {
- TypeName *sourcetype = linitial_node(TypeName, castNode(List, object));
- TypeName *targettype = lsecond_node(TypeName, castNode(List, object));
- Oid sourcetypeid;
- Oid targettypeid;
- sourcetypeid = LookupTypeNameOid(NULL, sourcetype, missing_ok);
- targettypeid = LookupTypeNameOid(NULL, targettype, missing_ok);
- address.classId = CastRelationId;
- address.objectId =
- get_cast_oid(sourcetypeid, targettypeid, missing_ok);
- address.objectSubId = 0;
- }
- break;
- case OBJECT_TRANSFORM:
- {
- TypeName *typename = linitial_node(TypeName, castNode(List, object));
- char *langname = strVal(lsecond(castNode(List, object)));
- Oid type_id = LookupTypeNameOid(NULL, typename, missing_ok);
- Oid lang_id = get_language_oid(langname, missing_ok);
- address.classId = TransformRelationId;
- address.objectId =
- get_transform_oid(type_id, lang_id, missing_ok);
- address.objectSubId = 0;
- }
- break;
- case OBJECT_TSPARSER:
- address.classId = TSParserRelationId;
- address.objectId = get_ts_parser_oid(castNode(List, object), missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_TSDICTIONARY:
- address.classId = TSDictionaryRelationId;
- address.objectId = get_ts_dict_oid(castNode(List, object), missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_TSTEMPLATE:
- address.classId = TSTemplateRelationId;
- address.objectId = get_ts_template_oid(castNode(List, object), missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_TSCONFIGURATION:
- address.classId = TSConfigRelationId;
- address.objectId = get_ts_config_oid(castNode(List, object), missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_USER_MAPPING:
- address = get_object_address_usermapping(castNode(List, object),
- missing_ok);
- break;
- case OBJECT_PUBLICATION_REL:
- address = get_object_address_publication_rel(castNode(List, object),
- &relation,
- missing_ok);
- break;
- case OBJECT_DEFACL:
- address = get_object_address_defacl(castNode(List, object),
- missing_ok);
- break;
- case OBJECT_STATISTIC_EXT:
- address.classId = StatisticExtRelationId;
- address.objectId = get_statistics_object_oid(castNode(List, object),
- missing_ok);
- address.objectSubId = 0;
- break;
- default:
- elog(ERROR, "unrecognized objtype: %d", (int) objtype);
- /* placate compiler, in case it thinks elog might return */
- address.classId = InvalidOid;
- address.objectId = InvalidOid;
- address.objectSubId = 0;
- }
- /*
- * If we could not find the supplied object, return without locking.
- */
- if (!OidIsValid(address.objectId))
- {
- Assert(missing_ok);
- return address;
- }
- /*
- * If we're retrying, see if we got the same answer as last time. If
- * so, we're done; if not, we locked the wrong thing, so give up our
- * lock.
- */
- if (OidIsValid(old_address.classId))
- {
- if (old_address.classId == address.classId
- && old_address.objectId == address.objectId
- && old_address.objectSubId == address.objectSubId)
- break;
- if (old_address.classId != RelationRelationId)
- {
- if (IsSharedRelation(old_address.classId))
- UnlockSharedObject(old_address.classId,
- old_address.objectId,
- 0, lockmode);
- else
- UnlockDatabaseObject(old_address.classId,
- old_address.objectId,
- 0, lockmode);
- }
- }
- /*
- * If we're dealing with a relation or attribute, then the relation is
- * already locked. Otherwise, we lock it now.
- */
- if (address.classId != RelationRelationId)
- {
- if (IsSharedRelation(address.classId))
- LockSharedObject(address.classId, address.objectId, 0,
- lockmode);
- else
- LockDatabaseObject(address.classId, address.objectId, 0,
- lockmode);
- }
- /*
- * At this point, we've resolved the name to an OID and locked the
- * corresponding database object. However, it's possible that by the
- * time we acquire the lock on the object, concurrent DDL has modified
- * the database in such a way that the name we originally looked up no
- * longer resolves to that OID.
- *
- * We can be certain that this isn't an issue if (a) no shared
- * invalidation messages have been processed or (b) we've locked a
- * relation somewhere along the line. All the relation name lookups
- * in this module ultimately use RangeVarGetRelid() to acquire a
- * relation lock, and that function protects against the same kinds of
- * races we're worried about here. Even when operating on a
- * constraint, rule, or trigger, we still acquire AccessShareLock on
- * the relation, which is enough to freeze out any concurrent DDL.
- *
- * In all other cases, however, it's possible that the name we looked
- * up no longer refers to the object we locked, so we retry the lookup
- * and see whether we get the same answer.
- */
- if (inval_count == SharedInvalidMessageCounter || relation != NULL)
- break;
- old_address = address;
- }
- /* Return the object address and the relation. */
- *relp = relation;
- return address;
- }
- /*
- * Return an ObjectAddress based on a RangeVar and an object name. The
- * name of the relation identified by the RangeVar is prepended to the
- * (possibly empty) list passed in as object. This is useful to find
- * the ObjectAddress of objects that depend on a relation. All other
- * considerations are exactly as for get_object_address above.
- */
- ObjectAddress
- get_object_address_rv(ObjectType objtype, RangeVar *rel, List *object,
- Relation *relp, LOCKMODE lockmode,
- bool missing_ok)
- {
- if (rel)
- {
- object = lcons(makeString(rel->relname), object);
- if (rel->schemaname)
- object = lcons(makeString(rel->schemaname), object);
- if (rel->catalogname)
- object = lcons(makeString(rel->catalogname), object);
- }
- return get_object_address(objtype, (Node *) object,
- relp, lockmode, missing_ok);
- }
- /*
- * Find an ObjectAddress for a type of object that is identified by an
- * unqualified name.
- */
- static ObjectAddress
- get_object_address_unqualified(ObjectType objtype,
- Value *strval, bool missing_ok)
- {
- const char *name;
- ObjectAddress address;
- name = strVal(strval);
- /* Translate name to OID. */
- switch (objtype)
- {
- case OBJECT_ACCESS_METHOD:
- address.classId = AccessMethodRelationId;
- address.objectId = get_am_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_DATABASE:
- address.classId = DatabaseRelationId;
- address.objectId = get_database_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_EXTENSION:
- address.classId = ExtensionRelationId;
- address.objectId = get_extension_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_TABLESPACE:
- address.classId = TableSpaceRelationId;
- address.objectId = get_tablespace_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_ROLE:
- address.classId = AuthIdRelationId;
- address.objectId = get_role_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_SCHEMA:
- address.classId = NamespaceRelationId;
- address.objectId = get_namespace_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_LANGUAGE:
- address.classId = LanguageRelationId;
- address.objectId = get_language_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_FDW:
- address.classId = ForeignDataWrapperRelationId;
- address.objectId = get_foreign_data_wrapper_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_FOREIGN_SERVER:
- address.classId = ForeignServerRelationId;
- address.objectId = get_foreign_server_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_EVENT_TRIGGER:
- address.classId = EventTriggerRelationId;
- address.objectId = get_event_trigger_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_PUBLICATION:
- address.classId = PublicationRelationId;
- address.objectId = get_publication_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_SUBSCRIPTION:
- address.classId = SubscriptionRelationId;
- address.objectId = get_subscription_oid(name, missing_ok);
- address.objectSubId = 0;
- break;
- default:
- elog(ERROR, "unrecognized objtype: %d", (int) objtype);
- /* placate compiler, which doesn't know elog won't return */
- address.classId = InvalidOid;
- address.objectId = InvalidOid;
- address.objectSubId = 0;
- }
- return address;
- }
- /*
- * Locate a relation by qualified name.
- */
- static ObjectAddress
- get_relation_by_qualified_name(ObjectType objtype, List *object,
- Relation *relp, LOCKMODE lockmode,
- bool missing_ok)
- {
- Relation relation;
- ObjectAddress address;
- address.classId = RelationRelationId;
- address.objectId = InvalidOid;
- address.objectSubId = 0;
- relation = relation_openrv_extended(makeRangeVarFromNameList(object),
- lockmode, missing_ok);
- if (!relation)
- return address;
- switch (objtype)
- {
- case OBJECT_INDEX:
- if (relation->rd_rel->relkind != RELKIND_INDEX &&
- relation->rd_rel->relkind != RELKIND_PARTITIONED_INDEX)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not an index",
- RelationGetRelationName(relation))));
- break;
- case OBJECT_SEQUENCE:
- if (relation->rd_rel->relkind != RELKIND_SEQUENCE)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a sequence",
- RelationGetRelationName(relation))));
- break;
- case OBJECT_TABLE:
- if (relation->rd_rel->relkind != RELKIND_RELATION &&
- relation->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a table",
- RelationGetRelationName(relation))));
- break;
- case OBJECT_VIEW:
- if (relation->rd_rel->relkind != RELKIND_VIEW)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a view",
- RelationGetRelationName(relation))));
- break;
- case OBJECT_MATVIEW:
- if (relation->rd_rel->relkind != RELKIND_MATVIEW)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a materialized view",
- RelationGetRelationName(relation))));
- break;
- case OBJECT_FOREIGN_TABLE:
- if (relation->rd_rel->relkind != RELKIND_FOREIGN_TABLE)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a foreign table",
- RelationGetRelationName(relation))));
- break;
- default:
- elog(ERROR, "unrecognized objtype: %d", (int) objtype);
- break;
- }
- /* Done. */
- address.objectId = RelationGetRelid(relation);
- *relp = relation;
- return address;
- }
- /*
- * Find object address for an object that is attached to a relation.
- *
- * Note that we take only an AccessShareLock on the relation. We need not
- * pass down the LOCKMODE from get_object_address(), because that is the lock
- * mode for the object itself, not the relation to which it is attached.
- */
- static ObjectAddress
- get_object_address_relobject(ObjectType objtype, List *object,
- Relation *relp, bool missing_ok)
- {
- ObjectAddress address;
- Relation relation = NULL;
- int nnames;
- const char *depname;
- List *relname;
- Oid reloid;
- /* Extract name of dependent object. */
- depname = strVal(llast(object));
- /* Separate relation name from dependent object name. */
- nnames = list_length(object);
- if (nnames < 2)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("must specify relation and object name")));
- /* Extract relation name and open relation. */
- relname = list_truncate(list_copy(object), nnames - 1);
- relation = table_openrv_extended(makeRangeVarFromNameList(relname),
- AccessShareLock,
- missing_ok);
- reloid = relation ? RelationGetRelid(relation) : InvalidOid;
- switch (objtype)
- {
- case OBJECT_RULE:
- address.classId = RewriteRelationId;
- address.objectId = relation ?
- get_rewrite_oid(reloid, depname, missing_ok) : InvalidOid;
- address.objectSubId = 0;
- break;
- case OBJECT_TRIGGER:
- address.classId = TriggerRelationId;
- address.objectId = relation ?
- get_trigger_oid(reloid, depname, missing_ok) : InvalidOid;
- address.objectSubId = 0;
- break;
- case OBJECT_TABCONSTRAINT:
- address.classId = ConstraintRelationId;
- address.objectId = relation ?
- get_relation_constraint_oid(reloid, depname, missing_ok) :
- InvalidOid;
- address.objectSubId = 0;
- break;
- case OBJECT_POLICY:
- address.classId = PolicyRelationId;
- address.objectId = relation ?
- get_relation_policy_oid(reloid, depname, missing_ok) :
- InvalidOid;
- address.objectSubId = 0;
- break;
- default:
- elog(ERROR, "unrecognized objtype: %d", (int) objtype);
- }
- /* Avoid relcache leak when object not found. */
- if (!OidIsValid(address.objectId))
- {
- if (relation != NULL)
- table_close(relation, AccessShareLock);
- relation = NULL; /* department of accident prevention */
- return address;
- }
- /* Done. */
- *relp = relation;
- return address;
- }
- /*
- * Find the ObjectAddress for an attribute.
- */
- static ObjectAddress
- get_object_address_attribute(ObjectType objtype, List *object,
- Relation *relp, LOCKMODE lockmode,
- bool missing_ok)
- {
- ObjectAddress address;
- List *relname;
- Oid reloid;
- Relation relation;
- const char *attname;
- AttrNumber attnum;
- /* Extract relation name and open relation. */
- if (list_length(object) < 2)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("column name must be qualified")));
- attname = strVal(lfirst(list_tail(object)));
- relname = list_truncate(list_copy(object), list_length(object) - 1);
- /* XXX no missing_ok support here */
- relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
- reloid = RelationGetRelid(relation);
- /* Look up attribute and construct return value. */
- attnum = get_attnum(reloid, attname);
- if (attnum == InvalidAttrNumber)
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("column \"%s\" of relation \"%s\" does not exist",
- attname, NameListToString(relname))));
- address.classId = RelationRelationId;
- address.objectId = InvalidOid;
- address.objectSubId = InvalidAttrNumber;
- relation_close(relation, lockmode);
- return address;
- }
- address.classId = RelationRelationId;
- address.objectId = reloid;
- address.objectSubId = attnum;
- *relp = relation;
- return address;
- }
- /*
- * Find the ObjectAddress for an attribute's default value.
- */
- static ObjectAddress
- get_object_address_attrdef(ObjectType objtype, List *object,
- Relation *relp, LOCKMODE lockmode,
- bool missing_ok)
- {
- ObjectAddress address;
- List *relname;
- Oid reloid;
- Relation relation;
- const char *attname;
- AttrNumber attnum;
- TupleDesc tupdesc;
- Oid defoid;
- /* Extract relation name and open relation. */
- if (list_length(object) < 2)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("column name must be qualified")));
- attname = strVal(llast(object));
- relname = list_truncate(list_copy(object), list_length(object) - 1);
- /* XXX no missing_ok support here */
- relation = relation_openrv(makeRangeVarFromNameList(relname), lockmode);
- reloid = RelationGetRelid(relation);
- tupdesc = RelationGetDescr(relation);
- /* Look up attribute number and scan pg_attrdef to find its tuple */
- attnum = get_attnum(reloid, attname);
- defoid = InvalidOid;
- if (attnum != InvalidAttrNumber && tupdesc->constr != NULL)
- {
- Relation attrdef;
- ScanKeyData keys[2];
- SysScanDesc scan;
- HeapTuple tup;
- attrdef = relation_open(AttrDefaultRelationId, AccessShareLock);
- ScanKeyInit(&keys[0],
- Anum_pg_attrdef_adrelid,
- BTEqualStrategyNumber,
- F_OIDEQ,
- ObjectIdGetDatum(reloid));
- ScanKeyInit(&keys[1],
- Anum_pg_attrdef_adnum,
- BTEqualStrategyNumber,
- F_INT2EQ,
- Int16GetDatum(attnum));
- scan = systable_beginscan(attrdef, AttrDefaultIndexId, true,
- NULL, 2, keys);
- if (HeapTupleIsValid(tup = systable_getnext(scan)))
- {
- Form_pg_attrdef atdform = (Form_pg_attrdef) GETSTRUCT(tup);
- defoid = atdform->oid;
- }
- systable_endscan(scan);
- relation_close(attrdef, AccessShareLock);
- }
- if (!OidIsValid(defoid))
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_COLUMN),
- errmsg("default value for column \"%s\" of relation \"%s\" does not exist",
- attname, NameListToString(relname))));
- address.classId = AttrDefaultRelationId;
- address.objectId = InvalidOid;
- address.objectSubId = InvalidAttrNumber;
- relation_close(relation, lockmode);
- return address;
- }
- address.classId = AttrDefaultRelationId;
- address.objectId = defoid;
- address.objectSubId = 0;
- *relp = relation;
- return address;
- }
- /*
- * Find the ObjectAddress for a type or domain
- */
- static ObjectAddress
- get_object_address_type(ObjectType objtype, TypeName *typename, bool missing_ok)
- {
- ObjectAddress address;
- Type tup;
- address.classId = TypeRelationId;
- address.objectId = InvalidOid;
- address.objectSubId = 0;
- tup = LookupTypeName(NULL, typename, NULL, missing_ok);
- if (!HeapTupleIsValid(tup))
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("type \"%s\" does not exist",
- TypeNameToString(typename))));
- return address;
- }
- address.objectId = typeTypeId(tup);
- if (objtype == OBJECT_DOMAIN)
- {
- if (((Form_pg_type) GETSTRUCT(tup))->typtype != TYPTYPE_DOMAIN)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a domain",
- TypeNameToString(typename))));
- }
- ReleaseSysCache(tup);
- return address;
- }
- /*
- * Find the ObjectAddress for an opclass or opfamily.
- */
- static ObjectAddress
- get_object_address_opcf(ObjectType objtype, List *object, bool missing_ok)
- {
- Oid amoid;
- ObjectAddress address;
- /* XXX no missing_ok support here */
- amoid = get_index_am_oid(strVal(linitial(object)), false);
- object = list_copy_tail(object, 1);
- switch (objtype)
- {
- case OBJECT_OPCLASS:
- address.classId = OperatorClassRelationId;
- address.objectId = get_opclass_oid(amoid, object, missing_ok);
- address.objectSubId = 0;
- break;
- case OBJECT_OPFAMILY:
- address.classId = OperatorFamilyRelationId;
- address.objectId = get_opfamily_oid(amoid, object, missing_ok);
- address.objectSubId = 0;
- break;
- default:
- elog(ERROR, "unrecognized objtype: %d", (int) objtype);
- /* placate compiler, which doesn't know elog won't return */
- address.classId = InvalidOid;
- address.objectId = InvalidOid;
- address.objectSubId = 0;
- }
- return address;
- }
- /*
- * Find the ObjectAddress for an opclass/opfamily member.
- *
- * (The returned address corresponds to a pg_amop/pg_amproc object).
- */
- static ObjectAddress
- get_object_address_opf_member(ObjectType objtype,
- List *object, bool missing_ok)
- {
- ObjectAddress famaddr;
- ObjectAddress address;
- ListCell *cell;
- List *copy;
- TypeName *typenames[2];
- Oid typeoids[2];
- int membernum;
- int i;
- /*
- * The last element of the object list contains the strategy or procedure
- * number. We need to strip that out before getting the opclass/family
- * address. The rest can be used directly by get_object_address_opcf().
- */
- membernum = atoi(strVal(llast(linitial(object))));
- copy = list_truncate(list_copy(linitial(object)), list_length(linitial(object)) - 1);
- /* no missing_ok support here */
- famaddr = get_object_address_opcf(OBJECT_OPFAMILY, copy, false);
- /* find out left/right type names and OIDs */
- typenames[0] = typenames[1] = NULL;
- typeoids[0] = typeoids[1] = InvalidOid;
- i = 0;
- foreach(cell, lsecond(object))
- {
- ObjectAddress typaddr;
- typenames[i] = lfirst_node(TypeName, cell);
- typaddr = get_object_address_type(OBJECT_TYPE, typenames[i], missing_ok);
- typeoids[i] = typaddr.objectId;
- if (++i >= 2)
- break;
- }
- switch (objtype)
- {
- case OBJECT_AMOP:
- {
- HeapTuple tp;
- ObjectAddressSet(address, AccessMethodOperatorRelationId,
- InvalidOid);
- tp = SearchSysCache4(AMOPSTRATEGY,
- ObjectIdGetDatum(famaddr.objectId),
- ObjectIdGetDatum(typeoids[0]),
- ObjectIdGetDatum(typeoids[1]),
- Int16GetDatum(membernum));
- if (!HeapTupleIsValid(tp))
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("operator %d (%s, %s) of %s does not exist",
- membernum,
- TypeNameToString(typenames[0]),
- TypeNameToString(typenames[1]),
- getObjectDescription(&famaddr))));
- }
- else
- {
- address.objectId = ((Form_pg_amop) GETSTRUCT(tp))->oid;
- ReleaseSysCache(tp);
- }
- }
- break;
- case OBJECT_AMPROC:
- {
- HeapTuple tp;
- ObjectAddressSet(address, AccessMethodProcedureRelationId,
- InvalidOid);
- tp = SearchSysCache4(AMPROCNUM,
- ObjectIdGetDatum(famaddr.objectId),
- ObjectIdGetDatum(typeoids[0]),
- ObjectIdGetDatum(typeoids[1]),
- Int16GetDatum(membernum));
- if (!HeapTupleIsValid(tp))
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("function %d (%s, %s) of %s does not exist",
- membernum,
- TypeNameToString(typenames[0]),
- TypeNameToString(typenames[1]),
- getObjectDescription(&famaddr))));
- }
- else
- {
- address.objectId = ((Form_pg_amproc) GETSTRUCT(tp))->oid;
- ReleaseSysCache(tp);
- }
- }
- break;
- default:
- elog(ERROR, "unrecognized objtype: %d", (int) objtype);
- }
- return address;
- }
- /*
- * Find the ObjectAddress for a user mapping.
- */
- static ObjectAddress
- get_object_address_usermapping(List *object, bool missing_ok)
- {
- ObjectAddress address;
- Oid userid;
- char *username;
- char *servername;
- ForeignServer *server;
- HeapTuple tp;
- ObjectAddressSet(address, UserMappingRelationId, InvalidOid);
- /* fetch string names from input lists, for error messages */
- username = strVal(linitial(object));
- servername = strVal(lsecond(object));
- /* look up pg_authid OID of mapped user; InvalidOid if PUBLIC */
- if (strcmp(username, "public") == 0)
- userid = InvalidOid;
- else
- {
- tp = SearchSysCache1(AUTHNAME,
- CStringGetDatum(username));
- if (!HeapTupleIsValid(tp))
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
- username, servername)));
- return address;
- }
- userid = ((Form_pg_authid) GETSTRUCT(tp))->oid;
- ReleaseSysCache(tp);
- }
- /* Now look up the pg_user_mapping tuple */
- server = GetForeignServerByName(servername, true);
- if (!server)
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("server \"%s\" does not exist", servername)));
- return address;
- }
- tp = SearchSysCache2(USERMAPPINGUSERSERVER,
- ObjectIdGetDatum(userid),
- ObjectIdGetDatum(server->serverid));
- if (!HeapTupleIsValid(tp))
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("user mapping for user \"%s\" on server \"%s\" does not exist",
- username, servername)));
- return address;
- }
- address.objectId = ((Form_pg_user_mapping) GETSTRUCT(tp))->oid;
- ReleaseSysCache(tp);
- return address;
- }
- /*
- * Find the ObjectAddress for a publication relation. The first element of
- * the object parameter is the relation name, the second is the
- * publication name.
- */
- static ObjectAddress
- get_object_address_publication_rel(List *object,
- Relation *relp, bool missing_ok)
- {
- ObjectAddress address;
- Relation relation;
- List *relname;
- char *pubname;
- Publication *pub;
- ObjectAddressSet(address, PublicationRelRelationId, InvalidOid);
- relname = linitial(object);
- relation = relation_openrv_extended(makeRangeVarFromNameList(relname),
- AccessShareLock, missing_ok);
- if (!relation)
- return address;
- /* fetch publication name from input list */
- pubname = strVal(lsecond(object));
- /* Now look up the pg_publication tuple */
- pub = GetPublicationByName(pubname, missing_ok);
- if (!pub)
- {
- relation_close(relation, AccessShareLock);
- return address;
- }
- /* Find the publication relation mapping in syscache. */
- address.objectId =
- GetSysCacheOid2(PUBLICATIONRELMAP, Anum_pg_publication_rel_oid,
- ObjectIdGetDatum(RelationGetRelid(relation)),
- ObjectIdGetDatum(pub->oid));
- if (!OidIsValid(address.objectId))
- {
- if (!missing_ok)
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("publication relation \"%s\" in publication \"%s\" does not exist",
- RelationGetRelationName(relation), pubname)));
- relation_close(relation, AccessShareLock);
- return address;
- }
- *relp = relation;
- return address;
- }
- /*
- * Find the ObjectAddress for a default ACL.
- */
- static ObjectAddress
- get_object_address_defacl(List *object, 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(lsecond(object));
- if (list_length(object) >= 3)
- schema = (char *) strVal(lthird(object));
- else
- schema = NULL;
- /*
- * Decode defaclobjtype. Only first char is considered; the rest of the
- * string, if any, is blissfully ignored.
- */
- objtype = ((char *) strVal(linitial(object)))[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;
- case DEFACLOBJ_NAMESPACE:
- objtype_str = "schemas";
- break;
- default:
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("unrecognized default ACL object type \"%c\"", objtype),
- errhint("Valid object types are \"%c\", \"%c\", \"%c\", \"%c\", \"%c\".",
- DEFACLOBJ_RELATION,
- DEFACLOBJ_SEQUENCE,
- DEFACLOBJ_FUNCTION,
- DEFACLOBJ_TYPE,
- DEFACLOBJ_NAMESPACE)));
- }
- /*
- * Look up user ID. Behave as "default ACL not found" if the user doesn't
- * exist.
- */
- tp = SearchSysCache1(AUTHNAME,
- CStringGetDatum(username));
- if (!HeapTupleIsValid(tp))
- …
Large files files are truncated, but you can click here to view the full file