提交 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.
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","
ALTER SEQUENCE sequenceName [ RESTART WITH long ] [ INCREMENT BY long ]
","
......
......@@ -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>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>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.
eg: build -Dtest=org.h2.test.db.TestViewDropView test (patch from Kerry Sainsbury).
</li></ul>
......
......@@ -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>MySQL compatibility: DatabaseMetaData.stores*() methods should return the same values. Test with SquirrelSQL.
</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>Support INTERVAL data type (see Oracle and others).
</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>.
</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>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>Issue 178: Optimizer: index usage when both ascending and descending indexes are available.
</li><li>Issue 179: Related subqueries in HAVING clause
......
......@@ -13,6 +13,7 @@ import java.util.ArrayList;
import java.util.HashSet;
import org.h2.api.Trigger;
import org.h2.command.ddl.AlterIndexRename;
import org.h2.command.ddl.AlterSchemaRename;
import org.h2.command.ddl.AlterTableAddConstraint;
import org.h2.command.ddl.AlterTableAlterColumn;
import org.h2.command.ddl.AlterTableDropConstraint;
......@@ -588,7 +589,7 @@ public class Parser {
return command;
}
private Schema getSchema() {
private Schema getSchema(String schemaName) {
if (schemaName == null) {
return null;
}
......@@ -604,6 +605,11 @@ public class Parser {
return schema;
}
private Schema getSchema() {
return getSchema(schemaName);
}
private Column readTableColumn(TableFilter filter) {
String tableAlias = null;
String columnName = readColumnIdentifier();
......@@ -4029,6 +4035,8 @@ public class Parser {
return parseAlterUser();
} else if (readIf("INDEX")) {
return parseAlterIndex();
} else if (readIf("SCHEMA")) {
return parseAlterSchema();
} else if (readIf("SEQUENCE")) {
return parseAlterSequence();
} else if (readIf("VIEW")) {
......@@ -4069,6 +4077,20 @@ public class Parser {
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() {
String sequenceName = readIdentifierWithSchema();
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 {
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.
*
......
......@@ -65,6 +65,10 @@ Lists the schemas, tables, or the columns of a table."
ALTER INDEX indexName RENAME TO newIndexName
","
Renames an index."
"Commands (DDL)","ALTER SCHEMA RENAME","
ALTER SCHEMA schema RENAME TO newSchemaName
","
Renames a schema."
"Commands (DDL)","ALTER SEQUENCE","
ALTER SEQUENCE sequenceName [ RESTART WITH long ] [ INCREMENT BY long ]
","
......
......@@ -467,6 +467,25 @@ public class Schema extends DbObjectBase {
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.
*
......
......@@ -13,6 +13,7 @@ import org.h2.engine.Constants;
import org.h2.store.fs.FileSystemDisk;
import org.h2.test.bench.TestPerformance;
import org.h2.test.db.TestAlter;
import org.h2.test.db.TestAlterSchemaRename;
import org.h2.test.db.TestAutoRecompile;
import org.h2.test.db.TestBackup;
import org.h2.test.db.TestBigDb;
......@@ -494,6 +495,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
new TestScriptSimple().runTest(this);
new TestScript().runTest(this);
new TestAlter().runTest(this);
new TestAlterSchemaRename().runTest(this);
new TestAutoRecompile().runTest(this);
new TestBackup().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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论