src/backend/commands/Makefile | 2 +- src/backend/commands/collationcmds.c | 61 ----- src/backend/commands/conversioncmds.c | 61 ----- src/backend/commands/dropcmds.c | 456 +++++++++++++++++++++++++++++++++ src/backend/commands/extension.c | 63 ----- src/backend/commands/schemacmds.c | 63 ----- src/backend/commands/tablecmds.c | 248 ------------------ 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/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 + 21 files changed, 465 insertions(+), 910 deletions(-) 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 9e6138b..3f9f660 100644 --- a/src/backend/commands/collationcmds.c +++ b/src/backend/commands/collationcmds.c @@ -146,67 +146,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 2c1c6da..8dafec9 100644 --- a/src/backend/commands/conversioncmds.c +++ b/src/backend/commands/conversioncmds.c @@ -120,67 +120,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..64e8c3a --- /dev/null +++ b/src/backend/commands/dropcmds.c @@ -0,0 +1,456 @@ +/* + * 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" + +static void +notice_object_non_existent(ObjectType type, List *objname, List *objargs) +{ + switch (type) + { + case OBJECT_TABLE: + ereport(NOTICE, + (errmsg("table \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_INDEX: + ereport(NOTICE, + (errmsg("index \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_SEQUENCE: + ereport(NOTICE, + (errmsg("sequence \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_VIEW: + ereport(NOTICE, + (errmsg("view \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_FOREIGN_TABLE: + ereport(NOTICE, + (errmsg("foreign table \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_TYPE: + case OBJECT_DOMAIN: + { + TypeName *typename = makeTypeNameFromNameList(objname); + ereport(NOTICE, + (errmsg("type \"%s\" does not exist, skipping", + TypeNameToString(typename)))); + } + break; + + case OBJECT_COLLATION: + ereport(NOTICE, + (errmsg("collation \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_CONVERSION: + ereport(NOTICE, + (errmsg("conversion \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_SCHEMA: + ereport(NOTICE, + (errmsg("schema \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_TSPARSER: + ereport(NOTICE, + (errmsg("text search parser \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_TSDICTIONARY: + ereport(NOTICE, + (errmsg("text search dictionary \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_TSTEMPLATE: + ereport(NOTICE, + (errmsg("text search template \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_TSCONFIGURATION: + ereport(NOTICE, + (errmsg("text search configuration \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + case OBJECT_EXTENSION: + ereport(NOTICE, + (errmsg("extension \"%s\" does not exist, skipping", + NameListToString(objname)))); + break; + + default: + elog(ERROR, "unrecognized drop object type: %d", (int) type); + break; + } +} + +static Oid +get_object_namespace(const ObjectAddress *address) +{ + Oid namespaceId = InvalidOid; + Oid objectId = address->objectId; + HeapTuple tuple; + + switch (address->classId) + { + case RelationRelationId: + tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for relation %u", objectId); + namespaceId = ((Form_pg_class) GETSTRUCT(tuple))->relnamespace; + ReleaseSysCache(tuple); + break; + + case TypeRelationId: + tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for type %u", objectId); + namespaceId = ((Form_pg_type) GETSTRUCT(tuple))->typnamespace; + ReleaseSysCache(tuple); + break; + + case CollationRelationId: + tuple = SearchSysCache1(COLLOID, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for collation %u", objectId); + namespaceId = ((Form_pg_collation) GETSTRUCT(tuple))->collnamespace; + ReleaseSysCache(tuple); + break; + + case ConversionRelationId: + tuple = SearchSysCache1(CONVOID, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for conversion %u", objectId); + namespaceId = ((Form_pg_conversion) GETSTRUCT(tuple))->connamespace; + ReleaseSysCache(tuple); + break; + + case TSParserRelationId: + tuple = SearchSysCache1(TSPARSEROID, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for text search parser %u", + objectId); + namespaceId = ((Form_pg_ts_parser) GETSTRUCT(tuple))->prsnamespace; + ReleaseSysCache(tuple); + break; + + case TSDictionaryRelationId: + tuple = SearchSysCache1(TSDICTOID, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for text search dictionary %u", + objectId); + namespaceId = ((Form_pg_ts_dict) GETSTRUCT(tuple))->dictnamespace; + ReleaseSysCache(tuple); + break; + + case TSTemplateRelationId: + tuple = SearchSysCache1(TSTEMPLATEOID, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for text search template %u", + objectId); + namespaceId = ((Form_pg_ts_template) GETSTRUCT(tuple))->tmplnamespace; + ReleaseSysCache(tuple); + break; + + case TSConfigRelationId: + tuple = SearchSysCache1(TSCONFIGOID, ObjectIdGetDatum(objectId)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for text search dictionary %u", + objectId); + namespaceId = ((Form_pg_ts_config) GETSTRUCT(tuple))->cfgnamespace; + ReleaseSysCache(tuple); + break; + + default: + /* + * The supplied object type does not have its namespace. + */ + namespaceId = InvalidOid; + break; + } + return namespaceId; +} + +static ObjectAddress +get_relation_address(ObjectType objtype, List *objname, + Relation *relp, bool missing_ok) +{ + RangeVar *range = makeRangeVarFromNameList(objname); + Relation relation; + 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 */ + address.classId = RelationRelationId; + address.objectId = RangeVarGetRelid(range, true); + address.objectSubId = 0; + + if (!address.objectId) + { + if (!missing_ok) + { + switch (objtype) + { + case OBJECT_INDEX: + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("index \"%s\" does not exist", + NameListToString(objname)))); + break; + case OBJECT_SEQUENCE: + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("sequence \"%s\" does not exist", + NameListToString(objname)))); + break; + case OBJECT_TABLE: + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("table \"%s\" does not exist", + NameListToString(objname)))); + break; + case OBJECT_VIEW: + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_TABLE), + errmsg("view \"%s\" does not exist", + NameListToString(objname)))); + break; + case OBJECT_FOREIGN_TABLE: + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("foreign table \"%s\" does not exist", + NameListToString(objname)))); + break; + default: + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + break; + } + } + 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); + + switch (objtype) + { + case OBJECT_INDEX: + if (RelationGetForm(relation)->relkind != RELKIND_INDEX) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not an index", + NameListToString(objname)))); + break; + case OBJECT_SEQUENCE: + if (RelationGetForm(relation)->relkind != RELKIND_SEQUENCE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a sequence", + NameListToString(objname)))); + break; + case OBJECT_TABLE: + if (RelationGetForm(relation)->relkind != RELKIND_RELATION) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a table", + NameListToString(objname)))); + break; + case OBJECT_VIEW: + if (RelationGetForm(relation)->relkind != RELKIND_VIEW) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a view", + NameListToString(objname)))); + break; + case OBJECT_FOREIGN_TABLE: + if (RelationGetForm(relation)->relkind != RELKIND_FOREIGN_TABLE) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a foreign table", + NameListToString(objname)))); + break; + default: + elog(ERROR, "unrecognized objtype: %d", (int) objtype); + break; + } + + /* + * 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; +} + +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)) + { + notice_object_non_existent(stmt->removeType, + objname, objargs); + continue; + } + + /* + * Permission checks + */ + namespaceId = get_object_namespace(&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 a0385eb..fdd0d28 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -1555,69 +1555,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 5dd5763..1f941c9 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -148,69 +148,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 3bc350a..039d49d 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 @@ -638,201 +585,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 */ - relOid = RangeVarGetRelid(rel, true); - - /* 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 3355eaa..197dce7 100644 --- a/src/backend/commands/tsearchcmds.c +++ b/src/backend/commands/tsearchcmds.c @@ -283,65 +283,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 @@ -735,76 +676,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 @@ -1267,65 +1138,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 @@ -1720,72 +1532,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 c9133dd..0bd8882 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -2734,6 +2734,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 3a0267c..ea972be 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 7226032..2da12f3 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -4722,6 +4722,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; } @@ -4731,6 +4732,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 224e1f3..4336c5e 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -636,62 +636,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/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 bbc024f..641497b 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 void DefineIndex(RangeVar *heapRelation, @@ -116,12 +118,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); @@ -132,12 +132,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 3f971eb..eb93841 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -21,8 +21,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 00c1269..068ba00 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1919,6 +1919,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? */