From 11333426f103bedef311d1dd88b62176276b8544 Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Thu, 18 Jul 2002 16:47:26 +0000 Subject: [PATCH] Implement DROP SCHEMA. It lacks support for dropping conversions and operator classes, both of which are schema-local and so should really be droppable. --- doc/src/sgml/ref/allfiles.sgml | 3 +- doc/src/sgml/ref/drop_schema.sgml | 184 ++++++++++++++++++++++++++++++ doc/src/sgml/reference.sgml | 3 +- src/backend/catalog/dependency.c | 31 ++++- src/backend/catalog/heap.c | 21 +++- src/backend/catalog/index.c | 5 +- src/backend/catalog/pg_operator.c | 13 ++- src/backend/catalog/pg_proc.c | 8 +- src/backend/catalog/pg_type.c | 133 +++++++++++---------- src/backend/commands/schemacmds.c | 75 +++++++++++- src/backend/parser/gram.y | 24 +--- src/backend/tcop/postgres.c | 9 +- src/backend/tcop/utility.c | 21 ++-- src/bin/initdb/initdb.sh | 5 +- src/include/commands/schemacmds.h | 5 +- src/include/nodes/parsenodes.h | 5 +- 16 files changed, 438 insertions(+), 107 deletions(-) create mode 100644 doc/src/sgml/ref/drop_schema.sgml diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml index c039f661b0c..c9ece5af561 100644 --- a/doc/src/sgml/ref/allfiles.sgml +++ b/doc/src/sgml/ref/allfiles.sgml @@ -1,5 +1,5 @@ <!-- -$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.39 2002/04/25 21:47:07 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.40 2002/07/18 16:47:22 tgl Exp $ PostgreSQL documentation Complete list of usable sgml source files in this directory. --> @@ -79,6 +79,7 @@ Complete list of usable sgml source files in this directory. <!entity dropLanguage system "drop_language.sgml"> <!entity dropOperator system "drop_operator.sgml"> <!entity dropRule system "drop_rule.sgml"> +<!entity dropSchema system "drop_schema.sgml"> <!entity dropSequence system "drop_sequence.sgml"> <!entity dropTable system "drop_table.sgml"> <!entity dropTrigger system "drop_trigger.sgml"> diff --git a/doc/src/sgml/ref/drop_schema.sgml b/doc/src/sgml/ref/drop_schema.sgml new file mode 100644 index 00000000000..8c69893ae2f --- /dev/null +++ b/doc/src/sgml/ref/drop_schema.sgml @@ -0,0 +1,184 @@ +<!-- +$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_schema.sgml,v 1.1 2002/07/18 16:47:22 tgl Exp $ +PostgreSQL documentation +--> + +<refentry id="SQL-DROPSCHEMA"> + <refmeta> + <refentrytitle id="SQL-DROPSCHEMA-TITLE">DROP SCHEMA</refentrytitle> + <refmiscinfo>SQL - Language Statements</refmiscinfo> + </refmeta> + <refnamediv> + <refname> + DROP SCHEMA + </refname> + <refpurpose> + remove a schema + </refpurpose> + </refnamediv> + <refsynopsisdiv> + <refsynopsisdivinfo> + <date>2002-07-18</date> + </refsynopsisdivinfo> + <synopsis> +DROP SCHEMA <replaceable class="PARAMETER">name</replaceable> [, ...] [ CASCADE | RESTRICT ] + + </synopsis> + + <refsect2 id="R2-SQL-DROPSCHEMA-1"> + <refsect2info> + <date>2002-07-18</date> + </refsect2info> + <title> + Inputs + </title> + <para> + <variablelist> + <varlistentry> + <term><replaceable class="PARAMETER">name</replaceable></term> + <listitem> + <para> + The name of a schema. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>CASCADE</term> + <listitem> + <para> + Automatically drop objects (tables, functions, etc) that are contained + in the schema. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>RESTRICT</term> + <listitem> + <para> + Refuse to drop the schema if it contains any objects. + This is the default. + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </refsect2> + + <refsect2 id="R2-SQL-DROPSCHEMA-2"> + <refsect2info> + <date>2002-07-18</date> + </refsect2info> + <title> + Outputs + </title> + <para> + + <variablelist> + <varlistentry> + <term><computeroutput> +DROP SCHEMA + </computeroutput></term> + <listitem> + <para> + The message returned if the schema is successfully dropped. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><computeroutput> +ERROR: Schema "<replaceable class="parameter">name</replaceable>" does not exist + </computeroutput></term> + <listitem> + <para> + This message occurs if the specified schema does not exist. + </para> + </listitem> + </varlistentry> + </variablelist> + + </para> + </refsect2> + </refsynopsisdiv> + + <refsect1 id="R1-SQL-DROPSCHEMA-1"> + <refsect1info> + <date>2002-07-18</date> + </refsect1info> + <title> + Description + </title> + <para> + <command>DROP SCHEMA</command> removes schemas from the data base. + </para> + + <para> + A schema can only be dropped by its owner or a superuser. Note that + the owner can drop the schema (and thereby all contained objects) + even if he does not own some of the objects within the schema. + </para> + + <refsect2 id="R2-SQL-DROPSCHEMA-3"> + <refsect2info> + <date>2002-07-18</date> + </refsect2info> + <title> + Notes + </title> + <para> + Refer to the <command>CREATE SCHEMA</command> statement for + information on how to create a schema. + </para> + </refsect2> + </refsect1> + + <refsect1 id="R1-SQL-DROPSCHEMA-2"> + <title> + Usage + </title> + <para> + To remove schema <literal>mystuff</literal> from the database, + along with everything it contains: + + <programlisting> +DROP SCHEMA mystuff CASCADE; + </programlisting> + </para> + </refsect1> + + <refsect1 id="R1-SQL-DROPSCHEMA-3"> + <title> + Compatibility + </title> + + <refsect2 id="R2-SQL-DROPSCHEMA-4"> + <refsect2info> + <date>2002-07-18</date> + </refsect2info> + <title> + SQL92 + </title> + <para> + <command>DROP SCHEMA</command> is fully compatible with + <acronym>SQL92</acronym>, except that the standard only allows + one schema to be dropped per command. + </para> + </refsect2> + </refsect1> +</refentry> + +<!-- Keep this comment at the end of the file +Local variables: +mode: sgml +sgml-omittag:nil +sgml-shorttag:t +sgml-minimize-attributes:nil +sgml-always-quote-attributes:t +sgml-indent-step:1 +sgml-indent-data:t +sgml-parent-document:nil +sgml-default-dtd-file:"../reference.ced" +sgml-exposed-tags:nil +sgml-local-catalogs:"/usr/lib/sgml/catalog" +sgml-local-ecat-files:nil +End: +--> diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml index d1d40f3a72b..8249039826c 100644 --- a/doc/src/sgml/reference.sgml +++ b/doc/src/sgml/reference.sgml @@ -1,5 +1,5 @@ <!-- reference.sgml -$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.28 2002/04/25 21:47:06 tgl Exp $ +$Header: /cvsroot/pgsql/doc/src/sgml/reference.sgml,v 1.29 2002/07/18 16:47:22 tgl Exp $ PostgreSQL Reference Manual --> @@ -88,6 +88,7 @@ PostgreSQL Reference Manual &dropLanguage; &dropOperator; &dropRule; + &dropSchema; &dropSequence; &dropTable; &dropTrigger; diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 527cca3a85b..d2dc8b3795a 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.3 2002/07/16 05:53:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.4 2002/07/18 16:47:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,12 +25,14 @@ #include "catalog/pg_constraint.h" #include "catalog/pg_depend.h" #include "catalog/pg_language.h" +#include "catalog/pg_namespace.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_trigger.h" #include "catalog/pg_type.h" #include "commands/comment.h" #include "commands/defrem.h" #include "commands/proclang.h" +#include "commands/schemacmds.h" #include "commands/trigger.h" #include "lib/stringinfo.h" #include "miscadmin.h" @@ -54,6 +56,7 @@ typedef enum ObjectClasses OCLASS_OPERATOR, /* pg_operator */ OCLASS_REWRITE, /* pg_rewrite */ OCLASS_TRIGGER, /* pg_trigger */ + OCLASS_SCHEMA, /* pg_namespace */ MAX_OCLASS /* MUST BE LAST */ } ObjectClasses; @@ -597,6 +600,10 @@ doDeletion(const ObjectAddress *object) RemoveTriggerById(object->objectId); break; + case OCLASS_SCHEMA: + RemoveSchemaById(object->objectId); + break; + default: elog(ERROR, "doDeletion: Unsupported object class %u", object->classId); @@ -981,6 +988,7 @@ init_object_classes(void) object_classes[OCLASS_OPERATOR] = get_system_catalog_relid(OperatorRelationName); object_classes[OCLASS_REWRITE] = get_system_catalog_relid(RewriteRelationName); object_classes[OCLASS_TRIGGER] = get_system_catalog_relid(TriggerRelationName); + object_classes[OCLASS_SCHEMA] = get_system_catalog_relid(NamespaceRelationName); object_classes_initialized = true; } @@ -1045,6 +1053,11 @@ getObjectClass(const ObjectAddress *object) Assert(object->objectSubId == 0); return OCLASS_TRIGGER; } + if (object->classId == object_classes[OCLASS_SCHEMA]) + { + Assert(object->objectSubId == 0); + return OCLASS_SCHEMA; + } elog(ERROR, "getObjectClass: Unknown object class %u", object->classId); @@ -1265,6 +1278,22 @@ getObjectDescription(const ObjectAddress *object) break; } + case OCLASS_SCHEMA: + { + HeapTuple schemaTup; + + schemaTup = SearchSysCache(NAMESPACEOID, + ObjectIdGetDatum(object->objectId), + 0, 0, 0); + if (!HeapTupleIsValid(schemaTup)) + elog(ERROR, "getObjectDescription: Schema %u does not exist", + object->objectId); + appendStringInfo(&buffer, "schema %s", + NameStr(((Form_pg_namespace) GETSTRUCT(schemaTup))->nspname)); + ReleaseSysCache(schemaTup); + break; + } + default: appendStringInfo(&buffer, "unknown object %u %u %d", object->classId, diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 51933d32ede..076e1e0462b 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.209 2002/07/16 22:12:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.210 2002/07/18 16:47:22 tgl Exp $ * * * INTERFACE ROUTINES @@ -742,6 +742,25 @@ heap_create_with_catalog(const char *relname, AddNewAttributeTuples(new_rel_oid, new_rel_desc->rd_att, relhasoids, relkind); + /* + * make a dependency link to force the relation to be deleted if + * its namespace is. Skip this in bootstrap mode, since we don't + * make dependencies while bootstrapping. + */ + if (!IsBootstrapProcessingMode()) + { + ObjectAddress myself, + referenced; + + myself.classId = RelOid_pg_class; + myself.objectId = new_rel_oid; + myself.objectSubId = 0; + referenced.classId = get_system_catalog_relid(NamespaceRelationName); + referenced.objectId = relnamespace; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + /* * store constraints and defaults passed in the tupdesc, if any. * diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index c827edfb3e5..92d4d361a5b 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.184 2002/07/16 05:53:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.185 2002/07/18 16:47:23 tgl Exp $ * * * INTERFACE ROUTINES @@ -670,6 +670,9 @@ index_create(Oid heapRelationId, * linked to the table. If it's not a CONSTRAINT, make the dependency * directly on the table. * + * We don't need a dependency on the namespace, because there'll be + * an indirect dependency via our parent table. + * * During bootstrap we can't register any dependencies, and we don't * try to make a constraint either. */ diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c index 09c3f6be76f..a2a591f1e62 100644 --- a/src/backend/catalog/pg_operator.c +++ b/src/backend/catalog/pg_operator.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.71 2002/07/16 22:12:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.72 2002/07/18 16:47:23 tgl Exp $ * * NOTES * these routines moved here from commands/define.c and somewhat cleaned up. @@ -907,7 +907,7 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId) * Create dependencies for a new operator (either a freshly inserted * complete operator, a new shell operator, or a just-updated shell). * - * NB: the OidIsValid tests in this routine are *all* necessary, in case + * NB: the OidIsValid tests in this routine are necessary, in case * the given operator is a shell. */ static void @@ -924,6 +924,15 @@ makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid) /* In case we are updating a shell, delete any existing entries */ deleteDependencyRecordsFor(myself.classId, myself.objectId); + /* Dependency on namespace */ + if (OidIsValid(oper->oprnamespace)) + { + referenced.classId = get_system_catalog_relid(NamespaceRelationName); + referenced.objectId = oper->oprnamespace; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + /* Dependency on left type */ if (OidIsValid(oper->oprleft)) { diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 18746d9e219..f8693fa7fec 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.77 2002/07/16 22:12:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.78 2002/07/18 16:47:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -268,6 +268,12 @@ ProcedureCreate(const char *procedureName, myself.objectId = retval; myself.objectSubId = 0; + /* dependency on namespace */ + referenced.classId = get_system_catalog_relid(NamespaceRelationName); + referenced.objectId = procNamespace; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + /* dependency on implementation language */ referenced.classId = get_system_catalog_relid(LanguageRelationName); referenced.objectId = languageObjectId; diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c index 88f113beb01..5cd5d291d7e 100644 --- a/src/backend/catalog/pg_type.c +++ b/src/backend/catalog/pg_type.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.73 2002/07/12 18:43:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.74 2002/07/18 16:47:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ #include "catalog/pg_type.h" #include "miscadmin.h" #include "utils/builtins.h" +#include "utils/lsyscache.h" #include "utils/syscache.h" @@ -167,8 +168,6 @@ TypeCreate(const char *typeName, NameData name; TupleDesc tupDesc; int i; - ObjectAddress myself, - referenced; /* * validate size specifications: either positive (fixed-length) or -1 @@ -302,74 +301,90 @@ TypeCreate(const char *typeName, } /* - * Create dependencies + * Create dependencies. We can/must skip this in bootstrap mode. */ - myself.classId = RelOid_pg_type; - myself.objectId = typeObjectId; - myself.objectSubId = 0; - - /* Normal dependencies on the I/O functions */ - referenced.classId = RelOid_pg_proc; - referenced.objectId = inputProcedure; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - - referenced.classId = RelOid_pg_proc; - referenced.objectId = outputProcedure; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - - if (receiveProcedure != inputProcedure) + if (!IsBootstrapProcessingMode()) { + ObjectAddress myself, + referenced; + + myself.classId = RelOid_pg_type; + myself.objectId = typeObjectId; + myself.objectSubId = 0; + + /* dependency on namespace */ + /* skip for relation rowtype, since we have indirect dependency */ + if (!OidIsValid(relationOid)) + { + referenced.classId = get_system_catalog_relid(NamespaceRelationName); + referenced.objectId = typeNamespace; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + /* Normal dependencies on the I/O functions */ referenced.classId = RelOid_pg_proc; - referenced.objectId = receiveProcedure; + referenced.objectId = inputProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - } - if (sendProcedure != outputProcedure) - { referenced.classId = RelOid_pg_proc; - referenced.objectId = sendProcedure; + referenced.objectId = outputProcedure; referenced.objectSubId = 0; recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); - } - /* - * If the type is a rowtype for a relation, mark it as internally - * dependent on the relation. This allows it to be auto-dropped - * when the relation is, and not otherwise. - */ - if (OidIsValid(relationOid)) - { - referenced.classId = RelOid_pg_class; - referenced.objectId = relationOid; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); - } + if (receiveProcedure != inputProcedure) + { + referenced.classId = RelOid_pg_proc; + referenced.objectId = receiveProcedure; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } + + if (sendProcedure != outputProcedure) + { + referenced.classId = RelOid_pg_proc; + referenced.objectId = sendProcedure; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } - /* - * If the type is an array type, mark it auto-dependent on the - * base type. (This is a compromise between the typical case where the - * array type is automatically generated and the case where it is manually - * created: we'd prefer INTERNAL for the former case and NORMAL for the - * latter.) - */ - if (OidIsValid(elementType)) - { - referenced.classId = RelOid_pg_type; - referenced.objectId = elementType; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO); - } + /* + * If the type is a rowtype for a relation, mark it as internally + * dependent on the relation. This allows it to be auto-dropped + * when the relation is, and not otherwise. + */ + if (OidIsValid(relationOid)) + { + referenced.classId = RelOid_pg_class; + referenced.objectId = relationOid; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_INTERNAL); + } - /* Normal dependency from a domain to its base type. */ - if (OidIsValid(baseType)) - { - referenced.classId = RelOid_pg_type; - referenced.objectId = baseType; - referenced.objectSubId = 0; - recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + /* + * If the type is an array type, mark it auto-dependent on the base + * type. (This is a compromise between the typical case where the + * array type is automatically generated and the case where it is + * manually created: we'd prefer INTERNAL for the former case and + * NORMAL for the latter.) + */ + if (OidIsValid(elementType)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = elementType; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO); + } + + /* Normal dependency from a domain to its base type. */ + if (OidIsValid(baseType)) + { + referenced.classId = RelOid_pg_type; + referenced.objectId = baseType; + referenced.objectSubId = 0; + recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL); + } } /* diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c index a790a28bccd..621006758c5 100644 --- a/src/backend/commands/schemacmds.c +++ b/src/backend/commands/schemacmds.c @@ -1,20 +1,23 @@ /*------------------------------------------------------------------------- * * schemacmds.c - * schema creation command support code + * schema creation/manipulation commands * * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.4 2002/06/11 13:40:50 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.5 2002/07/18 16:47:24 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "access/heapam.h" #include "catalog/catalog.h" +#include "catalog/catname.h" +#include "catalog/dependency.h" #include "catalog/namespace.h" #include "catalog/pg_namespace.h" #include "commands/schemacmds.h" @@ -23,6 +26,7 @@ #include "tcop/utility.h" #include "utils/acl.h" #include "utils/lsyscache.h" +#include "utils/syscache.h" /* @@ -139,3 +143,70 @@ CreateSchemaCommand(CreateSchemaStmt *stmt) /* Reset current user */ SetUserId(saved_userid); } + + +/* + * RemoveSchema + * Removes a schema. + */ +void +RemoveSchema(List *names, DropBehavior behavior) +{ + char *namespaceName; + Oid namespaceId; + ObjectAddress object; + + if (length(names) != 1) + elog(ERROR, "Schema name may not be qualified"); + namespaceName = strVal(lfirst(names)); + + namespaceId = GetSysCacheOid(NAMESPACENAME, + CStringGetDatum(namespaceName), + 0, 0, 0); + if (!OidIsValid(namespaceId)) + elog(ERROR, "Schema \"%s\" does not exist", namespaceName); + + /* Permission check */ + if (!pg_namespace_ownercheck(namespaceId, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, namespaceName); + + /* + * Do the deletion. Objects contained in the schema are removed + * by means of their dependency links to the schema. + * + * XXX currently, index opclasses don't have creation/deletion + * commands, so they will not get removed when the containing + * schema is removed. This is annoying but not fatal. + */ + object.classId = get_system_catalog_relid(NamespaceRelationName); + object.objectId = namespaceId; + object.objectSubId = 0; + + performDeletion(&object, behavior); +} + + +/* + * Guts of schema deletion. + */ +void +RemoveSchemaById(Oid schemaOid) +{ + Relation relation; + HeapTuple tup; + + relation = heap_openr(NamespaceRelationName, RowExclusiveLock); + + tup = SearchSysCache(NAMESPACEOID, + ObjectIdGetDatum(schemaOid), + 0, 0, 0); + if (!HeapTupleIsValid(tup)) + elog(ERROR, "RemoveSchemaById: schema %u not found", + schemaOid); + + simple_heap_delete(relation, &tup->t_self); + + ReleaseSysCache(tup); + + heap_close(relation, RowExclusiveLock); +} diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 17a3b61e762..d7af8d956af 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.344 2002/07/18 04:43:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.345 2002/07/18 16:47:24 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -132,7 +132,7 @@ static void doNegateFloat(Value *v); } %type <node> stmt, schema_stmt, - AlterDatabaseSetStmt, AlterGroupStmt, AlterSchemaStmt, + AlterDatabaseSetStmt, AlterGroupStmt, AlterTableStmt, AlterUserStmt, AlterUserSetStmt, AnalyzeStmt, ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt, CopyStmt, CreateAsStmt, @@ -140,7 +140,7 @@ static void doNegateFloat(Value *v); CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateAssertStmt, CreateTrigStmt, CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt, - DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, + DropGroupStmt, DropPLangStmt, DropStmt, DropAssertStmt, DropTrigStmt, DropRuleStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt, GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, @@ -468,7 +468,6 @@ stmtmulti: stmtmulti ';' stmt stmt : AlterDatabaseSetStmt | AlterGroupStmt - | AlterSchemaStmt | AlterTableStmt | AlterUserStmt | AlterUserSetStmt @@ -488,7 +487,6 @@ stmt : | ClusterStmt | DefineStmt | DropStmt - | DropSchemaStmt | TruncateStmt | CommentStmt | DropGroupStmt @@ -746,7 +744,6 @@ DropGroupStmt: * * Manipulate a schema * - * *****************************************************************************/ CreateSchemaStmt: @@ -773,20 +770,6 @@ CreateSchemaStmt: } ; -AlterSchemaStmt: - ALTER SCHEMA ColId - { - elog(ERROR, "ALTER SCHEMA not yet supported"); - } - ; - -DropSchemaStmt: - DROP SCHEMA ColId opt_drop_behavior - { - elog(ERROR, "DROP SCHEMA not yet supported"); - } - ; - OptSchemaName: ColId { $$ = $1; } | /* EMPTY */ { $$ = NULL; } @@ -2306,6 +2289,7 @@ drop_type: TABLE { $$ = DROP_TABLE; } | TYPE_P { $$ = DROP_TYPE; } | DOMAIN_P { $$ = DROP_DOMAIN; } | CONVERSION_P { $$ = DROP_CONVERSION; } + | SCHEMA { $$ = DROP_SCHEMA; } ; any_name_list: diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 154e478687b..862faf34cae 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.270 2002/07/13 01:02:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.271 2002/07/18 16:47:25 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1693,7 +1693,7 @@ PostgresMain(int argc, char *argv[], const char *username) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.270 $ $Date: 2002/07/13 01:02:14 $\n"); + puts("$Revision: 1.271 $ $Date: 2002/07/18 16:47:25 $\n"); } /* @@ -2220,7 +2220,10 @@ CreateCommandTag(Node *parsetree) tag = "DROP DOMAIN"; break; case DROP_CONVERSION: - tag = "DROP CONVERSON"; + tag = "DROP CONVERSION"; + break; + case DROP_SCHEMA: + tag = "DROP SCHEMA"; break; default: tag = "???"; diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 86373943667..8ba7466ee28 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.162 2002/07/12 18:43:17 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.163 2002/07/18 16:47:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -252,11 +252,7 @@ ProcessUtility(Node *parsetree, * relation and attribute manipulation */ case T_CreateSchemaStmt: - { - CreateSchemaStmt *stmt = (CreateSchemaStmt *) parsetree; - - CreateSchemaCommand(stmt); - } + CreateSchemaCommand((CreateSchemaStmt *) parsetree); break; case T_CreateStmt: @@ -322,17 +318,20 @@ ProcessUtility(Node *parsetree, break; case DROP_CONVERSION: - /* RemoveDomain does its own permissions checks */ + /* does its own permissions checks */ DropConversionCommand(names); break; + + case DROP_SCHEMA: + /* RemoveSchema does its own permissions checks */ + RemoveSchema(names, stmt->behavior); + break; } /* - * Make sure subsequent loop iterations will see - * results of this one; needed if removing multiple - * rules for same table, for example. + * We used to need to do CommandCounterIncrement() + * here, but now it's done inside performDeletion(). */ - CommandCounterIncrement(); } } break; diff --git a/src/bin/initdb/initdb.sh b/src/bin/initdb/initdb.sh index a88eed353b1..9902a24fc4f 100644 --- a/src/bin/initdb/initdb.sh +++ b/src/bin/initdb/initdb.sh @@ -27,7 +27,7 @@ # Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # -# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.159 2002/07/18 02:02:30 ishii Exp $ +# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.160 2002/07/18 16:47:25 tgl Exp $ # #------------------------------------------------------------------------- @@ -717,6 +717,9 @@ INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_language; INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_operator; INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_rewrite; INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_trigger; +-- restriction here to avoid pinning the public namespace +INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_namespace \ + WHERE nspname LIKE 'pg%'; EOF if [ "$?" -ne 0 ]; then exit_nicely diff --git a/src/include/commands/schemacmds.h b/src/include/commands/schemacmds.h index 6adf9a4517e..63205500c27 100644 --- a/src/include/commands/schemacmds.h +++ b/src/include/commands/schemacmds.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: schemacmds.h,v 1.1 2002/04/15 05:22:04 tgl Exp $ + * $Id: schemacmds.h,v 1.2 2002/07/18 16:47:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,4 +19,7 @@ extern void CreateSchemaCommand(CreateSchemaStmt *parsetree); +extern void RemoveSchema(List *names, DropBehavior behavior); +extern void RemoveSchemaById(Oid schemaOid); + #endif /* SCHEMACMDS_H */ diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index e6b27d03af4..26e2e0ab299 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.190 2002/07/18 04:43:51 momjian Exp $ + * $Id: parsenodes.h,v 1.191 2002/07/18 16:47:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1136,7 +1136,7 @@ typedef struct CreateDomainStmt } CreateDomainStmt; /* ---------------------- - * Drop Table|Sequence|View|Index|Type|Domain Statement + * Drop Table|Sequence|View|Index|Type|Domain|Conversion|Schema Statement * ---------------------- */ @@ -1147,6 +1147,7 @@ typedef struct CreateDomainStmt #define DROP_TYPE 5 #define DROP_DOMAIN 6 #define DROP_CONVERSION 7 +#define DROP_SCHEMA 8 typedef struct DropStmt { -- GitLab