summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Winkler2011-02-28 09:19:18 (EST)
committerStefan Winkler2011-02-28 09:19:18 (EST)
commit334a22268c9b9f09dc4db6292a17db47a9e7f590 (patch)
tree0d8b50cb4f73c74e6274a046aa88ff0fcd6f7e1c
parent94b6f046e0d550d56d0dc94261cc97028bc4c641 (diff)
downloadcdo-334a22268c9b9f09dc4db6292a17db47a9e7f590.zip
cdo-334a22268c9b9f09dc4db6292a17db47a9e7f590.tar.gz
cdo-334a22268c9b9f09dc4db6292a17db47a9e7f590.tar.bz2
[336532] [DB] MySQL exception when merging branches
https://bugs.eclipse.org/bugs/show_bug.cgi?id=336532
-rw-r--r--plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java7
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBMysql.java55
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java1
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_336382_Test.java58
-rw-r--r--plugins/org.eclipse.net4j.db.h2/.options4
-rw-r--r--plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java6
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/db/IDBAdapter.java8
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/spi/db/DBAdapter.java9
8 files changed, 134 insertions, 14 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java
index 26d6886..c1b5754 100644
--- a/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java
+++ b/plugins/org.eclipse.emf.cdo.server.db/src/org/eclipse/emf/cdo/server/internal/db/mapping/horizontal/ObjectTypeTable.java
@@ -49,8 +49,6 @@ import java.sql.Statement;
*/
public class ObjectTypeTable extends AbstractObjectTypeMapper
{
- private static final String SQL_STATE_UNIQUE_KEY_VIOLATION = "23001";
-
private IDBTable table;
private IDBField idField;
@@ -104,7 +102,8 @@ public class ObjectTypeTable extends AbstractObjectTypeMapper
public final void putObjectType(IDBStoreAccessor accessor, long timeStamp, CDOID id, EClass type)
{
- IIDHandler idHandler = getMappingStrategy().getStore().getIDHandler();
+ IDBStore store = getMappingStrategy().getStore();
+ IIDHandler idHandler = store.getIDHandler();
IPreparedStatementCache statementCache = accessor.getStatementCache();
PreparedStatement stmt = null;
@@ -125,7 +124,7 @@ public class ObjectTypeTable extends AbstractObjectTypeMapper
catch (SQLException ex)
{
// Unique key violation can occur in rare cases (merging new objects from other branches)
- if (!SQL_STATE_UNIQUE_KEY_VIOLATION.equals(ex.getSQLState()))
+ if (!store.getDBAdapter().isDuplicateKeyException(ex))
{
throw new DBException(ex);
}
diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBMysql.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBMysql.java
index bef117f..d98d488 100644
--- a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBMysql.java
+++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/AllTestsDBMysql.java
@@ -12,8 +12,12 @@
package org.eclipse.emf.cdo.tests.db;
import org.eclipse.emf.cdo.server.IRepository.Props;
-import org.eclipse.emf.cdo.server.db.CDODBUtil;
import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy;
+import org.eclipse.emf.cdo.server.internal.db.mapping.horizontal.HorizontalBranchingMappingStrategyWithRanges;
+import org.eclipse.emf.cdo.tests.BranchingSameSessionTest;
+import org.eclipse.emf.cdo.tests.BranchingTest;
+import org.eclipse.emf.cdo.tests.MergingTest;
+import org.eclipse.emf.cdo.tests.config.impl.ConfigTest;
import org.eclipse.net4j.db.DBUtil;
import org.eclipse.net4j.db.IDBAdapter;
@@ -27,6 +31,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import junit.framework.Test;
@@ -37,6 +42,17 @@ import junit.framework.TestSuite;
*/
public class AllTestsDBMysql extends DBConfigs
{
+ /**
+ * Instructions to test with MySQL: - create a mysql instance - set HOST to the host where the DB is running
+ * (listening on TCP) - set USER to a user who can create and drop databases (root, essentially) - set PASS to the
+ * password of the said user
+ */
+ public static final String HOST = "localhost";
+
+ public static final String USER = "root";
+
+ public static final String PASS = "root";
+
public static Test suite()
{
return new AllTestsDBMysql().getTestSuite("CDO Tests (DBStore MySql Horizontal)");
@@ -57,7 +73,18 @@ public class AllTestsDBMysql extends DBConfigs
@Override
protected boolean hasBranchingSupport()
{
- return false;
+ return true;
+ }
+
+ @Override
+ protected void initTestClasses(List<Class<? extends ConfigTest>> testClasses)
+ {
+ // add branching tests for this testsuite
+ testClasses.add(BranchingTest.class);
+ testClasses.add(BranchingSameSessionTest.class);
+ testClasses.add(MergingTest.class);
+
+ super.initTestClasses(testClasses);
}
/**
@@ -71,7 +98,7 @@ public class AllTestsDBMysql extends DBConfigs
private transient DataSource setupDataSource;
- private transient ArrayList<String> databases = new ArrayList<String>();
+ private transient List<String> databases = new ArrayList<String>();
public Mysql(String name)
{
@@ -81,7 +108,7 @@ public class AllTestsDBMysql extends DBConfigs
@Override
protected IMappingStrategy createMappingStrategy()
{
- return CDODBUtil.createHorizontalMappingStrategy(true);
+ return new HorizontalBranchingMappingStrategyWithRanges();
}
@Override
@@ -97,8 +124,13 @@ public class AllTestsDBMysql extends DBConfigs
initDatabase("test_" + repoName);
- ds.setUrl("jdbc:mysql://localhost/test_" + repoName);
- ds.setUser("sa");
+ ds.setUrl("jdbc:mysql://" + HOST + "/test_" + repoName);
+ ds.setUser(USER);
+ if (PASS != null)
+ {
+ ds.setPassword(PASS);
+ }
+
return ds;
}
@@ -138,6 +170,7 @@ public class AllTestsDBMysql extends DBConfigs
{
Connection connection = null;
Statement stmt = null;
+
try
{
connection = getSetupDataSource().getConnection();
@@ -159,8 +192,13 @@ public class AllTestsDBMysql extends DBConfigs
if (setupDataSource == null)
{
MysqlDataSource ds = new MysqlDataSource();
- ds.setUrl("jdbc:mysql://localhost");
- ds.setUser("sa");
+ ds.setUrl("jdbc:mysql://" + HOST);
+ ds.setUser(USER);
+ if (PASS != null)
+ {
+ ds.setPassword(PASS);
+ }
+
setupDataSource = ds;
}
@@ -172,6 +210,7 @@ public class AllTestsDBMysql extends DBConfigs
{
super.initRepositoryProperties(props);
props.put(Props.SUPPORTING_AUDITS, "true");
+ props.put(Props.SUPPORTING_BRANCHES, "true");
}
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java
index 5570ed3..2df911f 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllConfigs.java
@@ -207,6 +207,7 @@ public abstract class AllConfigs extends ConfigTestSuite
testClasses.add(Bugzilla_335675_Test.class);
testClasses.add(Bugzilla_335772_Test.class);
testClasses.add(Bugzilla_336314_Test.class);
+ testClasses.add(Bugzilla_336382_Test.class);
testClasses.add(Bugzilla_336590_Test.class);
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_336382_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_336382_Test.java
new file mode 100644
index 0000000..a156c18
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_336382_Test.java
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2004 - 2011 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:
+ * Stefan Winkler - initial API and implementation
+ */
+package org.eclipse.emf.cdo.tests.bugzilla;
+
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.tests.AbstractCDOTest;
+import org.eclipse.emf.cdo.tests.model1.Company;
+import org.eclipse.emf.cdo.transaction.CDOMerger;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+
+import org.eclipse.emf.spi.cdo.DefaultCDOMerger;
+
+/**
+ * @author Stefan Winkler
+ */
+public class Bugzilla_336382_Test extends AbstractCDOTest
+{
+ public void testPromoteToBranch() throws Exception
+ {
+ skipUnlessBranching();
+
+ CDOSession session = openSession();
+
+ CDOBranch mainBranch = session.getBranchManager().getMainBranch();
+ long timestamp = mainBranch.getBase().getTimeStamp();
+ CDOBranch sourceBranch = mainBranch.createBranch("branch1", timestamp);
+
+ {
+ CDOTransaction tx = session.openTransaction(sourceBranch);
+ CDOResource res = tx.createResource("/test");
+
+ Company company = getModel1Factory().createCompany();
+ company.setName("Foo");
+ company.setStreet("Bar");
+ company.setCity("somewhere");
+ res.getContents().add(company);
+ tx.commit();
+ }
+
+ CDOBranch targetBranch = mainBranch.createBranch("branch2", timestamp);
+
+ CDOTransaction transaction = session.openTransaction(targetBranch);
+
+ CDOMerger merger = new DefaultCDOMerger.PerFeature.ManyValued();
+ transaction.merge(sourceBranch.getHead(), merger);
+ transaction.commit();
+ }
+}
diff --git a/plugins/org.eclipse.net4j.db.h2/.options b/plugins/org.eclipse.net4j.db.h2/.options
index 9a0c12b..5be4a14 100644
--- a/plugins/org.eclipse.net4j.db.h2/.options
+++ b/plugins/org.eclipse.net4j.db.h2/.options
@@ -1,4 +1,4 @@
# Debugging and tracing options
-org.eclipse.net4j.db.hsqldb/debug = true
-org.eclipse.net4j.db.hsqldb/debug.sql = true
+org.eclipse.net4j.db.h2/debug = true
+org.eclipse.net4j.db.h2/debug.sql = true
diff --git a/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java b/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java
index dc395e4..c83f9bf 100644
--- a/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java
+++ b/plugins/org.eclipse.net4j.db.mysql/src/org/eclipse/net4j/db/mysql/MYSQLAdapter.java
@@ -149,4 +149,10 @@ public class MYSQLAdapter extends DBAdapter
return super.isTypeIndexable(type);
}
}
+
+ @Override
+ public boolean isDuplicateKeyException(SQLException ex)
+ {
+ return "23000".equals(ex.getSQLState());
+ }
}
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 c366e37..67badc4 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
@@ -19,6 +19,7 @@ import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Driver;
+import java.sql.SQLException;
import java.sql.Statement;
import java.util.Collection;
import java.util.Set;
@@ -77,4 +78,11 @@ public interface IDBAdapter
* @since 4.0
*/
public boolean isValidFirstChar(char ch);
+
+ /**
+ * Check if an exception indicates a constraint violation (duplicate key)
+ *
+ * @since 4.0
+ */
+ public boolean isDuplicateKeyException(SQLException ex);
}
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 4c17128..cf816ac 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
@@ -508,4 +508,13 @@ public abstract class DBAdapter implements IDBAdapter
{
return true;
}
+
+ /**
+ * @since 4.0
+ */
+ public boolean isDuplicateKeyException(SQLException ex)
+ {
+ /* SQL code for duplicate keys is 23001 */
+ return "23001".equals(ex.getSQLState());
+ }
}