src/backend/catalog/objectaddress.c | 613 +++++++++++++++++++++++++++++------ src/include/catalog/objectaddress.h | 13 + 2 files changed, 534 insertions(+), 92 deletions(-) diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 8feb601..2250058 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -82,6 +82,425 @@ static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname, List *objargs, bool missing_ok); static bool object_exists(ObjectAddress address); +/* + * ObjectProperty + * + * This array provides a common part of system object structure; to help + * consolidate routines to handle various kind of object classes. + */ +typedef struct +{ + ObjectType objtype; /* OBJECT_* defined at parsenodes.h */ + const char *objtype_text; /* text name of the object type */ + Oid class_id; /* Oid of catalog */ + Oid index_id; /* Oid of index to lookup by oid */ + int cacheid_by_oid; /* cache id to lookup by oid */ + int cacheid_by_name; /* cache id to lookup by name + schema */ + AttrNumber attnum_name; /* attnum of name field */ + AttrNumber attnum_namespace; /* attnum of namespace field */ + AttrNumber attnum_owner; /* attnum of owner field */ + AttrNumber attnum_relid; /* attnum of relid field */ +} ObjectPropertyType; + +static ObjectPropertyType ObjectProperty[] = +{ + { + OBJECT_AGGREGATE, + "aggregate", + ProcedureRelationId, + ProcedureOidIndexId, + PROCOID, + -1, + Anum_pg_proc_proname, + Anum_pg_proc_pronamespace, + Anum_pg_proc_proowner, + InvalidAttrNumber, + }, + { + OBJECT_ATTRIBUTE, + "attribute", + AttributeRelationId, + AttributeRelidNumIndexId, + ATTNUM, + -1, + Anum_pg_attribute_attname, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_attribute_attrelid, + }, + { + OBJECT_CAST, + "cast", + CastRelationId, + CastOidIndexId, + -1, + -1, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + }, + { + OBJECT_COLUMN, + "column", + AttributeRelationId, + AttributeRelidNumIndexId, + ATTNUM, + -1, + Anum_pg_attribute_attname, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_attribute_attrelid, + }, + { + OBJECT_CONSTRAINT, + "constraint", + ConstraintRelationId, + ConstraintOidIndexId, + CONSTROID, + -1, + Anum_pg_constraint_conname, + Anum_pg_constraint_connamespace, + InvalidAttrNumber, + Anum_pg_constraint_conrelid, + }, + { + OBJECT_COLLATION, + "collation", + CollationRelationId, + CollationOidIndexId, + COLLOID, + -1, + Anum_pg_collation_collname, + Anum_pg_collation_collnamespace, + Anum_pg_collation_collowner, + InvalidAttrNumber, + }, + { + OBJECT_CONVERSION, + "conversion", + ConversionRelationId, + ConversionOidIndexId, + CONVOID, + CONNAMENSP, + Anum_pg_conversion_conname, + Anum_pg_conversion_connamespace, + Anum_pg_conversion_conowner, + InvalidAttrNumber, + }, + { + OBJECT_DATABASE, + "database", + DatabaseRelationId, + DatabaseOidIndexId, + DATABASEOID, + -1, + Anum_pg_database_datname, + InvalidAttrNumber, + Anum_pg_database_datdba, + InvalidAttrNumber, + }, + { + OBJECT_DOMAIN, + "domain", + TypeRelationId, + TypeOidIndexId, + TYPEOID, + TYPENAMENSP, + Anum_pg_type_typname, + Anum_pg_type_typnamespace, + Anum_pg_type_typowner, + InvalidAttrNumber, + }, + { + OBJECT_EXTENSION, + "extension", + ExtensionRelationId, + ExtensionOidIndexId, + -1, + -1, + Anum_pg_extension_extname, + Anum_pg_extension_extnamespace, + Anum_pg_extension_extowner, + InvalidAttrNumber, + }, + { + OBJECT_FDW, + "foreign-data wrapper", + ForeignDataWrapperRelationId, + ForeignDataWrapperOidIndexId, + FOREIGNDATAWRAPPEROID, + FOREIGNDATAWRAPPERNAME, + Anum_pg_foreign_data_wrapper_fdwname, + InvalidAttrNumber, + Anum_pg_foreign_data_wrapper_fdwowner, + InvalidAttrNumber, + }, + { + OBJECT_FOREIGN_SERVER, + "server", + ForeignServerRelationId, + ForeignServerOidIndexId, + FOREIGNSERVEROID, + FOREIGNSERVERNAME, + Anum_pg_foreign_server_srvname, + InvalidAttrNumber, + Anum_pg_foreign_server_srvowner, + InvalidAttrNumber, + }, + { + OBJECT_FOREIGN_TABLE, + "foreign table", + RelationRelationId, + ClassOidIndexId, + RELOID, + RELNAMENSP, + Anum_pg_class_relname, + Anum_pg_class_relnamespace, + Anum_pg_class_relowner, + InvalidAttrNumber, + }, + { + OBJECT_FUNCTION, + "function", + ProcedureRelationId, + ProcedureOidIndexId, + PROCOID, + -1, + Anum_pg_proc_proname, + Anum_pg_proc_pronamespace, + Anum_pg_proc_proowner, + InvalidAttrNumber, + }, + { + OBJECT_INDEX, + "index", + RelationRelationId, + ClassOidIndexId, + RELOID, + RELNAMENSP, + Anum_pg_class_relname, + Anum_pg_class_relnamespace, + Anum_pg_class_relowner, + InvalidAttrNumber, + }, + { + OBJECT_LANGUAGE, + "language", + LanguageRelationId, + LanguageOidIndexId, + LANGOID, + LANGNAME, + Anum_pg_language_lanname, + InvalidAttrNumber, + Anum_pg_language_lanowner, + InvalidAttrNumber, + }, + { + OBJECT_LARGEOBJECT, + "large object", + LargeObjectMetadataRelationId, + LargeObjectMetadataOidIndexId, + -1, + -1, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_largeobject_metadata_lomowner, + InvalidAttrNumber, + }, + { + OBJECT_OPCLASS, + "operator class", + OperatorClassRelationId, + OpclassOidIndexId, + CLAOID, + -1, + Anum_pg_opclass_opcname, + Anum_pg_opclass_opcnamespace, + Anum_pg_opclass_opcowner, + InvalidAttrNumber, + }, + { + OBJECT_OPERATOR, + "operator", + OperatorRelationId, + OperatorOidIndexId, + OPEROID, + OPERNAMENSP, + Anum_pg_operator_oprname, + Anum_pg_operator_oprnamespace, + Anum_pg_operator_oprowner, + InvalidAttrNumber, + }, + { + OBJECT_OPFAMILY, + "operator family", + OperatorFamilyRelationId, + OpfamilyOidIndexId, + OPFAMILYOID, + -1, + Anum_pg_opfamily_opfname, + Anum_pg_opfamily_opfnamespace, + Anum_pg_opfamily_opfowner, + InvalidAttrNumber, + }, + { + OBJECT_ROLE, + "role", + AuthIdRelationId, + AuthIdOidIndexId, + AUTHOID, + AUTHNAME, + Anum_pg_authid_rolname, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + }, + { + OBJECT_RULE, + "rule", + RewriteRelationId, + RewriteOidIndexId, + -1, + RULERELNAME, + Anum_pg_rewrite_ev_class, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_rewrite_ev_class, + }, + { + OBJECT_SCHEMA, + "schema", + NamespaceRelationId, + NamespaceOidIndexId, + NAMESPACEOID, + NAMESPACENAME, + Anum_pg_namespace_nspname, + InvalidAttrNumber, + Anum_pg_namespace_nspowner, + InvalidAttrNumber, + }, + { + OBJECT_SEQUENCE, + "sequence", + RelationRelationId, + ClassOidIndexId, + RELOID, + RELNAMENSP, + Anum_pg_class_relname, + Anum_pg_class_relnamespace, + Anum_pg_class_relowner, + InvalidAttrNumber, + }, + { + OBJECT_TABLE, + "table", + RelationRelationId, + ClassOidIndexId, + RELOID, + RELNAMENSP, + Anum_pg_class_relname, + Anum_pg_class_relnamespace, + Anum_pg_class_relowner, + InvalidAttrNumber, + }, + { + OBJECT_TABLESPACE, + "tablespace", + TableSpaceRelationId, + TablespaceOidIndexId, + -1, + -1, + Anum_pg_tablespace_spcname, + InvalidAttrNumber, + Anum_pg_tablespace_spcowner, + InvalidAttrNumber, + }, + { + OBJECT_TRIGGER, + "trigger", + TriggerRelationId, + TriggerOidIndexId, + -1, + -1, + Anum_pg_trigger_tgname, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_trigger_tgrelid, + }, + { + OBJECT_TSCONFIGURATION, + "text search configuration", + TSConfigRelationId, + TSConfigOidIndexId, + TSCONFIGOID, + TSCONFIGNAMENSP, + Anum_pg_ts_config_cfgname, + Anum_pg_ts_config_cfgnamespace, + Anum_pg_ts_config_cfgowner, + InvalidAttrNumber, + }, + { + OBJECT_TSDICTIONARY, + "text search dictionary", + TSDictionaryRelationId, + TSDictionaryOidIndexId, + TSDICTOID, + TSDICTNAMENSP, + Anum_pg_ts_dict_dictname, + Anum_pg_ts_dict_dictnamespace, + Anum_pg_ts_dict_dictowner, + InvalidAttrNumber, + }, + { + OBJECT_TSPARSER, + "text search parser", + TSParserRelationId, + TSParserOidIndexId, + TSPARSEROID, + TSPARSERNAMENSP, + Anum_pg_ts_parser_prsname, + Anum_pg_ts_parser_prsnamespace, + InvalidAttrNumber, + InvalidAttrNumber, + }, + { + OBJECT_TSTEMPLATE, + "text search template", + TSTemplateRelationId, + TSTemplateOidIndexId, + TSTEMPLATEOID, + TSTEMPLATENAMENSP, + Anum_pg_ts_template_tmplname, + Anum_pg_ts_template_tmplnamespace, + InvalidAttrNumber, + InvalidAttrNumber, + }, + { + OBJECT_TYPE, + "type", + TypeRelationId, + TypeOidIndexId, + TYPEOID, + TYPENAMENSP, + Anum_pg_type_typname, + Anum_pg_type_typnamespace, + Anum_pg_type_typowner, + InvalidAttrNumber, + }, + { + OBJECT_VIEW, + "view", + RelationRelationId, + ClassOidIndexId, + RELOID, + RELNAMENSP, + Anum_pg_class_relname, + Anum_pg_class_relnamespace, + Anum_pg_class_relowner, + InvalidAttrNumber, + }, +}; /* * Translate an object name and arguments (as passed by the parser) to an @@ -667,11 +1086,85 @@ get_object_address_opcf(ObjectType objtype, } /* + * Returns property of the supplied object type + */ +static ObjectPropertyType * +get_object_property(ObjectType objtype) +{ + int index; + + for (index = 0; index < lengthof(ObjectProperty); index++) + { + if (ObjectProperty[index].objtype == objtype) + return &ObjectProperty[index]; + + } + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return NULL; /* be compiler quiet */ +} + + +const char * +get_object_property_typetext(ObjectType objtype) +{ + return get_object_property(objtype)->objtype_text; +} + +Oid +get_object_property_class_id(ObjectType objtype) +{ + return get_object_property(objtype)->class_id; +} + +Oid +get_object_property_index_id(ObjectType objtype) +{ + return get_object_property(objtype)->index_id; +} + +int +get_object_property_catid_by_oid(ObjectType objtype) +{ + return get_object_property(objtype)->cacheid_by_oid; +} + +int +get_object_property_catid_by_name(ObjectType objtype) +{ + return get_object_property(objtype)->cacheid_by_name; +} + +AttrNumber +get_object_property_attnum_name(ObjectType objtype) +{ + return get_object_property(objtype)->attnum_name; +} + +AttrNumber +get_object_property_attnum_namespace(ObjectType objtype) +{ + return get_object_property(objtype)->attnum_namespace; +} + +AttrNumber +get_object_property_attnum_owner(ObjectType objtype) +{ + return get_object_property(objtype)->attnum_owner; +} + +AttrNumber +get_object_property_attnum_relid(ObjectType objtype) +{ + return get_object_property(objtype)->attnum_relid; +} + +/* * Test whether an object exists. */ static bool object_exists(ObjectAddress address) { + int index; int cache = -1; Oid indexoid = InvalidOid; Relation rel; @@ -697,99 +1190,35 @@ object_exists(ObjectAddress address) } return found; } - - /* - * For object types that have a relevant syscache, we use it; for - * everything else, we'll have to do an index-scan. This switch sets - * either the cache to be used for the syscache lookup, or the index to be - * used for the index scan. - */ - switch (address.classId) + else if (address.classId == LargeObjectRelationId) { - case RelationRelationId: - cache = RELOID; - break; - case RewriteRelationId: - indexoid = RewriteOidIndexId; - break; - case TriggerRelationId: - indexoid = TriggerOidIndexId; - break; - case ConstraintRelationId: - cache = CONSTROID; - break; - case DatabaseRelationId: - cache = DATABASEOID; - break; - case TableSpaceRelationId: - cache = TABLESPACEOID; - break; - case AuthIdRelationId: - cache = AUTHOID; - break; - case NamespaceRelationId: - cache = NAMESPACEOID; - break; - case LanguageRelationId: - cache = LANGOID; - break; - case TypeRelationId: - cache = TYPEOID; - break; - case ProcedureRelationId: - cache = PROCOID; - break; - case OperatorRelationId: - cache = OPEROID; - break; - case CollationRelationId: - cache = COLLOID; - break; - case ConversionRelationId: - cache = CONVOID; - break; - case OperatorClassRelationId: - cache = CLAOID; - break; - case OperatorFamilyRelationId: - cache = OPFAMILYOID; - break; - case LargeObjectRelationId: - - /* - * Weird backward compatibility hack: ObjectAddress notation uses - * LargeObjectRelationId for large objects, but since PostgreSQL - * 9.0, the relevant catalog is actually - * LargeObjectMetadataRelationId. - */ - address.classId = LargeObjectMetadataRelationId; - indexoid = LargeObjectMetadataOidIndexId; - break; - case CastRelationId: - indexoid = CastOidIndexId; - break; - case ForeignDataWrapperRelationId: - cache = FOREIGNDATAWRAPPEROID; - break; - case ForeignServerRelationId: - cache = FOREIGNSERVEROID; - break; - case TSParserRelationId: - cache = TSPARSEROID; - break; - case TSDictionaryRelationId: - cache = TSDICTOID; - break; - case TSTemplateRelationId: - cache = TSTEMPLATEOID; - break; - case TSConfigRelationId: - cache = TSCONFIGOID; - break; - case ExtensionRelationId: - indexoid = ExtensionOidIndexId; - break; - default: + /* + * Weird backward compatibility hack: ObjectAddress notation uses + * LargeObjectRelationId for large objects, but since PostgreSQL + * 9.0, the relevant catalog is actually + * LargeObjectMetadataRelationId. + */ + address.classId = LargeObjectMetadataRelationId; + indexoid = LargeObjectMetadataOidIndexId; + } + else + { + /* + * For object types that have a relevant syscache, we use it; for + * everything else, we'll have to do an index-scan. This switch sets + * either the cache to be used for the syscache lookup, or the index + * to be used for the index scan. + */ + for (index = 0; index < lengthof(ObjectProperty); index++) + { + if (ObjectProperty[index].class_id == address.classId) + { + cache = ObjectProperty[index].cacheid_by_oid; + indexoid = ObjectProperty[index].index_id; + break; + } + } + if (index == lengthof(ObjectProperty)) elog(ERROR, "unrecognized classid: %u", address.classId); } diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h index 2da6309..9ad2490 100644 --- a/src/include/catalog/objectaddress.h +++ b/src/include/catalog/objectaddress.h @@ -35,4 +35,17 @@ extern void check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address, List *objname, List *objargs, Relation relation); +/* + * Obtain property of object type + */ +extern const char *get_object_property_typetext(ObjectType objtype); +extern Oid get_object_property_class_id(ObjectType objtype); +extern Oid get_object_property_index_id(ObjectType objtype); +extern int get_object_property_catid_by_oid(ObjectType objtype); +extern int get_object_property_catid_by_name(ObjectType objtype); +extern AttrNumber get_object_property_attnum_name(ObjectType objtype); +extern AttrNumber get_object_property_attnum_namespace(ObjectType objtype); +extern AttrNumber get_object_property_attnum_owner(ObjectType objtype); +extern AttrNumber get_object_property_attnum_relid(ObjectType objtype); + #endif /* PARSE_OBJECT_H */