diff options
author | Eike Stepper | 2013-03-03 09:30:59 +0000 |
---|---|---|
committer | Eike Stepper | 2013-03-07 13:43:54 +0000 |
commit | da92d60f79c7828b1c7108a973f9e247826caeb9 (patch) | |
tree | e248206705b0f3b5ad586af78738495843237882 | |
parent | f7a7cb9e550d49c5fb6bcb1c57a59e15c3482c26 (diff) | |
download | cdo-da92d60f79c7828b1c7108a973f9e247826caeb9.tar.gz cdo-da92d60f79c7828b1c7108a973f9e247826caeb9.tar.xz cdo-da92d60f79c7828b1c7108a973f9e247826caeb9.zip |
[401763] Make CDO Server more robust against data dictionary changes
https://bugs.eclipse.org/bugs/show_bug.cgi?id=401763
35 files changed, 1308 insertions, 174 deletions
diff --git a/plugins/org.eclipse.net4j.db.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.net4j.db.tests/META-INF/MANIFEST.MF index 4655634fcb..9342dc7d2c 100644 --- a/plugins/org.eclipse.net4j.db.tests/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.net4j.db.tests/META-INF/MANIFEST.MF @@ -11,13 +11,21 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-ClassPath: . Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.4.0,4.0.0)", org.eclipse.net4j.tests;bundle-version="[4.0.0,5.0.0)";visibility:=reexport, - org.eclipse.net4j.db.derby;bundle-version="[4.0.0,5.0.0)";visibility:=reexport, + org.eclipse.net4j.db.h2;bundle-version="[4.0.0,5.0.0)";visibility:=reexport, + org.eclipse.net4j.db.derby;bundle-version="[4.0.0,5.0.0)";resolution:=optional;visibility:=reexport, org.eclipse.net4j.db.hsqldb;bundle-version="[4.0.0,5.0.0)";resolution:=optional;visibility:=reexport, org.eclipse.net4j.db.mysql;bundle-version="[4.0.0,5.0.0)";resolution:=optional;visibility:=reexport, org.eclipse.net4j.db.postgresql;bundle-version="[4.0.0,5.0.0)";resolution:=optional;visibility:=reexport -Import-Package: com.mysql.jdbc;version="[5.1.0,6.0.0)";resolution:=optional, +Import-Package: org.h2;version="[1.0.0,2.0.0)";resolution:=optional, + org.h2.command;version="[1.0.0,2.0.0)";resolution:=optional, + org.h2.expression;version="[1.0.0,2.0.0)";resolution:=optional, + org.h2.jdbc;version="[1.0.0,2.0.0)";resolution:=optional, + org.h2.jdbcx;version="[1.0.0,2.0.0)";resolution:=optional, + org.h2.util;version="[1.0.0,2.0.0)";resolution:=optional, + org.h2.value;version="[1.0.0,2.0.0)";resolution:=optional, + com.mysql.jdbc;version="[5.1.0,6.0.0)";resolution:=optional, com.mysql.jdbc.jdbc2.optional;version="[5.1.0,6.0.0)";resolution:=optional, - org.apache.derby.jdbc;version="[10.0.0,11.0.0)", + org.apache.derby.jdbc;version="[10.0.0,11.0.0)";resolution:=optional, org.hsqldb.jdbc;version="[2.0.0,3.0.0)";resolution:=optional Export-Package: org.eclipse.net4j.db.tests;version="4.0.200";x-internal:=true, org.eclipse.net4j.db.tests.bundle;version="4.0.200";x-internal:=true diff --git a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/AbstractDBTest.java b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/AbstractDBTest.java index 69d0a170d1..af98636a14 100644 --- a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/AbstractDBTest.java +++ b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/AbstractDBTest.java @@ -13,7 +13,10 @@ package org.eclipse.net4j.db.tests; import org.eclipse.net4j.db.DBType; import org.eclipse.net4j.db.DBUtil; import org.eclipse.net4j.db.IDBAdapter; +import org.eclipse.net4j.db.IDBConnection; import org.eclipse.net4j.db.IDBConnectionProvider; +import org.eclipse.net4j.db.IDBInstance; +import org.eclipse.net4j.db.IDBSchemaTransaction; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.db.ddl.IDBSchema; @@ -30,9 +33,11 @@ import java.util.Set; */ public abstract class AbstractDBTest extends AbstractOMTest { - protected IDBAdapter dbAdapter; + private IDBAdapter dbAdapter; - protected IDBConnectionProvider dbConnectionProvider; + private IDBConnectionProvider dbConnectionProvider; + + private Connection internalConnection; @Override protected void doSetUp() throws Exception @@ -46,44 +51,58 @@ public abstract class AbstractDBTest extends AbstractOMTest @Override protected void doTearDown() throws Exception { + if (internalConnection != null) + { + DBUtil.dropAllTables(internalConnection, null); + DBUtil.close(internalConnection); + internalConnection = null; + } + + dbConnectionProvider = null; + dbAdapter = null; } protected abstract IDBAdapter createDBAdapter(); protected abstract DataSource createDataSource(); - protected Connection getConnection() + private Connection getConnection() { - return dbConnectionProvider.getConnection(); + if (internalConnection == null) + { + internalConnection = dbConnectionProvider.getConnection(); + } + + return internalConnection; } - public void testDBTypes() throws Exception + public void _testDBTypes() throws Exception { - IDBSchema schema = DBUtil.createSchema("testDBTypes"); //$NON-NLS-1$ + IDBSchema schema = DBUtil.createSchema("testDBTypes"); DBType[] dbTypes = DBType.values(); int count = 0; int i = 0; for (DBType dbType : dbTypes) { - IDBTable table = schema.addTable("table_" + i); //$NON-NLS-1$ - table.addField("field", dbType); //$NON-NLS-1$ + IDBTable table = schema.addTable("table_" + i); + table.addField("field", dbType); ++count; if (dbAdapter.isTypeIndexable(dbType)) { - IDBTable idx_table = schema.addTable("idx_table" + i); //$NON-NLS-1$ - IDBField idx_field = idx_table.addField("field", dbType); //$NON-NLS-1$ + IDBTable idx_table = schema.addTable("idx_table" + i); + IDBField idx_field = idx_table.addField("field", dbType); idx_table.addIndex(IDBIndex.Type.NON_UNIQUE, idx_field); ++count; - IDBTable uni_table = schema.addTable("uni_table" + i); //$NON-NLS-1$ - IDBField uni_field = uni_table.addField("field", dbType); //$NON-NLS-1$ + IDBTable uni_table = schema.addTable("uni_table" + i); + IDBField uni_field = uni_table.addField("field", dbType); uni_table.addIndex(IDBIndex.Type.UNIQUE, uni_field); ++count; - IDBTable pk_table = schema.addTable("pk_table" + i); //$NON-NLS-1$ - IDBField pk_field = pk_table.addField("field", dbType); //$NON-NLS-1$ + IDBTable pk_table = schema.addTable("pk_table" + i); + IDBField pk_field = pk_table.addField("field", dbType); pk_table.addIndex(IDBIndex.Type.PRIMARY_KEY, pk_field); ++count; } @@ -91,37 +110,73 @@ public abstract class AbstractDBTest extends AbstractOMTest ++i; } - Set<IDBTable> tables = schema.create(dbAdapter, dbConnectionProvider); + Set<IDBTable> tables = schema.create(dbAdapter, getConnection()); assertEquals(count, tables.size()); } - // public void testEscapeStrings() throws Exception - // { - // IDBSchema schema = DBUtil.createSchema("testEscapeStrings"); //$NON-NLS-1$ - // IDBTable table = schema.addTable("testtable"); //$NON-NLS-1$ - // IDBField field = table.addField("strval", DBType.VARCHAR, 255); //$NON-NLS-1$ - // schema.create(dbAdapter, dbConnectionProvider); - // - // insertString(field, "My name is 'nobody', not body"); //$NON-NLS-1$ - // insertString(field, "a = 'hello'"); //$NON-NLS-1$ - // insertString(field, "'hello' == a"); //$NON-NLS-1$ - // insertString(field, "'hello'"); //$NON-NLS-1$ - // } - // - // private void insertString(IDBField field, String val) - // { - // Connection connection = getConnection(); - // IDBTable table = field.getTable(); - // - // try - // { - // DBUtil.insertRow(connection, dbAdapter, table, val); - // Object[] result = DBUtil.select(connection, (String)null, field); - // assertEquals(val, result[0]); - // } - // finally - // { - // DBUtil.update(connection, "DELETE FROM " + table); //$NON-NLS-1$ - // } - // } + public void testSchemaEmpty() throws Exception + { + IDBSchema schema = DBUtil.readSchema("test", getConnection()); + assertEquals(true, schema.isEmpty()); + } + + public void testSchemaAddition() throws Exception + { + IDBInstance dbInstance = DBUtil.createInstance(dbAdapter, dbConnectionProvider, "test"); + assertEquals(true, dbInstance.getDBSchema().isLocked()); + assertEquals(true, dbInstance.getDBSchema().isEmpty()); + + IDBConnection dbConnection = dbInstance.openDBConnection(); + IDBSchemaTransaction transaction = dbConnection.startSchemaTransaction(); + assertEquals(false, transaction.getDBSchema().isLocked()); + assertEquals(true, transaction.getDBSchema().isEmpty()); + assertEquals(dbInstance.getDBSchema().getName(), transaction.getDBSchema().getName()); + + IDBTable table1 = transaction.getDBSchema().addTable("table1"); + IDBField field11 = table1.addField("field1", DBType.INTEGER); + IDBField field12 = table1.addField("field2", DBType.VARCHAR, 64); + IDBField field13 = table1.addField("field3", DBType.BOOLEAN); + IDBIndex index11 = table1.addIndex("index1", IDBIndex.Type.PRIMARY_KEY, field11, field12); + IDBIndex index12 = table1.addIndex("index2", IDBIndex.Type.UNIQUE, field11, field12); + IDBIndex index13 = table1.addIndex("index3", IDBIndex.Type.NON_UNIQUE, field12); + + IDBTable table2 = transaction.getDBSchema().addTable("table2"); + IDBField field21 = table2.addField("field1", DBType.INTEGER); + IDBField field22 = table2.addField("field2", DBType.VARCHAR, 64); + IDBField field23 = table2.addField("field3", DBType.BOOLEAN); + IDBIndex index21 = table2.addIndex("index1", IDBIndex.Type.PRIMARY_KEY, field21, field22); + IDBIndex index22 = table2.addIndex("index2", IDBIndex.Type.UNIQUE, field21, field22); + IDBIndex index23 = table2.addIndex("index3", IDBIndex.Type.NON_UNIQUE, field22); + + transaction.commit(); + assertEquals(true, dbInstance.getDBSchema().isLocked()); + assertEquals(false, dbInstance.getDBSchema().isEmpty()); + assertEquals(2, dbInstance.getDBSchema().getTables().length); + + assertEquals(table1.getName(), dbInstance.getDBSchema().getTables()[0].getName()); + assertEquals(table1.getFieldCount(), dbInstance.getDBSchema().getTables()[0].getFieldCount()); + assertEquals(field11.getName(), dbInstance.getDBSchema().getTables()[0].getField(0).getName()); + assertEquals(field12.getName(), dbInstance.getDBSchema().getTables()[0].getField(1).getName()); + assertEquals(field13.getName(), dbInstance.getDBSchema().getTables()[0].getField(2).getName()); + assertEquals(table1.getIndexCount(), dbInstance.getDBSchema().getTables()[0].getIndexCount()); + assertEquals(index11.getName(), dbInstance.getDBSchema().getTables()[0].getIndex(0).getName()); + assertEquals(index11.getType(), dbInstance.getDBSchema().getTables()[0].getIndex(0).getType()); + assertEquals(index12.getName(), dbInstance.getDBSchema().getTables()[0].getIndex(1).getName()); + assertEquals(index12.getType(), dbInstance.getDBSchema().getTables()[0].getIndex(1).getType()); + assertEquals(index13.getName(), dbInstance.getDBSchema().getTables()[0].getIndex(2).getName()); + assertEquals(index13.getType(), dbInstance.getDBSchema().getTables()[0].getIndex(2).getType()); + + assertEquals(table2.getName(), dbInstance.getDBSchema().getTables()[1].getName()); + assertEquals(table2.getFieldCount(), dbInstance.getDBSchema().getTables()[1].getFieldCount()); + assertEquals(field21.getName(), dbInstance.getDBSchema().getTables()[1].getField(0).getName()); + assertEquals(field22.getName(), dbInstance.getDBSchema().getTables()[1].getField(1).getName()); + assertEquals(field23.getName(), dbInstance.getDBSchema().getTables()[1].getField(2).getName()); + assertEquals(table2.getIndexCount(), dbInstance.getDBSchema().getTables()[1].getIndexCount()); + assertEquals(index21.getName(), dbInstance.getDBSchema().getTables()[1].getIndex(0).getName()); + assertEquals(index21.getType(), dbInstance.getDBSchema().getTables()[1].getIndex(0).getType()); + assertEquals(index22.getName(), dbInstance.getDBSchema().getTables()[1].getIndex(1).getName()); + assertEquals(index22.getType(), dbInstance.getDBSchema().getTables()[1].getIndex(1).getType()); + assertEquals(index23.getName(), dbInstance.getDBSchema().getTables()[1].getIndex(2).getName()); + assertEquals(index23.getType(), dbInstance.getDBSchema().getTables()[1].getIndex(2).getType()); + } } diff --git a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/AllTests.java b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/AllTests.java index 7d3a5cd3b6..9289c2ec7e 100644 --- a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/AllTests.java +++ b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/AllTests.java @@ -4,7 +4,7 @@ * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Eike Stepper - initial API and implementation */ @@ -20,10 +20,10 @@ public class AllTests { public static Test suite() { - TestSuite suite = new TestSuite("Tests for Net4j"); //$NON-NLS-1$ + TestSuite suite = new TestSuite("Tests for Net4j DB"); // $JUnit-BEGIN$ - suite.addTestSuite(DerbyTest.class); + suite.addTestSuite(H2Test.class); // $JUnit-END$ return suite; diff --git a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/DerbyTest.java b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/DerbyTest.java index 52ad5ef007..689f10fe20 100644 --- a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/DerbyTest.java +++ b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/DerbyTest.java @@ -12,7 +12,6 @@ package org.eclipse.net4j.db.tests; import org.eclipse.net4j.db.IDBAdapter; import org.eclipse.net4j.util.io.IOUtil; -import org.eclipse.net4j.util.io.TMPUtil; import org.apache.derby.jdbc.EmbeddedDataSource; @@ -36,13 +35,13 @@ public class DerbyTest extends AbstractDBTest @Override protected DataSource createDataSource() { - dbFolder = TMPUtil.createTempFolder("derby_"); //$NON-NLS-1$ + dbFolder = createTempFolder("derby_"); deleteDBFolder(); - msg("Using DB folder: " + dbFolder.getAbsolutePath()); //$NON-NLS-1$ + msg("Using DB folder: " + dbFolder.getAbsolutePath()); EmbeddedDataSource dataSource = new EmbeddedDataSource(); dataSource.setDatabaseName(dbFolder.getAbsolutePath()); - dataSource.setCreateDatabase("create"); //$NON-NLS-1$ + dataSource.setCreateDatabase("create"); return dataSource; } diff --git a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/H2Test.java b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/H2Test.java new file mode 100644 index 0000000000..e6b2fbce69 --- /dev/null +++ b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/H2Test.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.tests; + +import org.eclipse.net4j.db.IDBAdapter; +import org.eclipse.net4j.util.io.IOUtil; + +import org.h2.jdbcx.JdbcDataSource; + +import javax.sql.DataSource; + +import java.io.File; + +/** + * @author Eike Stepper + */ +public class H2Test extends AbstractDBTest +{ + private File dbFolder; + + @Override + protected IDBAdapter createDBAdapter() + { + return new org.eclipse.net4j.db.h2.H2Adapter(); + } + + @Override + protected DataSource createDataSource() + { + dbFolder = createTempFolder("h2_"); + deleteDBFolder(); + msg("Using DB folder: " + dbFolder.getAbsolutePath()); + + JdbcDataSource dataSource = new JdbcDataSource(); + dataSource.setURL("jdbc:h2:" + dbFolder.getAbsolutePath() + "/h2test"); + return dataSource; + } + + @Override + protected void doTearDown() throws Exception + { + deleteDBFolder(); + super.doTearDown(); + } + + private void deleteDBFolder() + { + IOUtil.delete(dbFolder); + } +} diff --git a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/HsqldbTest.java b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/HsqldbTest.java index edebd301d3..6442d3fa82 100644 --- a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/HsqldbTest.java +++ b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/HsqldbTest.java @@ -30,8 +30,8 @@ public class HsqldbTest extends AbstractDBTest protected DataSource createDataSource() { HSQLDBDataSource dataSource = new HSQLDBDataSource(); - dataSource.setDatabase("jdbc:hsqldb:mem:dbtest"); //$NON-NLS-1$ - dataSource.setUser("sa"); //$NON-NLS-1$ + dataSource.setDatabase("jdbc:hsqldb:mem:dbtest"); + dataSource.setUser("sa"); return dataSource; } } diff --git a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/TestSchema.java b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/TestSchema.java index abf56ff939..9ca4be9869 100644 --- a/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/TestSchema.java +++ b/plugins/org.eclipse.net4j.db.tests/src/org/eclipse/net4j/db/tests/TestSchema.java @@ -26,51 +26,51 @@ public class TestSchema extends DBSchema /** * DBTable cdo_repository */ - public static final IDBTable REPOSITORY = INSTANCE.addTable("cdo_repository"); //$NON-NLS-1$ + public static final IDBTable REPOSITORY = INSTANCE.addTable("cdo_repository"); public static final IDBField REPOSITORY_NAME = // - REPOSITORY.addField("name", DBType.VARCHAR, 255); //$NON-NLS-1$ + REPOSITORY.addField("name", DBType.VARCHAR, 255); public static final IDBField REPOSITORY_UUID = // - REPOSITORY.addField("uuid", DBType.VARCHAR, 64); //$NON-NLS-1$ + REPOSITORY.addField("uuid", DBType.VARCHAR, 64); public static final IDBField REPOSITORY_STARTS = // - REPOSITORY.addField("starts", DBType.BIGINT); //$NON-NLS-1$ + REPOSITORY.addField("starts", DBType.BIGINT); public static final IDBField REPOSITORY_STARTED = // - REPOSITORY.addField("started", DBType.BIGINT); //$NON-NLS-1$ + REPOSITORY.addField("started", DBType.BIGINT); public static final IDBField REPOSITORY_STOPPED = // - REPOSITORY.addField("stopped", DBType.BIGINT); //$NON-NLS-1$ + REPOSITORY.addField("stopped", DBType.BIGINT); public static final IDBField REPOSITORY_NEXT_CDOID = // - REPOSITORY.addField("next_cdoid", DBType.BIGINT); //$NON-NLS-1$ + REPOSITORY.addField("next_cdoid", DBType.BIGINT); /** * DBTable cdo_packages */ - public static final IDBTable PACKAGES = INSTANCE.addTable("cdo_packages"); //$NON-NLS-1$ + public static final IDBTable PACKAGES = INSTANCE.addTable("cdo_packages"); public static final IDBField PACKAGES_ID = // - PACKAGES.addField("id", DBType.INTEGER); //$NON-NLS-1$ + PACKAGES.addField("id", DBType.INTEGER); public static final IDBField PACKAGES_URI = // - PACKAGES.addField("uri", DBType.VARCHAR, 255); //$NON-NLS-1$ + PACKAGES.addField("uri", DBType.VARCHAR, 255); public static final IDBField PACKAGES_NAME = // - PACKAGES.addField("name", DBType.VARCHAR, 255); //$NON-NLS-1$ + PACKAGES.addField("name", DBType.VARCHAR, 255); public static final IDBField PACKAGES_ECORE = // - PACKAGES.addField("ecore", DBType.CLOB); //$NON-NLS-1$ + PACKAGES.addField("ecore", DBType.CLOB); public static final IDBField PACKAGES_DYNAMIC = // - PACKAGES.addField("dynamic", DBType.BOOLEAN); //$NON-NLS-1$ + PACKAGES.addField("dynamic", DBType.BOOLEAN); public static final IDBField PACKAGES_RANGE_LB = // - PACKAGES.addField("range_lb", DBType.BIGINT); //$NON-NLS-1$ + PACKAGES.addField("range_lb", DBType.BIGINT); public static final IDBField PACKAGES_RANGE_UB = // - PACKAGES.addField("range_ub", DBType.BIGINT); //$NON-NLS-1$ + PACKAGES.addField("range_ub", DBType.BIGINT); public static final IDBIndex INDEX_PACKAGES_PK = // PACKAGES.addIndex(IDBIndex.Type.PRIMARY_KEY, PACKAGES_ID); @@ -81,22 +81,22 @@ public class TestSchema extends DBSchema /** * DBTable cdo_classes */ - public static final IDBTable CLASSES = INSTANCE.addTable("cdo_classes"); //$NON-NLS-1$ + public static final IDBTable CLASSES = INSTANCE.addTable("cdo_classes"); public static final IDBField CLASSES_ID = // - CLASSES.addField("id", DBType.INTEGER); //$NON-NLS-1$ + CLASSES.addField("id", DBType.INTEGER); public static final IDBField CLASSES_PACKAGE = // - CLASSES.addField("package", DBType.INTEGER); //$NON-NLS-1$ + CLASSES.addField("package", DBType.INTEGER); public static final IDBField CLASSES_CLASSIFIER = // - CLASSES.addField("classifier", DBType.INTEGER); //$NON-NLS-1$ + CLASSES.addField("classifier", DBType.INTEGER); public static final IDBField CLASSES_NAME = // - CLASSES.addField("name", DBType.VARCHAR, 255); //$NON-NLS-1$ + CLASSES.addField("name", DBType.VARCHAR, 255); public static final IDBField CLASSES_ABSTRACT = // - CLASSES.addField("abstract", DBType.BOOLEAN); //$NON-NLS-1$ + CLASSES.addField("abstract", DBType.BOOLEAN); public static final IDBIndex INDEX_CLASSES_PK = // CLASSES.addIndex(IDBIndex.Type.PRIMARY_KEY, CLASSES_ID); @@ -104,16 +104,16 @@ public class TestSchema extends DBSchema /** * DBTable cdo_supertypes */ - public static final IDBTable SUPERTYPES = INSTANCE.addTable("cdo_supertypes"); //$NON-NLS-1$ + public static final IDBTable SUPERTYPES = INSTANCE.addTable("cdo_supertypes"); public static final IDBField SUPERTYPES_TYPE = // - SUPERTYPES.addField("type_id", DBType.INTEGER); //$NON-NLS-1$ + SUPERTYPES.addField("type_id", DBType.INTEGER); public static final IDBField SUPERTYPES_SUPERTYPE_PACKAGE = // - SUPERTYPES.addField("supertype_package", DBType.VARCHAR, 255); //$NON-NLS-1$ + SUPERTYPES.addField("supertype_package", DBType.VARCHAR, 255); public static final IDBField SUPERTYPES_SUPERTYPE_CLASSIFIER = // - SUPERTYPES.addField("supertype_classifier", DBType.INTEGER); //$NON-NLS-1$ + SUPERTYPES.addField("supertype_classifier", DBType.INTEGER); public static final IDBIndex INDEX_SUPERTYPES_PK = // SUPERTYPES.addIndex(IDBIndex.Type.PRIMARY_KEY, SUPERTYPES_TYPE); @@ -121,37 +121,37 @@ public class TestSchema extends DBSchema /** * DBTable cdo_features */ - public static final IDBTable FEATURES = INSTANCE.addTable("cdo_features"); //$NON-NLS-1$ + public static final IDBTable FEATURES = INSTANCE.addTable("cdo_features"); public static final IDBField FEATURES_ID = // - FEATURES.addField("id", DBType.INTEGER); //$NON-NLS-1$ + FEATURES.addField("id", DBType.INTEGER); public static final IDBField FEATURES_CLASS = // - FEATURES.addField("class", DBType.INTEGER); //$NON-NLS-1$ + FEATURES.addField("class", DBType.INTEGER); public static final IDBField FEATURES_FEATURE = // - FEATURES.addField("feature", DBType.INTEGER); //$NON-NLS-1$ + FEATURES.addField("feature", DBType.INTEGER); public static final IDBField FEATURES_NAME = // - FEATURES.addField("name", DBType.VARCHAR, 255); //$NON-NLS-1$ + FEATURES.addField("name", DBType.VARCHAR, 255); public static final IDBField FEATURES_TYPE = // - FEATURES.addField("type", DBType.INTEGER); //$NON-NLS-1$ + FEATURES.addField("type", DBType.INTEGER); public static final IDBField FEATURES_REFERENCE_PACKAGE = // - FEATURES.addField("reference_package", DBType.VARCHAR, 255); //$NON-NLS-1$ + FEATURES.addField("reference_package", DBType.VARCHAR, 255); public static final IDBField FEATURES_REFERENCE_CLASSIFIER = // - FEATURES.addField("reference_classifier", DBType.INTEGER); //$NON-NLS-1$ + FEATURES.addField("reference_classifier", DBType.INTEGER); public static final IDBField FEATURES_MANY = // - FEATURES.addField("many", DBType.BOOLEAN); //$NON-NLS-1$ + FEATURES.addField("many", DBType.BOOLEAN); public static final IDBField FEATURES_CONTAINMENT = // - FEATURES.addField("containment", DBType.BOOLEAN); //$NON-NLS-1$ + FEATURES.addField("containment", DBType.BOOLEAN); public static final IDBField FEATURES_INDEX = // - FEATURES.addField("idx", DBType.INTEGER); //$NON-NLS-1$ + FEATURES.addField("idx", DBType.INTEGER); public static final IDBIndex INDEX_FEATURES_PK = // FEATURES.addIndex(IDBIndex.Type.PRIMARY_KEY, FEATURES_ID); @@ -159,43 +159,43 @@ public class TestSchema extends DBSchema /** * Name of object table */ - public static final String CDO_OBJECTS = "cdo_objects"; //$NON-NLS-1$ + public static final String CDO_OBJECTS = "cdo_objects"; /** * Field names of attribute tables */ - public static final String ATTRIBUTES_ID = "cdo_id"; //$NON-NLS-1$ + public static final String ATTRIBUTES_ID = "cdo_id"; - public static final String ATTRIBUTES_VERSION = "cdo_version"; //$NON-NLS-1$ + public static final String ATTRIBUTES_VERSION = "cdo_version"; - public static final String ATTRIBUTES_CLASS = "cdo_class"; //$NON-NLS-1$ + public static final String ATTRIBUTES_CLASS = "cdo_class"; - public static final String ATTRIBUTES_CREATED = "cdo_created"; //$NON-NLS-1$ + public static final String ATTRIBUTES_CREATED = "cdo_created"; - public static final String ATTRIBUTES_REVISED = "cdo_revised"; //$NON-NLS-1$ + public static final String ATTRIBUTES_REVISED = "cdo_revised"; - public static final String ATTRIBUTES_RESOURCE = "cdo_resource"; //$NON-NLS-1$ + public static final String ATTRIBUTES_RESOURCE = "cdo_resource"; - public static final String ATTRIBUTES_CONTAINER = "cdo_container"; //$NON-NLS-1$ + public static final String ATTRIBUTES_CONTAINER = "cdo_container"; - public static final String ATTRIBUTES_FEATURE = "cdo_feature"; //$NON-NLS-1$ + public static final String ATTRIBUTES_FEATURE = "cdo_feature"; /** * Field names of reference tables */ - public static final String REFERENCES_FEATURE = "cdo_feature"; //$NON-NLS-1$ + public static final String REFERENCES_FEATURE = "cdo_feature"; - public static final String REFERENCES_SOURCE = "cdo_source"; //$NON-NLS-1$ + public static final String REFERENCES_SOURCE = "cdo_source"; - public static final String REFERENCES_VERSION = "cdo_version"; //$NON-NLS-1$ + public static final String REFERENCES_VERSION = "cdo_version"; - public static final String REFERENCES_IDX = "cdo_idx"; //$NON-NLS-1$ + public static final String REFERENCES_IDX = "cdo_idx"; - public static final String REFERENCES_TARGET = "cdo_target"; //$NON-NLS-1$ + public static final String REFERENCES_TARGET = "cdo_target"; private TestSchema() { - super("CDO"); //$NON-NLS-1$ + super("CDO"); } static diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java index 8a485fb6c8..f55f1d7951 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/DBUtil.java @@ -14,6 +14,7 @@ import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.internal.db.DBConnection; +import org.eclipse.net4j.internal.db.DBInstance; import org.eclipse.net4j.internal.db.DataSourceConnectionProvider; import org.eclipse.net4j.internal.db.bundle.OM; import org.eclipse.net4j.spi.db.DBSchema; @@ -136,6 +137,15 @@ public final class DBUtil } } + /** + * @since 4.2 + */ + public static IDBInstance createInstance(IDBAdapter dbAdapter, IDBConnectionProvider dbConnectionProvider, + String schemaName) + { + return new DBInstance(dbAdapter, dbConnectionProvider, schemaName); + } + public static IDBSchema createSchema(String name) { return new DBSchema(name); @@ -584,6 +594,56 @@ public final class DBUtil } /** + * @since 4.2 + */ + public static <T> T execute(IDBConnectionProvider connectionProvider, RunnableWithConnection<T> runnable) + { + Connection connection = null; + + try + { + connection = connectionProvider.getConnection(); + return runnable.run(connection); + } + catch (SQLException ex) + { + throw new DBException(ex); + } + finally + { + close(connection); + } + } + + /** + * @since 4.2 + */ + public static void execute(Connection connection, CharSequence sql) + { + String string = sql.toString(); + if (TRACER.isEnabled()) + { + TRACER.trace(string); + } + + Statement statement = null; + + try + { + statement = connection.createStatement(); + statement.execute(string); + } + catch (SQLException ex) + { + throw new DBException(ex); + } + finally + { + close(statement); + } + } + + /** * @since 4.1 */ public static void executeBatch(PreparedStatement stmt, int counter) @@ -1128,11 +1188,20 @@ public final class DBUtil } /** + * @since 4.2 + * @author Eike Stepper + */ + public interface RunnableWithConnection<T> + { + public T run(Connection connection) throws SQLException; + } + + /** * Call-back interface with a {@link #done(boolean) method} that is called <i>after</i> * a number of table rows have been handled by one of the subtypes of this interface. * - * @author Eike Stepper * @since 4.1 + * @author Eike Stepper */ public interface RowHandler { @@ -1143,8 +1212,8 @@ public final class DBUtil * A {@link RowHandler row handler} with a {@link #handleRow(ExtendedDataOutput, Connection, IDBField[], Object[]) method} * that is called once per row serialized within {@link DBUtil#serializeTable(ExtendedDataOutput, Connection, IDBTable, String, String, SerializeRowHandler) DBUtil.serializeTable()}. * - * @author Eike Stepper * @since 4.1 + * @author Eike Stepper */ public interface SerializeRowHandler extends RowHandler { @@ -1156,8 +1225,8 @@ public final class DBUtil * A {@link RowHandler row handler} with a {@link #handleRow(ExtendedDataInput, Connection, IDBField[], Object[]) method} * that is called once per row deserialized within {@link DBUtil#deserializeTable(ExtendedDataInput, Connection, IDBTable, OMMonitor, DeserializeRowHandler) DBUtil.deserializeTable()}. * - * @author Eike Stepper * @since 4.1 + * @author Eike Stepper */ public interface DeserializeRowHandler extends RowHandler { diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java index 3bbf1e78d0..b33026448c 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java @@ -12,6 +12,7 @@ package org.eclipse.net4j.db; import org.eclipse.net4j.db.ddl.IDBField; +import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; import org.eclipse.net4j.internal.db.DBAdapterRegistry; @@ -56,7 +57,7 @@ public interface IDBAdapter /** * @since 4.2 */ - public void updateSchema(IDBSchemaDelta delta, Connection connection) throws DBException; + public void updateSchema(Connection connection, IDBSchema schema, IDBSchemaDelta delta) throws DBException; public Set<IDBTable> createTables(Iterable<? extends IDBTable> tables, Connection connection) throws DBException; diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBField.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBField.java index 559e474a09..b66a873f44 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBField.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBField.java @@ -25,7 +25,7 @@ public interface IDBField extends IDBSchemaElement public IDBTable getTable(); - public void setName(String name); + public void setName(String name); // TODO Move to IDBSchemaElement public DBType getType(); @@ -41,7 +41,7 @@ public interface IDBField extends IDBSchemaElement public boolean isNotNull(); - public void setNotNull(boolean on); + public void setNotNull(boolean notNull); public int getPosition(); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java index 6f490babf8..e3da8c7b55 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBIndex.java @@ -26,8 +26,30 @@ public interface IDBIndex extends IDBSchemaElement /** * @since 4.2 */ + public void setType(Type type); + + public int getPosition(); + + /** + * @since 4.2 + */ + public IDBIndexField addIndexField(IDBField field); + + /** + * @since 4.2 + */ + public IDBIndexField getIndexField(String name); + + /** + * @since 4.2 + */ public IDBIndexField getIndexField(int position); + /** + * @since 4.2 + */ + public IDBField getField(String name); + public IDBField getField(int position); public int getFieldCount(); @@ -39,8 +61,6 @@ public interface IDBIndex extends IDBSchemaElement public IDBField[] getFields(); - public int getPosition(); - /** * The type of an {@link IDBIndex index} specification in a {@link IDBTable DB table}. * diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java index 3a87535c0e..a69b0162c0 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchema.java @@ -32,6 +32,11 @@ import java.util.Set; */ public interface IDBSchema extends IDBSchemaElement, IContainer<IDBTable> { + /** + * @since 4.2 + */ + public boolean isLocked(); + public IDBTable addTable(String name) throws DBException; /** diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaElement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaElement.java index e6ddb97fe5..f26f6d5919 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaElement.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBSchemaElement.java @@ -26,4 +26,9 @@ public interface IDBSchemaElement extends IDBElement public String getName(); public String getFullName(); + + /** + * @since 4.2 + */ + public void remove(); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java index 8095bd0a99..554727e02d 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/IDBTable.java @@ -35,7 +35,7 @@ public interface IDBTable extends IDBSchemaElement public IDBField getField(String name); - public IDBField getField(int index); + public IDBField getField(int position); public int getFieldCount(); @@ -48,6 +48,16 @@ public interface IDBTable extends IDBSchemaElement */ public IDBIndex addIndex(String name, IDBIndex.Type type, IDBField... fields); + /** + * @since 4.2 + */ + public IDBIndex getIndex(String name); + + /** + * @since 4.2 + */ + public IDBIndex getIndex(int position); + public int getIndexCount(); public IDBIndex[] getIndices(); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDelta.java index 4308379502..41cc7ab387 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDelta.java @@ -11,6 +11,8 @@ package org.eclipse.net4j.db.ddl.delta; import org.eclipse.net4j.db.IDBElement; +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.db.ddl.IDBSchemaElement; import java.io.Serializable; import java.util.Map; @@ -29,13 +31,23 @@ public interface IDBDelta extends IDBElement, Serializable public ChangeKind getChangeKind(); + public <T> IDBPropertyDelta<T> getPropertyDelta(String name); + + public <T> T getPropertyValue(String name); + + public <T> T getPropertyValue(String name, boolean old); + public Map<String, IDBPropertyDelta<?>> getPropertyDeltas(); + public void accept(IDBDeltaVisitor visitor); + + public IDBSchemaElement getElement(IDBSchema schema); + /** * @author Eike Stepper */ public enum ChangeKind { - CHANGED, ADDED, REMOVED + ADDED, REMOVED, CHANGED } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDeltaVisitor.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDeltaVisitor.java new file mode 100644 index 0000000000..5efb7475fb --- /dev/null +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBDeltaVisitor.java @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.net4j.db.ddl.delta; + +import org.eclipse.net4j.db.DBType; +import org.eclipse.net4j.db.ddl.IDBField; +import org.eclipse.net4j.db.ddl.IDBIndex; +import org.eclipse.net4j.db.ddl.IDBIndexField; +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBDelta.ChangeKind; + +/** + * @since 4.2 + * @author Eike Stepper + */ +public interface IDBDeltaVisitor +{ + public void visit(IDBSchemaDelta schemaDelta); + + public void visit(IDBTableDelta tableDelta); + + public void visit(IDBFieldDelta fieldDelta); + + public void visit(IDBIndexDelta indexDelta); + + public void visit(IDBIndexFieldDelta indexFieldDelta); + + /** + * @author Eike Stepper + */ + public static class Default implements IDBDeltaVisitor + { + protected void visitDefault(IDBDelta delta) + { + } + + public void visit(IDBSchemaDelta delta) + { + ChangeKind changeKind = delta.getChangeKind(); + switch (changeKind) + { + case ADDED: + added(delta); + break; + + case REMOVED: + removed(delta); + break; + + case CHANGED: + changed(delta); + break; + + default: + throw new IllegalStateException("Illegal change kind: " + changeKind); + } + } + + protected void added(IDBSchemaDelta delta) + { + visitDefault(delta); + } + + protected void removed(IDBSchemaDelta delta) + { + visitDefault(delta); + } + + protected void changed(IDBSchemaDelta delta) + { + visitDefault(delta); + } + + public void visit(IDBTableDelta delta) + { + ChangeKind changeKind = delta.getChangeKind(); + switch (changeKind) + { + case ADDED: + added(delta); + break; + + case REMOVED: + removed(delta); + break; + + case CHANGED: + changed(delta); + break; + + default: + throw new IllegalStateException("Illegal change kind: " + changeKind); + } + } + + protected void added(IDBTableDelta delta) + { + visitDefault(delta); + } + + protected void removed(IDBTableDelta delta) + { + visitDefault(delta); + } + + protected void changed(IDBTableDelta delta) + { + visitDefault(delta); + } + + public void visit(IDBFieldDelta delta) + { + ChangeKind changeKind = delta.getChangeKind(); + switch (changeKind) + { + case ADDED: + added(delta); + break; + + case REMOVED: + removed(delta); + break; + + case CHANGED: + changed(delta); + break; + + default: + throw new IllegalStateException("Illegal change kind: " + changeKind); + } + } + + protected void added(IDBFieldDelta delta) + { + visitDefault(delta); + } + + protected void removed(IDBFieldDelta delta) + { + visitDefault(delta); + } + + protected void changed(IDBFieldDelta delta) + { + visitDefault(delta); + } + + public void visit(IDBIndexDelta delta) + { + ChangeKind changeKind = delta.getChangeKind(); + switch (changeKind) + { + case ADDED: + added(delta); + break; + + case REMOVED: + removed(delta); + break; + + case CHANGED: + changed(delta); + break; + + default: + throw new IllegalStateException("Illegal change kind: " + changeKind); + } + } + + protected void added(IDBIndexDelta delta) + { + visitDefault(delta); + } + + protected void removed(IDBIndexDelta delta) + { + visitDefault(delta); + } + + protected void changed(IDBIndexDelta delta) + { + visitDefault(delta); + } + + public void visit(IDBIndexFieldDelta delta) + { + ChangeKind changeKind = delta.getChangeKind(); + switch (changeKind) + { + case ADDED: + added(delta); + break; + + case REMOVED: + removed(delta); + break; + + case CHANGED: + changed(delta); + break; + + default: + throw new IllegalStateException("Illegal change kind: " + changeKind); + } + } + + protected void added(IDBIndexFieldDelta delta) + { + visitDefault(delta); + } + + protected void removed(IDBIndexFieldDelta delta) + { + visitDefault(delta); + } + + protected void changed(IDBIndexFieldDelta delta) + { + visitDefault(delta); + } + } + + /** + * @author Eike Stepper + */ + public static class Applier extends IDBDeltaVisitor.Default + { + private final IDBSchema schema; + + public Applier(IDBSchema schema) + { + this.schema = schema; + } + + public final IDBSchema getSchema() + { + return schema; + } + + @Override + protected void added(IDBTableDelta delta) + { + String name = delta.getName(); + schema.addTable(name); + } + + @Override + protected void removed(IDBTableDelta delta) + { + IDBTable table = delta.getElement(schema); + table.remove(); + } + + @Override + protected void changed(IDBTableDelta delta) + { + } + + @Override + protected void added(IDBFieldDelta delta) + { + String name = delta.getName(); + DBType type = delta.getPropertyValue(IDBFieldDelta.TYPE_PROPERTY); + int precision = delta.getPropertyValue(IDBFieldDelta.PRECISION_PROPERTY); + int scale = delta.getPropertyValue(IDBFieldDelta.SCALE_PROPERTY); + boolean notNull = delta.getPropertyValue(IDBFieldDelta.NOT_NULL_PROPERTY); + + IDBTable table = delta.getParent().getElement(schema); + table.addField(name, type, precision, scale, notNull); + } + + @Override + protected void removed(IDBFieldDelta delta) + { + IDBField field = delta.getElement(schema); + field.remove(); + } + + @Override + protected void changed(IDBFieldDelta delta) + { + } + + @Override + protected void added(IDBIndexDelta delta) + { + String name = delta.getName(); + IDBIndex.Type type = delta.getPropertyValue(IDBIndexDelta.TYPE_PROPERTY); + + IDBTable table = delta.getParent().getElement(schema); + table.addIndex(name, type); + } + + @Override + protected void removed(IDBIndexDelta delta) + { + IDBIndex index = delta.getElement(schema); + index.remove(); + } + + @Override + protected void changed(IDBIndexDelta delta) + { + } + + @Override + protected void added(IDBIndexFieldDelta delta) + { + IDBIndexDelta parent = delta.getParent(); + IDBTable table = parent.getParent().getElement(schema); + + String name = delta.getName(); + IDBField field = table.getField(name); + + IDBIndex index = parent.getElement(schema); + index.addIndexField(field); + } + + @Override + protected void removed(IDBIndexFieldDelta delta) + { + IDBIndexField indexField = delta.getElement(schema); + indexField.remove(); + } + + @Override + protected void changed(IDBIndexFieldDelta delta) + { + } + } +} diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBFieldDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBFieldDelta.java index 73920f3f18..2877d68480 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBFieldDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBFieldDelta.java @@ -10,6 +10,9 @@ */ package org.eclipse.net4j.db.ddl.delta; +import org.eclipse.net4j.db.ddl.IDBField; +import org.eclipse.net4j.db.ddl.IDBSchema; + /** * @since 4.2 * @author Eike Stepper @@ -18,4 +21,15 @@ package org.eclipse.net4j.db.ddl.delta; */ public interface IDBFieldDelta extends IDBTableElementDelta { + public static final String TYPE_PROPERTY = "type"; + + public static final String PRECISION_PROPERTY = "precision"; + + public static final String SCALE_PROPERTY = "scale"; + + public static final String NOT_NULL_PROPERTY = "notNull"; + + public static final String POSITION_PROPERTY = "position"; + + public IDBField getElement(IDBSchema schema); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexDelta.java index 9e0eae173c..6ed3f5194c 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexDelta.java @@ -10,6 +10,8 @@ */ package org.eclipse.net4j.db.ddl.delta; +import org.eclipse.net4j.db.ddl.IDBIndex; +import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.util.container.IContainer; import java.util.Map; @@ -22,5 +24,9 @@ import java.util.Map; */ public interface IDBIndexDelta extends IDBTableElementDelta, IContainer<IDBIndexFieldDelta> { + public static final String TYPE_PROPERTY = "type"; + public Map<String, IDBIndexFieldDelta> getIndexFieldDeltas(); + + public IDBIndex getElement(IDBSchema schema); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexFieldDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexFieldDelta.java index 4f388d2ba4..79bc4afd42 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexFieldDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBIndexFieldDelta.java @@ -10,6 +10,9 @@ */ package org.eclipse.net4j.db.ddl.delta; +import org.eclipse.net4j.db.ddl.IDBIndexField; +import org.eclipse.net4j.db.ddl.IDBSchema; + /** * @since 4.2 * @author Eike Stepper @@ -18,5 +21,9 @@ package org.eclipse.net4j.db.ddl.delta; */ public interface IDBIndexFieldDelta extends IDBDelta, Comparable<IDBIndexFieldDelta> { + public static final String POSITION_PROPERTY = "position"; + public IDBIndexDelta getParent(); + + public IDBIndexField getElement(IDBSchema schema); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBSchemaDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBSchemaDelta.java index d24cd6b4e3..261cce398e 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBSchemaDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBSchemaDelta.java @@ -10,6 +10,7 @@ */ package org.eclipse.net4j.db.ddl.delta; +import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.util.container.IContainer; import java.util.Map; @@ -23,4 +24,8 @@ import java.util.Map; public interface IDBSchemaDelta extends IDBDelta, IContainer<IDBTableDelta>, Comparable<IDBSchemaDelta> { public Map<String, IDBTableDelta> getTableDeltas(); + + public IDBSchema getElement(IDBSchema schema); + + public void applyTo(IDBSchema schema); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableDelta.java index 8a3ed39285..ae169e8ac5 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/ddl/delta/IDBTableDelta.java @@ -10,6 +10,8 @@ */ package org.eclipse.net4j.db.ddl.delta; +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.util.container.IContainer; import java.util.Map; @@ -24,7 +26,11 @@ public interface IDBTableDelta extends IDBDelta, IContainer<IDBTableElementDelta { public IDBSchemaDelta getParent(); + public IDBFieldDelta[] getFieldDeltasSortedByPosition(); + public Map<String, IDBFieldDelta> getFieldDeltas(); public Map<String, IDBIndexDelta> getIndexDeltas(); + + public IDBTable getElement(IDBSchema schema); } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBInstance.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBInstance.java index 50c0ee396b..3a1bd541db 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBInstance.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBInstance.java @@ -10,15 +10,20 @@ */ package org.eclipse.net4j.internal.db; +import org.eclipse.net4j.db.DBUtil; +import org.eclipse.net4j.db.DBUtil.RunnableWithConnection; import org.eclipse.net4j.db.IDBAdapter; import org.eclipse.net4j.db.IDBConnection; import org.eclipse.net4j.db.IDBConnectionProvider; import org.eclipse.net4j.db.IDBInstance; import org.eclipse.net4j.db.IDBSchemaTransaction; import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.spi.db.DBSchema; import org.eclipse.net4j.util.container.IContainerDelta; import org.eclipse.net4j.util.container.SingleDeltaContainerEvent; +import java.sql.Connection; +import java.sql.SQLException; import java.util.HashSet; import java.util.Set; @@ -27,20 +32,32 @@ import java.util.Set; */ public final class DBInstance extends DBElement implements IDBInstance { + private final Set<IDBConnection> dbConnections = new HashSet<IDBConnection>(); + private IDBAdapter dbAdapter; + private IDBConnectionProvider dbConnectionProvider; + private IDBSchema dbSchema; private DBSchemaTransaction dbSchemaTransaction; - private IDBConnectionProvider dbConnectionProvider; - - private final Set<IDBConnection> dbConnections = new HashSet<IDBConnection>(); - private int statementCacheCapacity = DEFAULT_STATEMENT_CACHE_CAPACITY; - public DBInstance() + public DBInstance(IDBAdapter dbAdapter, IDBConnectionProvider dbConnectionProvider, final String schemaName) { + this.dbAdapter = dbAdapter; + this.dbConnectionProvider = dbConnectionProvider; + + dbSchema = DBUtil.execute(dbConnectionProvider, new RunnableWithConnection<IDBSchema>() + { + public IDBSchema run(Connection connection) throws SQLException + { + return DBUtil.readSchema(schemaName, connection); + } + }); + + ((DBSchema)dbSchema).lock(); } public IDBAdapter getDBAdapter() diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java index 3e69935119..a7811627e5 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBSchemaTransaction.java @@ -53,15 +53,17 @@ public final class DBSchemaTransaction extends DBElement implements IDBSchemaTra IDBAdapter dbAdapter = dbInstance.getDBAdapter(); Connection connection = dbConnection.getSQLConnection(); - IDBSchema oldSchema = dbInstance.getDBSchema(); + DBSchema oldSchema = (DBSchema)dbInstance.getDBSchema(); IDBSchemaDelta delta = dbSchema.compare(oldSchema); try { - dbAdapter.updateSchema(delta, connection); + oldSchema.unlock(); + dbAdapter.updateSchema(connection, oldSchema, delta); } finally { + oldSchema.lock(); close(); } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBField.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBField.java index 47966d6f3b..f16bc4fd10 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBField.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBField.java @@ -79,6 +79,7 @@ public class DBField extends DBSchemaElement implements IDBField public void setType(DBType type) { + table.getSchema().assertUnlocked(); this.type = type; } @@ -106,6 +107,7 @@ public class DBField extends DBSchemaElement implements IDBField public void setPrecision(int precision) { + table.getSchema().assertUnlocked(); this.precision = precision; } @@ -121,6 +123,7 @@ public class DBField extends DBSchemaElement implements IDBField public void setScale(int scale) { + table.getSchema().assertUnlocked(); this.scale = scale; } @@ -129,9 +132,10 @@ public class DBField extends DBSchemaElement implements IDBField return notNull; } - public void setNotNull(boolean on) + public void setNotNull(boolean notNull) { - notNull = on; + table.getSchema().assertUnlocked(); + this.notNull = notNull; } public int getPosition() @@ -139,11 +143,22 @@ public class DBField extends DBSchemaElement implements IDBField return position; } + public void setPosition(int position) + { + table.getSchema().assertUnlocked(); + this.position = position; + } + public String getFullName() { return table.getName() + "." + name; //$NON-NLS-1$ } + public void remove() + { + table.removeField(this); + } + public String formatPrecision() { int precision = getPrecision(); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java index d8d9bf4251..811f71e048 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndex.java @@ -10,10 +10,15 @@ */ package org.eclipse.net4j.internal.db.ddl; +import org.eclipse.net4j.db.DBException; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.db.ddl.IDBIndexField; -import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.spi.db.DBSchema; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; /** * @author Eike Stepper @@ -28,9 +33,7 @@ public class DBIndex extends DBSchemaElement implements IDBIndex private Type type; - private IDBField[] fields; - - private IDBIndexField[] indexFields; + private List<DBIndexField> indexFields = new ArrayList<DBIndexField>(); public int position; @@ -38,30 +41,23 @@ public class DBIndex extends DBSchemaElement implements IDBIndex { if (name == null) { - name = "idx_" + table.getName() + "_" + position; + name = table.getSchema().createIndexName(table, type, fields, position); } this.table = table; this.name = name; this.type = type; - this.fields = fields; - indexFields = new DBIndexField[fields.length]; for (int i = 0; i < fields.length; i++) { IDBField field = fields[i]; - indexFields[i] = new DBIndexField(this, (DBField)field, i); + addIndexField(field); } this.position = position; } - public DBIndex(DBTable table, Type type, IDBField[] fields, int position) - { - this(table, null, type, fields, position); - } - - public IDBSchema getSchema() + public DBSchema getSchema() { return table.getSchema(); } @@ -76,34 +72,119 @@ public class DBIndex extends DBSchemaElement implements IDBIndex return type; } - public IDBField getField(int position) + public void setType(Type type) { - return fields[position]; + table.getSchema().assertUnlocked(); + this.type = type; } - public IDBIndexField getIndexField(int position) + public int getPosition() { - return indexFields[position]; + return position; } - public int getFieldCount() + public void setPosition(int position) { - return indexFields.length; + table.getSchema().assertUnlocked(); + this.position = position; } - public IDBField[] getFields() + public DBIndexField addIndexField(IDBField field) { - return fields; + table.getSchema().assertUnlocked(); + + if (field.getTable() != table) + { + throw new DBException("Index field is from different table: " + field); //$NON-NLS-1$ + } + + String name = field.getName(); + if (getIndexField(name) != null) + { + throw new DBException("Index field exists: " + name); //$NON-NLS-1$ + } + + int position = indexFields.size(); + DBIndexField indexField = new DBIndexField(this, (DBField)field, position); + indexFields.add(indexField); + return indexField; } - public IDBIndexField[] getIndexFields() + public void removeIndexField(IDBIndexField indexFieldToRemove) { - return indexFields; + table.getSchema().assertUnlocked(); + + boolean found = false; + for (Iterator<DBIndexField> it = indexFields.iterator(); it.hasNext();) + { + DBIndexField indexField = it.next(); + if (found) + { + indexField.setPosition(indexField.getPosition() - 1); + } + else if (indexField == indexFieldToRemove) + { + it.remove(); + found = true; + } + } } - public int getPosition() + public DBIndexField getIndexField(String name) { - return position; + for (DBIndexField indexField : indexFields) + { + if (indexField.getName().equals(name)) + { + return indexField; + } + } + + return null; + } + + public DBIndexField getIndexField(int position) + { + return indexFields.get(position); + } + + public DBField getField(String name) + { + for (DBIndexField indexField : indexFields) + { + if (indexField.getName().equals(name)) + { + return indexField.getField(); + } + } + + return null; + } + + public DBField getField(int position) + { + return indexFields.get(position).getField(); + } + + public int getFieldCount() + { + return indexFields.size(); + } + + public DBIndexField[] getIndexFields() + { + return indexFields.toArray(new DBIndexField[indexFields.size()]); + } + + public DBField[] getFields() + { + DBField[] fields = new DBField[indexFields.size()]; + for (int i = 0; i < fields.length; i++) + { + fields[i] = getField(i); + } + + return fields; } public String getName() @@ -115,4 +196,9 @@ public class DBIndex extends DBSchemaElement implements IDBIndex { return getName(); } + + public void remove() + { + table.removeIndex(this); + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndexField.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndexField.java index 101bf4aeee..13bdeffbdb 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndexField.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBIndexField.java @@ -46,6 +46,12 @@ public class DBIndexField extends DBSchemaElement implements IDBIndexField return position; } + public void setPosition(int position) + { + index.getTable().getSchema().assertUnlocked(); + this.position = position; + } + public IDBSchema getSchema() { return field.getSchema(); @@ -60,4 +66,9 @@ public class DBIndexField extends DBSchemaElement implements IDBIndexField { return field.getFullName(); } + + public void remove() + { + index.removeIndexField(this); + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java index eed81e88a4..99925617f0 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/DBTable.java @@ -16,12 +16,10 @@ import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.db.ddl.IDBIndex.Type; import org.eclipse.net4j.db.ddl.IDBTable; -import org.eclipse.net4j.db.ddl.delta.IDBDelta.ChangeKind; -import org.eclipse.net4j.internal.db.ddl.delta.DBSchemaDelta; -import org.eclipse.net4j.internal.db.ddl.delta.DBTableDelta; import org.eclipse.net4j.spi.db.DBSchema; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; /** @@ -85,21 +83,43 @@ public class DBTable extends DBSchemaElement implements IDBTable public DBField addField(String name, DBType type, int precision, int scale, boolean notNull) { schema.assertUnlocked(); + if (getField(name) != null) { - throw new DBException("DBField exists: " + name); //$NON-NLS-1$ + throw new DBException("Field exists: " + name); //$NON-NLS-1$ } - DBField field = new DBField(this, name, type, precision, scale, notNull, fields.size()); + int position = fields.size(); + DBField field = new DBField(this, name, type, precision, scale, notNull, position); fields.add(field); return field; } + public void removeField(IDBField fieldToRemove) + { + schema.assertUnlocked(); + + boolean found = false; + for (Iterator<DBField> it = fields.iterator(); it.hasNext();) + { + DBField field = it.next(); + if (found) + { + field.setPosition(field.getPosition() - 1); + } + else if (field == fieldToRemove) + { + it.remove(); + found = true; + } + } + } + public DBField getField(String name) { for (DBField field : fields) { - if (name.equals(field.getName())) + if (field.getName().equals(name)) { return field; } @@ -108,9 +128,9 @@ public class DBTable extends DBSchemaElement implements IDBTable return null; } - public DBField getField(int index) + public DBField getField(int position) { - return fields.get(index); + return fields.get(position); } public int getFieldCount() @@ -126,6 +146,7 @@ public class DBTable extends DBSchemaElement implements IDBTable public DBIndex addIndex(String name, Type type, IDBField... fields) { schema.assertUnlocked(); + DBIndex index = new DBIndex(this, name, type, fields, indices.size()); indices.add(index); return index; @@ -136,6 +157,44 @@ public class DBTable extends DBSchemaElement implements IDBTable return addIndex(null, type, fields); } + public void removeIndex(IDBIndex indexToRemove) + { + schema.assertUnlocked(); + + boolean found = false; + for (Iterator<DBIndex> it = indices.iterator(); it.hasNext();) + { + DBIndex index = it.next(); + if (found) + { + index.setPosition(index.getPosition() - 1); + } + else if (index == indexToRemove) + { + it.remove(); + found = true; + } + } + } + + public DBIndex getIndex(String name) + { + for (DBIndex index : indices) + { + if (index.getName().equals(name)) + { + return index; + } + } + + return null; + } + + public DBIndex getIndex(int position) + { + return indices.get(position); + } + public int getIndexCount() { return indices.size(); @@ -164,6 +223,11 @@ public class DBTable extends DBSchemaElement implements IDBTable return name; } + public void remove() + { + schema.removeTable(name); + } + public String sqlInsert() { StringBuilder builder = new StringBuilder(); @@ -184,9 +248,4 @@ public class DBTable extends DBSchemaElement implements IDBTable builder.append(")"); //$NON-NLS-1$ return builder.toString(); } - - public DBTableDelta createDelta(DBSchemaDelta parent) - { - return new DBTableDelta(parent, name, ChangeKind.ADDED); - } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBDelta.java index efcaa24edc..fe27e48ccb 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBDelta.java @@ -66,6 +66,29 @@ public abstract class DBDelta extends DBElement implements IDBDelta return changeKind; } + public <T> IDBPropertyDelta<T> getPropertyDelta(String name) + { + @SuppressWarnings("unchecked") + IDBPropertyDelta<T> propertyDelta = (IDBPropertyDelta<T>)propertyDeltas.get(name); + return propertyDelta; + } + + public <T> T getPropertyValue(String name) + { + return getPropertyValue(name, false); + } + + public <T> T getPropertyValue(String name, boolean old) + { + IDBPropertyDelta<T> propertyDelta = getPropertyDelta(name); + if (old) + { + return propertyDelta.getOldValue(); + } + + return propertyDelta.getValue(); + } + public final Map<String, IDBPropertyDelta<?>> getPropertyDeltas() { return Collections.unmodifiableMap(propertyDeltas); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBFieldDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBFieldDelta.java index 3cff743278..53cd451df4 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBFieldDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBFieldDelta.java @@ -12,7 +12,10 @@ package org.eclipse.net4j.internal.db.ddl.delta; import org.eclipse.net4j.db.DBType; import org.eclipse.net4j.db.ddl.IDBField; +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBDeltaVisitor; import org.eclipse.net4j.db.ddl.delta.IDBFieldDelta; import org.eclipse.net4j.db.ddl.delta.IDBPropertyDelta; import org.eclipse.net4j.util.ObjectUtil; @@ -37,35 +40,38 @@ public final class DBFieldDelta extends DBTableElementDelta implements IDBFieldD DBType oldType = oldField == null ? null : oldField.getType(); if (!ObjectUtil.equals(type, oldType)) { - addPropertyDelta(new DBPropertyDelta<DBType>("type", IDBPropertyDelta.Type.STRING, type, oldType)); + addPropertyDelta(new DBPropertyDelta<DBType>(TYPE_PROPERTY, IDBPropertyDelta.Type.STRING, type, oldType)); } Integer precision = field == null ? null : field.getPrecision(); Integer oldPrecision = oldField == null ? null : oldField.getPrecision(); if (!ObjectUtil.equals(precision, oldPrecision)) { - addPropertyDelta(new DBPropertyDelta<Integer>("precision", IDBPropertyDelta.Type.INTEGER, precision, oldPrecision)); + addPropertyDelta(new DBPropertyDelta<Integer>(PRECISION_PROPERTY, IDBPropertyDelta.Type.INTEGER, precision, + oldPrecision)); } Integer scale = field == null ? null : field.getScale(); Integer oldScale = oldField == null ? null : oldField.getScale(); if (!ObjectUtil.equals(scale, oldScale)) { - addPropertyDelta(new DBPropertyDelta<Integer>("scale", IDBPropertyDelta.Type.INTEGER, scale, oldScale)); + addPropertyDelta(new DBPropertyDelta<Integer>(SCALE_PROPERTY, IDBPropertyDelta.Type.INTEGER, scale, oldScale)); } Boolean notNull = field == null ? null : field.isNotNull(); Boolean oldNotNull = oldField == null ? null : oldField.isNotNull(); if (!ObjectUtil.equals(notNull, oldNotNull)) { - addPropertyDelta(new DBPropertyDelta<Boolean>("notNull", IDBPropertyDelta.Type.BOOLEAN, notNull, oldNotNull)); + addPropertyDelta(new DBPropertyDelta<Boolean>(NOT_NULL_PROPERTY, IDBPropertyDelta.Type.BOOLEAN, notNull, + oldNotNull)); } Integer position = oldField == null ? null : field.getPosition(); Integer oldPosition = oldField == null ? null : oldField.getPosition(); if (!ObjectUtil.equals(position, oldPosition)) { - addPropertyDelta(new DBPropertyDelta<Integer>("position", IDBPropertyDelta.Type.INTEGER, position, oldPosition)); + addPropertyDelta(new DBPropertyDelta<Integer>(POSITION_PROPERTY, IDBPropertyDelta.Type.INTEGER, position, + oldPosition)); } } @@ -80,4 +86,20 @@ public final class DBFieldDelta extends DBTableElementDelta implements IDBFieldD { return Type.FIELD; } + + public void accept(IDBDeltaVisitor visitor) + { + visitor.visit(this); + } + + public IDBField getElement(IDBSchema schema) + { + IDBTable table = getParent().getElement(schema); + if (table == null) + { + return null; + } + + return table.getField(getName()); + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexDelta.java index c669e23b62..baea331d77 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexDelta.java @@ -12,7 +12,10 @@ package org.eclipse.net4j.internal.db.ddl.delta; import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.db.ddl.IDBIndexField; +import org.eclipse.net4j.db.ddl.IDBSchema; +import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBDeltaVisitor; import org.eclipse.net4j.db.ddl.delta.IDBIndexDelta; import org.eclipse.net4j.db.ddl.delta.IDBIndexFieldDelta; import org.eclipse.net4j.db.ddl.delta.IDBPropertyDelta; @@ -50,7 +53,7 @@ public final class DBIndexDelta extends DBTableElementDelta implements IDBIndexD IDBIndex.Type oldType = oldIndex == null ? null : oldIndex.getType(); if (!ObjectUtil.equals(type, oldType)) { - addPropertyDelta(new DBPropertyDelta<IDBIndex.Type>("type", IDBPropertyDelta.Type.STRING, type, oldType)); + addPropertyDelta(new DBPropertyDelta<IDBIndex.Type>(TYPE_PROPERTY, IDBPropertyDelta.Type.STRING, type, oldType)); } IDBIndexField[] indexFields = index == null ? DBIndex.NO_INDEX_FIELDS : index.getIndexFields(); @@ -118,4 +121,24 @@ public final class DBIndexDelta extends DBTableElementDelta implements IDBIndexD { indexFieldDeltas.put(indexFieldDelta.getName(), indexFieldDelta); } + + public void accept(IDBDeltaVisitor visitor) + { + visitor.visit(this); + for (IDBIndexFieldDelta indexFieldDelta : getElements()) + { + indexFieldDelta.accept(visitor); + } + } + + public IDBIndex getElement(IDBSchema schema) + { + IDBTable table = getParent().getElement(schema); + if (table == null) + { + return null; + } + + return table.getIndex(getName()); + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexFieldDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexFieldDelta.java index 6aac156e05..82ea36e41d 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexFieldDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBIndexFieldDelta.java @@ -10,8 +10,11 @@ */ package org.eclipse.net4j.internal.db.ddl.delta; +import org.eclipse.net4j.db.ddl.IDBIndex; import org.eclipse.net4j.db.ddl.IDBIndexField; +import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBDeltaVisitor; import org.eclipse.net4j.db.ddl.delta.IDBIndexDelta; import org.eclipse.net4j.db.ddl.delta.IDBIndexFieldDelta; import org.eclipse.net4j.db.ddl.delta.IDBPropertyDelta; @@ -37,7 +40,8 @@ public final class DBIndexFieldDelta extends DBDelta implements IDBIndexFieldDel Integer oldPosition = oldIndexField == null ? null : oldIndexField.getPosition(); if (!ObjectUtil.equals(position, oldPosition)) { - addPropertyDelta(new DBPropertyDelta<Integer>("position", IDBPropertyDelta.Type.INTEGER, position, oldPosition)); + addPropertyDelta(new DBPropertyDelta<Integer>(POSITION_PROPERTY, IDBPropertyDelta.Type.INTEGER, position, + oldPosition)); } } @@ -58,4 +62,20 @@ public final class DBIndexFieldDelta extends DBDelta implements IDBIndexFieldDel { return getName().compareTo(o.getName()); } + + public void accept(IDBDeltaVisitor visitor) + { + visitor.visit(this); + } + + public IDBIndexField getElement(IDBSchema schema) + { + IDBIndex index = getParent().getElement(schema); + if (index == null) + { + return null; + } + + return index.getIndexField(getName()); + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBSchemaDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBSchemaDelta.java index 2b3d3dd19a..b47cdcd73d 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBSchemaDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBSchemaDelta.java @@ -12,6 +12,7 @@ package org.eclipse.net4j.internal.db.ddl.delta; import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBDeltaVisitor; import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; import org.eclipse.net4j.db.ddl.delta.IDBTableDelta; import org.eclipse.net4j.spi.db.DBSchema; @@ -84,4 +85,24 @@ public final class DBSchemaDelta extends DBDelta implements IDBSchemaDelta { tableDeltas.put(tableDelta.getName(), tableDelta); } + + public void accept(IDBDeltaVisitor visitor) + { + visitor.visit(this); + for (IDBTableDelta tableDelta : getElements()) + { + tableDelta.accept(visitor); + } + } + + public IDBSchema getElement(IDBSchema schema) + { + return schema; + } + + public void applyTo(IDBSchema schema) + { + IDBDeltaVisitor visitor = new IDBDeltaVisitor.Applier(schema); + accept(visitor); + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableDelta.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableDelta.java index ff7559a3bd..73edbf30d9 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableDelta.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/ddl/delta/DBTableDelta.java @@ -12,8 +12,10 @@ package org.eclipse.net4j.internal.db.ddl.delta; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; +import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; import org.eclipse.net4j.db.ddl.delta.IDBDelta; +import org.eclipse.net4j.db.ddl.delta.IDBDeltaVisitor; import org.eclipse.net4j.db.ddl.delta.IDBFieldDelta; import org.eclipse.net4j.db.ddl.delta.IDBIndexDelta; import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; @@ -23,6 +25,7 @@ import org.eclipse.net4j.internal.db.ddl.DBTable; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.Map; @@ -82,6 +85,33 @@ public final class DBTableDelta extends DBDelta implements IDBTableDelta return (IDBSchemaDelta)super.getParent(); } + public IDBFieldDelta[] getFieldDeltasSortedByPosition() + { + IDBFieldDelta[] result = fieldDeltas.values().toArray(new IDBFieldDelta[fieldDeltas.size()]); + Arrays.sort(result, new Comparator<IDBFieldDelta>() + { + public int compare(IDBFieldDelta o1, IDBFieldDelta o2) + { + int v1 = getValue(o1); + int v2 = getValue(o2); + return v2 - v1; + } + + private Integer getValue(IDBFieldDelta fieldDelta) + { + Integer value = fieldDelta.getPropertyValue(IDBFieldDelta.POSITION_PROPERTY); + if (value == null) + { + return 0; + } + + return value; + } + }); + + return result; + } + public Map<String, IDBFieldDelta> getFieldDeltas() { return Collections.unmodifiableMap(fieldDeltas); @@ -130,4 +160,18 @@ public final class DBTableDelta extends DBDelta implements IDBTableDelta { indexDeltas.put(indexDelta.getName(), indexDelta); } + + public void accept(IDBDeltaVisitor visitor) + { + visitor.visit(this); + for (IDBTableElementDelta tableElementDelta : getElements()) + { + tableElementDelta.accept(visitor); + } + } + + public IDBTable getElement(IDBSchema schema) + { + return schema.getTable(getName()); + } } diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java index 44249fe4bb..c3facf6231 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java @@ -17,9 +17,15 @@ import org.eclipse.net4j.db.DBUtil; import org.eclipse.net4j.db.IDBAdapter; import org.eclipse.net4j.db.ddl.IDBField; import org.eclipse.net4j.db.ddl.IDBIndex; +import org.eclipse.net4j.db.ddl.IDBSchema; import org.eclipse.net4j.db.ddl.IDBTable; +import org.eclipse.net4j.db.ddl.delta.IDBDelta.ChangeKind; +import org.eclipse.net4j.db.ddl.delta.IDBDeltaVisitor; +import org.eclipse.net4j.db.ddl.delta.IDBIndexDelta; import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta; +import org.eclipse.net4j.db.ddl.delta.IDBTableDelta; import org.eclipse.net4j.internal.db.bundle.OM; +import org.eclipse.net4j.util.CheckUtil; import org.eclipse.net4j.util.om.trace.ContextTracer; import javax.sql.DataSource; @@ -128,7 +134,141 @@ public abstract class DBAdapter implements IDBAdapter /** * @since 4.2 */ - public void updateSchema(IDBSchemaDelta delta, Connection connection) throws DBException + public void updateSchema(final Connection connection, final IDBSchema schema, IDBSchemaDelta delta) + throws DBException + { + // Apply delta to in-memory representation of the schema + delta.applyTo(schema); + + // Call DDL methods to update the database schema + IDBDeltaVisitor schemaUpdater = new IDBDeltaVisitor.Default() + { + @Override + public void visit(IDBTableDelta delta) + { + IDBTable table = delta.getElement(schema); + ChangeKind changeKind = delta.getChangeKind(); + switch (changeKind) + { + case ADDED: + createTable(connection, table, delta); + break; + + case REMOVED: + dropTable(connection, table, delta); + break; + + case CHANGED: + alterTable(connection, table, delta); + break; + + default: + throw new IllegalStateException("Illegal change kind: " + changeKind); + } + } + + @Override + public void visit(IDBIndexDelta delta) + { + IDBIndex element = delta.getElement(schema); + ChangeKind changeKind = delta.getChangeKind(); + switch (changeKind) + { + case ADDED: + createIndex(connection, element, delta); + break; + + case REMOVED: + dropIndex(connection, element, delta); + break; + + case CHANGED: + dropIndex(connection, element, delta); + createIndex(connection, element, delta); + break; + + default: + throw new IllegalStateException("Illegal change kind: " + changeKind); + } + } + }; + + delta.accept(schemaUpdater); + } + + /** + * @since 4.2 + */ + protected void createTable(Connection connection, IDBTable table, IDBTableDelta delta) + { + CheckUtil.checkArg(delta.getChangeKind() == ChangeKind.ADDED, "Not added: " + delta.getName()); + + StringBuilder builder = new StringBuilder(); + builder.append("CREATE TABLE "); //$NON-NLS-1$ + builder.append(delta.getName()); + builder.append(" ("); //$NON-NLS-1$ + appendFieldDefs(builder, table, createFieldDefinitions(table)); + builder.append(")"); //$NON-NLS-1$ + + DBUtil.execute(connection, builder); + } + + /** + * @since 4.2 + */ + protected void dropTable(Connection connection, IDBTable table, IDBTableDelta delta) + { + String sql = getDropTableSQL(table); + DBUtil.execute(connection, sql); + } + + /** + * @since 4.2 + */ + protected void alterTable(Connection connection, IDBTable table, IDBTableDelta delta) + { + } + + /** + * @since 4.2 + */ + protected void createIndex(Connection connection, IDBIndex index, IDBIndexDelta delta) + { + IDBTable table = index.getTable(); + String indexName = getIndexNameFor(index, index.getPosition()); + + StringBuilder builder = new StringBuilder(); + builder.append("CREATE "); //$NON-NLS-1$ + if (index.getType() == IDBIndex.Type.UNIQUE || index.getType() == IDBIndex.Type.PRIMARY_KEY) + { + builder.append("UNIQUE "); //$NON-NLS-1$ + } + + builder.append("INDEX "); //$NON-NLS-1$ + builder.append(indexName); + builder.append(" ON "); //$NON-NLS-1$ + builder.append(table); + builder.append(" ("); //$NON-NLS-1$ + IDBField[] fields = index.getFields(); + for (int i = 0; i < fields.length; i++) + { + if (i != 0) + { + builder.append(", "); //$NON-NLS-1$ + } + + addIndexField(builder, fields[i]); + } + + builder.append(")"); //$NON-NLS-1$ + + DBUtil.execute(connection, builder); + } + + /** + * @since 4.2 + */ + protected void dropIndex(Connection connection, IDBIndex index, IDBIndexDelta delta) { } @@ -390,6 +530,12 @@ public abstract class DBAdapter implements IDBAdapter return getTypeName(field) + (field.isNotNull() ? " NOT NULL" : ""); //$NON-NLS-1$ //$NON-NLS-2$ } + // protected String getTypeName(DBType type) + // { + // new DBField(null,null) + // return getTypeName(field); + // } + protected String getTypeName(IDBField field) { DBType type = field.getType(); diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java index c83554a78e..a0302c423e 100644 --- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java +++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBSchema.java @@ -194,6 +194,15 @@ public class DBSchema extends DBSchemaElement implements IDBSchema return getTables(); } + /** + * @since 4.2 + */ + public void remove() + { + assertUnlocked(); + tables.clear(); + } + public boolean isLocked() { return locked; @@ -204,6 +213,14 @@ public class DBSchema extends DBSchemaElement implements IDBSchema return locked = true; } + /** + * @since 4.2 + */ + public boolean unlock() + { + return locked = false; + } + public Set<IDBTable> create(IDBAdapter dbAdapter, Connection connection) throws DBException { return dbAdapter.createTables(tables.values(), connection); @@ -323,11 +340,19 @@ public class DBSchema extends DBSchemaElement implements IDBSchema return new DBSchemaDelta(this, oldSchema); } + /** + * @since 4.2 + */ + public String createIndexName(IDBTable table, IDBIndex.Type type, IDBField[] fields, int position) + { + return "idx_" + table.getName() + "_" + position; + } + public void assertUnlocked() throws DBException { if (locked) { - throw new DBException("DBSchema locked: " + name); //$NON-NLS-1$ + throw new DBException("Schema locked: " + name); //$NON-NLS-1$ } } |