summaryrefslogtreecommitdiffstats
path: root/server/sonar-db-migration
diff options
context:
space:
mode:
authorJacek <jacek.poreda@sonarsource.com>2020-12-22 13:03:08 +0100
committersonartech <sonartech@sonarsource.com>2020-12-23 20:10:14 +0000
commit3f789f5fad5957680fdeb3d4c5592b61bc48df1c (patch)
treee7a2fb56e1323bf1afcace75b5a4f449535d929f /server/sonar-db-migration
parenta0ee873fb078986f9794213cd844f2f73499ceda (diff)
downloadsonarqube-3f789f5fad5957680fdeb3d4c5592b61bc48df1c.tar.gz
sonarqube-3f789f5fad5957680fdeb3d4c5592b61bc48df1c.zip
SONAR-14297 Make migration app xml->db re-entrant in case failure
Diffstat (limited to 'server/sonar-db-migration')
-rw-r--r--server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDb.java9
-rw-r--r--server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDbTest.java40
2 files changed, 48 insertions, 1 deletions
diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDb.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDb.java
index 62257488f0f..7dff6036a36 100644
--- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDb.java
+++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDb.java
@@ -74,6 +74,7 @@ public class MigrateApplicationDefinitionsFromXmlToDb extends DataChange {
static final int TEXT_VALUE_MAX_LENGTH = 4000;
private static final String SELECT_APPLICATION_UUID_BY_KEY = "select uuid from projects where kee = ? and qualifier = 'APP'";
private static final String SELECT_PROJECTS_BY_KEYS = "select kee,uuid from projects where kee in (%s) and qualifier = 'TRK'";
+ private static final String SELECT_PROJECTS_BY_APP = "select project_uuid from app_projects where application_uuid = ?";
private static final String UPDATE_INTERNAL_PROP_TEXT_VALUE = "update internal_properties set text_value = ?, clob_value = NULL where kee = ?";
private static final String UPDATE_INTERNAL_PROP_CLOB_VALUE = "update internal_properties set clob_value = ?, text_value = NULL where kee = ?";
private static final String VIEWS_DEF_KEY = "views.def";
@@ -126,13 +127,19 @@ public class MigrateApplicationDefinitionsFromXmlToDb extends DataChange {
return;
}
+ List<String> alreadyAddedProjects = context.prepareSelect(SELECT_PROJECTS_BY_APP).setString(1, applicationUuid)
+ .list(r -> r.getString(1));
+
String queryParam = projects.stream().map(uuid -> "'" + uuid + "'").collect(Collectors.joining(","));
Map<String, String> projectUuidsByKeys = context.prepareSelect(format(SELECT_PROJECTS_BY_KEYS, queryParam))
.list(r -> new AbstractMap.SimpleEntry<>(r.getString(1), r.getString(2)))
.stream()
+ .filter(project -> !alreadyAddedProjects.contains(project.getValue()))
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
- insertApplicationProjects(context, app, applicationUuid, projectUuidsByKeys, now);
+ if (!projectUuidsByKeys.isEmpty()) {
+ insertApplicationProjects(context, app, applicationUuid, projectUuidsByKeys, now);
+ }
if (!app.getApplicationBranches().isEmpty()) {
insertApplicationBranchesProjects(context, app, applicationUuid, projectUuidsByKeys, now);
}
diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDbTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDbTest.java
index 856943d0644..04d30fd5478 100644
--- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDbTest.java
+++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v86/MigrateApplicationDefinitionsFromXmlToDbTest.java
@@ -434,6 +434,41 @@ public class MigrateApplicationDefinitionsFromXmlToDbTest {
}
@Test
+ public void migration_is_resilient() throws SQLException {
+ setupProjectsAndApps();
+ insertViewsDefInternalProperty(COMPLEX_XML_BEFORE);
+
+ // first attempt
+ underTest.execute();
+
+ // xml stays the same (stopped during migration)
+ updateViewsDefInternalProperty(COMPLEX_XML_BEFORE);
+
+ // second attempt should not fail
+ underTest.execute();
+
+ assertThat(db.select("select uuid from projects"))
+ .extracting(r -> r.get("UUID"))
+ .containsExactlyInAnyOrder(PROJECT_1_UUID, PROJECT_2_UUID, APP_1_UUID, APP_2_UUID);
+ assertThat(db.select("select application_uuid, project_uuid from app_projects"))
+ .extracting(r -> r.get("APPLICATION_UUID"), r -> r.get("PROJECT_UUID"))
+ .containsExactlyInAnyOrder(
+ tuple(APP_1_UUID, PROJECT_1_UUID),
+ tuple(APP_1_UUID, PROJECT_2_UUID),
+ tuple(APP_2_UUID, PROJECT_1_UUID),
+ tuple(APP_2_UUID, PROJECT_2_UUID));
+ assertThat(db.select("select application_uuid, project_uuid, application_branch_uuid, project_branch_uuid from app_branch_project_branch"))
+ .extracting(r -> r.get("APPLICATION_UUID"), r -> r.get("PROJECT_UUID"), r -> r.get("APPLICATION_BRANCH_UUID"), r -> r.get("PROJECT_BRANCH_UUID"))
+ .containsExactlyInAnyOrder(
+ tuple(APP_1_UUID, PROJECT_1_UUID, APP_1_BRANCH_1_UUID, PROJECT_1_BRANCH_1_UUID),
+ tuple(APP_1_UUID, PROJECT_2_UUID, APP_1_BRANCH_1_UUID, PROJECT_2_BRANCH_1_UUID),
+ tuple(APP_1_UUID, PROJECT_1_UUID, APP_1_BRANCH_2_UUID, PROJECT_1_BRANCH_2_UUID),
+ tuple(APP_1_UUID, PROJECT_2_UUID, APP_1_BRANCH_2_UUID, PROJECT_2_BRANCH_1_UUID),
+ tuple(APP_2_UUID, PROJECT_1_UUID, APP_2_BRANCH_1_UUID, PROJECT_1_BRANCH_1_UUID),
+ tuple(APP_2_UUID, PROJECT_2_UUID, APP_2_BRANCH_1_UUID, PROJECT_2_BRANCH_1_UUID));
+ }
+
+ @Test
public void migrates_applications_without_application_branches_to_new_tables() throws SQLException {
setupFullProject1();
setupProject2();
@@ -681,6 +716,11 @@ public class MigrateApplicationDefinitionsFromXmlToDbTest {
"created_at", system2.now());
}
+ private void updateViewsDefInternalProperty(@Nullable String xml) {
+ db.executeUpdateSql("update internal_properties set text_value = ? where kee = 'views.def'",
+ xml);
+ }
+
private void insertProject(String uuid, String key, String qualifier) {
db.executeInsert("PROJECTS",
"UUID", uuid,