提交 276ad6f5 authored 作者: sainsbury.kerry's avatar sainsbury.kerry

Implemented "Support ALTER SCHEMA name RENAME TO newName (rename schema)"

上级 e0403b2c
...@@ -177,6 +177,15 @@ This command commits an open transaction. ...@@ -177,6 +177,15 @@ This command commits an open transaction.
ALTER INDEX IDXNAME RENAME TO IDX_TEST_NAME ALTER INDEX IDXNAME RENAME TO IDX_TEST_NAME
" "
"Commands (DDL)","ALTER SCHEMA RENAME","
ALTER SCHEMA schema RENAME TO newSchemaName
","
Renames a schema.
This command commits an open transaction.
","
ALTER SCHEMA TEST RENAME TO PRODUCTION
"
"Commands (DDL)","ALTER SEQUENCE"," "Commands (DDL)","ALTER SEQUENCE","
ALTER SEQUENCE sequenceName [ RESTART WITH long ] [ INCREMENT BY long ] ALTER SEQUENCE sequenceName [ RESTART WITH long ] [ INCREMENT BY long ]
"," ","
......
...@@ -59,6 +59,7 @@ Change Log ...@@ -59,6 +59,7 @@ Change Log
</li><li>Cluster: non-admin users could not connect when one of the cluster node was stopped. Issue 206. </li><li>Cluster: non-admin users could not connect when one of the cluster node was stopped. Issue 206.
</li><li>DROP VIEW now supports the CASCADE and RESTRICT clauses (patch from Kerry Sainsbury) </li><li>DROP VIEW now supports the CASCADE and RESTRICT clauses (patch from Kerry Sainsbury)
</li><li>CREATE VIEW now supports the OR REPLACE clause (patch from Kerry Sainsbury) </li><li>CREATE VIEW now supports the OR REPLACE clause (patch from Kerry Sainsbury)
</li><li>Support ALTER SCHEMA name RENAME TO newName (rename schema). (patch from Kerry Sainsbury)
</li><li>Build tool: ability to only run one test using the -Dtest=className setting. </li><li>Build tool: ability to only run one test using the -Dtest=className setting.
eg: build -Dtest=org.h2.test.db.TestViewDropView test (patch from Kerry Sainsbury). eg: build -Dtest=org.h2.test.db.TestViewDropView test (patch from Kerry Sainsbury).
</li></ul> </li></ul>
......
...@@ -380,7 +380,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>. ...@@ -380,7 +380,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Improve SQL documentation, see http://www.w3schools.com/sql/ </li><li>Improve SQL documentation, see http://www.w3schools.com/sql/
</li><li>MySQL compatibility: DatabaseMetaData.stores*() methods should return the same values. Test with SquirrelSQL. </li><li>MySQL compatibility: DatabaseMetaData.stores*() methods should return the same values. Test with SquirrelSQL.
</li><li>MS SQL Server compatibility: support DATEPART syntax. </li><li>MS SQL Server compatibility: support DATEPART syntax.
</li><li>Oracle compatibility: support CREATE OR REPLACE VIEW syntax.
</li><li>Sybase/DB2/Oracle compatibility: support out parameters in stored procedures - See http://code.google.com/p/h2database/issues/detail?id=83 </li><li>Sybase/DB2/Oracle compatibility: support out parameters in stored procedures - See http://code.google.com/p/h2database/issues/detail?id=83
</li><li>Support INTERVAL data type (see Oracle and others). </li><li>Support INTERVAL data type (see Oracle and others).
</li><li>Combine Server and Console tool (only keep Server). </li><li>Combine Server and Console tool (only keep Server).
...@@ -464,7 +463,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>. ...@@ -464,7 +463,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>User defined functions: allow to store the bytecode (of just the class, or the jar file of the extension) in the database. </li><li>User defined functions: allow to store the bytecode (of just the class, or the jar file of the extension) in the database.
</li><li>Compatibility: ResultSet.getObject() on a CLOB (TEXT) should return String for PostgreSQL and MySQL. </li><li>Compatibility: ResultSet.getObject() on a CLOB (TEXT) should return String for PostgreSQL and MySQL.
</li><li>Optimizer: WHERE X=? AND Y IN(?), it always uses the index on Y. Should be cost based. </li><li>Optimizer: WHERE X=? AND Y IN(?), it always uses the index on Y. Should be cost based.
</li><li>Support ALTER SCHEMA name RENAME TO newName (rename schema).
</li><li>Make the cache scan resistant (currently a small cache is faster than a large cache for large table scans). </li><li>Make the cache scan resistant (currently a small cache is faster than a large cache for large table scans).
</li><li>Issue 178: Optimizer: index usage when both ascending and descending indexes are available. </li><li>Issue 178: Optimizer: index usage when both ascending and descending indexes are available.
</li><li>Issue 179: Related subqueries in HAVING clause </li><li>Issue 179: Related subqueries in HAVING clause
......
...@@ -13,6 +13,7 @@ import java.util.ArrayList; ...@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import org.h2.api.Trigger; import org.h2.api.Trigger;
import org.h2.command.ddl.AlterIndexRename; import org.h2.command.ddl.AlterIndexRename;
import org.h2.command.ddl.AlterSchemaRename;
import org.h2.command.ddl.AlterTableAddConstraint; import org.h2.command.ddl.AlterTableAddConstraint;
import org.h2.command.ddl.AlterTableAlterColumn; import org.h2.command.ddl.AlterTableAlterColumn;
import org.h2.command.ddl.AlterTableDropConstraint; import org.h2.command.ddl.AlterTableDropConstraint;
...@@ -588,7 +589,7 @@ public class Parser { ...@@ -588,7 +589,7 @@ public class Parser {
return command; return command;
} }
private Schema getSchema() { private Schema getSchema(String schemaName) {
if (schemaName == null) { if (schemaName == null) {
return null; return null;
} }
...@@ -604,6 +605,11 @@ public class Parser { ...@@ -604,6 +605,11 @@ public class Parser {
return schema; return schema;
} }
private Schema getSchema() {
return getSchema(schemaName);
}
private Column readTableColumn(TableFilter filter) { private Column readTableColumn(TableFilter filter) {
String tableAlias = null; String tableAlias = null;
String columnName = readColumnIdentifier(); String columnName = readColumnIdentifier();
...@@ -4029,6 +4035,8 @@ public class Parser { ...@@ -4029,6 +4035,8 @@ public class Parser {
return parseAlterUser(); return parseAlterUser();
} else if (readIf("INDEX")) { } else if (readIf("INDEX")) {
return parseAlterIndex(); return parseAlterIndex();
} else if (readIf("SCHEMA")) {
return parseAlterSchema();
} else if (readIf("SEQUENCE")) { } else if (readIf("SEQUENCE")) {
return parseAlterSequence(); return parseAlterSequence();
} else if (readIf("VIEW")) { } else if (readIf("VIEW")) {
...@@ -4069,6 +4077,20 @@ public class Parser { ...@@ -4069,6 +4077,20 @@ public class Parser {
return command; return command;
} }
private AlterSchemaRename parseAlterSchema() {
String schemaName = readIdentifierWithSchema();
Schema old = getSchema();
AlterSchemaRename command = new AlterSchemaRename(session);
command.setOldSchema(getSchema(schemaName));
read("RENAME");
read("TO");
String newName = readIdentifierWithSchema(old.getName());
checkSchema(old);
command.setNewName(newName);
return command;
}
private AlterSequence parseAlterSequence() { private AlterSequence parseAlterSequence() {
String sequenceName = readIdentifierWithSchema(); String sequenceName = readIdentifierWithSchema();
Sequence sequence = getSchema().getSequence(sequenceName); Sequence sequence = getSchema().getSequence(sequenceName);
......
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.command.ddl;
import org.h2.constant.ErrorCode;
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 java.util.ArrayList;
/**
* This class represents the statement
* ALTER SCHEMA RENAME
*/
public class AlterSchemaRename extends DefineCommand {
private Schema oldSchema;
private String newSchemaName;
public AlterSchemaRename(Session session) {
super(session);
}
public void setOldSchema(Schema Schema) {
oldSchema = Schema;
}
public void setNewName(String name) {
newSchemaName = name;
}
public int update() {
session.commit(true);
Database db = session.getDatabase();
if (db.findSchema(newSchemaName) != null || newSchemaName.equals(oldSchema.getName())) {
throw DbException.get(ErrorCode.SCHEMA_ALREADY_EXISTS_1, newSchemaName);
}
session.getUser().checkAdmin();
db.renameDatabaseObject(session, oldSchema, newSchemaName);
ArrayList<SchemaObject> all = db.getAllSchemaObjects();
for (SchemaObject schemaObject : all) {
db.update(session, schemaObject);
}
return 0;
}
}
...@@ -1226,6 +1226,20 @@ public class Database implements DataHandler { ...@@ -1226,6 +1226,20 @@ public class Database implements DataHandler {
return New.arrayList(roles.values()); return New.arrayList(roles.values());
} }
/**
* Get all schema objects.
*
* @return all objects of all types
*/
public ArrayList<SchemaObject> getAllSchemaObjects() {
initMetaTables();
ArrayList<SchemaObject> list = New.arrayList();
for (Schema schema : schemas.values()) {
list.addAll(schema.getAll());
}
return list;
}
/** /**
* Get all schema objects of the given type. * Get all schema objects of the given type.
* *
......
...@@ -65,6 +65,10 @@ Lists the schemas, tables, or the columns of a table." ...@@ -65,6 +65,10 @@ Lists the schemas, tables, or the columns of a table."
ALTER INDEX indexName RENAME TO newIndexName ALTER INDEX indexName RENAME TO newIndexName
"," ","
Renames an index." Renames an index."
"Commands (DDL)","ALTER SCHEMA RENAME","
ALTER SCHEMA schema RENAME TO newSchemaName
","
Renames a schema."
"Commands (DDL)","ALTER SEQUENCE"," "Commands (DDL)","ALTER SEQUENCE","
ALTER SEQUENCE sequenceName [ RESTART WITH long ] [ INCREMENT BY long ] ALTER SEQUENCE sequenceName [ RESTART WITH long ] [ INCREMENT BY long ]
"," ","
......
...@@ -467,6 +467,25 @@ public class Schema extends DbObjectBase { ...@@ -467,6 +467,25 @@ public class Schema extends DbObjectBase {
return sequence; return sequence;
} }
/**
* Get all objects.
*
* @return a (possible empty) list of all objects
*/
public ArrayList<SchemaObject> getAll() {
ArrayList<SchemaObject> all = New.arrayList();
all.addAll(getMap(DbObject.TABLE_OR_VIEW).values());
all.addAll(getMap(DbObject.SEQUENCE).values());
all.addAll(getMap(DbObject.INDEX).values());
all.addAll(getMap(DbObject.TRIGGER).values());
all.addAll(getMap(DbObject.CONSTRAINT).values());
all.addAll(getMap(DbObject.CONSTANT).values());
all.addAll(getMap(DbObject.FUNCTION_ALIAS).values());
return all;
}
/** /**
* Get all objects of the given type. * Get all objects of the given type.
* *
......
...@@ -13,6 +13,7 @@ import org.h2.engine.Constants; ...@@ -13,6 +13,7 @@ import org.h2.engine.Constants;
import org.h2.store.fs.FileSystemDisk; import org.h2.store.fs.FileSystemDisk;
import org.h2.test.bench.TestPerformance; import org.h2.test.bench.TestPerformance;
import org.h2.test.db.TestAlter; import org.h2.test.db.TestAlter;
import org.h2.test.db.TestAlterSchemaRename;
import org.h2.test.db.TestAutoRecompile; import org.h2.test.db.TestAutoRecompile;
import org.h2.test.db.TestBackup; import org.h2.test.db.TestBackup;
import org.h2.test.db.TestBigDb; import org.h2.test.db.TestBigDb;
...@@ -494,6 +495,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1` ...@@ -494,6 +495,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new TestScriptSimple().runTest(this); new TestScriptSimple().runTest(this);
new TestScript().runTest(this); new TestScript().runTest(this);
new TestAlter().runTest(this); new TestAlter().runTest(this);
new TestAlterSchemaRename().runTest(this);
new TestAutoRecompile().runTest(this); new TestAutoRecompile().runTest(this);
new TestBackup().runTest(this); new TestBackup().runTest(this);
new TestBigDb().runTest(this); new TestBigDb().runTest(this);
......
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.db;
import org.h2.constant.ErrorCode;
import org.h2.test.TestBase;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Test ALTER SCHEMA RENAME statements.
*/
public class TestAlterSchemaRename extends TestBase {
private Connection conn;
private Statement stat;
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws Exception {
deleteDb("alter");
conn = getConnection("alter");
stat = conn.createStatement();
testSimpleRename();
testRenameToExistingSchema();
testCrossSchemaViews();
testAlias();
conn.close();
deleteDb("alter");
}
private void testSimpleRename() throws SQLException {
stat.execute("create schema s1");
stat.execute("create table s1.tab(val int)");
stat.execute("insert into s1.tab(val) values (3)");
ResultSet rs = stat.executeQuery("select * from s1.tab");
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
stat.execute("alter schema s1 rename to s2");
rs = stat.executeQuery("select * from s2.tab");
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
stat.execute("drop schema s2");
}
private void testRenameToExistingSchema() throws SQLException {
stat.execute("create schema s1");
stat.execute("create schema s2");
try {
stat.execute("alter schema s1 rename to s2");
fail("Exception should be thrown");
} catch (SQLException e) {
assertEquals(ErrorCode.SCHEMA_ALREADY_EXISTS_1, e.getErrorCode());
}
stat.execute("drop schema s1");
stat.execute("drop schema s2");
}
private void testCrossSchemaViews() throws SQLException {
stat.execute("create schema s1");
stat.execute("create schema s2");
stat.execute("create table s1.tab(val int)");
stat.execute("insert into s1.tab(val) values (3)");
stat.execute("create view s1.v1 as select * from s1.tab");
stat.execute("create view s2.v1 as select val * 2 from s1.tab");
stat.execute("alter schema s2 rename to s2_new");
ResultSet rs = stat.executeQuery("select * from s1.v1");
assertTrue(rs.next());
assertEquals(3, rs.getInt(1));
rs = stat.executeQuery("select * from s2_new.v1");
assertTrue(rs.next());
assertEquals(6, rs.getInt(1));
if (!config.memory) {
conn.close();
conn = getConnection("alter");
stat = conn.createStatement();
stat.executeQuery("select * from s2_new.v1");
}
stat.execute("drop schema s1");
stat.execute("drop schema s2_new");
}
// Check that aliases in the schema got moved
private void testAlias() throws SQLException {
stat.execute("create schema s1");
stat.execute("CREATE ALIAS S1.REVERSE AS $$ " +
"String reverse(String s) {" +
" return new StringBuilder(s).reverse().toString();" +
"} $$;");
stat.execute("alter schema s1 rename to s2");
ResultSet rs = stat.executeQuery("CALL S2.REVERSE('1234')");
assertTrue(rs.next());
assertEquals("4321", rs.getString(1));
if (!config.memory) {
conn.close();
conn = getConnection("alter");
stat = conn.createStatement();
stat.executeQuery("CALL S2.REVERSE('1234')");
}
stat.execute("drop schema s2");
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论