From e184f159ade71372942f2840b62f6b71eeefb4c5 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 15 Dec 2015 09:50:07 +0100 Subject: [PATCH] SONAR-7137 Fix migration on MySQL Use another connection to select all duplicated components --- .../src/main/java/org/sonar/db/MyBatis.java | 3 +- .../v52/RemoveDuplicatedComponentKeys.java | 62 +++++++----------- .../org/sonar/db/version/v53/Component.java | 65 +++++++++++++++++++ .../db/version/v53/Migration53Mapper.java | 37 +++++++++++ .../db/version/v53/Migration53Mapper.xml | 7 ++ .../RemoveDuplicatedComponentKeysTest.java | 2 +- 6 files changed, 136 insertions(+), 40 deletions(-) create mode 100644 sonar-db/src/main/java/org/sonar/db/version/v53/Component.java create mode 100644 sonar-db/src/main/java/org/sonar/db/version/v53/Migration53Mapper.java create mode 100644 sonar-db/src/main/resources/org/sonar/db/version/v53/Migration53Mapper.xml diff --git a/sonar-db/src/main/java/org/sonar/db/MyBatis.java b/sonar-db/src/main/java/org/sonar/db/MyBatis.java index 9011a073e62..232b74dd359 100644 --- a/sonar-db/src/main/java/org/sonar/db/MyBatis.java +++ b/sonar-db/src/main/java/org/sonar/db/MyBatis.java @@ -132,6 +132,7 @@ import org.sonar.db.version.SchemaMigrationDto; import org.sonar.db.version.SchemaMigrationMapper; import org.sonar.db.version.v45.Migration45Mapper; import org.sonar.db.version.v50.Migration50Mapper; +import org.sonar.db.version.v53.Migration53Mapper; public class MyBatis { @@ -235,7 +236,7 @@ public class MyBatis { MeasureMapper.class, MetricMapper.class, CustomMeasureMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class, ComponentMapper.class, SnapshotMapper.class, ProjectQgateAssociationMapper.class, EventMapper.class, CeQueueMapper.class, CeActivityMapper.class, ComponentLinkMapper.class, - Migration45Mapper.class, Migration50Mapper.class + Migration45Mapper.class, Migration50Mapper.class, Migration53Mapper.class }; confBuilder.loadMappers(mappers); diff --git a/sonar-db/src/main/java/org/sonar/db/version/v52/RemoveDuplicatedComponentKeys.java b/sonar-db/src/main/java/org/sonar/db/version/v52/RemoveDuplicatedComponentKeys.java index 557c562fca0..658a521edfc 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/v52/RemoveDuplicatedComponentKeys.java +++ b/sonar-db/src/main/java/org/sonar/db/version/v52/RemoveDuplicatedComponentKeys.java @@ -29,9 +29,13 @@ import java.util.concurrent.atomic.AtomicLong; import javax.annotation.Nonnull; import org.sonar.core.util.ProgressLogger; import org.sonar.db.Database; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; import org.sonar.db.version.BaseDataChange; import org.sonar.db.version.Select; import org.sonar.db.version.Upsert; +import org.sonar.db.version.v53.Component; +import org.sonar.db.version.v53.Migration53Mapper; /** * Remove all duplicated component that have the same keys. @@ -44,9 +48,11 @@ import org.sonar.db.version.Upsert; public class RemoveDuplicatedComponentKeys extends BaseDataChange { private final AtomicLong counter = new AtomicLong(0L); + private final DbClient dbClient; - public RemoveDuplicatedComponentKeys(Database db) { + public RemoveDuplicatedComponentKeys(Database db, DbClient dbClient) { super(db); + this.dbClient = dbClient; } @Override @@ -54,10 +60,13 @@ public class RemoveDuplicatedComponentKeys extends BaseDataChange { Upsert componentUpdate = context.prepareUpsert("DELETE FROM projects WHERE id=?"); Upsert issuesUpdate = context.prepareUpsert("UPDATE issues SET component_uuid=?, project_uuid=? WHERE component_uuid=?"); + DbSession readSession = dbClient.openSession(false); + Migration53Mapper mapper = readSession.getMapper(Migration53Mapper.class); + ProgressLogger progress = ProgressLogger.create(getClass(), counter); progress.start(); try { - RemoveDuplicatedComponentHandler handler = new RemoveDuplicatedComponentHandler(context, componentUpdate, issuesUpdate); + RemoveDuplicatedComponentHandler handler = new RemoveDuplicatedComponentHandler(mapper, componentUpdate, issuesUpdate); context.prepareSelect( "SELECT p.kee, COUNT(p.kee) FROM projects p " + "GROUP BY p.kee " + @@ -70,40 +79,39 @@ public class RemoveDuplicatedComponentKeys extends BaseDataChange { progress.log(); } finally { progress.stop(); + dbClient.closeSession(readSession); componentUpdate.close(); issuesUpdate.close(); } } private class RemoveDuplicatedComponentHandler implements Select.RowHandler { - private final Context context; + private final Migration53Mapper mapper; private final Upsert componentUpdate; private final Upsert issuesUpdate; private boolean isEmpty = true; - public RemoveDuplicatedComponentHandler(Context context, Upsert componentUpdate, Upsert issuesUpdate) { - this.context = context; + public RemoveDuplicatedComponentHandler(Migration53Mapper mapper, Upsert componentUpdate, Upsert issuesUpdate) { + this.mapper = mapper; this.componentUpdate = componentUpdate; this.issuesUpdate = issuesUpdate; } @Override public void handle(Select.Row row) throws SQLException { - List components = context - .prepareSelect("SELECT p.id, p.uuid, p.project_uuid, p.enabled FROM projects p WHERE p.kee=? ORDER BY id") - .setString(1, row.getString(1)) - .list(ComponentRowReader.INSTANCE); + String componentKey = row.getString(1); + List components = mapper.selectComponentsByKey(componentKey); // We keep the enabled component or the last component of the list Component refComponent = FluentIterable.from(components).firstMatch(EnabledComponent.INSTANCE).or(components.get(components.size() - 1)); - for (Component componentToRemove : FluentIterable.from(components).filter(Predicates.not(new MatchComponentId(refComponent.id)))) { + for (Component componentToRemove : FluentIterable.from(components).filter(Predicates.not(new MatchComponentId(refComponent.getId())))) { componentUpdate - .setLong(1, componentToRemove.id) + .setLong(1, componentToRemove.getId()) .addBatch(); issuesUpdate - .setString(1, refComponent.uuid) - .setString(2, refComponent.projectUuid) - .setString(3, componentToRemove.uuid) + .setString(1, refComponent.getUuid()) + .setString(2, refComponent.getProjectUuid()) + .setString(3, componentToRemove.getUuid()) .addBatch(); counter.getAndIncrement(); isEmpty = false; @@ -120,7 +128,7 @@ public class RemoveDuplicatedComponentKeys extends BaseDataChange { @Override public boolean apply(@Nonnull Component input) { - return input.enabled; + return input.isEnabled(); } } @@ -134,30 +142,8 @@ public class RemoveDuplicatedComponentKeys extends BaseDataChange { @Override public boolean apply(@Nonnull Component input) { - return input.id == this.id; - } - } - - private enum ComponentRowReader implements Select.RowReader { - INSTANCE; - - @Override - public Component read(Select.Row row) throws SQLException { - return new Component(row.getLong(1), row.getString(2), row.getString(3), row.getBoolean(4)); + return input.getId() == this.id; } } - private static class Component { - private final long id; - private final String uuid; - private final String projectUuid; - private final boolean enabled; - - public Component(long id, String uuid, String projectUuid, boolean enabled) { - this.id = id; - this.uuid = uuid; - this.projectUuid = projectUuid; - this.enabled = enabled; - } - } } diff --git a/sonar-db/src/main/java/org/sonar/db/version/v53/Component.java b/sonar-db/src/main/java/org/sonar/db/version/v53/Component.java new file mode 100644 index 00000000000..e33bd11d5fc --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v53/Component.java @@ -0,0 +1,65 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.db.version.v53; + +public class Component { + + private long id; + private String uuid; + private String projectUuid; + private boolean enabled; + + public long getId() { + return id; + } + + public Component setId(long id) { + this.id = id; + return this; + } + + public String getUuid() { + return uuid; + } + + public Component setUuid(String uuid) { + this.uuid = uuid; + return this; + } + + public String getProjectUuid() { + return projectUuid; + } + + public Component setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; + return this; + } + + public boolean isEnabled() { + return enabled; + } + + public Component setEnabled(boolean enabled) { + this.enabled = enabled; + return this; + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v53/Migration53Mapper.java b/sonar-db/src/main/java/org/sonar/db/version/v53/Migration53Mapper.java new file mode 100644 index 00000000000..74a34e3706d --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v53/Migration53Mapper.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.db.version.v53; + +import java.util.List; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Result; +import org.apache.ibatis.annotations.Select; + +public interface Migration53Mapper { + + /** + * Return components having the same given key + */ + @Select("SELECT p.id AS \"id\", p.uuid AS \"uuid\", p.project_uuid AS \"projectUuid\", p.enabled AS \"enabled\" FROM projects p WHERE p.kee=#{key} ORDER BY id") + @Result(javaType = Component.class) + List selectComponentsByKey(@Param("key") String componentKey); + +} diff --git a/sonar-db/src/main/resources/org/sonar/db/version/v53/Migration53Mapper.xml b/sonar-db/src/main/resources/org/sonar/db/version/v53/Migration53Mapper.xml new file mode 100644 index 00000000000..509d00ff73e --- /dev/null +++ b/sonar-db/src/main/resources/org/sonar/db/version/v53/Migration53Mapper.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sonar-db/src/test/java/org/sonar/db/version/v52/RemoveDuplicatedComponentKeysTest.java b/sonar-db/src/test/java/org/sonar/db/version/v52/RemoveDuplicatedComponentKeysTest.java index 79d5b1511ab..122f0e94dee 100644 --- a/sonar-db/src/test/java/org/sonar/db/version/v52/RemoveDuplicatedComponentKeysTest.java +++ b/sonar-db/src/test/java/org/sonar/db/version/v52/RemoveDuplicatedComponentKeysTest.java @@ -39,7 +39,7 @@ public class RemoveDuplicatedComponentKeysTest { db.executeUpdateSql("truncate table projects"); db.executeUpdateSql("truncate table issues"); - migration = new RemoveDuplicatedComponentKeys(db.database()); + migration = new RemoveDuplicatedComponentKeys(db.database(), db.getDbClient()); } @Test -- 2.39.5