Unverified 提交 aa9191c5 authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #924 from katzyn/ddl

Add RESTRICT and CASCADE to DROP SCHEMA
......@@ -885,9 +885,11 @@ DROP ROLE READONLY
"
"Commands (DDL)","DROP SCHEMA","
DROP SCHEMA [ IF EXISTS ] schemaName
DROP SCHEMA [ IF EXISTS ] schemaName [ RESTRICT | CASCADE ]
","
Drops a schema.
The command will fail if objects in this schema exist and the RESTRICT clause is used (the default).
All objects in this schema are dropped as well if the CASCADE clause is used.
This command commits an open transaction in this connection.
","
DROP SCHEMA TEST_SCHEMA
......
......@@ -1692,6 +1692,11 @@ public class Parser {
command.setSchemaName(readUniqueIdentifier());
ifExists = readIfExists(ifExists);
command.setIfExists(ifExists);
if (readIf("CASCADE")) {
command.setDropAction(ConstraintActionType.CASCADE);
} else if (readIf("RESTRICT")) {
command.setDropAction(ConstraintActionType.RESTRICT);
}
return command;
} else if (readIf("ALL")) {
read("OBJECTS");
......
......@@ -7,10 +7,13 @@ package org.h2.command.ddl;
import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface;
import org.h2.constraint.ConstraintActionType;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.message.DbException;
import org.h2.schema.Schema;
import org.h2.schema.SchemaObject;
import org.h2.util.StatementBuilder;
/**
* This class represents the statement
......@@ -20,9 +23,12 @@ public class DropSchema extends DefineCommand {
private String schemaName;
private boolean ifExists;
private ConstraintActionType dropAction;
public DropSchema(Session session) {
super(session);
dropAction = session.getDatabase().getSettings().dropRestrict ?
ConstraintActionType.RESTRICT : ConstraintActionType.CASCADE;
}
public void setSchemaName(String name) {
......@@ -43,6 +49,16 @@ public class DropSchema extends DefineCommand {
if (!schema.canDrop()) {
throw DbException.get(ErrorCode.SCHEMA_CAN_NOT_BE_DROPPED_1, schemaName);
}
if (dropAction == ConstraintActionType.RESTRICT && !schema.isEmpty()) {
StatementBuilder buff = new StatementBuilder();
for (SchemaObject object : schema.getAll()) {
buff.appendExceptFirst(", ");
buff.append(object.getName());
}
if (buff.length() > 0) {
throw DbException.get(ErrorCode.CANNOT_DROP_2, schemaName, buff.toString());
}
}
db.removeDatabaseObject(session, schema);
}
return 0;
......@@ -52,6 +68,10 @@ public class DropSchema extends DefineCommand {
this.ifExists = ifExists;
}
public void setDropAction(ConstraintActionType dropAction) {
this.dropAction = dropAction;
}
@Override
public int getType() {
return CommandInterface.DROP_SCHEMA;
......
......@@ -100,7 +100,8 @@ public class DbSettings extends SettingsBase {
/**
* Database setting <code>DROP_RESTRICT</code> (default: true).<br />
* Whether the default action for DROP TABLE and DROP VIEW is RESTRICT.
* Whether the default action for DROP TABLE, DROP VIEW, and DROP SCHEMA
* is RESTRICT.
*/
public final boolean dropRestrict = get("DROP_RESTRICT", true);
......
......@@ -261,7 +261,7 @@ public class FullText {
public static void dropAll(Connection conn) throws SQLException {
init(conn);
Statement stat = conn.createStatement();
stat.execute("DROP SCHEMA IF EXISTS " + SCHEMA);
stat.execute("DROP SCHEMA IF EXISTS " + SCHEMA + " CASCADE");
removeAllTriggers(conn, TRIGGER_PREFIX);
FullTextSettings setting = FullTextSettings.getInstance(conn);
setting.removeAllIndexes();
......
......@@ -187,7 +187,7 @@ public class FullTextLucene extends FullText {
*/
public static void dropAll(Connection conn) throws SQLException {
Statement stat = conn.createStatement();
stat.execute("DROP SCHEMA IF EXISTS " + SCHEMA);
stat.execute("DROP SCHEMA IF EXISTS " + SCHEMA + " CASCADE");
removeAllTriggers(conn, TRIGGER_PREFIX);
removeIndexFiles(conn);
}
......
......@@ -116,6 +116,16 @@ public class Schema extends DbObjectBase {
return DbObject.SCHEMA;
}
/**
* Return whether is this schema is empty (does not contain any objects).
*
* @return {@code true} if this schema is empty, {@code false} otherwise
*/
public boolean isEmpty() {
return tablesAndViews.isEmpty() && synonyms.isEmpty() && indexes.isEmpty() && sequences.isEmpty()
&& triggers.isEmpty() && constraints.isEmpty() && constants.isEmpty() && functions.isEmpty();
}
@Override
public void removeChildrenAndResources(Session session) {
while (triggers != null && triggers.size() > 0) {
......@@ -567,6 +577,7 @@ public class Schema extends DbObjectBase {
public ArrayList<SchemaObject> getAll() {
ArrayList<SchemaObject> all = New.arrayList();
all.addAll(getMap(DbObject.TABLE_OR_VIEW).values());
all.addAll(getMap(DbObject.SYNONYM).values());
all.addAll(getMap(DbObject.SEQUENCE).values());
all.addAll(getMap(DbObject.INDEX).values());
all.addAll(getMap(DbObject.TRIGGER).values());
......
......@@ -63,7 +63,7 @@ public class TestAlterSchemaRename extends TestBase {
rs = stat.executeQuery("select * from s2.tab");
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
stat.execute("drop schema s2");
stat.execute("drop schema s2 cascade");
}
......@@ -97,8 +97,8 @@ public class TestAlterSchemaRename extends TestBase {
stat = conn.createStatement();
stat.executeQuery("select * from s2_new.v1");
}
stat.execute("drop schema s1");
stat.execute("drop schema s2_new");
stat.execute("drop schema s1 cascade");
stat.execute("drop schema s2_new cascade");
}
/**
......@@ -120,7 +120,7 @@ public class TestAlterSchemaRename extends TestBase {
stat = conn.createStatement();
stat.executeQuery("CALL S2.REVERSE('1234')");
}
stat.execute("drop schema s2");
stat.execute("drop schema s2 cascade");
}
}
\ No newline at end of file
......@@ -65,7 +65,7 @@ public class TestCompatibility extends TestBase {
stat.execute("insert into s2.test(id, name) values(1, 'a')");
stat.execute("insert into s2.test(id, name) values(1, 'b') " +
"on duplicate key update name = values(name)");
stat.execute("drop schema s2");
stat.execute("drop schema s2 cascade");
c.close();
}
......
......@@ -58,7 +58,7 @@ public class TestDrop extends TestBase {
stat.execute("CREATE TABLE TEST_SCHEMA.A (A INT);");
stat.execute("CREATE TABLE TEST_SCHEMA.B " +
"(B INT AS SELECT A FROM TEST_SCHEMA.A);");
stat.execute("DROP SCHEMA TEST_SCHEMA");
stat.execute("DROP SCHEMA TEST_SCHEMA CASCADE");
}
private void testInterSchemaDependency() throws SQLException {
......
......@@ -376,7 +376,7 @@ public class TestFunctions extends TestBase implements AggregateFunction {
assertContains(rs.getString("VIEW_DEFINITION"), "SCHEMA2.FUNC");
stat.execute("drop view test");
stat.execute("drop schema schema2");
stat.execute("drop schema schema2 cascade");
conn.close();
}
......
......@@ -388,7 +388,7 @@ public class TestRights extends TestBase {
execute("alter user test1 admin false");
assertThrows(ErrorCode.CANNOT_DROP_2, stat).
execute("drop user test1");
stat.execute("drop schema b");
stat.execute("drop schema b cascade");
stat.execute("alter user test1 admin false");
stat.execute("drop user test1");
conn.close();
......@@ -451,7 +451,7 @@ public class TestRights extends TestBase {
executeSuccess("INSERT INTO S.TEST (ID, NAME) VALUES (42, 'Adams')");
executeSuccess("UPDATE S.TEST Set NAME = 'Douglas'");
executeSuccess("DELETE FROM S.TEST");
executeSuccess("DROP SCHEMA S");
executeSuccess("DROP SCHEMA S CASCADE");
// ...and on other schemata
executeSuccess("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR)");
......
......@@ -68,7 +68,7 @@ public class TestSynonymForTable extends TestBase {
stat.execute("CREATE SCHEMA IF NOT EXISTS s1");
stat.execute("CREATE TABLE IF NOT EXISTS s1.backingtable(id INT PRIMARY KEY)");
stat.execute("CREATE OR REPLACE SYNONYM testsynonym FOR s1.backingtable");
stat.execute("DROP SCHEMA s1");
stat.execute("DROP SCHEMA s1 CASCADE");
assertThrows(JdbcSQLException.class, stat).execute("SELECT id FROM testsynonym");
conn.close();
......
......@@ -101,7 +101,7 @@ public class TestScript extends TestBase {
"uuid", "varchar", "varchar-ignorecase" }) {
testScript("datatypes/" + s + ".sql");
}
for (String s : new String[] { "alterTableAdd", "createView" }) {
for (String s : new String[] { "alterTableAdd", "createView", "dropSchema" }) {
testScript("ddl/" + s + ".sql");
}
for (String s : new String[] { "insertIgnore", "mergeUsing", "script", "with" }) {
......
-- Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
-- and the EPL 1.0 (http://h2database.com/html/license.html).
-- Initial Developer: H2 Group
--
CREATE SCHEMA TEST_SCHEMA;
> ok
DROP SCHEMA TEST_SCHEMA RESTRICT;
> ok
CREATE SCHEMA TEST_SCHEMA;
> ok
CREATE TABLE TEST_SCHEMA.TEST();
> ok
DROP SCHEMA TEST_SCHEMA RESTRICT;
> exception
DROP SCHEMA TEST_SCHEMA CASCADE;
> ok
CREATE SCHEMA TEST_SCHEMA;
> ok
CREATE VIEW TEST_SCHEMA.TEST AS SELECT 1;
> ok
DROP SCHEMA TEST_SCHEMA RESTRICT;
> exception
DROP SCHEMA TEST_SCHEMA CASCADE;
> ok
CREATE TABLE PUBLIC.SRC();
> ok
CREATE SCHEMA TEST_SCHEMA;
> ok
CREATE SYNONYM TEST_SCHEMA.TEST FOR PUBLIC.SRC;
> ok
DROP SCHEMA TEST_SCHEMA RESTRICT;
> exception
DROP SCHEMA TEST_SCHEMA CASCADE;
> ok
DROP TABLE PUBLIC.SRC;
> ok
CREATE SCHEMA TEST_SCHEMA;
> ok
CREATE SEQUENCE TEST_SCHEMA.TEST;
> ok
DROP SCHEMA TEST_SCHEMA RESTRICT;
> exception
DROP SCHEMA TEST_SCHEMA CASCADE;
> ok
CREATE SCHEMA TEST_SCHEMA;
> ok
CREATE CONSTANT TEST_SCHEMA.TEST VALUE 1;
> ok
DROP SCHEMA TEST_SCHEMA RESTRICT;
> exception
DROP SCHEMA TEST_SCHEMA CASCADE;
> ok
CREATE SCHEMA TEST_SCHEMA;
> ok
CREATE ALIAS TEST_SCHEMA.TEST FOR "java.lang.System.currentTimeMillis";
> ok
DROP SCHEMA TEST_SCHEMA RESTRICT;
> exception
DROP SCHEMA TEST_SCHEMA CASCADE;
> ok
......@@ -979,7 +979,7 @@ select * from v_test;
set schema public;
> ok
drop schema a;
drop schema a cascade;
> ok
set autocommit true;
......@@ -1289,10 +1289,10 @@ select * from a.x, b.x;
> -- --
> rows: 0
drop schema a;
drop schema a cascade;
> ok
drop schema b;
drop schema b cascade;
> ok
create table t1 (id int primary key);
......@@ -2551,7 +2551,7 @@ select nextval('abc'), currval('Abc'), nextval('TestSchema', 'ABC');
set schema public;
> ok
drop schema "TestSchema";
drop schema "TestSchema" cascade;
> ok
drop sequence main_seq;
......@@ -2623,7 +2623,7 @@ explain select * from public.test;
> SELECT TEST.ID FROM PUBLIC.TEST /* PUBLIC.TEST.tableScan */
> rows: 1
drop schema TEST_SCHEMA;
drop schema TEST_SCHEMA cascade;
> ok
set autocommit true;
......@@ -3049,7 +3049,7 @@ SELECT ONE, CONST.ONE FROM DUAL;
COMMENT ON CONSTANT ONE IS NULL;
> ok
DROP SCHEMA CONST;
DROP SCHEMA CONST CASCADE;
> ok
SELECT CONSTANT_SCHEMA, CONSTANT_NAME, DATA_TYPE, REMARKS, SQL FROM INFORMATION_SCHEMA.CONSTANTS;
......@@ -4074,7 +4074,7 @@ script NOPASSWORDS NOSETTINGS drop;
drop trigger s.test_trigger;
> ok
drop schema s;
drop schema s cascade;
> ok
CREATE MEMORY TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255), y int as id+1);
......@@ -5281,7 +5281,7 @@ SELECT INFORMATION_SCHEMA.SCHEMATA.* FROM INFORMATION_SCHEMA.SCHEMATA;
CREATE SCHEMA TEST_SCHEMA AUTHORIZATION SA;
> ok
DROP SCHEMA TEST_SCHEMA;
DROP SCHEMA TEST_SCHEMA RESTRICT;
> ok
create schema Contact_Schema AUTHORIZATION SA;
......@@ -5320,10 +5320,10 @@ drop table ClientServer_Schema.PrimaryKey_Seq;
drop table Contact_Schema.Address;
> ok
drop schema Contact_Schema;
drop schema Contact_Schema restrict;
> ok
drop schema ClientServer_Schema;
drop schema ClientServer_Schema restrict;
> ok
--- alter table add / drop / rename column ----------------------------------------------------------------------------------------------
......@@ -8747,7 +8747,7 @@ alter schema if exists x rename to z;
create table z.z (id int);
> ok
drop schema z;
drop schema z cascade;
> ok
----- Issue#493 -----
......
......@@ -258,7 +258,7 @@ select nextval('"test"."report_id_seq"');
> 2;
select nextval('test.report_id_seq');
> 3;
drop schema test;
drop schema test cascade;
create table master(id int primary key);
create table detail(id int primary key, x bigint, foreign key(x) references master(id) on delete cascade);
......@@ -346,14 +346,14 @@ create schema Contact;
CREATE TABLE Account (id BIGINT);
CREATE TABLE Person (id BIGINT, FOREIGN KEY (id) REFERENCES Account(id));
CREATE TABLE Contact.Contact (id BIGINT, FOREIGN KEY (id) REFERENCES public.Person(id));
drop schema contact;
drop schema contact cascade;
drop table account, person;
create schema Contact;
CREATE TABLE Account (id BIGINT primary key);
CREATE TABLE Person (id BIGINT primary key, FOREIGN KEY (id) REFERENCES Account);
CREATE TABLE Contact.Contact (id BIGINT primary key, FOREIGN KEY (id) REFERENCES public.Person);
drop schema contact;
drop schema contact cascade;
drop table account, person;
select extract(hour from timestamp '2001-02-03 14:15:16');
......@@ -554,8 +554,8 @@ create table b.test(id int);
insert into b.test values(2);
select a.test.id + b.test.id from a.test, b.test;
> 3;
drop schema a;
drop schema b;
drop schema a cascade;
drop schema b cascade;
select date '+0011-01-01';
> 0011-01-01;
......@@ -575,7 +575,7 @@ select TEST_SCHEMA.TEST_SEQ.CURRVAL;
> 0;
select TEST_SCHEMA.TEST_SEQ.nextval;
> 1;
drop schema TEST_SCHEMA;
drop schema TEST_SCHEMA cascade;
create table test(id int);
create trigger TEST_TRIGGER before insert on test call "org.h2.test.db.TestTriggersConstraints";
......@@ -635,7 +635,7 @@ select remarks from information_schema.schemata where schema_name = 'TESTS';
> Test Schema;
select remarks from information_schema.sequences where sequence_name = 'WALK';
> Walker;
drop schema tests;
drop schema tests cascade;
@reconnect;
create constant abc value 1;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论