Add a missing_ok argument to get_object_address().
authorRobert Haas <[email protected]>
Tue, 28 Jun 2011 01:17:25 +0000 (21:17 -0400)
committerRobert Haas <[email protected]>
Tue, 28 Jun 2011 01:19:31 +0000 (21:19 -0400)
This lays the groundwork for an upcoming patch to streamline the
handling of DROP commands.

KaiGai Kohei

src/backend/catalog/objectaddress.c
src/backend/commands/comment.c
src/backend/commands/extension.c
src/backend/commands/seclabel.c
src/backend/rewrite/rewriteSupport.c
src/include/catalog/objectaddress.h
src/include/rewrite/rewriteSupport.h

index bf25091582ff2be7bb6239c150c495065c00ceed..8de5bec57a13ae3cf9c077809f7b9c33cc0050bb 100644 (file)
 #include "utils/tqual.h"
 
 static ObjectAddress get_object_address_unqualified(ObjectType objtype,
-                              List *qualname);
-static Relation get_relation_by_qualified_name(ObjectType objtype,
-                              List *objname, LOCKMODE lockmode);
+                              List *qualname, bool missing_ok);
+static ObjectAddress get_relation_by_qualified_name(ObjectType objtype,
+                              List *objname, Relation *relp,
+                              LOCKMODE lockmode, bool missing_ok);
 static ObjectAddress get_object_address_relobject(ObjectType objtype,
-                            List *objname, Relation *relp);
+                            List *objname, Relation *relp, bool missing_ok);
 static ObjectAddress get_object_address_attribute(ObjectType objtype,
-                          List *objname, Relation *relp, LOCKMODE lockmode);
+                            List *objname, Relation *relp,
+                            LOCKMODE lockmode, bool missing_ok);
+static ObjectAddress get_object_address_type(ObjectType objtype,
+                       List *objname, bool missing_ok);
 static ObjectAddress get_object_address_opcf(ObjectType objtype, List *objname,
-                       List *objargs);
+                       List *objargs, bool missing_ok);
 static bool object_exists(ObjectAddress address);
 
 
