diff options
Diffstat (limited to 'src/backend/commands/typecmds.c')
-rw-r--r-- | src/backend/commands/typecmds.c | 186 |
1 files changed, 72 insertions, 114 deletions
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 880788fd22b..793e9262e3e 100644 --- a/src/backend/commands/typecmds.c +++ b/src/backend/commands/typecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.118 2008/05/09 23:32:04 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.119 2008/06/14 18:04:33 tgl Exp $ * * DESCRIPTION * The "DefineFoo" routines take the parse tree and pick out the @@ -483,66 +483,93 @@ DefineType(List *names, List *parameters) /* - * RemoveType - * Removes a datatype. + * RemoveTypes + * Implements DROP TYPE and DROP DOMAIN + * + * Note: if DOMAIN is specified, we enforce that each type is a domain, but + * we don't enforce the converse for DROP TYPE */ void -RemoveType(List *names, DropBehavior behavior, bool missing_ok) +RemoveTypes(DropStmt *drop) { - TypeName *typename; - Oid typeoid; - HeapTuple tup; - ObjectAddress object; - Form_pg_type typ; + ObjectAddresses *objects; + ListCell *cell; - /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeTypeNameFromNameList(names); + /* + * First we identify all the types, then we delete them in a single + * performMultipleDeletions() call. This is to avoid unwanted + * DROP RESTRICT errors if one of the types depends on another. + */ + objects = new_object_addresses(); - /* Use LookupTypeName here so that shell types can be removed. */ - tup = LookupTypeName(NULL, typename, NULL); - if (tup == NULL) + foreach(cell, drop->objects) { - if (!missing_ok) + List *names = (List *) lfirst(cell); + TypeName *typename; + Oid typeoid; + HeapTuple tup; + ObjectAddress object; + Form_pg_type typ; + + /* Make a TypeName so we can use standard type lookup machinery */ + typename = makeTypeNameFromNameList(names); + + /* Use LookupTypeName here so that shell types can be removed. */ + tup = LookupTypeName(NULL, typename, NULL); + if (tup == NULL) { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); + if (!drop->missing_ok) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("type \"%s\" does not exist", + TypeNameToString(typename)))); + } + else + { + ereport(NOTICE, + (errmsg("type \"%s\" does not exist, skipping", + TypeNameToString(typename)))); + } + continue; } - else + + typeoid = typeTypeId(tup); + typ = (Form_pg_type) GETSTRUCT(tup); + + /* Permission check: must own type or its namespace */ + if (!pg_type_ownercheck(typeoid, GetUserId()) && + !pg_namespace_ownercheck(typ->typnamespace, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, + TypeNameToString(typename)); + + if (drop->removeType == OBJECT_DOMAIN) { - ereport(NOTICE, - (errmsg("type \"%s\" does not exist, skipping", - TypeNameToString(typename)))); + /* Check that this is actually a domain */ + if (typ->typtype != TYPTYPE_DOMAIN) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a domain", + TypeNameToString(typename)))); } - return; - } - - typeoid = typeTypeId(tup); - typ = (Form_pg_type) GETSTRUCT(tup); + /* + * Note: we need no special check for array types here, as the normal + * treatment of internal dependencies handles it just fine + */ - /* Permission check: must own type or its namespace */ - if (!pg_type_ownercheck(typeoid, GetUserId()) && - !pg_namespace_ownercheck(typ->typnamespace, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - TypeNameToString(typename)); + object.classId = TypeRelationId; + object.objectId = typeoid; + object.objectSubId = 0; - /* - * Note: we need no special check for array types here, as the normal - * treatment of internal dependencies handles it just fine - */ + add_exact_object_address(&object, objects); - ReleaseSysCache(tup); + ReleaseSysCache(tup); + } - /* - * Do the deletion - */ - object.classId = TypeRelationId; - object.objectId = typeoid; - object.objectSubId = 0; + performMultipleDeletions(objects, drop->behavior); - performDeletion(&object, behavior); + free_object_addresses(objects); } @@ -924,75 +951,6 @@ DefineDomain(CreateDomainStmt *stmt) /* - * RemoveDomain - * Removes a domain. - * - * This is identical to RemoveType except we insist it be a domain. - */ -void -RemoveDomain(List *names, DropBehavior behavior, bool missing_ok) -{ - TypeName *typename; - Oid typeoid; - HeapTuple tup; - char typtype; - ObjectAddress object; - - /* Make a TypeName so we can use standard type lookup machinery */ - typename = makeTypeNameFromNameList(names); - - /* Use LookupTypeName here so that shell types can be removed. */ - tup = LookupTypeName(NULL, typename, NULL); - if (tup == NULL) - { - if (!missing_ok) - { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("type \"%s\" does not exist", - TypeNameToString(typename)))); - } - else - { - ereport(NOTICE, - (errmsg("type \"%s\" does not exist, skipping", - TypeNameToString(typename)))); - } - - return; - } - - typeoid = typeTypeId(tup); - - /* Permission check: must own type or its namespace */ - if (!pg_type_ownercheck(typeoid, GetUserId()) && - !pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace, - GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - TypeNameToString(typename)); - - /* Check that this is actually a domain */ - typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype; - - if (typtype != TYPTYPE_DOMAIN) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is not a domain", - TypeNameToString(typename)))); - - ReleaseSysCache(tup); - - /* - * Do the deletion - */ - object.classId = TypeRelationId; - object.objectId = typeoid; - object.objectSubId = 0; - - performDeletion(&object, behavior); -} - -/* * DefineEnum * Registers a new enum. */ |