src/backend/catalog/objectaddress.c | 653 ++++++++++++++++++++++++++++++----- src/include/catalog/objectaddress.h | 13 + src/include/nodes/parsenodes.h | 2 +- 3 files changed, 575 insertions(+), 93 deletions(-) diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index 8feb601..6094146 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -82,6 +82,463 @@ static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname, List *objargs, bool missing_ok); static bool object_exists(ObjectAddress address); +/* + * CatalogProperty + * + * It provides hint to the structure of corresponding system catalogs. + */ +typedef struct +{ + 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 */ +} CatalogProperty; + +static CatalogProperty prop_pg_attribute = { + AttributeRelationId, + AttributeRelidNumIndexId, + ATTNUM, + -1, + Anum_pg_attribute_attname, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_attribute_attrelid, +}; +static CatalogProperty prop_pg_authid = { + AuthIdRelationId, + AuthIdOidIndexId, + AUTHOID, + AUTHNAME, + Anum_pg_authid_rolname, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_cast = { + CastRelationId, + CastOidIndexId, + -1, + -1, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_class = { + RelationRelationId, + ClassOidIndexId, + RELOID, + RELNAMENSP, + Anum_pg_class_relname, + Anum_pg_class_relnamespace, + Anum_pg_class_relowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_constraint = { + ConstraintRelationId, + ConstraintOidIndexId, + CONSTROID, + -1, + Anum_pg_constraint_conname, + Anum_pg_constraint_connamespace, + InvalidAttrNumber, + Anum_pg_constraint_conrelid, +}; +static CatalogProperty prop_pg_collation = { + CollationRelationId, + CollationOidIndexId, + COLLOID, + -1, + Anum_pg_collation_collname, + Anum_pg_collation_collnamespace, + Anum_pg_collation_collowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_conversion = { + ConversionRelationId, + ConversionOidIndexId, + CONVOID, + CONNAMENSP, + Anum_pg_conversion_conname, + Anum_pg_conversion_connamespace, + Anum_pg_conversion_conowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_database = { + DatabaseRelationId, + DatabaseOidIndexId, + DATABASEOID, + -1, + Anum_pg_database_datname, + InvalidAttrNumber, + Anum_pg_database_datdba, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_extension = { + ExtensionRelationId, + ExtensionOidIndexId, + -1, + -1, + Anum_pg_extension_extname, + Anum_pg_extension_extnamespace, + Anum_pg_extension_extowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_foreign_data_wrapper = { + ForeignDataWrapperRelationId, + ForeignDataWrapperOidIndexId, + FOREIGNDATAWRAPPEROID, + FOREIGNDATAWRAPPERNAME, + Anum_pg_foreign_data_wrapper_fdwname, + InvalidAttrNumber, + Anum_pg_foreign_data_wrapper_fdwowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_foreign_server = { + ForeignServerRelationId, + ForeignServerOidIndexId, + FOREIGNSERVEROID, + FOREIGNSERVERNAME, + Anum_pg_foreign_server_srvname, + InvalidAttrNumber, + Anum_pg_foreign_server_srvowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_language = { + LanguageRelationId, + LanguageOidIndexId, + LANGOID, + LANGNAME, + Anum_pg_language_lanname, + InvalidAttrNumber, + Anum_pg_language_lanowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_largeobject = { + LargeObjectMetadataRelationId, + LargeObjectMetadataOidIndexId, + -1, + -1, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_largeobject_metadata_lomowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_namespace = { + NamespaceRelationId, + NamespaceOidIndexId, + NAMESPACEOID, + NAMESPACENAME, + Anum_pg_namespace_nspname, + InvalidAttrNumber, + Anum_pg_namespace_nspowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_opclass = { + OperatorClassRelationId, + OpclassOidIndexId, + CLAOID, + -1, + Anum_pg_opclass_opcname, + Anum_pg_opclass_opcnamespace, + Anum_pg_opclass_opcowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_operator = { + OperatorRelationId, + OperatorOidIndexId, + OPEROID, + OPERNAMENSP, + Anum_pg_operator_oprname, + Anum_pg_operator_oprnamespace, + Anum_pg_operator_oprowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_opfamily = { + OperatorFamilyRelationId, + OpfamilyOidIndexId, + OPFAMILYOID, + -1, + Anum_pg_opfamily_opfname, + Anum_pg_opfamily_opfnamespace, + Anum_pg_opfamily_opfowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_proc = { + ProcedureRelationId, + ProcedureOidIndexId, + PROCOID, + -1, + Anum_pg_proc_proname, + Anum_pg_proc_pronamespace, + Anum_pg_proc_proowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_rewrite = { + RewriteRelationId, + RewriteOidIndexId, + -1, + RULERELNAME, + Anum_pg_rewrite_ev_class, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_rewrite_ev_class, +}; +static CatalogProperty prop_pg_tablespace = { + TableSpaceRelationId, + TablespaceOidIndexId, + -1, + -1, + Anum_pg_tablespace_spcname, + InvalidAttrNumber, + Anum_pg_tablespace_spcowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_trigger = { + TriggerRelationId, + TriggerOidIndexId, + -1, + -1, + Anum_pg_trigger_tgname, + InvalidAttrNumber, + InvalidAttrNumber, + Anum_pg_trigger_tgrelid, +}; +static CatalogProperty prop_pg_ts_config = { + TSConfigRelationId, + TSConfigOidIndexId, + TSCONFIGOID, + TSCONFIGNAMENSP, + Anum_pg_ts_config_cfgname, + Anum_pg_ts_config_cfgnamespace, + Anum_pg_ts_config_cfgowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_ts_dict = { + TSDictionaryRelationId, + TSDictionaryOidIndexId, + TSDICTOID, + TSDICTNAMENSP, + Anum_pg_ts_dict_dictname, + Anum_pg_ts_dict_dictnamespace, + Anum_pg_ts_dict_dictowner, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_ts_parser = { + TSParserRelationId, + TSParserOidIndexId, + TSPARSEROID, + TSPARSERNAMENSP, + Anum_pg_ts_parser_prsname, + Anum_pg_ts_parser_prsnamespace, + InvalidAttrNumber, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_ts_template = { + TSTemplateRelationId, + TSTemplateOidIndexId, + TSTEMPLATEOID, + TSTEMPLATENAMENSP, + Anum_pg_ts_template_tmplname, + Anum_pg_ts_template_tmplnamespace, + InvalidAttrNumber, + InvalidAttrNumber, +}; +static CatalogProperty prop_pg_type = { + TypeRelationId, + TypeOidIndexId, + TYPEOID, + TYPENAMENSP, + Anum_pg_type_typname, + Anum_pg_type_typnamespace, + Anum_pg_type_typowner, + InvalidAttrNumber, +}; + +/* + * ObjectProperty + * + * This array provides a common part of system object structure; to help + * consolidate routines to handle various kind of object classes. + */ +static struct +{ + ObjectType objtype; + const char *objtype_text; + CatalogProperty *objprop; +} ObjectProperty[] = +{ + { + OBJECT_AGGREGATE, + "aggregate", + &prop_pg_proc, + }, + { + OBJECT_ATTRIBUTE, + "attribute", + &prop_pg_attribute, + }, + { + OBJECT_CAST, + "cast", + &prop_pg_cast, + }, + { + OBJECT_COLUMN, + "column", + &prop_pg_attribute, + }, + { + OBJECT_CONSTRAINT, + "constraint", + &prop_pg_constraint, + }, + { + OBJECT_COLLATION, + "collation", + &prop_pg_collation, + }, + { + OBJECT_CONVERSION, + "conversion", + &prop_pg_conversion, + }, + { + OBJECT_DATABASE, + "database", + &prop_pg_database, + }, + { + OBJECT_DOMAIN, + "domain", + &prop_pg_type, + }, + { + OBJECT_EXTENSION, + "extension", + &prop_pg_extension, + }, + { + OBJECT_FDW, + "foreign-data wrapper", + &prop_pg_foreign_data_wrapper, + }, + { + OBJECT_FOREIGN_SERVER, + "server", + &prop_pg_foreign_server, + }, + { + OBJECT_FOREIGN_TABLE, + "foreign table", + &prop_pg_class, + }, + { + OBJECT_FUNCTION, + "function", + &prop_pg_proc, + }, + { + OBJECT_INDEX, + "index", + &prop_pg_class, + }, + { + OBJECT_LANGUAGE, + "language", + &prop_pg_language, + }, + { + OBJECT_LARGEOBJECT, + "large object", + &prop_pg_largeobject, + }, + { + OBJECT_OPCLASS, + "operator class", + &prop_pg_opclass, + }, + { + OBJECT_OPERATOR, + "operator", + &prop_pg_operator, + }, + { + OBJECT_OPFAMILY, + "operator family", + &prop_pg_opfamily, + }, + { + OBJECT_ROLE, + "role", + &prop_pg_authid, + }, + { + OBJECT_RULE, + "rule", + &prop_pg_rewrite, + }, + { + OBJECT_SCHEMA, + "schema", + &prop_pg_namespace, + }, + { + OBJECT_SEQUENCE, + "sequence", + &prop_pg_class, + }, + { + OBJECT_TABLE, + "table", + &prop_pg_class, + }, + { + OBJECT_TABLESPACE, + "tablespace", + &prop_pg_tablespace, + }, + { + OBJECT_TRIGGER, + "trigger", + &prop_pg_trigger, + }, + { + OBJECT_TSCONFIGURATION, + "text search configuration", + &prop_pg_ts_config, + }, + { + OBJECT_TSDICTIONARY, + "text search dictionary", + &prop_pg_ts_dict, + }, + { + OBJECT_TSPARSER, + "text search parser", + &prop_pg_ts_parser, + }, + { + OBJECT_TSTEMPLATE, + "text search template", + &prop_pg_ts_template, + }, + { + OBJECT_TYPE, + "type", + &prop_pg_type, + }, + { + OBJECT_VIEW, + "view", + &prop_pg_class, + }, +}; /* * Translate an object name and arguments (as passed by the parser) to an @@ -667,11 +1124,87 @@ get_object_address_opcf(ObjectType objtype, } /* + * Returns property of the supplied object type + */ +const char * +get_object_property_typetext(ObjectType objtype) +{ + if (objtype < 0 || objtype >= lengthof(ObjectProperty)) + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return ObjectProperty[(int)objtype].objtype_text; +} + +Oid +get_object_property_class_id(ObjectType objtype) +{ + if (objtype < 0 || objtype >= lengthof(ObjectProperty)) + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return ObjectProperty[(int)objtype].objprop->class_id; +} + +Oid +get_object_property_index_id(ObjectType objtype) +{ + if (objtype < 0 || objtype >= lengthof(ObjectProperty)) + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return ObjectProperty[(int)objtype].objprop->index_id; +} + +int +get_object_property_catid_by_oid(ObjectType objtype) +{ + if (objtype < 0 || objtype >= lengthof(ObjectProperty)) + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return ObjectProperty[(int)objtype].objprop->cacheid_by_oid; +} + +int +get_object_property_catid_by_name(ObjectType objtype) +{ + if (objtype < 0 || objtype >= lengthof(ObjectProperty)) + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return ObjectProperty[(int)objtype].objprop->cacheid_by_name; +} + +AttrNumber +get_object_property_attnum_name(ObjectType objtype) +{ + if (objtype < 0 || objtype >= lengthof(ObjectProperty)) + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return ObjectProperty[(int)objtype].objprop->attnum_name; +} + +AttrNumber +get_object_property_attnum_namespace(ObjectType objtype) +{ + if (objtype < 0 || objtype >= lengthof(ObjectProperty)) + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return ObjectProperty[(int)objtype].objprop->attnum_namespace; +} + +AttrNumber +get_object_property_attnum_owner(ObjectType objtype) +{ + if (objtype < 0 || objtype >= lengthof(ObjectProperty)) + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return ObjectProperty[(int)objtype].objprop->attnum_owner; +} + +AttrNumber +get_object_property_attnum_relid(ObjectType objtype) +{ + if (objtype < 0 || objtype >= lengthof(ObjectProperty)) + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + return ObjectProperty[(int)objtype].objprop->attnum_relid; +} + +/* * Test whether an object exists. */ static bool object_exists(ObjectAddress address) { + int objtype; int cache = -1; Oid indexoid = InvalidOid; Relation rel; @@ -697,99 +1230,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 (objtype = 0; objtype < lengthof(ObjectProperty); objtype++) + { + if (ObjectProperty[objtype].objprop->class_id == address.classId) + { + cache = ObjectProperty[objtype].objprop->cacheid_by_oid; + indexoid = ObjectProperty[objtype].objprop->index_id; + break; + } + } + if (objtype == 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 */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index a4fb3b5..8773cf9 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1103,7 +1103,7 @@ typedef struct SetOperationStmt typedef enum ObjectType { - OBJECT_AGGREGATE, + OBJECT_AGGREGATE = 0, OBJECT_ATTRIBUTE, /* type's attribute, when distinct from column */ OBJECT_CAST, OBJECT_COLUMN,