diff options
5 files changed, 508 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/AbstractCapabilityTest.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/AbstractCapabilityTest.java new file mode 100644 index 0000000000..56e9390959 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/AbstractCapabilityTest.java @@ -0,0 +1,340 @@ +/** + * Copyright (c) 2004 - 2009 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.emf.cdo.tests.db.capabilities; + +import org.eclipse.net4j.db.IDBConnectionProvider; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import junit.framework.TestCase; + +/** + * This is a simple test case that can be used to analyze how a DBMS handles DML in the middle of a transaction. + * + * @author Stefan Winkler + */ +public abstract class AbstractCapabilityTest extends TestCase +{ + public AbstractCapabilityTest(String name) + { + super(name); + } + + abstract protected IDBConnectionProvider getConnectionProvider(); + + @Override + protected void setUp() throws Exception + { + // create table + Connection conn = getConnectionProvider().getConnection(); + conn.setAutoCommit(false); + Statement stmt = conn.createStatement(); + + // make sure tables don't exist! + try + { + stmt.execute("drop table status_table"); + } + catch (Exception e) + { + } + + try + { + stmt.execute("drop table change_table"); + } + catch (Exception e) + { + } + + stmt.execute("create table status_table (trans varchar(255), status varchar(255))"); + stmt.execute("insert into status_table values ('transaction1', 'unchanged')"); + stmt.execute("insert into status_table values ('transaction2', 'unchanged')"); + + stmt.execute("create table change_table (trans varchar(255), status varchar(255))"); + stmt.execute("insert into change_table values ('transaction1', 'unchanged')"); + stmt.execute("insert into change_table values ('transaction2', 'unchanged')"); + + conn.commit(); + stmt.close(); + conn.close(); + }; + + @Override + protected void tearDown() throws Exception + { + Connection conn = getConnectionProvider().getConnection(); + conn.setAutoCommit(true); + Statement stmt = conn.createStatement(); + + stmt.execute("drop table status_table"); + stmt.execute("drop table change_table"); + + stmt.close(); + conn.close(); + + } + + public void testDirtyRead() throws Exception + { + msg("TEST " + getClass().getSimpleName() + " - DIRTY READ"); + msg("----------------------------------------------------------"); + msg("Transaction 1 changes a value, transaction 2 will read the value."); + msg("The value of transaction 2 should be UNCHANGED (else we have a dirty read)"); + + Thread t = new Thread() + { + @Override + public void run() + { + try + { + IDBConnectionProvider provider = getConnectionProvider(); + Connection transaction1 = provider.getConnection(); + transaction1.setAutoCommit(false); + Statement tx1stmt = transaction1.createStatement(); + tx1stmt.executeUpdate("update status_table set status = 'changed' where trans = 'transaction1'"); + msg("Read value (transaction 1) is " + + select(transaction1, "select status from status_table where trans = 'transaction1'").toUpperCase()); + sleep(1000); + + transaction1.rollback(); + transaction1.close(); + } + catch (Exception e) + { + throw new Error(e); + } + }; + }; + t.start(); + + Thread.sleep(300); + + IDBConnectionProvider provider = getConnectionProvider(); + Connection transaction2 = provider.getConnection(); + + transaction2.setAutoCommit(false); + + msg("Read value (transaction 2) is " + + select(transaction2, "select status from status_table where trans = 'transaction1'").toUpperCase()); + msg("----------------------------------------------------------"); + transaction2.rollback(); + transaction2.close(); + } + + public void testRollback() throws Exception + { + msg("TEST " + getClass().getSimpleName() + " - ROLLBACK"); + msg("----------------------------------------------------------"); + msg("Transaction changes a value and does a rollback."); + msg("The value of after rollback should be UNCHANGED."); + + IDBConnectionProvider provider = getConnectionProvider(); + Connection transaction1 = provider.getConnection(); + transaction1.setAutoCommit(false); + + Statement tx1stmt = transaction1.createStatement(); + tx1stmt.executeUpdate("update status_table set status = 'changed' where trans = 'transaction1'"); + + msg("Read value before rollback is " + + select(transaction1, "select status from status_table where trans = 'transaction1'").toUpperCase()); + + transaction1.rollback(); + transaction1.close(); + + Connection view = provider.getConnection(); + msg("Read value after rollback is " + + select(view, "select status from status_table where trans = 'transaction1'").toUpperCase()); + view.close(); + msg("----------------------------------------------------------"); + } + + public void testDml() throws Exception + { + msg("TEST " + getClass().getSimpleName() + " - DML"); + msg("----------------------------------------------------------"); + msg("Transaction 1 will execute DML, transaction 2 will just change its data."); + + Thread t = new Thread() + { + @Override + public void run() + { + try + { + IDBConnectionProvider provider = getConnectionProvider(); + Connection transaction2 = provider.getConnection(); + Statement tx2stmt = transaction2.createStatement(); + transaction2.setAutoCommit(false); + tx2stmt.executeUpdate("update status_table set status = 'changed' where trans = 'transaction2'"); + tx2stmt.executeUpdate("update change_table set status = 'changed' where trans = 'transaction2'"); + tx2stmt.close(); + sleep(1000); + transaction2.rollback(); + transaction2.close(); + } + catch (Exception e) + { + throw new Error(e); + } + } + }; + t.start(); + + Thread.sleep(100); + + IDBConnectionProvider provider = getConnectionProvider(); + Connection transaction1 = provider.getConnection(); + transaction1.setAutoCommit(false); + + Statement tx1stmt = transaction1.createStatement(); + + tx1stmt.executeUpdate("update status_table set status = 'changed' where trans = 'transaction1'"); + tx1stmt.executeUpdate("update change_table set status = 'changed' where trans = 'transaction1'"); + + tx1stmt.execute("alter table change_table add new_column varchar(255) default 'added column present'"); + + tx1stmt.close(); + + transaction1.rollback(); + transaction1.close(); + + t.join(); + + Connection view = provider.getConnection(); + + msg("transaction1: unchanged table record is " + + select(view, "select status from status_table where trans = 'transaction1'").toUpperCase()); + msg("transaction2: unchanged table record is " + + select(view, "select status from status_table where trans = 'transaction2'").toUpperCase()); + + msg("transaction1: changed table record is " + + select(view, "select status from change_table where trans = 'transaction1'").toUpperCase()); + msg("transaction2: changed table record is " + + select(view, "select status from change_table where trans = 'transaction2'").toUpperCase()); + + String present = "present"; + try + { + select(view, "select new_column from change_table where trans = 'transaction2'"); + } + catch (SQLException e) + { + present = "not present"; + } + + msg("Added column is " + present.toUpperCase()); + view.close(); + + msg("----------------------------------------------------------"); + + } + + private void msg(String string) + { + System.out.println(string); + } + + private String select(Connection conn, String sql) throws SQLException + { + ResultSet rs = null; + try + { + rs = conn.createStatement().executeQuery(sql); + rs.next(); + return rs.getString(1); + } + finally + { + if (rs != null) + { + try + { + rs.close(); + } + catch (SQLException ex) + { + // NOP + } + } + } + } + + @SuppressWarnings("unused") + private void sqlDump(Connection conn, String sql) + { + ResultSet rs = null; + try + { + System.out.format("Dumping output of %s\n", sql); //$NON-NLS-1$ + rs = conn.createStatement().executeQuery(sql); + int numCol = rs.getMetaData().getColumnCount(); + + StringBuilder row = new StringBuilder(" "); + for (int c = 1; c <= numCol; c++) + { + row.append(String.format("%15s | ", rs.getMetaData().getColumnLabel(c))); //$NON-NLS-1$ + } + + System.out.println(row.toString()); + + row = new StringBuilder(); + for (int c = 1; c <= numCol; c++) + { + row.append("-----------------+"); //$NON-NLS-1$ + } + + System.out.println(row.toString()); + + while (rs.next()) + { + row = new StringBuilder(" "); + for (int c = 1; c <= numCol; c++) + { + row.append(String.format("%15s | ", rs.getString(c))); //$NON-NLS-1$ + } + + System.out.println(row.toString()); + } + + row = new StringBuilder(); + for (int c = 1; c <= numCol; c++) + { + row.append("-----------------+"); //$NON-NLS-1$ + } + + System.out.println(row.toString()); + } + catch (SQLException ex) + { + // NOP + } + finally + { + if (rs != null) + { + try + { + rs.close(); + } + catch (SQLException ex) + { + // NOP + } + } + } + } + +} diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/DerbyTest.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/DerbyTest.java new file mode 100644 index 0000000000..7216c95b3b --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/DerbyTest.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2004 - 2009 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.emf.cdo.tests.db.capabilities; + +import org.eclipse.net4j.db.DBUtil; +import org.eclipse.net4j.db.IDBConnectionProvider; +import org.eclipse.net4j.util.io.TMPUtil; + +import org.apache.derby.jdbc.EmbeddedDataSource; + +import java.io.File; + +/** + * @author Stefan Winkler + */ +public class DerbyTest extends AbstractCapabilityTest +{ + public DerbyTest() + { + super("derby"); + File dbFolder = TMPUtil.createTempFolder("derby_", "_test", new File("c:/temp")); + dbFolder.delete(); + EmbeddedDataSource derbyds = new EmbeddedDataSource(); + derbyds.setDatabaseName(dbFolder.getAbsolutePath()); + derbyds.setCreateDatabase("create"); + provider = DBUtil.createConnectionProvider(derbyds); + + } + + IDBConnectionProvider provider = null; + + @Override + protected IDBConnectionProvider getConnectionProvider() + { + return provider; + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/H2Test.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/H2Test.java new file mode 100644 index 0000000000..5d2af41992 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/H2Test.java @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2004 - 2009 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.emf.cdo.tests.db.capabilities; + +import org.eclipse.net4j.db.DBUtil; +import org.eclipse.net4j.db.IDBConnectionProvider; + +import org.h2.jdbcx.JdbcDataSource; + +/** + * @author Stefan Winkler + */ +public class H2Test extends AbstractCapabilityTest +{ + public H2Test() + { + super("h2"); + JdbcDataSource h2ds = new JdbcDataSource(); + h2ds = new JdbcDataSource(); + h2ds.setURL("jdbc:h2:file:c:/temp/h2test"); + h2ds.setUser("sa"); + provider = DBUtil.createConnectionProvider(h2ds); + } + + IDBConnectionProvider provider = null; + + @Override + protected IDBConnectionProvider getConnectionProvider() + { + return provider; + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/HsqlTest.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/HsqlTest.java new file mode 100644 index 0000000000..5c409d2a9f --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/HsqlTest.java @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2004 - 2009 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.emf.cdo.tests.db.capabilities; + +import org.eclipse.net4j.db.DBUtil; +import org.eclipse.net4j.db.IDBConnectionProvider; + +import org.hsqldb.jdbc.jdbcDataSource; + +/** + * @author Stefan Winkler + */ +public class HsqlTest extends AbstractCapabilityTest +{ + + public HsqlTest() + { + super("hsqldb"); + jdbcDataSource hsqlds = new jdbcDataSource(); + hsqlds.setDatabase("jdbc:hsqldb:file:c:/temp/hsql_test"); + hsqlds.setUser("sa"); + + provider = DBUtil.createConnectionProvider(hsqlds); + } + + IDBConnectionProvider provider = null; + + @Override + protected IDBConnectionProvider getConnectionProvider() + { + return provider; + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/MysqlTest.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/MysqlTest.java new file mode 100644 index 0000000000..5cfa883032 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/capabilities/MysqlTest.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2004 - 2009 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.emf.cdo.tests.db.capabilities; + +import org.eclipse.net4j.db.DBUtil; +import org.eclipse.net4j.db.IDBConnectionProvider; + +import com.mysql.jdbc.jdbc2.optional.MysqlDataSource; + +/** + * @author Stefan Winkler + */ +public class MysqlTest extends AbstractCapabilityTest +{ + + private IDBConnectionProvider provider; + + public MysqlTest() + { + super("mysql"); + MysqlDataSource mysqlds = new MysqlDataSource(); + mysqlds.setUrl("jdbc:mysql://localhost:33306/winkler_r2"); + mysqlds.setUser("winkler"); + mysqlds.setPassword("winkler"); + provider = DBUtil.createConnectionProvider(mysqlds); + } + + @Override + protected IDBConnectionProvider getConnectionProvider() + { + return provider; + } + +} |