pgsql-v9.2-drop-reworks-2.v4.patch
application/octet-stream
Filename: pgsql-v9.2-drop-reworks-2.v4.patch
Type: application/octet-stream
Part: 2
Message:
Re: [v9.2] DROP statement reworks
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v9
| File | + | − |
|---|---|---|
| src/backend/catalog/objectaddress.c | 36 | 0 |
| src/backend/commands/collationcmds.c | 0 | 61 |
| src/backend/commands/conversioncmds.c | 0 | 61 |
| src/backend/commands/dropcmds.c | 233 | 0 |
| src/backend/commands/extension.c | 0 | 63 |
| src/backend/commands/Makefile | 1 | 1 |
| src/backend/commands/schemacmds.c | 0 | 63 |
| src/backend/commands/tablecmds.c | 0 | 255 |
| src/backend/commands/tsearchcmds.c | 0 | 254 |
| src/backend/commands/typecmds.c | 0 | 92 |
| src/backend/nodes/copyfuncs.c | 1 | 0 |
| src/backend/nodes/equalfuncs.c | 1 | 0 |
| src/backend/parser/gram.y | 2 | 0 |
| src/backend/tcop/utility.c | 1 | 56 |
| src/include/catalog/objectaddress.h | 3 | 0 |
| src/include/commands/collationcmds.h | 0 | 1 |
| src/include/commands/conversioncmds.h | 0 | 1 |
| src/include/commands/defrem.h | 2 | 4 |
| src/include/commands/extension.h | 0 | 1 |
| src/include/commands/schemacmds.h | 0 | 1 |
| src/include/commands/tablecmds.h | 0 | 2 |
| src/include/commands/typecmds.h | 0 | 1 |
| src/include/nodes/parsenodes.h | 1 | 0 |
| src/test/regress/expected/drop_if_exists.out | 1 | 1 |
src/backend/catalog/objectaddress.c | 36 ++++
src/backend/commands/Makefile | 2 +-
src/backend/commands/collationcmds.c | 61 ------
src/backend/commands/conversioncmds.c | 61 ------
src/backend/commands/dropcmds.c | 233 +++++++++++++++++++++++
src/backend/commands/extension.c | 63 -------
src/backend/commands/schemacmds.c | 63 -------
src/backend/commands/tablecmds.c | 255 --------------------------
src/backend/commands/tsearchcmds.c | 254 -------------------------
src/backend/commands/typecmds.c | 92 ---------
src/backend/nodes/copyfuncs.c | 1 +
src/backend/nodes/equalfuncs.c | 1 +
src/backend/parser/gram.y | 2 +
src/backend/tcop/utility.c | 57 +------
src/include/catalog/objectaddress.h | 3 +
src/include/commands/collationcmds.h | 1 -
src/include/commands/conversioncmds.h | 1 -
src/include/commands/defrem.h | 6 +-
src/include/commands/extension.h | 1 -
src/include/commands/schemacmds.h | 1 -
src/include/commands/tablecmds.h | 2 -
src/include/commands/typecmds.h | 1 -
src/include/nodes/parsenodes.h | 1 +
src/test/regress/expected/drop_if_exists.out | 2 +-
24 files changed, 282 insertions(+), 918 deletions(-)
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 2250058..798fc70 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -1405,3 +1405,39 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
(int) objtype);
}
}
+
+/*
+ * get_object_namespace
+ *
+ * It returns OID of the namespace that owns the object specified with
+ * 'address' argument. If the required object type does not belong to
+ * a particula namespace, it returns InvalidOid.
+ */
+Oid
+get_object_namespace(ObjectType objtype, const ObjectAddress *address)
+{
+ AttrNumber attnum_namespace;
+ HeapTuple tuple;
+ int cacheId;
+ Datum datum;
+ bool isnull;
+
+ attnum_namespace = get_object_property_attnum_namespace(objtype);
+ if (attnum_namespace == InvalidAttrNumber)
+ return InvalidOid;
+
+ cacheId = get_object_property_catid_by_oid(objtype);
+ Assert(cacheId >= 0);
+
+ tuple = SearchSysCache1(cacheId, ObjectIdGetDatum(address->objectId));
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup failed for %s %u",
+ get_object_property_typetext(objtype), address->objectId);
+
+ datum = SysCacheGetAttr(cacheId, tuple, attnum_namespace, &isnull);
+ Assert(!isnull);
+
+ ReleaseSysCache(tuple);
+
+ return DatumGetObjectId(datum);
+}
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
index 81fd658..4af7aad 100644
--- a/src/backend/commands/Makefile
+++ b/src/backend/commands/Makefile
@@ -14,7 +14,7 @@ include $(top_builddir)/src/Makefile.global
OBJS = aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o \
collationcmds.o constraint.o conversioncmds.o copy.o \
- dbcommands.o define.o discard.o explain.o extension.o \
+ dbcommands.o define.o discard.o dropcmds.o explain.o extension.o \
foreigncmds.o functioncmds.o \
indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o \
portalcmds.o prepare.o proclang.o \
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index a0a0c7d..20aa204 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -145,67 +145,6 @@ DefineCollation(List *names, List *parameters)
}
/*
- * DROP COLLATION
- */
-void
-DropCollationsCommand(DropStmt *drop)
-{
- ObjectAddresses *objects;
- ListCell *cell;
-
- /*
- * First we identify all the collations, then we delete them in a single
- * performMultipleDeletions() call. This is to avoid unwanted DROP
- * RESTRICT errors if one of the collations depends on another. (Not that
- * that is very likely, but we may as well do this consistently.)
- */
- objects = new_object_addresses();
-
- foreach(cell, drop->objects)
- {
- List *name = (List *) lfirst(cell);
- Oid collationOid;
- HeapTuple tuple;
- Form_pg_collation coll;
- ObjectAddress object;
-
- collationOid = get_collation_oid(name, drop->missing_ok);
-
- if (!OidIsValid(collationOid))
- {
- ereport(NOTICE,
- (errmsg("collation \"%s\" does not exist, skipping",
- NameListToString(name))));
- continue;
- }
-
- tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(collationOid));
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "cache lookup failed for collation %u",
- collationOid);
- coll = (Form_pg_collation) GETSTRUCT(tuple);
-
- /* Permission check: must own collation or its namespace */
- if (!pg_collation_ownercheck(collationOid, GetUserId()) &&
- !pg_namespace_ownercheck(coll->collnamespace, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
- NameStr(coll->collname));
-
- object.classId = CollationRelationId;
- object.objectId = collationOid;
- object.objectSubId = 0;
-
- add_exact_object_address(&object, objects);
-
- ReleaseSysCache(tuple);
- }
-
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-/*
* Rename collation
*/
void
diff --git a/src/backend/commands/conversioncmds.c b/src/backend/commands/conversioncmds.c
index cd7ae60..7d6063d 100644
--- a/src/backend/commands/conversioncmds.c
+++ b/src/backend/commands/conversioncmds.c
@@ -118,67 +118,6 @@ CreateConversionCommand(CreateConversionStmt *stmt)
}
/*
- * DROP CONVERSION
- */
-void
-DropConversionsCommand(DropStmt *drop)
-{
- ObjectAddresses *objects;
- ListCell *cell;
-
- /*
- * First we identify all the conversions, then we delete them in a single
- * performMultipleDeletions() call. This is to avoid unwanted DROP
- * RESTRICT errors if one of the conversions depends on another. (Not that
- * that is very likely, but we may as well do this consistently.)
- */
- objects = new_object_addresses();
-
- foreach(cell, drop->objects)
- {
- List *name = (List *) lfirst(cell);
- Oid conversionOid;
- HeapTuple tuple;
- Form_pg_conversion con;
- ObjectAddress object;
-
- conversionOid = get_conversion_oid(name, drop->missing_ok);
-
- if (!OidIsValid(conversionOid))
- {
- ereport(NOTICE,
- (errmsg("conversion \"%s\" does not exist, skipping",
- NameListToString(name))));
- continue;
- }
-
- tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(conversionOid));
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "cache lookup failed for conversion %u",
- conversionOid);
- con = (Form_pg_conversion) GETSTRUCT(tuple);
-
- /* Permission check: must own conversion or its namespace */
- if (!pg_conversion_ownercheck(conversionOid, GetUserId()) &&
- !pg_namespace_ownercheck(con->connamespace, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
- NameStr(con->conname));
-
- object.classId = ConversionRelationId;
- object.objectId = conversionOid;
- object.objectSubId = 0;
-
- add_exact_object_address(&object, objects);
-
- ReleaseSysCache(tuple);
- }
-
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-/*
* Rename conversion
*/
void
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
new file mode 100644
index 0000000..6316115
--- /dev/null
+++ b/src/backend/commands/dropcmds.c
@@ -0,0 +1,233 @@
+/*
+ * dropcmds.c
+ * routine to support DROP statement commonly
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/namespace.h"
+#include "catalog/objectaddress.h"
+#include "catalog/pg_class.h"
+#include "catalog/pg_collation.h"
+#include "catalog/pg_conversion.h"
+#include "catalog/pg_extension.h"
+#include "catalog/pg_index.h"
+#include "catalog/pg_namespace.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 "commands/defrem.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "parser/parse_type.h"
+#include "storage/lmgr.h"
+#include "utils/acl.h"
+#include "utils/inval.h"
+#include "utils/syscache.h"
+
+/*
+ * get_relation_address
+ *
+ * It is a routine to handle a case when relation objects are dropped,
+ * because it requires special case handling, so there are a few
+ * differences compared to regular get_object_address.
+ */
+static ObjectAddress
+get_relation_address(ObjectType objtype, List *objname,
+ Relation *relp, bool missing_ok)
+{
+ RangeVar *range = makeRangeVarFromNameList(objname);
+ Relation relation;
+ char relkind;
+ ObjectAddress address;
+
+ /*
+ * These next few steps are a great deal like relation_openrv, but we
+ * don't bother building a relcache entry since we don't need it.
+ *
+ * Check for shared-cache-inval messages before trying to access the
+ * relation. This is needed to cover the case where the name
+ * identifies a rel that has been dropped and recreated since the
+ * start of our transaction: if we don't flush the old syscache entry,
+ * then we'll latch onto that entry and suffer an error later.
+ */
+ AcceptInvalidationMessages();
+
+ /*
+ * Look up the appropriate relation using namespace search.
+ *
+ * XXX: Doing this without a lock is unsafe in the presence of
+ * concurrent DDL, but acquiring a lock here might violate the rule
+ * that a table must be locked before its corresponding index.
+ * So, for now, we ignore the hazard.
+ */
+ address.classId = RelationRelationId;
+ address.objectId = RangeVarGetRelid(range, NoLock, true, false);
+ address.objectSubId = 0;
+
+ if (!address.objectId)
+ {
+ if (!missing_ok)
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("%s \"%s\" does not exist",
+ get_object_property_typetext(objtype),
+ NameListToString(objname))));
+
+ return address;
+ }
+
+ /*
+ * In DROP INDEX, attempt to acquire lock on the parent table before
+ * locking the index. index_drop() will need this anyway, and since
+ * regular queries lock tables before their indexes, we risk deadlock
+ * if we do it the other way around. No error if we don't find a
+ * pg_index entry, though --- that most likely means it isn't an
+ * index, and we'll fail below.
+ */
+ if (objtype == OBJECT_INDEX)
+ {
+ HeapTuple tuple =
+ SearchSysCache1(INDEXRELID, ObjectIdGetDatum(address.objectId));
+
+ if (HeapTupleIsValid(tuple))
+ {
+ Form_pg_index index = (Form_pg_index) GETSTRUCT(tuple);
+
+ LockRelationOid(index->indrelid, AccessExclusiveLock);
+ ReleaseSysCache(tuple);
+ }
+ }
+
+ /*
+ * Lock relation to be removed
+ */
+ relation = relation_open(address.objectId, AccessExclusiveLock);
+
+ /*
+ * Sanity checks to prevent unsuitable object type
+ */
+ relkind = RelationGetForm(relation)->relkind;
+ if ((objtype == OBJECT_INDEX && relkind != RELKIND_INDEX) ||
+ (objtype == OBJECT_SEQUENCE && relkind != RELKIND_SEQUENCE) ||
+ (objtype == OBJECT_TABLE && relkind != RELKIND_RELATION) ||
+ (objtype == OBJECT_VIEW && relkind != RELKIND_VIEW) ||
+ (objtype == OBJECT_FOREIGN_TABLE && relkind != RELKIND_FOREIGN_TABLE))
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("\"%s\" is not a %s",
+ NameListToString(objname),
+ get_object_property_typetext(objtype))));
+
+ /*
+ * Sanity checks to prevent system catalog unintentionally
+ */
+ if (!!allowSystemTableMods && IsSystemRelation(relation))
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied: \"%s\" is a system catalog",
+ NameListToString(objname))));
+ /* Done */
+ *relp = relation;
+ return address;
+}
+
+/*
+ * RemoveObjects
+ *
+ * Implements most of DROP xxx statements.
+ */
+void
+RemoveObjects(DropStmt *stmt)
+{
+ ObjectAddresses *objects;
+ ListCell *cell1;
+ ListCell *cell2 = NULL;
+
+ Assert(!stmt->arguments ||
+ list_length(stmt->objects) == list_length(stmt->arguments));
+
+ objects = new_object_addresses();
+
+ foreach(cell1, stmt->objects)
+ {
+ ObjectAddress address;
+ List *objname = lfirst(cell1);
+ List *objargs = NIL;
+ Relation relation = NULL;
+ Oid namespaceId;
+
+ if (stmt->arguments)
+ {
+ cell2 = (!cell2 ? list_head(stmt->arguments) : lnext(cell2));
+ objargs = lfirst(cell2);
+ }
+
+ /*
+ * Resolve object name and arguments into ObjectAddress
+ */
+ switch (stmt->removeType)
+ {
+ case OBJECT_INDEX:
+ case OBJECT_SEQUENCE:
+ case OBJECT_TABLE:
+ case OBJECT_VIEW:
+ case OBJECT_FOREIGN_TABLE:
+ address = get_relation_address(stmt->removeType,
+ objname,
+ &relation,
+ stmt->missing_ok);
+ break;
+
+ default:
+ address = get_object_address(stmt->removeType,
+ objname, objargs,
+ &relation,
+ AccessExclusiveLock,
+ stmt->missing_ok);
+ break;
+ }
+
+ /*
+ * Raise an notice, if supplied object was not found
+ */
+ if (!OidIsValid(address.objectId))
+ {
+ ereport(NOTICE,
+ (errmsg("%s \"%s\" does not exist, skipping",
+ get_object_property_typetext(stmt->removeType),
+ NameListToString(objname))));
+ continue;
+ }
+
+ /*
+ * Permission checks
+ */
+ namespaceId = get_object_namespace(stmt->removeType, &address);
+ if (!OidIsValid(namespaceId) ||
+ !pg_namespace_ownercheck(namespaceId, GetUserId()))
+ check_object_ownership(GetUserId(), stmt->removeType, address,
+ objname, objargs, relation);
+
+ /*
+ * If get_object_address() opened the relation for us, we close it
+ * to keep the reference count correct - but we retain any locks
+ * acquired by get_object_address() until commit time, to guard
+ * against concurrent activities.
+ */
+ if (relation)
+ heap_close(relation, NoLock);
+
+ add_exact_object_address(&address, objects);
+ }
+ performMultipleDeletions(objects, stmt->behavior);
+
+ free_object_addresses(objects);
+}
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 5da5981..b8bbe53 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -1562,69 +1562,6 @@ InsertExtensionTuple(const char *extName, Oid extOwner,
return extensionOid;
}
-
-/*
- * RemoveExtensions
- * Implements DROP EXTENSION.
- */
-void
-RemoveExtensions(DropStmt *drop)
-{
- ObjectAddresses *objects;
- ListCell *cell;
-
- /*
- * First we identify all the extensions, then we delete them in a single
- * performMultipleDeletions() call. This is to avoid unwanted DROP
- * RESTRICT errors if one of the extensions depends on another.
- */
- objects = new_object_addresses();
-
- foreach(cell, drop->objects)
- {
- List *names = (List *) lfirst(cell);
- char *extensionName;
- Oid extensionId;
- ObjectAddress object;
-
- if (list_length(names) != 1)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("extension name cannot be qualified")));
- extensionName = strVal(linitial(names));
-
- extensionId = get_extension_oid(extensionName, drop->missing_ok);
-
- if (!OidIsValid(extensionId))
- {
- ereport(NOTICE,
- (errmsg("extension \"%s\" does not exist, skipping",
- extensionName)));
- continue;
- }
-
- /* Permission check: must own extension */
- if (!pg_extension_ownercheck(extensionId, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
- extensionName);
-
- object.classId = ExtensionRelationId;
- object.objectId = extensionId;
- object.objectSubId = 0;
-
- add_exact_object_address(&object, objects);
- }
-
- /*
- * Do the deletions. Objects contained in the extension(s) are removed by
- * means of their dependency links to the extensions.
- */
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-
/*
* Guts of extension deletion.
*
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index 9d1d653..8daa9d0 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -146,69 +146,6 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
SetUserIdAndSecContext(saved_uid, save_sec_context);
}
-
-/*
- * RemoveSchemas
- * Implements DROP SCHEMA.
- */
-void
-RemoveSchemas(DropStmt *drop)
-{
- ObjectAddresses *objects;
- ListCell *cell;
-
- /*
- * First we identify all the schemas, then we delete them in a single
- * performMultipleDeletions() call. This is to avoid unwanted DROP
- * RESTRICT errors if one of the schemas depends on another.
- */
- objects = new_object_addresses();
-
- foreach(cell, drop->objects)
- {
- List *names = (List *) lfirst(cell);
- char *namespaceName;
- Oid namespaceId;
- ObjectAddress object;
-
- if (list_length(names) != 1)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("schema name cannot be qualified")));
- namespaceName = strVal(linitial(names));
-
- namespaceId = get_namespace_oid(namespaceName, drop->missing_ok);
-
- if (!OidIsValid(namespaceId))
- {
- ereport(NOTICE,
- (errmsg("schema \"%s\" does not exist, skipping",
- namespaceName)));
- continue;
- }
-
- /* Permission check */
- if (!pg_namespace_ownercheck(namespaceId, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
- namespaceName);
-
- object.classId = NamespaceRelationId;
- object.objectId = namespaceId;
- object.objectSubId = 0;
-
- add_exact_object_address(&object, objects);
- }
-
- /*
- * Do the deletions. Objects contained in the schema(s) are removed by
- * means of their dependency links to the schema.
- */
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-
/*
* Guts of schema deletion.
*/
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 1e8ad2b..471a48e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -182,59 +182,6 @@ typedef struct NewColumnValue
ExprState *exprstate; /* execution state */
} NewColumnValue;
-/*
- * Error-reporting support for RemoveRelations
- */
-struct dropmsgstrings
-{
- char kind;
- int nonexistent_code;
- const char *nonexistent_msg;
- const char *skipping_msg;
- const char *nota_msg;
- const char *drophint_msg;
-};
-
-static const struct dropmsgstrings dropmsgstringarray[] = {
- {RELKIND_RELATION,
- ERRCODE_UNDEFINED_TABLE,
- gettext_noop("table \"%s\" does not exist"),
- gettext_noop("table \"%s\" does not exist, skipping"),
- gettext_noop("\"%s\" is not a table"),
- gettext_noop("Use DROP TABLE to remove a table.")},
- {RELKIND_SEQUENCE,
- ERRCODE_UNDEFINED_TABLE,
- gettext_noop("sequence \"%s\" does not exist"),
- gettext_noop("sequence \"%s\" does not exist, skipping"),
- gettext_noop("\"%s\" is not a sequence"),
- gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
- {RELKIND_VIEW,
- ERRCODE_UNDEFINED_TABLE,
- gettext_noop("view \"%s\" does not exist"),
- gettext_noop("view \"%s\" does not exist, skipping"),
- gettext_noop("\"%s\" is not a view"),
- gettext_noop("Use DROP VIEW to remove a view.")},
- {RELKIND_INDEX,
- ERRCODE_UNDEFINED_OBJECT,
- gettext_noop("index \"%s\" does not exist"),
- gettext_noop("index \"%s\" does not exist, skipping"),
- gettext_noop("\"%s\" is not an index"),
- gettext_noop("Use DROP INDEX to remove an index.")},
- {RELKIND_COMPOSITE_TYPE,
- ERRCODE_UNDEFINED_OBJECT,
- gettext_noop("type \"%s\" does not exist"),
- gettext_noop("type \"%s\" does not exist, skipping"),
- gettext_noop("\"%s\" is not a type"),
- gettext_noop("Use DROP TYPE to remove a type.")},
- {RELKIND_FOREIGN_TABLE,
- ERRCODE_UNDEFINED_OBJECT,
- gettext_noop("foreign table \"%s\" does not exist"),
- gettext_noop("foreign table \"%s\" does not exist, skipping"),
- gettext_noop("\"%s\" is not a foreign table"),
- gettext_noop("Use DROP FOREIGN TABLE to remove a foreign table.")},
- {'\0', 0, NULL, NULL, NULL, NULL}
-};
-
/* Alter table target-type flags for ATSimplePermissions */
#define ATT_TABLE 0x0001
#define ATT_VIEW 0x0002
@@ -641,208 +588,6 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
}
/*
- * Emit the right error or warning message for a "DROP" command issued on a
- * non-existent relation
- */
-static void
-DropErrorMsgNonExistent(const char *relname, char rightkind, bool missing_ok)
-{
- const struct dropmsgstrings *rentry;
-
- for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
- {
- if (rentry->kind == rightkind)
- {
- if (!missing_ok)
- {
- ereport(ERROR,
- (errcode(rentry->nonexistent_code),
- errmsg(rentry->nonexistent_msg, relname)));
- }
- else
- {
- ereport(NOTICE, (errmsg(rentry->skipping_msg, relname)));
- break;
- }
- }
- }
-
- Assert(rentry->kind != '\0'); /* Should be impossible */
-}
-
-/*
- * Emit the right error message for a "DROP" command issued on a
- * relation of the wrong type
- */
-static void
-DropErrorMsgWrongType(const char *relname, char wrongkind, char rightkind)
-{
- const struct dropmsgstrings *rentry;
- const struct dropmsgstrings *wentry;
-
- for (rentry = dropmsgstringarray; rentry->kind != '\0'; rentry++)
- if (rentry->kind == rightkind)
- break;
- Assert(rentry->kind != '\0');
-
- for (wentry = dropmsgstringarray; wentry->kind != '\0'; wentry++)
- if (wentry->kind == wrongkind)
- break;
- /* wrongkind could be something we don't have in our table... */
-
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg(rentry->nota_msg, relname),
- (wentry->kind != '\0') ? errhint("%s", _(wentry->drophint_msg)) : 0));
-}
-
-/*
- * RemoveRelations
- * Implements DROP TABLE, DROP INDEX, DROP SEQUENCE, DROP VIEW,
- * DROP FOREIGN TABLE
- */
-void
-RemoveRelations(DropStmt *drop)
-{
- ObjectAddresses *objects;
- char relkind;
- ListCell *cell;
-
- /*
- * First we identify all the relations, then we delete them in a single
- * performMultipleDeletions() call. This is to avoid unwanted DROP
- * RESTRICT errors if one of the relations depends on another.
- */
-
- /* Determine required relkind */
- switch (drop->removeType)
- {
- case OBJECT_TABLE:
- relkind = RELKIND_RELATION;
- break;
-
- case OBJECT_INDEX:
- relkind = RELKIND_INDEX;
- break;
-
- case OBJECT_SEQUENCE:
- relkind = RELKIND_SEQUENCE;
- break;
-
- case OBJECT_VIEW:
- relkind = RELKIND_VIEW;
- break;
-
- case OBJECT_FOREIGN_TABLE:
- relkind = RELKIND_FOREIGN_TABLE;
- break;
-
- default:
- elog(ERROR, "unrecognized drop object type: %d",
- (int) drop->removeType);
- relkind = 0; /* keep compiler quiet */
- break;
- }
-
- /* Lock and validate each relation; build a list of object addresses */
- objects = new_object_addresses();
-
- foreach(cell, drop->objects)
- {
- RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell));
- Oid relOid;
- HeapTuple tuple;
- Form_pg_class classform;
- ObjectAddress obj;
-
- /*
- * These next few steps are a great deal like relation_openrv, but we
- * don't bother building a relcache entry since we don't need it.
- *
- * Check for shared-cache-inval messages before trying to access the
- * relation. This is needed to cover the case where the name
- * identifies a rel that has been dropped and recreated since the
- * start of our transaction: if we don't flush the old syscache entry,
- * then we'll latch onto that entry and suffer an error later.
- */
- AcceptInvalidationMessages();
-
- /*
- * Look up the appropriate relation using namespace search.
- *
- * XXX: Doing this without a lock is unsafe in the presence of
- * concurrent DDL, but acquiring a lock here might violate the rule
- * that a table must be locked before its corresponding index.
- * So, for now, we ignore the hazard.
- */
- relOid = RangeVarGetRelid(rel, NoLock, true, false);
-
- /* Not there? */
- if (!OidIsValid(relOid))
- {
- DropErrorMsgNonExistent(rel->relname, relkind, drop->missing_ok);
- continue;
- }
-
- /*
- * In DROP INDEX, attempt to acquire lock on the parent table before
- * locking the index. index_drop() will need this anyway, and since
- * regular queries lock tables before their indexes, we risk deadlock
- * if we do it the other way around. No error if we don't find a
- * pg_index entry, though --- that most likely means it isn't an
- * index, and we'll fail below.
- */
- if (relkind == RELKIND_INDEX)
- {
- tuple = SearchSysCache1(INDEXRELID, ObjectIdGetDatum(relOid));
- if (HeapTupleIsValid(tuple))
- {
- Form_pg_index index = (Form_pg_index) GETSTRUCT(tuple);
-
- LockRelationOid(index->indrelid, AccessExclusiveLock);
- ReleaseSysCache(tuple);
- }
- }
-
- /* Get the lock before trying to fetch the syscache entry */
- LockRelationOid(relOid, AccessExclusiveLock);
-
- tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "cache lookup failed for relation %u", relOid);
- classform = (Form_pg_class) GETSTRUCT(tuple);
-
- if (classform->relkind != relkind)
- DropErrorMsgWrongType(rel->relname, classform->relkind, relkind);
-
- /* Allow DROP to either table owner or schema owner */
- if (!pg_class_ownercheck(relOid, GetUserId()) &&
- !pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
- rel->relname);
-
- if (!allowSystemTableMods && IsSystemClass(classform))
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("permission denied: \"%s\" is a system catalog",
- rel->relname)));
-
- /* OK, we're ready to delete this one */
- obj.classId = RelationRelationId;
- obj.objectId = relOid;
- obj.objectSubId = 0;
-
- add_exact_object_address(&obj, objects);
-
- ReleaseSysCache(tuple);
- }
-
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-/*
* ExecuteTruncate
* Executes a TRUNCATE command.
*
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 16e6940..5f206d8 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -279,65 +279,6 @@ DefineTSParser(List *names, List *parameters)
}
/*
- * DROP TEXT SEARCH PARSER
- */
-void
-RemoveTSParsers(DropStmt *drop)
-{
- ObjectAddresses *objects;
- ListCell *cell;
-
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to drop text search parsers")));
-
- /*
- * First we identify all the objects, then we delete them in a single
- * performMultipleDeletions() call. This is to avoid unwanted DROP
- * RESTRICT errors if one of the objects depends on another.
- */
- objects = new_object_addresses();
-
- foreach(cell, drop->objects)
- {
- List *names = (List *) lfirst(cell);
- Oid prsOid;
- ObjectAddress object;
-
- prsOid = get_ts_parser_oid(names, true);
-
- if (!OidIsValid(prsOid))
- {
- if (!drop->missing_ok)
- {
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("text search parser \"%s\" does not exist",
- NameListToString(names))));
- }
- else
- {
- ereport(NOTICE,
- (errmsg("text search parser \"%s\" does not exist, skipping",
- NameListToString(names))));
- }
- continue;
- }
-
- object.classId = TSParserRelationId;
- object.objectId = prsOid;
- object.objectSubId = 0;
-
- add_exact_object_address(&object, objects);
- }
-
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-/*
* Guts of TS parser deletion.
*/
void
@@ -731,76 +672,6 @@ AlterTSDictionaryNamespace_oid(Oid dictId, Oid newNspOid)
}
/*
- * DROP TEXT SEARCH DICTIONARY
- */
-void
-RemoveTSDictionaries(DropStmt *drop)
-{
- ObjectAddresses *objects;
- ListCell *cell;
-
- /*
- * First we identify all the objects, then we delete them in a single
- * performMultipleDeletions() call. This is to avoid unwanted DROP
- * RESTRICT errors if one of the objects depends on another.
- */
- objects = new_object_addresses();
-
- foreach(cell, drop->objects)
- {
- List *names = (List *) lfirst(cell);
- Oid dictOid;
- ObjectAddress object;
- HeapTuple tup;
- Oid namespaceId;
-
- dictOid = get_ts_dict_oid(names, true);
-
- if (!OidIsValid(dictOid))
- {
- if (!drop->missing_ok)
- {
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("text search dictionary \"%s\" does not exist",
- NameListToString(names))));
- }
- else
- {
- ereport(NOTICE,
- (errmsg("text search dictionary \"%s\" does not exist, skipping",
- NameListToString(names))));
- }
- continue;
- }
-
- tup = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(dictOid));
- if (!HeapTupleIsValid(tup)) /* should not happen */
- elog(ERROR, "cache lookup failed for text search dictionary %u",
- dictOid);
-
- /* Permission check: must own dictionary or its namespace */
- namespaceId = ((Form_pg_ts_dict) GETSTRUCT(tup))->dictnamespace;
- if (!pg_ts_dict_ownercheck(dictOid, GetUserId()) &&
- !pg_namespace_ownercheck(namespaceId, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
- NameListToString(names));
-
- object.classId = TSDictionaryRelationId;
- object.objectId = dictOid;
- object.objectSubId = 0;
-
- add_exact_object_address(&object, objects);
-
- ReleaseSysCache(tup);
- }
-
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-/*
* Guts of TS dictionary deletion.
*/
void
@@ -1263,65 +1134,6 @@ AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid)
}
/*
- * DROP TEXT SEARCH TEMPLATE
- */
-void
-RemoveTSTemplates(DropStmt *drop)
-{
- ObjectAddresses *objects;
- ListCell *cell;
-
- if (!superuser())
- ereport(ERROR,
- (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
- errmsg("must be superuser to drop text search templates")));
-
- /*
- * First we identify all the objects, then we delete them in a single
- * performMultipleDeletions() call. This is to avoid unwanted DROP
- * RESTRICT errors if one of the objects depends on another.
- */
- objects = new_object_addresses();
-
- foreach(cell, drop->objects)
- {
- List *names = (List *) lfirst(cell);
- Oid tmplOid;
- ObjectAddress object;
-
- tmplOid = get_ts_template_oid(names, true);
-
- if (!OidIsValid(tmplOid))
- {
- if (!drop->missing_ok)
- {
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("text search template \"%s\" does not exist",
- NameListToString(names))));
- }
- else
- {
- ereport(NOTICE,
- (errmsg("text search template \"%s\" does not exist, skipping",
- NameListToString(names))));
- }
- continue;
- }
-
- object.classId = TSTemplateRelationId;
- object.objectId = tmplOid;
- object.objectSubId = 0;
-
- add_exact_object_address(&object, objects);
- }
-
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-/*
* Guts of TS template deletion.
*/
void
@@ -1715,72 +1527,6 @@ AlterTSConfigurationNamespace_oid(Oid cfgId, Oid newNspOid)
}
/*
- * DROP TEXT SEARCH CONFIGURATION
- */
-void
-RemoveTSConfigurations(DropStmt *drop)
-{
- ObjectAddresses *objects;
- ListCell *cell;
-
- /*
- * First we identify all the objects, then we delete them in a single
- * performMultipleDeletions() call. This is to avoid unwanted DROP
- * RESTRICT errors if one of the objects depends on another.
- */
- objects = new_object_addresses();
-
- foreach(cell, drop->objects)
- {
- List *names = (List *) lfirst(cell);
- Oid cfgOid;
- Oid namespaceId;
- ObjectAddress object;
- HeapTuple tup;
-
- tup = GetTSConfigTuple(names);
-
- if (!HeapTupleIsValid(tup))
- {
- if (!drop->missing_ok)
- {
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("text search configuration \"%s\" does not exist",
- NameListToString(names))));
- }
- else
- {
- ereport(NOTICE,
- (errmsg("text search configuration \"%s\" does not exist, skipping",
- NameListToString(names))));
- }
- continue;
- }
-
- /* Permission check: must own configuration or its namespace */
- cfgOid = HeapTupleGetOid(tup);
- namespaceId = ((Form_pg_ts_config) GETSTRUCT(tup))->cfgnamespace;
- if (!pg_ts_config_ownercheck(cfgOid, GetUserId()) &&
- !pg_namespace_ownercheck(namespaceId, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
- NameListToString(names));
-
- object.classId = TSConfigRelationId;
- object.objectId = cfgOid;
- object.objectSubId = 0;
-
- add_exact_object_address(&object, objects);
-
- ReleaseSysCache(tup);
- }
-
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-/*
* Guts of TS configuration deletion.
*/
void
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 7c27f85..5069c57 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -618,98 +618,6 @@ DefineType(List *names, List *parameters)
pfree(array_type);
}
-
-/*
- * 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
-RemoveTypes(DropStmt *drop)
-{
- ObjectAddresses *objects;
- ListCell *cell;
-
- /*
- * 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();
-
- foreach(cell, drop->objects)
- {
- 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)
- {
- 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;
- }
-
- 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,
- format_type_be(typeoid));
-
- if (drop->removeType == OBJECT_DOMAIN)
- {
- /* 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))));
- }
-
- /*
- * Note: we need no special check for array types here, as the normal
- * treatment of internal dependencies handles it just fine
- */
-
- object.classId = TypeRelationId;
- object.objectId = typeoid;
- object.objectSubId = 0;
-
- add_exact_object_address(&object, objects);
-
- ReleaseSysCache(tup);
- }
-
- performMultipleDeletions(objects, drop->behavior);
-
- free_object_addresses(objects);
-}
-
-
/*
* Guts of type deletion.
*/
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 661a516..3658e9c 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -2730,6 +2730,7 @@ _copyDropStmt(DropStmt *from)
DropStmt *newnode = makeNode(DropStmt);
COPY_NODE_FIELD(objects);
+ COPY_NODE_FIELD(arguments);
COPY_SCALAR_FIELD(removeType);
COPY_SCALAR_FIELD(behavior);
COPY_SCALAR_FIELD(missing_ok);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 4052a9a..7f7bda1 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1182,6 +1182,7 @@ static bool
_equalDropStmt(DropStmt *a, DropStmt *b)
{
COMPARE_NODE_FIELD(objects);
+ COMPARE_NODE_FIELD(arguments);
COMPARE_SCALAR_FIELD(removeType);
COMPARE_SCALAR_FIELD(behavior);
COMPARE_SCALAR_FIELD(missing_ok);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index e9f3896..f583917 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -4732,6 +4732,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
n->removeType = $2;
n->missing_ok = TRUE;
n->objects = $5;
+ n->arguments = NIL;
n->behavior = $6;
$$ = (Node *)n;
}
@@ -4741,6 +4742,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior
n->removeType = $2;
n->missing_ok = FALSE;
n->objects = $3;
+ n->arguments = NIL;
n->behavior = $4;
$$ = (Node *)n;
}
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 0749227..18aada7 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -644,62 +644,7 @@ standard_ProcessUtility(Node *parsetree,
break;
case T_DropStmt:
- {
- DropStmt *stmt = (DropStmt *) parsetree;
-
- switch (stmt->removeType)
- {
- case OBJECT_TABLE:
- case OBJECT_SEQUENCE:
- case OBJECT_VIEW:
- case OBJECT_INDEX:
- case OBJECT_FOREIGN_TABLE:
- RemoveRelations(stmt);
- break;
-
- case OBJECT_TYPE:
- case OBJECT_DOMAIN:
- RemoveTypes(stmt);
- break;
-
- case OBJECT_COLLATION:
- DropCollationsCommand(stmt);
- break;
-
- case OBJECT_CONVERSION:
- DropConversionsCommand(stmt);
- break;
-
- case OBJECT_SCHEMA:
- RemoveSchemas(stmt);
- break;
-
- case OBJECT_TSPARSER:
- RemoveTSParsers(stmt);
- break;
-
- case OBJECT_TSDICTIONARY:
- RemoveTSDictionaries(stmt);
- break;
-
- case OBJECT_TSTEMPLATE:
- RemoveTSTemplates(stmt);
- break;
-
- case OBJECT_TSCONFIGURATION:
- RemoveTSConfigurations(stmt);
- break;
-
- case OBJECT_EXTENSION:
- RemoveExtensions(stmt);
- break;
-
- default:
- elog(ERROR, "unrecognized drop object type: %d",
- (int) stmt->removeType);
- break;
- }
- }
+ RemoveObjects((DropStmt *) parsetree);
break;
case T_TruncateStmt:
diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h
index 9ad2490..d09d235 100644
--- a/src/include/catalog/objectaddress.h
+++ b/src/include/catalog/objectaddress.h
@@ -35,6 +35,9 @@ extern void check_object_ownership(Oid roleid,
ObjectType objtype, ObjectAddress address,
List *objname, List *objargs, Relation relation);
+extern Oid get_object_namespace(ObjectType objtype,
+ const ObjectAddress *address);
+
/*
* Obtain property of object type
*/
diff --git a/src/include/commands/collationcmds.h b/src/include/commands/collationcmds.h
index 6dbeb75..ce4727c 100644
--- a/src/include/commands/collationcmds.h
+++ b/src/include/commands/collationcmds.h
@@ -18,7 +18,6 @@
#include "nodes/parsenodes.h"
extern void DefineCollation(List *names, List *parameters);
-extern void DropCollationsCommand(DropStmt *drop);
extern void RenameCollation(List *name, const char *newname);
extern void AlterCollationOwner(List *name, Oid newOwnerId);
extern void AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId);
diff --git a/src/include/commands/conversioncmds.h b/src/include/commands/conversioncmds.h
index f77023f..c0e7cd9 100644
--- a/src/include/commands/conversioncmds.h
+++ b/src/include/commands/conversioncmds.h
@@ -18,7 +18,6 @@
#include "nodes/parsenodes.h"
extern void CreateConversionCommand(CreateConversionStmt *parsetree);
-extern void DropConversionsCommand(DropStmt *drop);
extern void RenameConversion(List *name, const char *newname);
extern void AlterConversionOwner(List *name, Oid newOwnerId);
extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId);
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 81c515e..64eeb73 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -16,6 +16,8 @@
#include "nodes/parsenodes.h"
+/* commands/dropcmds.c */
+extern void RemoveObjects(DropStmt *stmt);
/* commands/indexcmds.c */
extern Oid DefineIndex(RangeVar *heapRelation,
@@ -122,12 +124,10 @@ extern void DefineTSParser(List *names, List *parameters);
extern void RenameTSParser(List *oldname, const char *newname);
extern void AlterTSParserNamespace(List *name, const char *newschema);
extern Oid AlterTSParserNamespace_oid(Oid prsId, Oid newNspOid);
-extern void RemoveTSParsers(DropStmt *drop);
extern void RemoveTSParserById(Oid prsId);
extern void DefineTSDictionary(List *names, List *parameters);
extern void RenameTSDictionary(List *oldname, const char *newname);
-extern void RemoveTSDictionaries(DropStmt *drop);
extern void RemoveTSDictionaryById(Oid dictId);
extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId);
@@ -138,12 +138,10 @@ extern void DefineTSTemplate(List *names, List *parameters);
extern void RenameTSTemplate(List *oldname, const char *newname);
extern void AlterTSTemplateNamespace(List *name, const char *newschema);
extern Oid AlterTSTemplateNamespace_oid(Oid tmplId, Oid newNspOid);
-extern void RemoveTSTemplates(DropStmt *stmt);
extern void RemoveTSTemplateById(Oid tmplId);
extern void DefineTSConfiguration(List *names, List *parameters);
extern void RenameTSConfiguration(List *oldname, const char *newname);
-extern void RemoveTSConfigurations(DropStmt *stmt);
extern void RemoveTSConfigurationById(Oid cfgId);
extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId);
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index 2792c6d..f22ac80 100644
--- a/src/include/commands/extension.h
+++ b/src/include/commands/extension.h
@@ -29,7 +29,6 @@ extern Oid CurrentExtensionObject;
extern void CreateExtension(CreateExtensionStmt *stmt);
-extern void RemoveExtensions(DropStmt *stmt);
extern void RemoveExtensionById(Oid extId);
extern Oid InsertExtensionTuple(const char *extName, Oid extOwner,
diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h
index a9f8f6c..ec8d895 100644
--- a/src/include/commands/schemacmds.h
+++ b/src/include/commands/schemacmds.h
@@ -20,7 +20,6 @@
extern void CreateSchemaCommand(CreateSchemaStmt *parsetree,
const char *queryString);
-extern void RemoveSchemas(DropStmt *drop);
extern void RemoveSchemaById(Oid schemaOid);
extern void RenameSchema(const char *oldname, const char *newname);
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index 333e303..5509b28 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -22,8 +22,6 @@
extern Oid DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId);
-extern void RemoveRelations(DropStmt *drop);
-
extern void AlterTable(AlterTableStmt *stmt);
extern LOCKMODE AlterTableGetLockLevel(List *cmds);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index 23726fb..429a964 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -20,7 +20,6 @@
#define DEFAULT_TYPDELIM ','
extern void DefineType(List *names, List *parameters);
-extern void RemoveTypes(DropStmt *drop);
extern void RemoveTypeById(Oid typeOid);
extern void DefineDomain(CreateDomainStmt *stmt);
extern void DefineEnum(CreateEnumStmt *stmt);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 9998e2f..b124d63 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1921,6 +1921,7 @@ typedef struct DropStmt
{
NodeTag type;
List *objects; /* list of sublists of names (as Values) */
+ List *arguments; /* list of sublists of arguments (as Values) */
ObjectType removeType; /* object type */
DropBehavior behavior; /* RESTRICT or CASCADE behavior */
bool missing_ok; /* skip error if object is missing? */
diff --git a/src/test/regress/expected/drop_if_exists.out b/src/test/regress/expected/drop_if_exists.out
index 2a23b4c..173c384 100644
--- a/src/test/regress/expected/drop_if_exists.out
+++ b/src/test/regress/expected/drop_if_exists.out
@@ -56,7 +56,7 @@ ERROR: type "test_type_exists" does not exist
DROP DOMAIN test_domain_exists;
ERROR: type "test_domain_exists" does not exist
DROP DOMAIN IF EXISTS test_domain_exists;
-NOTICE: type "test_domain_exists" does not exist, skipping
+NOTICE: domain "test_domain_exists" does not exist, skipping
CREATE domain test_domain_exists as int not null check (value > 0);
DROP DOMAIN IF EXISTS test_domain_exists;
DROP DOMAIN test_domain_exists;