@@ -106,7 +110,7 @@ static bool object_exists(ObjectAddress address);
  */
 ObjectAddress
 get_object_address(ObjectType objtype, List *objname, List *objargs,
-                  Relation *relp, LOCKMODE lockmode)
+                  Relation *relp, LOCKMODE lockmode, bool missing_ok)
 {
    ObjectAddress address;
    Relation    relation = NULL;
@@ -121,21 +125,22 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
        case OBJECT_TABLE:
        case OBJECT_VIEW:
        case OBJECT_FOREIGN_TABLE:
-           relation =
-               get_relation_by_qualified_name(objtype, objname, lockmode);
-           address.classId = RelationRelationId;
-           address.objectId = RelationGetRelid(relation);
-           address.objectSubId = 0;
+           address =
+               get_relation_by_qualified_name(objtype, objname,
+                                              &relation, lockmode,
+                                              missing_ok);
            break;
        case OBJECT_COLUMN:
            address =
-               get_object_address_attribute(objtype, objname, &relation,
-                                            lockmode);
+               get_object_address_attribute(objtype, objname,
+                                            &relation, lockmode,
+                                            missing_ok);
            break;
        case OBJECT_RULE:
        case OBJECT_TRIGGER:
        case OBJECT_CONSTRAINT:
-           address = get_object_address_relobject(objtype, objname, &relation);
+           address = get_object_address_relobject(objtype, objname,
+                                                  &relation, missing_ok);
            break;
        case OBJECT_DATABASE:
        case OBJECT_EXTENSION:
@@ -145,23 +150,23 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
        case OBJECT_LANGUAGE:
        case OBJECT_FDW:
        case OBJECT_FOREIGN_SERVER:
-           address = get_object_address_unqualified(objtype, objname);
+           address = get_object_address_unqualified(objtype,
+                                                    objname, missing_ok);
            break;
        case OBJECT_TYPE:
        case OBJECT_DOMAIN:
-           address.classId = TypeRelationId;
-           address.objectId =
-               typenameTypeId(NULL, makeTypeNameFromNameList(objname));
-           address.objectSubId = 0;
+           address = get_object_address_type(objtype, objname, missing_ok);
            break;
        case OBJECT_AGGREGATE:
            address.classId = ProcedureRelationId;
-           address.objectId = LookupAggNameTypeNames(objname, objargs, false);
+           address.objectId =
+               LookupAggNameTypeNames(objname, objargs, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_FUNCTION:
            address.classId = ProcedureRelationId;
-           address.objectId = LookupFuncNameTypeNames(objname, objargs, false);
+           address.objectId =
+               LookupFuncNameTypeNames(objname, objargs, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_OPERATOR:
@@ -171,22 +176,23 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
                LookupOperNameTypeNames(NULL, objname,
                                        (TypeName *) linitial(objargs),
                                        (TypeName *) lsecond(objargs),
-                                       false, -1);
+                                       missing_ok, -1);
            address.objectSubId = 0;
            break;
        case OBJECT_COLLATION:
            address.classId = CollationRelationId;
-           address.objectId = get_collation_oid(objname, false);
+           address.objectId = get_collation_oid(objname, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_CONVERSION:
            address.classId = ConversionRelationId;
-           address.objectId = get_conversion_oid(objname, false);
+           address.objectId = get_conversion_oid(objname, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_OPCLASS:
        case OBJECT_OPFAMILY:
-           address = get_object_address_opcf(objtype, objname, objargs);
+           address = get_object_address_opcf(objtype,
+                                             objname, objargs, missing_ok);
            break;
        case OBJECT_LARGEOBJECT:
            Assert(list_length(objname) == 1);
@@ -194,10 +200,13 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
            address.objectId = oidparse(linitial(objname));
            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:
            {
@@ -208,28 +217,28 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
 
                address.classId = CastRelationId;
                address.objectId =
-                   get_cast_oid(sourcetypeid, targettypeid, false);
+                   get_cast_oid(sourcetypeid, targettypeid, missing_ok);
                address.objectSubId = 0;
            }
            break;
        case OBJECT_TSPARSER:
            address.classId = TSParserRelationId;
-           address.objectId = get_ts_parser_oid(objname, false);
+           address.objectId = get_ts_parser_oid(objname, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_TSDICTIONARY:
            address.classId = TSDictionaryRelationId;
-           address.objectId = get_ts_dict_oid(objname, false);
+           address.objectId = get_ts_dict_oid(objname, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_TSTEMPLATE:
            address.classId = TSTemplateRelationId;
-           address.objectId = get_ts_template_oid(objname, false);
+           address.objectId = get_ts_template_oid(objname, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_TSCONFIGURATION:
            address.classId = TSConfigRelationId;
-           address.objectId = get_ts_config_oid(objname, false);
+           address.objectId = get_ts_config_oid(objname, missing_ok);
            address.objectSubId = 0;
            break;
        default:
@@ -240,6 +249,15 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
            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 dealing with a relation or attribute, then the relation is
     * already locked.  If we're dealing with any other type of object, we
@@ -267,7 +285,8 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
  * unqualified name.
  */
 static ObjectAddress
-get_object_address_unqualified(ObjectType objtype, List *qualname)
+get_object_address_unqualified(ObjectType objtype,
+                              List *qualname, bool missing_ok)
 {
    const char *name;
    ObjectAddress address;
@@ -323,42 +342,42 @@ get_object_address_unqualified(ObjectType objtype, List *qualname)
    {
        case OBJECT_DATABASE:
            address.classId = DatabaseRelationId;
-           address.objectId = get_database_oid(name, false);
+           address.objectId = get_database_oid(name, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_EXTENSION:
            address.classId = ExtensionRelationId;
-           address.objectId = get_extension_oid(name, false);
+           address.objectId = get_extension_oid(name, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_TABLESPACE:
            address.classId = TableSpaceRelationId;
-           address.objectId = get_tablespace_oid(name, false);
+           address.objectId = get_tablespace_oid(name, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_ROLE:
            address.classId = AuthIdRelationId;
-           address.objectId = get_role_oid(name, false);
+           address.objectId = get_role_oid(name, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_SCHEMA:
            address.classId = NamespaceRelationId;
-           address.objectId = get_namespace_oid(name, false);
+           address.objectId = get_namespace_oid(name, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_LANGUAGE:
            address.classId = LanguageRelationId;
-           address.objectId = get_language_oid(name, false);
+           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, false);
+           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, false);
+           address.objectId = get_foreign_server_oid(name, missing_ok);
            address.objectSubId = 0;
            break;
        default:
@@ -375,13 +394,23 @@ get_object_address_unqualified(ObjectType objtype, List *qualname)
 /*
  * Locate a relation by qualified name.
  */
-static Relation
+static ObjectAddress
 get_relation_by_qualified_name(ObjectType objtype, List *objname,
-                              LOCKMODE lockmode)
+                              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(objname),
+                                       lockmode, missing_ok);
+   if (!relation)
+       return address;
 
-   relation = relation_openrv(makeRangeVarFromNameList(objname), lockmode);
    switch (objtype)
    {
        case OBJECT_INDEX:
@@ -424,7 +453,11 @@ get_relation_by_qualified_name(ObjectType objtype, List *objname,
            break;
    }
 
-   return relation;
+   /* Done */
+   address.objectId = RelationGetRelid(relation);
+   *relp = relation;
+
+   return address;
 }
 
 /*
@@ -435,7 +468,8 @@ get_relation_by_qualified_name(ObjectType objtype, List *objname,
  * mode for the object itself, not the relation to which it is attached.
  */
 static ObjectAddress
-get_object_address_relobject(ObjectType objtype, List *objname, Relation *relp)
+get_object_address_relobject(ObjectType objtype, List *objname,
+                            Relation *relp, bool missing_ok)
 {
    ObjectAddress address;
    Relation    relation = NULL;
@@ -461,9 +495,9 @@ get_object_address_relobject(ObjectType objtype, List *objname, Relation *relp)
        if (objtype != OBJECT_RULE)
            elog(ERROR, "must specify relation and object name");
        address.classId = RewriteRelationId;
-       address.objectId = get_rewrite_oid_without_relid(depname, &reloid);
+       address.objectId =
+           get_rewrite_oid_without_relid(depname, &reloid, missing_ok);
        address.objectSubId = 0;
-       relation = heap_open(reloid, AccessShareLock);
    }
    else
    {
@@ -480,17 +514,18 @@ get_object_address_relobject(ObjectType objtype, List *objname, Relation *relp)
        {
            case OBJECT_RULE:
                address.classId = RewriteRelationId;
-               address.objectId = get_rewrite_oid(reloid, depname, false);
+               address.objectId = get_rewrite_oid(reloid, depname, missing_ok);
                address.objectSubId = 0;
                break;
            case OBJECT_TRIGGER:
                address.classId = TriggerRelationId;
-               address.objectId = get_trigger_oid(reloid, depname, false);
+               address.objectId = get_trigger_oid(reloid, depname, missing_ok);
                address.objectSubId = 0;
                break;
            case OBJECT_CONSTRAINT:
                address.classId = ConstraintRelationId;
-               address.objectId = get_constraint_oid(reloid, depname, false);
+               address.objectId =
+                   get_constraint_oid(reloid, depname, missing_ok);
                address.objectSubId = 0;
                break;
            default:
@@ -512,13 +547,15 @@ get_object_address_relobject(ObjectType objtype, List *objname, Relation *relp)
  */
 static ObjectAddress
 get_object_address_attribute(ObjectType objtype, List *objname,
-                            Relation *relp, LOCKMODE lockmode)
+                            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. */
    attname = strVal(lfirst(list_tail(objname)));
@@ -527,24 +564,77 @@ get_object_address_attribute(ObjectType objtype, List *objname,
    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;
+       return address;
+   }
+
    address.classId = RelationRelationId;
    address.objectId = reloid;
-   address.objectSubId = get_attnum(reloid, attname);
-   if (address.objectSubId == InvalidAttrNumber)
-       ereport(ERROR,
-               (errcode(ERRCODE_UNDEFINED_COLUMN),
-                errmsg("column \"%s\" of relation \"%s\" does not exist",
-                       attname, RelationGetRelationName(relation))));
+   address.objectSubId = attnum;
 
    *relp = relation;
    return address;
 }
 
+/*
+ * Find the ObjectAddress for a type or domain
+ */
+static ObjectAddress
+get_object_address_type(ObjectType objtype,
+                       List *objname, bool missing_ok)
+{
+   ObjectAddress   address;
+   TypeName   *typename;
+   Type        tup;
+   typename = makeTypeNameFromNameList(objname);
+
+   address.classId = TypeRelationId;
+   address.objectId = InvalidOid;
+   address.objectSubId = 0;
+
+   tup = LookupTypeName(NULL, typename, NULL);
+   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 *objname, List *objargs)
+get_object_address_opcf(ObjectType objtype,
+                       List *objname, List *objargs, bool missing_ok)
 {
    Oid         amoid;
    ObjectAddress address;
@@ -556,12 +646,12 @@ get_object_address_opcf(ObjectType objtype, List *objname, List *objargs)
    {
        case OBJECT_OPCLASS:
            address.classId = OperatorClassRelationId;
-           address.objectId = get_opclass_oid(amoid, objname, false);
+           address.objectId = get_opclass_oid(amoid, objname, missing_ok);
            address.objectSubId = 0;
            break;
        case OBJECT_OPFAMILY:
            address.classId = OperatorFamilyRelationId;
-           address.objectId = get_opfamily_oid(amoid, objname, false);
+           address.objectId = get_opfamily_oid(amoid, objname, missing_ok);
            address.objectSubId = 0;
            break;
        default:
index 587a689496fc48f327a324239028ab3166e1332e..de4d5ded683197e9ab975d7b918e1cb4faa394cd 100644 (file)
@@ -69,7 +69,7 @@ CommentObject(CommentStmt *stmt)
     * against concurrent DROP operations.
     */
    address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
-                                &relation, ShareUpdateExclusiveLock);
+                                &relation, ShareUpdateExclusiveLock, false);
 
    /* Require ownership of the target object. */
    check_object_ownership(GetUserId(), stmt->objtype, address,
index 58695690500e69c2ddabef9c3842d467af24798d..08fb3d5d360f00bc0bb919454efc6adfca11ebbd 100644 (file)
@@ -2703,7 +2703,7 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
     * against concurrent DROP and ALTER EXTENSION ADD/DROP operations.
     */
    object = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
-                               &relation, ShareUpdateExclusiveLock);
+                               &relation, ShareUpdateExclusiveLock, false);
 
    /* Permission check: must own target object, too */
    check_object_ownership(GetUserId(), stmt->objtype, object,
index 7afb7139a6315347a02dfe90d8eb97a1c9ba0d22..51a5567a014a3f9d8f5ba45c3ac70b23252ffc1c 100644 (file)
@@ -88,7 +88,7 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
     * guard against concurrent modifications.
     */
    address = get_object_address(stmt->objtype, stmt->objname, stmt->objargs,
-                                &relation, ShareUpdateExclusiveLock);
+                                &relation, ShareUpdateExclusiveLock, false);
 
    /* Require ownership of the target object. */
    check_object_ownership(GetUserId(), stmt->objtype, address,
index 7770d032b1eaeaac656f514fd27eb3b7ceb9b806..4d6f508e0b6b0e914a9045a814b1bbfb6118b9d4 100644 (file)
@@ -132,7 +132,8 @@ get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok)
  * were unique across the entire database.
  */
 Oid
-get_rewrite_oid_without_relid(const char *rulename, Oid *reloid)
+get_rewrite_oid_without_relid(const char *rulename,
+                             Oid *reloid, bool missing_ok)
 {
    Relation    RewriteRelation;
    HeapScanDesc scanDesc;
@@ -151,20 +152,26 @@ get_rewrite_oid_without_relid(const char *rulename, Oid *reloid)
 
    htup = heap_getnext(scanDesc, ForwardScanDirection);
    if (!HeapTupleIsValid(htup))
-       ereport(ERROR,
-               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                errmsg("rule \"%s\" does not exist", rulename)));
-
-   ruleoid = HeapTupleGetOid(htup);
-   if (reloid != NULL)
-       *reloid = ((Form_pg_rewrite) GETSTRUCT(htup))->ev_class;
-
-   if (HeapTupleIsValid(htup = heap_getnext(scanDesc, ForwardScanDirection)))
-       ereport(ERROR,
-               (errcode(ERRCODE_DUPLICATE_OBJECT),
-                errmsg("there are multiple rules named \"%s\"", rulename),
-                errhint("Specify a relation name as well as a rule name.")));
-
+   {
+       if (!missing_ok)
+           ereport(ERROR,
+                   (errcode(ERRCODE_UNDEFINED_OBJECT),
+                    errmsg("rule \"%s\" does not exist", rulename)));
+       ruleoid = InvalidOid;
+   }
+   else
+   {
+       ruleoid = HeapTupleGetOid(htup);
+       if (reloid != NULL)
+           *reloid = ((Form_pg_rewrite) GETSTRUCT(htup))->ev_class;
+
+       htup = heap_getnext(scanDesc, ForwardScanDirection);
+       if (HeapTupleIsValid(htup))
+           ereport(ERROR,
+                   (errcode(ERRCODE_DUPLICATE_OBJECT),
+                    errmsg("there are multiple rules named \"%s\"", rulename),
+                    errhint("Specify a relation name as well as a rule name.")));
+   }
    heap_endscan(scanDesc);
    heap_close(RewriteRelation, AccessShareLock);
 
index 109a8a3ef533a6ac4b23182856a2e21ba380b44a..300b81d1f6913c011040d2767e5ecfcf2731c031 100644 (file)
@@ -28,7 +28,8 @@ typedef struct ObjectAddress
 } ObjectAddress;
 
 extern ObjectAddress get_object_address(ObjectType objtype, List *objname,
-                  List *objargs, Relation *relp, LOCKMODE lockmode);
+                                       List *objargs, Relation *relp,
+                                       LOCKMODE lockmode, bool missing_ok);
 
 extern void check_object_ownership(Oid roleid,
                       ObjectType objtype, ObjectAddress address,
index 77417ba034ae3581bd3a95bc10d0ccd9d0e4db32..22e6ca26cffc7ac89f31a0095fea993544dfcb42 100644 (file)
@@ -23,6 +23,7 @@ extern void SetRelationRuleStatus(Oid relationId, bool relHasRules,
                      bool relIsBecomingView);
 
 extern Oid get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok);
-extern Oid get_rewrite_oid_without_relid(const char *rulename, Oid *relid);
+extern Oid get_rewrite_oid_without_relid(const char *rulename,
+                                         Oid *relid, bool missing_ok);
 
 #endif   /* REWRITESUPPORT_H */